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 * <p> 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))).</p> 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 * <p> 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))).</p> 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 * <p> 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))).</p> 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 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 * <p> 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}.</p> 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 /** 446 * Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}. 447 * 448 * @param f function to convert 449 * @return converted function 450 * @deprecated this conversion method is temporary in version 3.1, as the {@link 451 * DifferentiableUnivariateFunction} interface itself is deprecated 452 */ 453 @Deprecated 454 public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) { 455 return new DifferentiableUnivariateFunction() { 456 457 /** {@inheritDoc} */ 458 public double value(final double x) { 459 return f.value(x); 460 } 461 462 /** {@inheritDoc} */ 463 public UnivariateFunction derivative() { 464 return new UnivariateFunction() { 465 /** {@inheritDoc} */ 466 public double value(final double x) { 467 return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1); 468 } 469 }; 470 } 471 472 }; 473 } 474 475 /** 476 * Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}. 477 * <p> 478 * Note that the converted function is able to handle {@link DerivativeStructure} up to order one. 479 * If the function is called with higher order, a {@link NumberIsTooLargeException} is thrown. 480 * </p> 481 * @param f function to convert 482 * @return converted function 483 * @deprecated this conversion method is temporary in version 3.1, as the {@link 484 * DifferentiableUnivariateFunction} interface itself is deprecated 485 */ 486 @Deprecated 487 public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) { 488 return new UnivariateDifferentiableFunction() { 489 490 /** {@inheritDoc} */ 491 public double value(final double x) { 492 return f.value(x); 493 } 494 495 /** {@inheritDoc} 496 * @exception NumberIsTooLargeException if derivation order is greater than 1 497 */ 498 public DerivativeStructure value(final DerivativeStructure t) 499 throws NumberIsTooLargeException { 500 switch (t.getOrder()) { 501 case 0 : 502 return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue())); 503 case 1 : { 504 final int parameters = t.getFreeParameters(); 505 final double[] derivatives = new double[parameters + 1]; 506 derivatives[0] = f.value(t.getValue()); 507 final double fPrime = f.derivative().value(t.getValue()); 508 int[] orders = new int[parameters]; 509 for (int i = 0; i < parameters; ++i) { 510 orders[i] = 1; 511 derivatives[i + 1] = fPrime * t.getPartialDerivative(orders); 512 orders[i] = 0; 513 } 514 return new DerivativeStructure(parameters, 1, derivatives); 515 } 516 default : 517 throw new NumberIsTooLargeException(t.getOrder(), 1, true); 518 } 519 } 520 521 }; 522 } 523 524 /** 525 * Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}. 526 * 527 * @param f function to convert 528 * @return converted function 529 * @deprecated this conversion method is temporary in version 3.1, as the {@link 530 * DifferentiableMultivariateFunction} interface itself is deprecated 531 */ 532 @Deprecated 533 public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) { 534 return new DifferentiableMultivariateFunction() { 535 536 /** {@inheritDoc} */ 537 public double value(final double[] x) { 538 return f.value(x); 539 } 540 541 /** {@inheritDoc} */ 542 public MultivariateFunction partialDerivative(final int k) { 543 return new MultivariateFunction() { 544 /** {@inheritDoc} */ 545 public double value(final double[] x) { 546 547 final int n = x.length; 548 549 // delegate computation to underlying function 550 final DerivativeStructure[] dsX = new DerivativeStructure[n]; 551 for (int i = 0; i < n; ++i) { 552 if (i == k) { 553 dsX[i] = new DerivativeStructure(1, 1, 0, x[i]); 554 } else { 555 dsX[i] = new DerivativeStructure(1, 1, x[i]); 556 } 557 } 558 final DerivativeStructure y = f.value(dsX); 559 560 // extract partial derivative 561 return y.getPartialDerivative(1); 562 563 } 564 }; 565 } 566 567 /** {@inheritDoc} */ 568 public MultivariateVectorFunction gradient() { 569 return new MultivariateVectorFunction() { 570 /** {@inheritDoc} */ 571 public double[] value(final double[] x) { 572 573 final int n = x.length; 574 575 // delegate computation to underlying function 576 final DerivativeStructure[] dsX = new DerivativeStructure[n]; 577 for (int i = 0; i < n; ++i) { 578 dsX[i] = new DerivativeStructure(n, 1, i, x[i]); 579 } 580 final DerivativeStructure y = f.value(dsX); 581 582 // extract gradient 583 final double[] gradient = new double[n]; 584 final int[] orders = new int[n]; 585 for (int i = 0; i < n; ++i) { 586 orders[i] = 1; 587 gradient[i] = y.getPartialDerivative(orders); 588 orders[i] = 0; 589 } 590 591 return gradient; 592 593 } 594 }; 595 } 596 597 }; 598 } 599 600 /** 601 * Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}. 602 * <p> 603 * Note that the converted function is able to handle {@link DerivativeStructure} elements 604 * that all have the same number of free parameters and order, and with order at most 1. 605 * If the function is called with inconsistent numbers of free parameters or higher order, a 606 * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown. 607 * </p> 608 * @param f function to convert 609 * @return converted function 610 * @deprecated this conversion method is temporary in version 3.1, as the {@link 611 * DifferentiableMultivariateFunction} interface itself is deprecated 612 */ 613 @Deprecated 614 public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) { 615 return new MultivariateDifferentiableFunction() { 616 617 /** {@inheritDoc} */ 618 public double value(final double[] x) { 619 return f.value(x); 620 } 621 622 /** {@inheritDoc} 623 * @exception NumberIsTooLargeException if derivation order is higher than 1 624 * @exception DimensionMismatchException if numbers of free parameters are inconsistent 625 */ 626 public DerivativeStructure value(final DerivativeStructure[] t) 627 throws DimensionMismatchException, NumberIsTooLargeException { 628 629 // check parameters and orders limits 630 final int parameters = t[0].getFreeParameters(); 631 final int order = t[0].getOrder(); 632 final int n = t.length; 633 if (order > 1) { 634 throw new NumberIsTooLargeException(order, 1, true); 635 } 636 637 // check all elements in the array are consistent 638 for (int i = 0; i < n; ++i) { 639 if (t[i].getFreeParameters() != parameters) { 640 throw new DimensionMismatchException(t[i].getFreeParameters(), parameters); 641 } 642 643 if (t[i].getOrder() != order) { 644 throw new DimensionMismatchException(t[i].getOrder(), order); 645 } 646 } 647 648 // delegate computation to underlying function 649 final double[] point = new double[n]; 650 for (int i = 0; i < n; ++i) { 651 point[i] = t[i].getValue(); 652 } 653 final double value = f.value(point); 654 final double[] gradient = f.gradient().value(point); 655 656 // merge value and gradient into one DerivativeStructure 657 final double[] derivatives = new double[parameters + 1]; 658 derivatives[0] = value; 659 final int[] orders = new int[parameters]; 660 for (int i = 0; i < parameters; ++i) { 661 orders[i] = 1; 662 for (int j = 0; j < n; ++j) { 663 derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders); 664 } 665 orders[i] = 0; 666 } 667 668 return new DerivativeStructure(parameters, order, derivatives); 669 670 } 671 672 }; 673 } 674 675 /** 676 * Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}. 677 * 678 * @param f function to convert 679 * @return converted function 680 * @deprecated this conversion method is temporary in version 3.1, as the {@link 681 * DifferentiableMultivariateVectorFunction} interface itself is deprecated 682 */ 683 @Deprecated 684 public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) { 685 return new DifferentiableMultivariateVectorFunction() { 686 687 /** {@inheritDoc} */ 688 public double[] value(final double[] x) { 689 return f.value(x); 690 } 691 692 /** {@inheritDoc} */ 693 public MultivariateMatrixFunction jacobian() { 694 return new MultivariateMatrixFunction() { 695 /** {@inheritDoc} */ 696 public double[][] value(final double[] x) { 697 698 final int n = x.length; 699 700 // delegate computation to underlying function 701 final DerivativeStructure[] dsX = new DerivativeStructure[n]; 702 for (int i = 0; i < n; ++i) { 703 dsX[i] = new DerivativeStructure(n, 1, i, x[i]); 704 } 705 final DerivativeStructure[] y = f.value(dsX); 706 707 // extract Jacobian 708 final double[][] jacobian = new double[y.length][n]; 709 final int[] orders = new int[n]; 710 for (int i = 0; i < y.length; ++i) { 711 for (int j = 0; j < n; ++j) { 712 orders[j] = 1; 713 jacobian[i][j] = y[i].getPartialDerivative(orders); 714 orders[j] = 0; 715 } 716 } 717 718 return jacobian; 719 720 } 721 }; 722 } 723 724 }; 725 } 726 727 /** 728 * Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}. 729 * <p> 730 * Note that the converted function is able to handle {@link DerivativeStructure} elements 731 * that all have the same number of free parameters and order, and with order at most 1. 732 * If the function is called with inconsistent numbers of free parameters or higher order, a 733 * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown. 734 * </p> 735 * @param f function to convert 736 * @return converted function 737 * @deprecated this conversion method is temporary in version 3.1, as the {@link 738 * DifferentiableMultivariateFunction} interface itself is deprecated 739 */ 740 @Deprecated 741 public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) { 742 return new MultivariateDifferentiableVectorFunction() { 743 744 /** {@inheritDoc} */ 745 public double[] value(final double[] x) { 746 return f.value(x); 747 } 748 749 /** {@inheritDoc} 750 * @exception NumberIsTooLargeException if derivation order is higher than 1 751 * @exception DimensionMismatchException if numbers of free parameters are inconsistent 752 */ 753 public DerivativeStructure[] value(final DerivativeStructure[] t) 754 throws DimensionMismatchException, NumberIsTooLargeException { 755 756 // check parameters and orders limits 757 final int parameters = t[0].getFreeParameters(); 758 final int order = t[0].getOrder(); 759 final int n = t.length; 760 if (order > 1) { 761 throw new NumberIsTooLargeException(order, 1, true); 762 } 763 764 // check all elements in the array are consistent 765 for (int i = 0; i < n; ++i) { 766 if (t[i].getFreeParameters() != parameters) { 767 throw new DimensionMismatchException(t[i].getFreeParameters(), parameters); 768 } 769 770 if (t[i].getOrder() != order) { 771 throw new DimensionMismatchException(t[i].getOrder(), order); 772 } 773 } 774 775 // delegate computation to underlying function 776 final double[] point = new double[n]; 777 for (int i = 0; i < n; ++i) { 778 point[i] = t[i].getValue(); 779 } 780 final double[] value = f.value(point); 781 final double[][] jacobian = f.jacobian().value(point); 782 783 // merge value and Jacobian into a DerivativeStructure array 784 final DerivativeStructure[] merged = new DerivativeStructure[value.length]; 785 for (int k = 0; k < merged.length; ++k) { 786 final double[] derivatives = new double[parameters + 1]; 787 derivatives[0] = value[k]; 788 final int[] orders = new int[parameters]; 789 for (int i = 0; i < parameters; ++i) { 790 orders[i] = 1; 791 for (int j = 0; j < n; ++j) { 792 derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders); 793 } 794 orders[i] = 0; 795 } 796 merged[k] = new DerivativeStructure(parameters, order, derivatives); 797 } 798 799 return merged; 800 801 } 802 803 }; 804 } 805 806}