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 }