View Javadoc
1   /*
2    * Licensed to the Hipparchus project under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.hipparchus.analysis.differentiation;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.exception.LocalizedCoreFormats;
22  import org.hipparchus.exception.MathIllegalArgumentException;
23  import org.hipparchus.util.FastMath;
24  import org.hipparchus.util.MathArrays;
25  import org.hipparchus.util.MathUtils;
26  
27  /** Class representing both the value and the differentials of a function.
28   * <p>This class is a stripped-down version of {@link FieldDerivativeStructure}
29   * with only one {@link FieldDerivativeStructure#getFreeParameters() free parameter}
30   * and {@link FieldDerivativeStructure#getOrder() derivation order} also limited to one.
31   * It should have less overhead than {@link FieldDerivativeStructure} in its domain.</p>
32   * <p>This class is an implementation of Rall's numbers. Rall's numbers are an
33   * extension to the real numbers used throughout mathematical expressions; they hold
34   * the derivative together with the value of a function.</p>
35   * <p>{@link FieldUnivariateDerivative1} instances can be used directly thanks to
36   * the arithmetic operators to the mathematical functions provided as
37   * methods by this class (+, -, *, /, %, sin, cos ...).</p>
38   * <p>Implementing complex expressions by hand using these classes is
39   * a tedious and error-prone task but has the advantage of having no limitation
40   * on the derivation order despite not requiring users to compute the derivatives by
41   * themselves.</p>
42   * <p>Instances of this class are guaranteed to be immutable.</p>
43   * @param <T> the type of the function parameters and value
44   * @see DerivativeStructure
45   * @see UnivariateDerivative1
46   * @see UnivariateDerivative2
47   * @see Gradient
48   * @see FieldDerivativeStructure
49   * @see FieldUnivariateDerivative2
50   * @see FieldGradient
51   * @since 1.7
52   */
53  public class FieldUnivariateDerivative1<T extends CalculusFieldElement<T>>
54      extends FieldUnivariateDerivative<T, FieldUnivariateDerivative1<T>>
55          implements FieldDerivative1<T, FieldUnivariateDerivative1<T>> {
56  
57      /** Value of the function. */
58      private final T f0;
59  
60      /** First derivative of the function. */
61      private final T f1;
62  
63      /** Build an instance with values and derivative.
64       * @param f0 value of the function
65       * @param f1 first derivative of the function
66       */
67      public FieldUnivariateDerivative1(final T f0, final T f1) {
68          this.f0 = f0;
69          this.f1 = f1;
70      }
71  
72      /** Build an instance from a {@link DerivativeStructure}.
73       * @param ds derivative structure
74       * @exception MathIllegalArgumentException if either {@code ds} parameters
75       * is not 1 or {@code ds} order is not 1
76       */
77      public FieldUnivariateDerivative1(final FieldDerivativeStructure<T> ds) throws MathIllegalArgumentException {
78          MathUtils.checkDimension(ds.getFreeParameters(), 1);
79          MathUtils.checkDimension(ds.getOrder(), 1);
80          this.f0 = ds.getValue();
81          this.f1 = ds.getPartialDerivative(1);
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public FieldUnivariateDerivative1<T> newInstance(final double value) {
87          final T zero = f0.getField().getZero();
88          return new FieldUnivariateDerivative1<>(zero.newInstance(value), zero);
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public FieldUnivariateDerivative1<T> newInstance(final T value) {
94          final T zero = f0.getField().getZero();
95          return new FieldUnivariateDerivative1<>(value, zero);
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public FieldUnivariateDerivative1<T> withValue(final T value) {
101         return new FieldUnivariateDerivative1<>(value, f1);
102     }
103 
104     /** Get the value part of the univariate derivative.
105      * @return value part of the univariate derivative
106      */
107     @Override
108     public T getValue() {
109         return f0;
110     }
111 
112     /** Get a derivative from the univariate derivative.
113      * @param n derivation order (must be between 0 and {@link #getOrder()}, both inclusive)
114      * @return n<sup>th</sup> derivative, or {@code NaN} if n is
115      * either negative or strictly larger than {@link #getOrder()}
116      */
117     @Override
118     public T getDerivative(final int n) {
119         switch (n) {
120             case 0 :
121                 return f0;
122             case 1 :
123                 return f1;
124             default :
125                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED, n);
126         }
127     }
128 
129     /** Get the first derivative.
130      * @return first derivative
131      * @see #getValue()
132      */
133     public T getFirstDerivative() {
134         return f1;
135     }
136 
137     /** Get the {@link Field} the value and parameters of the function belongs to.
138      * @return {@link Field} the value and parameters of the function belongs to
139      */
140     public Field<T> getValueField() {
141         return f0.getField();
142     }
143 
144     /** Convert the instance to a {@link FieldDerivativeStructure}.
145      * @return derivative structure with same value and derivative as the instance
146      */
147     @Override
148     public FieldDerivativeStructure<T> toDerivativeStructure() {
149         return getField().getConversionFactory().build(f0, f1);
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     public FieldUnivariateDerivative1<T> add(final double a) {
155         return new FieldUnivariateDerivative1<>(f0.add(a), f1);
156     }
157 
158     /** {@inheritDoc} */
159     @Override
160     public FieldUnivariateDerivative1<T> add(final FieldUnivariateDerivative1<T> a) {
161         return new FieldUnivariateDerivative1<>(f0.add(a.f0), f1.add(a.f1));
162     }
163 
164     /** {@inheritDoc} */
165     @Override
166     public FieldUnivariateDerivative1<T> subtract(final double a) {
167         return new FieldUnivariateDerivative1<>(f0.subtract(a), f1);
168     }
169 
170     /** {@inheritDoc} */
171     @Override
172     public FieldUnivariateDerivative1<T> subtract(final FieldUnivariateDerivative1<T> a) {
173         return new FieldUnivariateDerivative1<>(f0.subtract(a.f0), f1.subtract(a.f1));
174     }
175 
176     /** '&times;' operator.
177      * @param a right hand side parameter of the operator
178      * @return this&times;a
179      */
180     public FieldUnivariateDerivative1<T> multiply(final T a) {
181         return new FieldUnivariateDerivative1<>(f0.multiply(a), f1.multiply(a));
182     }
183 
184     /** {@inheritDoc} */
185     @Override
186     public FieldUnivariateDerivative1<T> multiply(final int n) {
187         return new FieldUnivariateDerivative1<>(f0.multiply(n), f1.multiply(n));
188     }
189 
190     /** {@inheritDoc} */
191     @Override
192     public FieldUnivariateDerivative1<T> multiply(final double a) {
193         return new FieldUnivariateDerivative1<>(f0.multiply(a), f1.multiply(a));
194     }
195 
196     /** {@inheritDoc} */
197     @Override
198     public FieldUnivariateDerivative1<T> multiply(final FieldUnivariateDerivative1<T> a) {
199         return new FieldUnivariateDerivative1<>(f0.multiply(a.f0),
200                                                 a.f0.linearCombination(f1, a.f0, f0, a.f1));
201     }
202 
203     /** '&divide;' operator.
204      * @param a right hand side parameter of the operator
205      * @return this&divide;a
206      */
207     public FieldUnivariateDerivative1<T> divide(final T a) {
208         final T inv1 = a.reciprocal();
209         return new FieldUnivariateDerivative1<>(f0.multiply(inv1), f1.multiply(inv1));
210     }
211 
212     /** {@inheritDoc} */
213     @Override
214     public FieldUnivariateDerivative1<T> divide(final double a) {
215         final double inv1 = 1.0 / a;
216         return new FieldUnivariateDerivative1<>(f0.multiply(inv1), f1.multiply(inv1));
217     }
218 
219     /** {@inheritDoc} */
220     @Override
221     public FieldUnivariateDerivative1<T> divide(final FieldUnivariateDerivative1<T> a) {
222         final T inv1 = a.f0.reciprocal();
223         final T inv2 = inv1.multiply(inv1);
224         return new FieldUnivariateDerivative1<>(f0.multiply(inv1),
225                                                 a.f0.linearCombination(f1, a.f0, f0.negate(), a.f1).multiply(inv2));
226     }
227 
228     /** IEEE remainder operator.
229      * @param a right hand side parameter of the operator
230      * @return this - n &times; a where n is the closest integer to this/a
231      * (the even integer is chosen for n if this/a is halfway between two integers)
232      */
233     public FieldUnivariateDerivative1<T> remainder(final T a) {
234         return new FieldUnivariateDerivative1<>(FastMath.IEEEremainder(f0, a), f1);
235     }
236 
237     /** {@inheritDoc} */
238     @Override
239     public FieldUnivariateDerivative1<T> remainder(final double a) {
240         return new FieldUnivariateDerivative1<>(FastMath.IEEEremainder(f0, a), f1);
241     }
242 
243     /** {@inheritDoc} */
244     @Override
245     public FieldUnivariateDerivative1<T> remainder(final FieldUnivariateDerivative1<T> a) {
246 
247         // compute k such that lhs % rhs = lhs - k rhs
248         final T rem = FastMath.IEEEremainder(f0, a.f0);
249         final T k   = FastMath.rint(f0.subtract(rem).divide(a.f0));
250 
251         return new FieldUnivariateDerivative1<>(rem, f1.subtract(k.multiply(a.f1)));
252 
253     }
254 
255     /** {@inheritDoc} */
256     @Override
257     public FieldUnivariateDerivative1<T> negate() {
258         return new FieldUnivariateDerivative1<>(f0.negate(), f1.negate());
259     }
260 
261     /** {@inheritDoc} */
262     @Override
263     public FieldUnivariateDerivative1<T> abs() {
264         if (Double.doubleToLongBits(f0.getReal()) < 0) {
265             // we use the bits representation to also handle -0.0
266             return negate();
267         } else {
268             return this;
269         }
270     }
271 
272     /**
273      * Returns the instance with the sign of the argument.
274      * A NaN {@code sign} argument is treated as positive.
275      *
276      * @param sign the sign for the returned value
277      * @return the instance with the same sign as the {@code sign} argument
278      */
279     public FieldUnivariateDerivative1<T> copySign(final T sign) {
280         long m = Double.doubleToLongBits(f0.getReal());
281         long s = Double.doubleToLongBits(sign.getReal());
282         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
283             return this;
284         }
285         return negate(); // flip sign
286     }
287 
288     /** {@inheritDoc} */
289     @Override
290     public FieldUnivariateDerivative1<T> copySign(final FieldUnivariateDerivative1<T> sign) {
291         long m = Double.doubleToLongBits(f0.getReal());
292         long s = Double.doubleToLongBits(sign.f0.getReal());
293         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
294             return this;
295         }
296         return negate(); // flip sign
297     }
298 
299     /** {@inheritDoc} */
300     @Override
301     public FieldUnivariateDerivative1<T> copySign(final double sign) {
302         long m = Double.doubleToLongBits(f0.getReal());
303         long s = Double.doubleToLongBits(sign);
304         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
305             return this;
306         }
307         return negate(); // flip sign
308     }
309 
310     /** {@inheritDoc} */
311     @Override
312     public FieldUnivariateDerivative1<T> scalb(final int n) {
313         return new FieldUnivariateDerivative1<>(FastMath.scalb(f0, n), FastMath.scalb(f1, n));
314     }
315 
316     /** {@inheritDoc} */
317     @Override
318     public FieldUnivariateDerivative1<T> hypot(final FieldUnivariateDerivative1<T> y) {
319 
320         if (Double.isInfinite(f0.getReal()) || Double.isInfinite(y.f0.getReal())) {
321             return new FieldUnivariateDerivative1<>(f0.newInstance(Double.POSITIVE_INFINITY),
322                                                     f0.getField().getZero());
323         } else if (Double.isNaN(f0.getReal()) || Double.isNaN(y.f0.getReal())) {
324             return new FieldUnivariateDerivative1<>(f0.newInstance(Double.NaN),
325                                                     f0.getField().getZero());
326         } else {
327 
328             final int expX = getExponent();
329             final int expY = y.getExponent();
330             if (expX > expY + 27) {
331                 // y is negligible with respect to x
332                 return abs();
333             } else if (expY > expX + 27) {
334                 // x is negligible with respect to y
335                 return y.abs();
336             } else {
337 
338                 // find an intermediate scale to avoid both overflow and underflow
339                 final int middleExp = (expX + expY) / 2;
340 
341                 // scale parameters without losing precision
342                 final FieldUnivariateDerivative1<T> scaledX = scalb(-middleExp);
343                 final FieldUnivariateDerivative1<T> scaledY = y.scalb(-middleExp);
344 
345                 // compute scaled hypotenuse
346                 final FieldUnivariateDerivative1<T> scaledH =
347                         scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();
348 
349                 // remove scaling
350                 return scaledH.scalb(middleExp);
351 
352             }
353 
354         }
355     }
356 
357     /** Compute composition of the instance by a function.
358      * @param g0 value of the function at the current point (i.e. at {@code g(getValue())})
359      * @param g1 first derivative of the function at the current point (i.e. at {@code g'(getValue())})
360      * @return g(this)
361      */
362     @Override
363     public FieldUnivariateDerivative1<T> compose(final T g0, final T g1) {
364         return new FieldUnivariateDerivative1<>(g0, g1.multiply(f1));
365     }
366 
367     /** {@inheritDoc} */
368     @Override
369     public FieldUnivariateDerivative1<T> rootN(final int n) {
370         if (n == 2) {
371             return sqrt();
372         } else if (n == 3) {
373             return cbrt();
374         } else {
375             final T r = FastMath.pow(f0, 1.0 / n);
376             return compose(r, FastMath.pow(r, n - 1).multiply(n).reciprocal());
377         }
378     }
379 
380     /** {@inheritDoc} */
381     @Override
382     public FieldUnivariateDerivative1Field<T> getField() {
383         return FieldUnivariateDerivative1Field.getUnivariateDerivative1Field(f0.getField());
384     }
385 
386     /** Compute a<sup>x</sup> where a is a double and x a {@link FieldUnivariateDerivative1}
387      * @param a number to exponentiate
388      * @param x power to apply
389      * @param <T> the type of the function parameters and value
390      * @return a<sup>x</sup>
391      */
392     public static <T extends CalculusFieldElement<T>> FieldUnivariateDerivative1<T> pow(final double a, final FieldUnivariateDerivative1<T> x) {
393         if (a == 0) {
394             return x.getField().getZero();
395         } else {
396             final T aX = FastMath.pow(x.f0.newInstance(a), x.f0);
397             return new FieldUnivariateDerivative1<>(aX, aX.multiply(FastMath.log(a)).multiply(x.f1));
398         }
399     }
400 
401     /** {@inheritDoc} */
402     @Override
403     public FieldUnivariateDerivative1<T> pow(final double p) {
404         if (p == 0) {
405             return getField().getOne();
406         } else {
407             final T f0Pm1 = FastMath.pow(f0, p - 1);
408             return compose(f0Pm1.multiply(f0), f0Pm1.multiply(p));
409         }
410     }
411 
412     /** {@inheritDoc} */
413     @Override
414     public FieldUnivariateDerivative1<T> pow(final int n) {
415         if (n == 0) {
416             return getField().getOne();
417         } else {
418             final T f0Nm1 = FastMath.pow(f0, n - 1);
419             return compose(f0Nm1.multiply(f0), f0Nm1.multiply(n));
420         }
421     }
422 
423     /** {@inheritDoc} */
424     @Override
425     public FieldUnivariateDerivative1<T> atan2(final FieldUnivariateDerivative1<T> x) {
426         final T inv = f0.square().add(x.f0.multiply(x.f0)).reciprocal();
427         return new FieldUnivariateDerivative1<>(FastMath.atan2(f0, x.f0),
428                                                 f0.linearCombination(x.f0, f1, x.f1.negate(), f0).multiply(inv));
429     }
430 
431     /** {@inheritDoc} */
432     @Override
433     public FieldUnivariateDerivative1<T> toDegrees() {
434         return new FieldUnivariateDerivative1<>(FastMath.toDegrees(f0), FastMath.toDegrees(f1));
435     }
436 
437     /** {@inheritDoc} */
438     @Override
439     public FieldUnivariateDerivative1<T> toRadians() {
440         return new FieldUnivariateDerivative1<>(FastMath.toRadians(f0), FastMath.toRadians(f1));
441     }
442 
443     /** Evaluate Taylor expansion of a univariate derivative.
444      * @param delta parameter offset Δx
445      * @return value of the Taylor expansion at x + Δx
446      */
447     public T taylor(final double delta) {
448         return f0.add(f1.multiply(delta));
449     }
450 
451     /** Evaluate Taylor expansion of a univariate derivative.
452      * @param delta parameter offset Δx
453      * @return value of the Taylor expansion at x + Δx
454      */
455     public T taylor(final T delta) {
456         return f0.add(f1.multiply(delta));
457     }
458 
459     /**
460      * Compute a linear combination.
461      * @param a Factors.
462      * @param b Factors.
463      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
464      * @throws MathIllegalArgumentException if arrays dimensions don't match
465      */
466     public FieldUnivariateDerivative1<T> linearCombination(final T[] a, final FieldUnivariateDerivative1<T>[] b) {
467 
468         // extract values and first derivatives
469         final Field<T> field = b[0].f0.getField();
470         final int      n  = b.length;
471         final T[] b0 = MathArrays.buildArray(field, n);
472         final T[] b1 = MathArrays.buildArray(field, n);
473         for (int i = 0; i < n; ++i) {
474             b0[i] = b[i].f0;
475             b1[i] = b[i].f1;
476         }
477 
478         return new FieldUnivariateDerivative1<>(b[0].f0.linearCombination(a, b0),
479                                                 b[0].f0.linearCombination(a, b1));
480 
481     }
482 
483     /** {@inheritDoc} */
484     @Override
485     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T>[] a,
486                                                            final FieldUnivariateDerivative1<T>[] b) {
487 
488         // extract values and first derivatives
489         final Field<T> field = a[0].f0.getField();
490         final int n  = a.length;
491         final T[] a0 = MathArrays.buildArray(field, n);
492         final T[] b0 = MathArrays.buildArray(field, n);
493         final T[] a1 = MathArrays.buildArray(field, 2 * n);
494         final T[] b1 = MathArrays.buildArray(field, 2 * n);
495         for (int i = 0; i < n; ++i) {
496             final FieldUnivariateDerivative1<T> ai = a[i];
497             final FieldUnivariateDerivative1<T> bi = b[i];
498             a0[i]         = ai.f0;
499             b0[i]         = bi.f0;
500             a1[2 * i]     = ai.f0;
501             a1[2 * i + 1] = ai.f1;
502             b1[2 * i]     = bi.f1;
503             b1[2 * i + 1] = bi.f0;
504         }
505 
506         return new FieldUnivariateDerivative1<>(a[0].f0.linearCombination(a0, b0),
507                                                 a[0].f0.linearCombination(a1, b1));
508 
509     }
510 
511     /** {@inheritDoc} */
512     @Override
513     public FieldUnivariateDerivative1<T> linearCombination(final double[] a, final FieldUnivariateDerivative1<T>[] b) {
514 
515         // extract values and first derivatives
516         final Field<T> field = b[0].f0.getField();
517         final int      n  = b.length;
518         final T[] b0 = MathArrays.buildArray(field, n);
519         final T[] b1 = MathArrays.buildArray(field, n);
520         for (int i = 0; i < n; ++i) {
521             b0[i] = b[i].f0;
522             b1[i] = b[i].f1;
523         }
524 
525         return new FieldUnivariateDerivative1<>(b[0].f0.linearCombination(a, b0),
526                                                 b[0].f0.linearCombination(a, b1));
527 
528     }
529 
530     /** {@inheritDoc} */
531     @Override
532     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T> a1, final FieldUnivariateDerivative1<T> b1,
533                                                            final FieldUnivariateDerivative1<T> a2, final FieldUnivariateDerivative1<T> b2) {
534         return new FieldUnivariateDerivative1<>(a1.f0.linearCombination(a1.f0, b1.f0,
535                                                                         a2.f0, b2.f0),
536                                                 a1.f0.linearCombination(a1.f0, b1.f1,
537                                                                         a1.f1, b1.f0,
538                                                                         a2.f0, b2.f1,
539                                                                         a2.f1, b2.f0));
540     }
541 
542     /** {@inheritDoc} */
543     @Override
544     public FieldUnivariateDerivative1<T> linearCombination(final double a1, final FieldUnivariateDerivative1<T> b1,
545                                                            final double a2, final FieldUnivariateDerivative1<T> b2) {
546         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
547                                                                         a2, b2.f0),
548                                                 b1.f0.linearCombination(a1, b1.f1,
549                                                                         a2, b2.f1));
550     }
551 
552     /** {@inheritDoc} */
553     @Override
554     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T> a1, final FieldUnivariateDerivative1<T> b1,
555                                                            final FieldUnivariateDerivative1<T> a2, final FieldUnivariateDerivative1<T> b2,
556                                                            final FieldUnivariateDerivative1<T> a3, final FieldUnivariateDerivative1<T> b3) {
557         final Field<T> field = a1.f0.getField();
558         final T[] a = MathArrays.buildArray(field, 6);
559         final T[] b = MathArrays.buildArray(field, 6);
560         a[0] = a1.f0;
561         a[1] = a1.f1;
562         a[2] = a2.f0;
563         a[3] = a2.f1;
564         a[4] = a3.f0;
565         a[5] = a3.f1;
566         b[0] = b1.f1;
567         b[1] = b1.f0;
568         b[2] = b2.f1;
569         b[3] = b2.f0;
570         b[4] = b3.f1;
571         b[5] = b3.f0;
572         return new FieldUnivariateDerivative1<>(a1.f0.linearCombination(a1.f0, b1.f0,
573                                                                         a2.f0, b2.f0,
574                                                                         a3.f0, b3.f0),
575                                                 a1.f0.linearCombination(a, b));
576     }
577 
578     /**
579      * Compute a linear combination.
580      * @param a1 first factor of the first term
581      * @param b1 second factor of the first term
582      * @param a2 first factor of the second term
583      * @param b2 second factor of the second term
584      * @param a3 first factor of the third term
585      * @param b3 second factor of the third term
586      * @return a<sub>1</sub>&times;b<sub>1</sub> +
587      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
588      * @see #linearCombination(double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1)
589      * @see #linearCombination(double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1, double, FieldUnivariateDerivative1)
590      * @exception MathIllegalArgumentException if number of free parameters or orders are inconsistent
591      */
592     public FieldUnivariateDerivative1<T> linearCombination(final T a1, final FieldUnivariateDerivative1<T> b1,
593                                                            final T a2, final FieldUnivariateDerivative1<T> b2,
594                                                            final T a3, final FieldUnivariateDerivative1<T> b3) {
595         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
596                                                                         a2, b2.f0,
597                                                                         a3, b3.f0),
598                                                 b1.f0.linearCombination(a1, b1.f1,
599                                                                         a2, b2.f1,
600                                                                         a3, b3.f1));
601     }
602 
603     /** {@inheritDoc} */
604     @Override
605     public FieldUnivariateDerivative1<T> linearCombination(final double a1, final FieldUnivariateDerivative1<T> b1,
606                                                            final double a2, final FieldUnivariateDerivative1<T> b2,
607                                                            final double a3, final FieldUnivariateDerivative1<T> b3) {
608         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
609                                                                         a2, b2.f0,
610                                                                         a3, b3.f0),
611                                                 b1.f0.linearCombination(a1, b1.f1,
612                                                                         a2, b2.f1,
613                                                                         a3, b3.f1));
614     }
615 
616     /** {@inheritDoc} */
617     @Override
618     public FieldUnivariateDerivative1<T> linearCombination(final FieldUnivariateDerivative1<T> a1, final FieldUnivariateDerivative1<T> b1,
619                                                            final FieldUnivariateDerivative1<T> a2, final FieldUnivariateDerivative1<T> b2,
620                                                            final FieldUnivariateDerivative1<T> a3, final FieldUnivariateDerivative1<T> b3,
621                                                            final FieldUnivariateDerivative1<T> a4, final FieldUnivariateDerivative1<T> b4) {
622         final Field<T> field = a1.f0.getField();
623         final T[] a = MathArrays.buildArray(field, 8);
624         final T[] b = MathArrays.buildArray(field, 8);
625         a[0] = a1.f0;
626         a[1] = a1.f1;
627         a[2] = a2.f0;
628         a[3] = a2.f1;
629         a[4] = a3.f0;
630         a[5] = a3.f1;
631         a[6] = a4.f0;
632         a[7] = a4.f1;
633         b[0] = b1.f1;
634         b[1] = b1.f0;
635         b[2] = b2.f1;
636         b[3] = b2.f0;
637         b[4] = b3.f1;
638         b[5] = b3.f0;
639         b[6] = b4.f1;
640         b[7] = b4.f0;
641         return new FieldUnivariateDerivative1<>(a1.f0.linearCombination(a1.f0, b1.f0,
642                                                                         a2.f0, b2.f0,
643                                                                         a3.f0, b3.f0,
644                                                                         a4.f0, b4.f0),
645                                                 a1.f0.linearCombination(a, b));
646     }
647 
648     /** {@inheritDoc} */
649     @Override
650     public FieldUnivariateDerivative1<T> linearCombination(final double a1, final FieldUnivariateDerivative1<T> b1,
651                                                            final double a2, final FieldUnivariateDerivative1<T> b2,
652                                                            final double a3, final FieldUnivariateDerivative1<T> b3,
653                                                            final double a4, final FieldUnivariateDerivative1<T> b4) {
654         return new FieldUnivariateDerivative1<>(b1.f0.linearCombination(a1, b1.f0,
655                                                                         a2, b2.f0,
656                                                                         a3, b3.f0,
657                                                                         a4, b4.f0),
658                                                 b1.f0.linearCombination(a1, b1.f1,
659                                                                         a2, b2.f1,
660                                                                         a3, b3.f1,
661                                                                         a4, b4.f1));
662     }
663 
664     /** {@inheritDoc} */
665     @Override
666     public FieldUnivariateDerivative1<T> getPi() {
667         final T zero = getValueField().getZero();
668         return new FieldUnivariateDerivative1<>(zero.getPi(), zero);
669     }
670 
671     /** Test for the equality of two univariate derivatives.
672      * <p>
673      * univariate derivatives are considered equal if they have the same derivatives.
674      * </p>
675      * @param other Object to test for equality to this
676      * @return true if two univariate derivatives are equal
677      */
678     @Override
679     public boolean equals(Object other) {
680 
681         if (this == other) {
682             return true;
683         }
684 
685         if (other instanceof FieldUnivariateDerivative1) {
686             @SuppressWarnings("unchecked")
687             final FieldUnivariateDerivative1<T> rhs = (FieldUnivariateDerivative1<T>) other;
688             return f0.equals(rhs.f0) && f1.equals(rhs.f1);
689         }
690 
691         return false;
692 
693     }
694 
695     /** Get a hashCode for the univariate derivative.
696      * @return a hash code value for this object
697      */
698     @Override
699     public int hashCode() {
700         return 453 - 19 * f0.hashCode() + 37 * f1.hashCode();
701     }
702 
703 }