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 package org.apache.commons.math3.analysis.differentiation; 018 019 import java.io.Serializable; 020 021 import org.apache.commons.math3.Field; 022 import org.apache.commons.math3.FieldElement; 023 import org.apache.commons.math3.exception.DimensionMismatchException; 024 import org.apache.commons.math3.exception.NumberIsTooLargeException; 025 import org.apache.commons.math3.util.FastMath; 026 027 /** Class representing both the value and the differentials of a function. 028 * <p>This class is the workhorse of the differentiation package.</p> 029 * <p>This class is an implementation of the extension to Rall's 030 * numbers described in Dan Kalman's paper <a 031 * href="http://www.math.american.edu/People/kalman/pdffiles/mmgautodiff.pdf">Doubly 032 * Recursive Multivariate Automatic Differentiation</a>, Mathematics Magazine, vol. 75, 033 * no. 3, June 2002.</p>. Rall's numbers are an extension to the real numbers used 034 * throughout mathematical expressions; they hold the derivative together with the 035 * value of a function. Dan Kalman's derivative structures hold all partial derivatives 036 * up to any specified order, with respect to any number of free parameters. Rall's 037 * numbers therefore can be seen as derivative structures for order one derivative and 038 * one free parameter, and real numbers can be seen as derivative structures with zero 039 * order derivative and no free parameters.</p> 040 * <p>{@link DerivativeStructure} instances can be used directly thanks to 041 * the arithmetic operators to the mathematical functions provided as static 042 * methods by this class (+, -, *, /, %, sin, cos ...).</p> 043 * <p>Implementing complex expressions by hand using these classes is 044 * a tedious and error-prone task but has the advantage of having no limitation 045 * on the derivation order despite no requiring users to compute the derivatives by 046 * themselves. Implementing complex expression can also be done by developing computation 047 * code using standard primitive double values and to use {@link 048 * UnivariateFunctionDifferentiator differentiators} to create the {@link 049 * DerivativeStructure}-based instances. This method is simpler but may be limited in 050 * the accuracy and derivation orders and may be computationally intensive (this is 051 * typically the case for {@link FiniteDifferencesDifferentiator finite differences 052 * differentiator}.</p> 053 * <p>Instances of this class are guaranteed to be immutable.</p> 054 * @see DSCompiler 055 * @version $Id: DerivativeStructure.java 1416643 2012-12-03 19:37:14Z tn $ 056 * @since 3.1 057 */ 058 public class DerivativeStructure implements FieldElement<DerivativeStructure>, Serializable { 059 060 /** Serializable UID. */ 061 private static final long serialVersionUID = 20120730L; 062 063 /** Compiler for the current dimensions. */ 064 private transient DSCompiler compiler; 065 066 /** Combined array holding all values. */ 067 private final double[] data; 068 069 /** Build an instance with all values and derivatives set to 0. 070 * @param compiler compiler to use for computation 071 */ 072 private DerivativeStructure(final DSCompiler compiler) { 073 this.compiler = compiler; 074 this.data = new double[compiler.getSize()]; 075 } 076 077 /** Build an instance with all values and derivatives set to 0. 078 * @param parameters number of free parameters 079 * @param order derivation order 080 */ 081 public DerivativeStructure(final int parameters, final int order) { 082 this(DSCompiler.getCompiler(parameters, order)); 083 } 084 085 /** Build an instance representing a constant value. 086 * @param parameters number of free parameters 087 * @param order derivation order 088 * @param value value of the constant 089 * @see #DerivativeStructure(int, int, int, double) 090 */ 091 public DerivativeStructure(final int parameters, final int order, final double value) { 092 this(parameters, order); 093 this.data[0] = value; 094 } 095 096 /** Build an instance representing a variable. 097 * <p>Instances built using this constructor are considered 098 * to be the free variables with respect to which differentials 099 * are computed. As such, their differential with respect to 100 * themselves is +1.</p> 101 * @param parameters number of free parameters 102 * @param order derivation order 103 * @param index index of the variable (from 0 to {@code parameters - 1}) 104 * @param value value of the variable 105 * @exception NumberIsTooLargeException if {@code index >= parameters}. 106 * @see #DerivativeStructure(int, int, double) 107 */ 108 public DerivativeStructure(final int parameters, final int order, 109 final int index, final double value) 110 throws NumberIsTooLargeException { 111 this(parameters, order, value); 112 113 if (index >= parameters) { 114 throw new NumberIsTooLargeException(index, parameters, false); 115 } 116 117 if (order > 0) { 118 // the derivative of the variable with respect to itself is 1. 119 data[DSCompiler.getCompiler(index, order).getSize()] = 1.0; 120 } 121 122 } 123 124 /** Linear combination constructor. 125 * The derivative structure built will be a1 * ds1 + a2 * ds2 126 * @param a1 first scale factor 127 * @param ds1 first base (unscaled) derivative structure 128 * @param a2 second scale factor 129 * @param ds2 second base (unscaled) derivative structure 130 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 131 */ 132 public DerivativeStructure(final double a1, final DerivativeStructure ds1, 133 final double a2, final DerivativeStructure ds2) 134 throws DimensionMismatchException { 135 this(ds1.compiler); 136 compiler.checkCompatibility(ds2.compiler); 137 compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, data, 0); 138 } 139 140 /** Linear combination constructor. 141 * The derivative structure built will be a1 * ds1 + a2 * ds2 + a3 * ds3 142 * @param a1 first scale factor 143 * @param ds1 first base (unscaled) derivative structure 144 * @param a2 second scale factor 145 * @param ds2 second base (unscaled) derivative structure 146 * @param a3 third scale factor 147 * @param ds3 third base (unscaled) derivative structure 148 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 149 */ 150 public DerivativeStructure(final double a1, final DerivativeStructure ds1, 151 final double a2, final DerivativeStructure ds2, 152 final double a3, final DerivativeStructure ds3) 153 throws DimensionMismatchException { 154 this(ds1.compiler); 155 compiler.checkCompatibility(ds2.compiler); 156 compiler.checkCompatibility(ds3.compiler); 157 compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, a3, ds3.data, 0, data, 0); 158 } 159 160 /** Linear combination constructor. 161 * The derivative structure built will be a1 * ds1 + a2 * ds2 + a3 * ds3 + a4 * ds4 162 * @param a1 first scale factor 163 * @param ds1 first base (unscaled) derivative structure 164 * @param a2 second scale factor 165 * @param ds2 second base (unscaled) derivative structure 166 * @param a3 third scale factor 167 * @param ds3 third base (unscaled) derivative structure 168 * @param a4 fourth scale factor 169 * @param ds4 fourth base (unscaled) derivative structure 170 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 171 */ 172 public DerivativeStructure(final double a1, final DerivativeStructure ds1, 173 final double a2, final DerivativeStructure ds2, 174 final double a3, final DerivativeStructure ds3, 175 final double a4, final DerivativeStructure ds4) 176 throws DimensionMismatchException { 177 this(ds1.compiler); 178 compiler.checkCompatibility(ds2.compiler); 179 compiler.checkCompatibility(ds3.compiler); 180 compiler.checkCompatibility(ds4.compiler); 181 compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, 182 a3, ds3.data, 0, a4, ds4.data, 0, 183 data, 0); 184 } 185 186 /** Build an instance from all its derivatives. 187 * @param parameters number of free parameters 188 * @param order derivation order 189 * @param derivatives derivatives sorted according to 190 * {@link DSCompiler#getPartialDerivativeIndex(int...)} 191 * @exception DimensionMismatchException if derivatives array does not match the 192 * {@link DSCompiler#getSize() size} expected by the compiler 193 * @see #getAllDerivatives() 194 */ 195 public DerivativeStructure(final int parameters, final int order, final double ... derivatives) 196 throws DimensionMismatchException { 197 this(parameters, order); 198 if (derivatives.length != data.length) { 199 throw new DimensionMismatchException(derivatives.length, data.length); 200 } 201 System.arraycopy(derivatives, 0, data, 0, data.length); 202 } 203 204 /** Copy constructor. 205 * @param ds instance to copy 206 */ 207 private DerivativeStructure(final DerivativeStructure ds) { 208 this.compiler = ds.compiler; 209 this.data = ds.data.clone(); 210 } 211 212 /** Get the number of free parameters. 213 * @return number of free parameters 214 */ 215 public int getFreeParameters() { 216 return compiler.getFreeParameters(); 217 } 218 219 /** Get the derivation order. 220 * @return derivation order 221 */ 222 public int getOrder() { 223 return compiler.getOrder(); 224 } 225 226 /** Get the value part of the derivative structure. 227 * @return value part of the derivative structure 228 * @see #getPartialDerivative(int...) 229 */ 230 public double getValue() { 231 return data[0]; 232 } 233 234 /** Get a partial derivative. 235 * @param orders derivation orders with respect to each variable (if all orders are 0, 236 * the value is returned) 237 * @return partial derivative 238 * @see #getValue() 239 * @exception DimensionMismatchException if the numbers of variables does not 240 * match the instance 241 * @exception NumberIsTooLargeException if sum of derivation orders is larger 242 * than the instance limits 243 */ 244 public double getPartialDerivative(final int ... orders) 245 throws DimensionMismatchException, NumberIsTooLargeException { 246 return data[compiler.getPartialDerivativeIndex(orders)]; 247 } 248 249 /** Get all partial derivatives. 250 * @return a fresh copy of partial derivatives, in an array sorted according to 251 * {@link DSCompiler#getPartialDerivativeIndex(int...)} 252 */ 253 public double[] getAllDerivatives() { 254 return data.clone(); 255 } 256 257 /** '+' operator. 258 * @param a right hand side parameter of the operator 259 * @return this+a 260 */ 261 public DerivativeStructure add(final double a) { 262 final DerivativeStructure ds = new DerivativeStructure(this); 263 ds.data[0] += a; 264 return ds; 265 } 266 267 /** '+' operator. 268 * @param a right hand side parameter of the operator 269 * @return this+a 270 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 271 */ 272 public DerivativeStructure add(final DerivativeStructure a) 273 throws DimensionMismatchException { 274 compiler.checkCompatibility(a.compiler); 275 final DerivativeStructure ds = new DerivativeStructure(this); 276 compiler.add(data, 0, a.data, 0, ds.data, 0); 277 return ds; 278 } 279 280 /** '-' operator. 281 * @param a right hand side parameter of the operator 282 * @return this-a 283 */ 284 public DerivativeStructure subtract(final double a) { 285 return add(-a); 286 } 287 288 /** '-' operator. 289 * @param a right hand side parameter of the operator 290 * @return this-a 291 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 292 */ 293 public DerivativeStructure subtract(final DerivativeStructure a) 294 throws DimensionMismatchException { 295 compiler.checkCompatibility(a.compiler); 296 final DerivativeStructure ds = new DerivativeStructure(this); 297 compiler.subtract(data, 0, a.data, 0, ds.data, 0); 298 return ds; 299 } 300 301 /** {@inheritDoc} */ 302 public DerivativeStructure multiply(final int n) { 303 return multiply((double) n); 304 } 305 306 /** '×' operator. 307 * @param a right hand side parameter of the operator 308 * @return this×a 309 */ 310 public DerivativeStructure multiply(final double a) { 311 final DerivativeStructure ds = new DerivativeStructure(this); 312 for (int i = 0; i < ds.data.length; ++i) { 313 ds.data[i] *= a; 314 } 315 return ds; 316 } 317 318 /** '×' operator. 319 * @param a right hand side parameter of the operator 320 * @return this×a 321 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 322 */ 323 public DerivativeStructure multiply(final DerivativeStructure a) 324 throws DimensionMismatchException { 325 compiler.checkCompatibility(a.compiler); 326 final DerivativeStructure result = new DerivativeStructure(compiler); 327 compiler.multiply(data, 0, a.data, 0, result.data, 0); 328 return result; 329 } 330 331 /** '÷s;' operator. 332 * @param a right hand side parameter of the operator 333 * @return this÷s;a 334 */ 335 public DerivativeStructure divide(final double a) { 336 final DerivativeStructure ds = new DerivativeStructure(this); 337 for (int i = 0; i < ds.data.length; ++i) { 338 ds.data[i] /= a; 339 } 340 return ds; 341 } 342 343 /** '÷s;' operator. 344 * @param a right hand side parameter of the operator 345 * @return this÷s;a 346 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 347 */ 348 public DerivativeStructure divide(final DerivativeStructure a) 349 throws DimensionMismatchException { 350 compiler.checkCompatibility(a.compiler); 351 final DerivativeStructure result = new DerivativeStructure(compiler); 352 compiler.divide(data, 0, a.data, 0, result.data, 0); 353 return result; 354 } 355 356 /** '%' operator. 357 * @param a right hand side parameter of the operator 358 * @return this%a 359 */ 360 public DerivativeStructure remainder(final double a) { 361 final DerivativeStructure ds = new DerivativeStructure(this); 362 ds.data[0] = ds.data[0] % a; 363 return ds; 364 } 365 366 /** '%' operator. 367 * @param a right hand side parameter of the operator 368 * @return this%a 369 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 370 */ 371 public DerivativeStructure remainder(final DerivativeStructure a) 372 throws DimensionMismatchException { 373 compiler.checkCompatibility(a.compiler); 374 final DerivativeStructure result = new DerivativeStructure(compiler); 375 compiler.remainder(data, 0, a.data, 0, result.data, 0); 376 return result; 377 } 378 379 /** unary '-' operator. 380 * @return -this 381 */ 382 public DerivativeStructure negate() { 383 final DerivativeStructure ds = new DerivativeStructure(compiler); 384 for (int i = 0; i < ds.data.length; ++i) { 385 ds.data[i] = -data[i]; 386 } 387 return ds; 388 } 389 390 /** absolute value. 391 * @return abs(this) 392 */ 393 public DerivativeStructure abs() { 394 if (Double.doubleToLongBits(data[0]) < 0) { 395 // we use the bits representation to also handle -0.0 396 return negate(); 397 } else { 398 return this; 399 } 400 } 401 402 /** Get the smallest whole number larger than instance. 403 * @return ceil(this) 404 */ 405 public DerivativeStructure ceil() { 406 return new DerivativeStructure(compiler.getFreeParameters(), 407 compiler.getOrder(), 408 FastMath.ceil(data[0])); 409 } 410 411 /** Get the largest whole number smaller than instance. 412 * @return floor(this) 413 */ 414 public DerivativeStructure floor() { 415 return new DerivativeStructure(compiler.getFreeParameters(), 416 compiler.getOrder(), 417 FastMath.floor(data[0])); 418 } 419 420 /** Get the whole number that is the nearest to the instance, or the even one if x is exactly half way between two integers. 421 * @return a double number r such that r is an integer r - 0.5 <= this <= r + 0.5 422 */ 423 public DerivativeStructure rint() { 424 return new DerivativeStructure(compiler.getFreeParameters(), 425 compiler.getOrder(), 426 FastMath.rint(data[0])); 427 } 428 429 /** Get the closest long to instance value. 430 * @return closest long to {@link #getValue()} 431 */ 432 public long round() { 433 return FastMath.round(data[0]); 434 } 435 436 /** Compute the signum of the instance. 437 * The signum is -1 for negative numbers, +1 for positive numbers and 0 otherwise 438 * @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a 439 */ 440 public DerivativeStructure signum() { 441 return new DerivativeStructure(compiler.getFreeParameters(), 442 compiler.getOrder(), 443 FastMath.signum(data[0])); 444 } 445 446 /** 447 * Returns the instance with the sign of the argument. 448 * A NaN {@code sign} argument is treated as positive. 449 * 450 * @param sign the sign for the returned value 451 * @return the instance with the same sign as the {@code sign} argument 452 */ 453 public DerivativeStructure copySign(final double sign){ 454 long m = Double.doubleToLongBits(data[0]); 455 long s = Double.doubleToLongBits(sign); 456 if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK 457 return this; 458 } 459 return negate(); // flip sign 460 } 461 462 /** 463 * Return the exponent of the instance value, removing the bias. 464 * <p> 465 * For double numbers of the form 2<sup>x</sup>, the unbiased 466 * exponent is exactly x. 467 * </p> 468 * @return exponent for instance in IEEE754 representation, without bias 469 */ 470 public int getExponent() { 471 return FastMath.getExponent(data[0]); 472 } 473 474 /** 475 * Multiply the instance by a power of 2. 476 * @param n power of 2 477 * @return this × 2<sup>n</sup> 478 */ 479 public DerivativeStructure scalb(final int n) { 480 final DerivativeStructure ds = new DerivativeStructure(compiler); 481 for (int i = 0; i < ds.data.length; ++i) { 482 ds.data[i] = FastMath.scalb(data[i], n); 483 } 484 return ds; 485 } 486 487 /** 488 * Returns the hypotenuse of a triangle with sides {@code x} and {@code y} 489 * - sqrt(<i>x</i><sup>2</sup> +<i>y</i><sup>2</sup>)<br/> 490 * avoiding intermediate overflow or underflow. 491 * 492 * <ul> 493 * <li> If either argument is infinite, then the result is positive infinity.</li> 494 * <li> else, if either argument is NaN then the result is NaN.</li> 495 * </ul> 496 * 497 * @param x a value 498 * @param y a value 499 * @return sqrt(<i>x</i><sup>2</sup> +<i>y</i><sup>2</sup>) 500 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 501 */ 502 public static DerivativeStructure hypot(final DerivativeStructure x, final DerivativeStructure y) 503 throws DimensionMismatchException { 504 505 x.compiler.checkCompatibility(y.compiler); 506 507 if (Double.isInfinite(x.data[0]) || Double.isInfinite(y.data[0])) { 508 return new DerivativeStructure(x.compiler.getFreeParameters(), 509 x.compiler.getFreeParameters(), 510 Double.POSITIVE_INFINITY); 511 } else if (Double.isNaN(x.data[0]) || Double.isNaN(y.data[0])) { 512 return new DerivativeStructure(x.compiler.getFreeParameters(), 513 x.compiler.getFreeParameters(), 514 Double.NaN); 515 } else { 516 517 final int expX = x.getExponent(); 518 final int expY = y.getExponent(); 519 if (expX > expY + 27) { 520 // y is neglectible with respect to x 521 return x.abs(); 522 } else if (expY > expX + 27) { 523 // x is neglectible with respect to y 524 return y.abs(); 525 } else { 526 527 // find an intermediate scale to avoid both overflow and underflow 528 final int middleExp = (expX + expY) / 2; 529 530 // scale parameters without losing precision 531 final DerivativeStructure scaledX = x.scalb(-middleExp); 532 final DerivativeStructure scaledY = y.scalb(-middleExp); 533 534 // compute scaled hypotenuse 535 final DerivativeStructure scaledH = 536 scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt(); 537 538 // remove scaling 539 return scaledH.scalb(middleExp); 540 541 } 542 543 } 544 } 545 546 /** Compute composition of the instance by a univariate function. 547 * @param f array of value and derivatives of the function at 548 * the current point (i.e. [f({@link #getValue()}), 549 * f'({@link #getValue()}), f''({@link #getValue()})...]). 550 * @return f(this) 551 * @exception DimensionMismatchException if the number of derivatives 552 * in the array is not equal to {@link #getOrder() order} + 1 553 */ 554 public DerivativeStructure compose(final double ... f) { 555 if (f.length != getOrder() + 1) { 556 throw new DimensionMismatchException(f.length, getOrder() + 1); 557 } 558 final DerivativeStructure result = new DerivativeStructure(compiler); 559 compiler.compose(data, 0, f, result.data, 0); 560 return result; 561 } 562 563 /** {@inheritDoc} */ 564 public DerivativeStructure reciprocal() { 565 final DerivativeStructure result = new DerivativeStructure(compiler); 566 compiler.pow(data, 0, -1, result.data, 0); 567 return result; 568 } 569 570 /** Square root. 571 * @return square root of the instance 572 */ 573 public DerivativeStructure sqrt() { 574 return rootN(2); 575 } 576 577 /** Cubic root. 578 * @return cubic root of the instance 579 */ 580 public DerivativeStructure cbrt() { 581 return rootN(3); 582 } 583 584 /** N<sup>th</sup> root. 585 * @param n order of the root 586 * @return n<sup>th</sup> root of the instance 587 */ 588 public DerivativeStructure rootN(final int n) { 589 final DerivativeStructure result = new DerivativeStructure(compiler); 590 compiler.rootN(data, 0, n, result.data, 0); 591 return result; 592 } 593 594 /** {@inheritDoc} */ 595 public Field<DerivativeStructure> getField() { 596 return new Field<DerivativeStructure>() { 597 598 /** {@inheritDoc} */ 599 public DerivativeStructure getZero() { 600 return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), 0.0); 601 } 602 603 /** {@inheritDoc} */ 604 public DerivativeStructure getOne() { 605 return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), 1.0); 606 } 607 608 /** {@inheritDoc} */ 609 public Class<? extends FieldElement<DerivativeStructure>> getRuntimeClass() { 610 return DerivativeStructure.class; 611 } 612 613 }; 614 } 615 616 /** Power operation. 617 * @param p power to apply 618 * @return this<sup>p</sup> 619 */ 620 public DerivativeStructure pow(final double p) { 621 final DerivativeStructure result = new DerivativeStructure(compiler); 622 compiler.pow(data, 0, p, result.data, 0); 623 return result; 624 } 625 626 /** Integer power operation. 627 * @param n power to apply 628 * @return this<sup>n</sup> 629 */ 630 public DerivativeStructure pow(final int n) { 631 final DerivativeStructure result = new DerivativeStructure(compiler); 632 compiler.pow(data, 0, n, result.data, 0); 633 return result; 634 } 635 636 /** Power operation. 637 * @param e exponent 638 * @return this<sup>e</sup> 639 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 640 */ 641 public DerivativeStructure pow(final DerivativeStructure e) 642 throws DimensionMismatchException { 643 compiler.checkCompatibility(e.compiler); 644 final DerivativeStructure result = new DerivativeStructure(compiler); 645 compiler.pow(data, 0, e.data, 0, result.data, 0); 646 return result; 647 } 648 649 /** Exponential. 650 * @return exponential of the instance 651 */ 652 public DerivativeStructure exp() { 653 final DerivativeStructure result = new DerivativeStructure(compiler); 654 compiler.exp(data, 0, result.data, 0); 655 return result; 656 } 657 658 /** Exponential minus 1. 659 * @return exponential minus one of the instance 660 */ 661 public DerivativeStructure expm1() { 662 final DerivativeStructure result = new DerivativeStructure(compiler); 663 compiler.expm1(data, 0, result.data, 0); 664 return result; 665 } 666 667 /** Natural logarithm. 668 * @return logarithm of the instance 669 */ 670 public DerivativeStructure log() { 671 final DerivativeStructure result = new DerivativeStructure(compiler); 672 compiler.log(data, 0, result.data, 0); 673 return result; 674 } 675 676 /** Shifted natural logarithm. 677 * @return logarithm of one plus the instance 678 */ 679 public DerivativeStructure log1p() { 680 final DerivativeStructure result = new DerivativeStructure(compiler); 681 compiler.log1p(data, 0, result.data, 0); 682 return result; 683 } 684 685 /** Base 10 logarithm. 686 * @return base 10 logarithm of the instance 687 */ 688 public DerivativeStructure log10() { 689 final DerivativeStructure result = new DerivativeStructure(compiler); 690 compiler.log10(data, 0, result.data, 0); 691 return result; 692 } 693 694 /** Cosine operation. 695 * @return cos(this) 696 */ 697 public DerivativeStructure cos() { 698 final DerivativeStructure result = new DerivativeStructure(compiler); 699 compiler.cos(data, 0, result.data, 0); 700 return result; 701 } 702 703 /** Sine operation. 704 * @return sin(this) 705 */ 706 public DerivativeStructure sin() { 707 final DerivativeStructure result = new DerivativeStructure(compiler); 708 compiler.sin(data, 0, result.data, 0); 709 return result; 710 } 711 712 /** Tangent operation. 713 * @return tan(this) 714 */ 715 public DerivativeStructure tan() { 716 final DerivativeStructure result = new DerivativeStructure(compiler); 717 compiler.tan(data, 0, result.data, 0); 718 return result; 719 } 720 721 /** Arc cosine operation. 722 * @return acos(this) 723 */ 724 public DerivativeStructure acos() { 725 final DerivativeStructure result = new DerivativeStructure(compiler); 726 compiler.acos(data, 0, result.data, 0); 727 return result; 728 } 729 730 /** Arc sine operation. 731 * @return asin(this) 732 */ 733 public DerivativeStructure asin() { 734 final DerivativeStructure result = new DerivativeStructure(compiler); 735 compiler.asin(data, 0, result.data, 0); 736 return result; 737 } 738 739 /** Arc tangent operation. 740 * @return atan(this) 741 */ 742 public DerivativeStructure atan() { 743 final DerivativeStructure result = new DerivativeStructure(compiler); 744 compiler.atan(data, 0, result.data, 0); 745 return result; 746 } 747 748 /** Two arguments arc tangent operation. 749 * @param y first argument of the arc tangent 750 * @param x second argument of the arc tangent 751 * @return atan2(y, x) 752 * @exception DimensionMismatchException if number of free parameters or orders are inconsistent 753 */ 754 public static DerivativeStructure atan2(final DerivativeStructure y, final DerivativeStructure x) 755 throws DimensionMismatchException { 756 y.compiler.checkCompatibility(x.compiler); 757 final DerivativeStructure result = new DerivativeStructure(y.compiler); 758 y.compiler.atan2(y.data, 0, x.data, 0, result.data, 0); 759 return result; 760 } 761 762 /** Hyperbolic cosine operation. 763 * @return cosh(this) 764 */ 765 public DerivativeStructure cosh() { 766 final DerivativeStructure result = new DerivativeStructure(compiler); 767 compiler.cosh(data, 0, result.data, 0); 768 return result; 769 } 770 771 /** Hyperbolic sine operation. 772 * @return sinh(this) 773 */ 774 public DerivativeStructure sinh() { 775 final DerivativeStructure result = new DerivativeStructure(compiler); 776 compiler.sinh(data, 0, result.data, 0); 777 return result; 778 } 779 780 /** Hyperbolic tangent operation. 781 * @return tanh(this) 782 */ 783 public DerivativeStructure tanh() { 784 final DerivativeStructure result = new DerivativeStructure(compiler); 785 compiler.tanh(data, 0, result.data, 0); 786 return result; 787 } 788 789 /** Inverse hyperbolic cosine operation. 790 * @return acosh(this) 791 */ 792 public DerivativeStructure acosh() { 793 final DerivativeStructure result = new DerivativeStructure(compiler); 794 compiler.acosh(data, 0, result.data, 0); 795 return result; 796 } 797 798 /** Inverse hyperbolic sine operation. 799 * @return asin(this) 800 */ 801 public DerivativeStructure asinh() { 802 final DerivativeStructure result = new DerivativeStructure(compiler); 803 compiler.asinh(data, 0, result.data, 0); 804 return result; 805 } 806 807 /** Inverse hyperbolic tangent operation. 808 * @return atanh(this) 809 */ 810 public DerivativeStructure atanh() { 811 final DerivativeStructure result = new DerivativeStructure(compiler); 812 compiler.atanh(data, 0, result.data, 0); 813 return result; 814 } 815 816 /** Convert radians to degrees, with error of less than 0.5 ULP 817 * @return instance converted into degrees 818 */ 819 public DerivativeStructure toDegrees() { 820 final DerivativeStructure ds = new DerivativeStructure(compiler); 821 for (int i = 0; i < ds.data.length; ++i) { 822 ds.data[i] = FastMath.toDegrees(data[i]); 823 } 824 return ds; 825 } 826 827 /** Convert degrees to radians, with error of less than 0.5 ULP 828 * @return instance converted into radians 829 */ 830 public DerivativeStructure toRadians() { 831 final DerivativeStructure ds = new DerivativeStructure(compiler); 832 for (int i = 0; i < ds.data.length; ++i) { 833 ds.data[i] = FastMath.toRadians(data[i]); 834 } 835 return ds; 836 } 837 838 /** Evaluate Taylor expansion a derivative structure. 839 * @param delta parameters offsets (Δx, Δy, ...) 840 * @return value of the Taylor expansion at x + Δx, y + Δy, ... 841 */ 842 public double taylor(final double ... delta) { 843 return compiler.taylor(data, 0, delta); 844 } 845 846 /** 847 * Replace the instance with a data transfer object for serialization. 848 * @return data transfer object that will be serialized 849 */ 850 private Object writeReplace() { 851 return new DataTransferObject(compiler.getFreeParameters(), compiler.getOrder(), data); 852 } 853 854 /** Internal class used only for serialization. */ 855 private static class DataTransferObject implements Serializable { 856 857 /** Serializable UID. */ 858 private static final long serialVersionUID = 20120730L; 859 860 /** Number of variables. 861 * @serial 862 */ 863 private final int variables; 864 865 /** Derivation order. 866 * @serial 867 */ 868 private final int order; 869 870 /** Partial derivatives. 871 * @serial 872 */ 873 private final double[] data; 874 875 /** Simple constructor. 876 * @param variables number of variables 877 * @param order derivation order 878 * @param data partial derivatives 879 */ 880 public DataTransferObject(final int variables, final int order, final double[] data) { 881 this.variables = variables; 882 this.order = order; 883 this.data = data; 884 } 885 886 /** Replace the deserialized data transfer object with a {@link DerivativeStructure}. 887 * @return replacement {@link DerivativeStructure} 888 */ 889 private Object readResolve() { 890 return new DerivativeStructure(variables, order, data); 891 } 892 893 } 894 895 }