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 }