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 018package org.apache.commons.math3.analysis; 019 020import org.apache.commons.math3.analysis.differentiation.DerivativeStructure; 021import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableFunction; 022import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableVectorFunction; 023import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction; 024import org.apache.commons.math3.analysis.function.Identity; 025import org.apache.commons.math3.exception.DimensionMismatchException; 026import org.apache.commons.math3.exception.NotStrictlyPositiveException; 027import org.apache.commons.math3.exception.NumberIsTooLargeException; 028import org.apache.commons.math3.exception.util.LocalizedFormats; 029 030/** 031 * Utilities for manipulating function objects. 032 * 033 * @since 3.0 034 */ 035public class FunctionUtils { 036 /** 037 * Class only contains static methods. 038 */ 039 private FunctionUtils() {} 040 041 /** 042 * Composes functions. 043 * <br/> 044 * The functions in the argument list are composed sequentially, in the 045 * given order. For example, compose(f1,f2,f3) acts like f1(f2(f3(x))). 046 * 047 * @param f List of functions. 048 * @return the composite function. 049 */ 050 public static UnivariateFunction compose(final UnivariateFunction ... f) { 051 return new UnivariateFunction() { 052 /** {@inheritDoc} */ 053 public double value(double x) { 054 double r = x; 055 for (int i = f.length - 1; i >= 0; i--) { 056 r = f[i].value(r); 057 } 058 return r; 059 } 060 }; 061 } 062 063 /** 064 * Composes functions. 065 * <br/> 066 * The functions in the argument list are composed sequentially, in the 067 * given order. For example, compose(f1,f2,f3) acts like f1(f2(f3(x))). 068 * 069 * @param f List of functions. 070 * @return the composite function. 071 * @since 3.1 072 */ 073 public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) { 074 return new UnivariateDifferentiableFunction() { 075 076 /** {@inheritDoc} */ 077 public double value(final double t) { 078 double r = t; 079 for (int i = f.length - 1; i >= 0; i--) { 080 r = f[i].value(r); 081 } 082 return r; 083 } 084 085 /** {@inheritDoc} */ 086 public DerivativeStructure value(final DerivativeStructure t) { 087 DerivativeStructure r = t; 088 for (int i = f.length - 1; i >= 0; i--) { 089 r = f[i].value(r); 090 } 091 return r; 092 } 093 094 }; 095 } 096 097 /** 098 * Composes functions. 099 * <br/> 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))). 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 <br/> 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 * <br/> 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}. 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 /** Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}. 446 * @param f function to convert 447 * @return converted function 448 * @deprecated this conversion method is temporary in version 3.1, as the {@link 449 * DifferentiableUnivariateFunction} interface itself is deprecated 450 */ 451 @Deprecated 452 public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) { 453 return new DifferentiableUnivariateFunction() { 454 455 /** {@inheritDoc} */ 456 public double value(final double x) { 457 return f.value(x); 458 } 459 460 /** {@inheritDoc} */ 461 public UnivariateFunction derivative() { 462 return new UnivariateFunction() { 463 /** {@inheritDoc} */ 464 public double value(final double x) { 465 return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1); 466 } 467 }; 468 } 469 470 }; 471 } 472 473 /** Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}. 474 * <p> 475 * Note that the converted function is able to handle {@link DerivativeStructure} up to order one. 476 * If the function is called with higher order, a {@link NumberIsTooLargeException} will be thrown. 477 * </p> 478 * @param f function to convert 479 * @return converted function 480 * @deprecated this conversion method is temporary in version 3.1, as the {@link 481 * DifferentiableUnivariateFunction} interface itself is deprecated 482 */ 483 @Deprecated 484 public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) { 485 return new UnivariateDifferentiableFunction() { 486 487 /** {@inheritDoc} */ 488 public double value(final double x) { 489 return f.value(x); 490 } 491 492 /** {@inheritDoc} 493 * @exception NumberIsTooLargeException if derivation order is greater than 1 494 */ 495 public DerivativeStructure value(final DerivativeStructure t) 496 throws NumberIsTooLargeException { 497 switch (t.getOrder()) { 498 case 0 : 499 return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue())); 500 case 1 : { 501 final int parameters = t.getFreeParameters(); 502 final double[] derivatives = new double[parameters + 1]; 503 derivatives[0] = f.value(t.getValue()); 504 final double fPrime = f.derivative().value(t.getValue()); 505 int[] orders = new int[parameters]; 506 for (int i = 0; i < parameters; ++i) { 507 orders[i] = 1; 508 derivatives[i + 1] = fPrime * t.getPartialDerivative(orders); 509 orders[i] = 0; 510 } 511 return new DerivativeStructure(parameters, 1, derivatives); 512 } 513 default : 514 throw new NumberIsTooLargeException(t.getOrder(), 1, true); 515 } 516 } 517 518 }; 519 } 520 521 /** Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}. 522 * @param f function to convert 523 * @return converted function 524 * @deprecated this conversion method is temporary in version 3.1, as the {@link 525 * DifferentiableMultivariateFunction} interface itself is deprecated 526 */ 527 @Deprecated 528 public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) { 529 return new DifferentiableMultivariateFunction() { 530 531 /** {@inheritDoc} */ 532 public double value(final double[] x) { 533 return f.value(x); 534 } 535 536 /** {@inheritDoc} */ 537 public MultivariateFunction partialDerivative(final int k) { 538 return new MultivariateFunction() { 539 /** {@inheritDoc} */ 540 public double value(final double[] x) { 541 542 final int n = x.length; 543 544 // delegate computation to underlying function 545 final DerivativeStructure[] dsX = new DerivativeStructure[n]; 546 for (int i = 0; i < n; ++i) { 547 if (i == k) { 548 dsX[i] = new DerivativeStructure(1, 1, 0, x[i]); 549 } else { 550 dsX[i] = new DerivativeStructure(1, 1, x[i]); 551 } 552 } 553 final DerivativeStructure y = f.value(dsX); 554 555 // extract partial derivative 556 return y.getPartialDerivative(1); 557 558 } 559 }; 560 } 561 562 public MultivariateVectorFunction gradient() { 563 return new MultivariateVectorFunction() { 564 /** {@inheritDoc} */ 565 public double[] value(final double[] x) { 566 567 final int n = x.length; 568 569 // delegate computation to underlying function 570 final DerivativeStructure[] dsX = new DerivativeStructure[n]; 571 for (int i = 0; i < n; ++i) { 572 dsX[i] = new DerivativeStructure(n, 1, i, x[i]); 573 } 574 final DerivativeStructure y = f.value(dsX); 575 576 // extract gradient 577 final double[] gradient = new double[n]; 578 final int[] orders = new int[n]; 579 for (int i = 0; i < n; ++i) { 580 orders[i] = 1; 581 gradient[i] = y.getPartialDerivative(orders); 582 orders[i] = 0; 583 } 584 585 return gradient; 586 587 } 588 }; 589 } 590 591 }; 592 } 593 594 /** Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}. 595 * <p> 596 * Note that the converted function is able to handle {@link DerivativeStructure} elements 597 * that all have the same number of free parameters and order, and with order at most 1. 598 * If the function is called with inconsistent numbers of free parameters or higher order, a 599 * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown. 600 * </p> 601 * @param f function to convert 602 * @return converted function 603 * @deprecated this conversion method is temporary in version 3.1, as the {@link 604 * DifferentiableMultivariateFunction} interface itself is deprecated 605 */ 606 @Deprecated 607 public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) { 608 return new MultivariateDifferentiableFunction() { 609 610 /** {@inheritDoc} */ 611 public double value(final double[] x) { 612 return f.value(x); 613 } 614 615 /** {@inheritDoc} 616 * @exception NumberIsTooLargeException if derivation order is higher than 1 617 * @exception DimensionMismatchException if numbers of free parameters are inconsistent 618 */ 619 public DerivativeStructure value(final DerivativeStructure[] t) 620 throws DimensionMismatchException, NumberIsTooLargeException { 621 622 // check parameters and orders limits 623 final int parameters = t[0].getFreeParameters(); 624 final int order = t[0].getOrder(); 625 final int n = t.length; 626 if (order > 1) { 627 throw new NumberIsTooLargeException(order, 1, true); 628 } 629 630 // check all elements in the array are consistent 631 for (int i = 0; i < n; ++i) { 632 if (t[i].getFreeParameters() != parameters) { 633 throw new DimensionMismatchException(t[i].getFreeParameters(), parameters); 634 } 635 636 if (t[i].getOrder() != order) { 637 throw new DimensionMismatchException(t[i].getOrder(), order); 638 } 639 } 640 641 // delegate computation to underlying function 642 final double[] point = new double[n]; 643 for (int i = 0; i < n; ++i) { 644 point[i] = t[i].getValue(); 645 } 646 final double value = f.value(point); 647 final double[] gradient = f.gradient().value(point); 648 649 // merge value and gradient into one DerivativeStructure 650 final double[] derivatives = new double[parameters + 1]; 651 derivatives[0] = value; 652 final int[] orders = new int[parameters]; 653 for (int i = 0; i < parameters; ++i) { 654 orders[i] = 1; 655 for (int j = 0; j < n; ++j) { 656 derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders); 657 } 658 orders[i] = 0; 659 } 660 661 return new DerivativeStructure(parameters, order, derivatives); 662 663 } 664 665 }; 666 } 667 668 /** Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}. 669 * @param f function to convert 670 * @return converted function 671 * @deprecated this conversion method is temporary in version 3.1, as the {@link 672 * DifferentiableMultivariateVectorFunction} interface itself is deprecated 673 */ 674 @Deprecated 675 public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) { 676 return new DifferentiableMultivariateVectorFunction() { 677 678 /** {@inheritDoc} */ 679 public double[] value(final double[] x) { 680 return f.value(x); 681 } 682 683 public MultivariateMatrixFunction jacobian() { 684 return new MultivariateMatrixFunction() { 685 /** {@inheritDoc} */ 686 public double[][] value(final double[] x) { 687 688 final int n = x.length; 689 690 // delegate computation to underlying function 691 final DerivativeStructure[] dsX = new DerivativeStructure[n]; 692 for (int i = 0; i < n; ++i) { 693 dsX[i] = new DerivativeStructure(n, 1, i, x[i]); 694 } 695 final DerivativeStructure[] y = f.value(dsX); 696 697 // extract Jacobian 698 final double[][] jacobian = new double[y.length][n]; 699 final int[] orders = new int[n]; 700 for (int i = 0; i < y.length; ++i) { 701 for (int j = 0; j < n; ++j) { 702 orders[j] = 1; 703 jacobian[i][j] = y[i].getPartialDerivative(orders); 704 orders[j] = 0; 705 } 706 } 707 708 return jacobian; 709 710 } 711 }; 712 } 713 714 }; 715 } 716 717 /** Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}. 718 * <p> 719 * Note that the converted function is able to handle {@link DerivativeStructure} elements 720 * that all have the same number of free parameters and order, and with order at most 1. 721 * If the function is called with inconsistent numbers of free parameters or higher order, a 722 * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown. 723 * </p> 724 * @param f function to convert 725 * @return converted function 726 * @deprecated this conversion method is temporary in version 3.1, as the {@link 727 * DifferentiableMultivariateFunction} interface itself is deprecated 728 */ 729 @Deprecated 730 public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) { 731 return new MultivariateDifferentiableVectorFunction() { 732 733 /** {@inheritDoc} */ 734 public double[] value(final double[] x) { 735 return f.value(x); 736 } 737 738 /** {@inheritDoc} 739 * @exception NumberIsTooLargeException if derivation order is higher than 1 740 * @exception DimensionMismatchException if numbers of free parameters are inconsistent 741 */ 742 public DerivativeStructure[] value(final DerivativeStructure[] t) 743 throws DimensionMismatchException, NumberIsTooLargeException { 744 745 // check parameters and orders limits 746 final int parameters = t[0].getFreeParameters(); 747 final int order = t[0].getOrder(); 748 final int n = t.length; 749 if (order > 1) { 750 throw new NumberIsTooLargeException(order, 1, true); 751 } 752 753 // check all elements in the array are consistent 754 for (int i = 0; i < n; ++i) { 755 if (t[i].getFreeParameters() != parameters) { 756 throw new DimensionMismatchException(t[i].getFreeParameters(), parameters); 757 } 758 759 if (t[i].getOrder() != order) { 760 throw new DimensionMismatchException(t[i].getOrder(), order); 761 } 762 } 763 764 // delegate computation to underlying function 765 final double[] point = new double[n]; 766 for (int i = 0; i < n; ++i) { 767 point[i] = t[i].getValue(); 768 } 769 final double[] value = f.value(point); 770 final double[][] jacobian = f.jacobian().value(point); 771 772 // merge value and Jacobian into a DerivativeStructure array 773 final DerivativeStructure[] merged = new DerivativeStructure[value.length]; 774 for (int k = 0; k < merged.length; ++k) { 775 final double[] derivatives = new double[parameters + 1]; 776 derivatives[0] = value[k]; 777 final int[] orders = new int[parameters]; 778 for (int i = 0; i < parameters; ++i) { 779 orders[i] = 1; 780 for (int j = 0; j < n; ++j) { 781 derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders); 782 } 783 orders[i] = 0; 784 } 785 merged[k] = new DerivativeStructure(parameters, order, derivatives); 786 } 787 788 return merged; 789 790 } 791 792 }; 793 } 794 795}