View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) 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 ASF 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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus;
23  
24  import org.hipparchus.exception.MathIllegalArgumentException;
25  import org.hipparchus.util.FastMath;
26  import org.hipparchus.util.FieldSinCos;
27  import org.hipparchus.util.FieldSinhCosh;
28  import org.hipparchus.util.MathArrays;
29  
30  /**
31   * Interface representing a <a href="http://mathworld.wolfram.com/Field.html">field</a>
32   * with calculus capabilities (sin, cos, ...).
33   * @param <T> the type of the field elements
34   * @see FieldElement
35   * @since 1.7
36   */
37  public interface CalculusFieldElement<T extends FieldElement<T>> extends FieldElement<T> {
38  
39      /** Get the addendum to the real value of the number.
40       * <p>
41       * The addendum is considered to be the part that when added back to
42       * the {@link #getReal() real part} recovers the instance. This means
43       * that when {@code e.getReal()} is finite (i.e. neither infinite
44       * nor NaN), then {@code e.getAddendum().add(e.getReal())} is {@code e}
45       * and {@code e.subtract(e.getReal())} is {@code e.getAddendum()}.
46       * Beware that for non-finite numbers, these two equalities may not hold.
47       * The first equality (with the addition), always holds even for infinity
48       * and NaNs if the real part is independent of the addendum (this is the
49       * case for all derivatives types, as well as for complex and Dfp, but it
50       * is not the case for Tuple and FieldTuple). The second equality (with
51       * the subtraction), generally doesn't hold for non-finite numbers, because
52       * the subtraction generates NaNs.
53       * </p>
54       * @return real value
55       * @since 4.0
56       */
57      T getAddendum();
58  
59      /** Get the Archimedes constant π.
60       * <p>
61       * Archimedes constant is the ratio of a circle's circumference to its diameter.
62       * </p>
63       * @return Archimedes constant π
64       * @since 2.0
65       */
66      default T getPi() {
67          return newInstance(FastMath.PI);
68      }
69  
70      /** Create an instance corresponding to a constant real value.
71       * @param value constant real value
72       * @return instance corresponding to a constant real value
73       */
74      T newInstance(double value);
75  
76      /** '+' operator.
77       * @param a right hand side parameter of the operator
78       * @return this+a
79       */
80      default T add(double a) {
81          return add(newInstance(a));
82      }
83  
84      /** '-' operator.
85       * @param a right hand side parameter of the operator
86       * @return this-a
87       */
88      default T subtract(double a) {
89          return subtract(newInstance(a));
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      default T subtract(T a) {
95          return add(a.negate());
96      }
97  
98      /** '&times;' operator.
99       * @param a right hand side parameter of the operator
100      * @return this&times;a
101      */
102     default T multiply(double a) {
103         return multiply(newInstance(a));
104     }
105 
106     /** {@inheritDoc} */
107     @Override
108     default T multiply(int n) {
109         return multiply((double) n);
110     }
111 
112     /** '&divide;' operator.
113      * @param a right hand side parameter of the operator
114      * @return this&divide;a
115      */
116     default T divide(double a) {
117         return divide(newInstance(a));
118     }
119 
120     /**
121      * Return the exponent of the instance, removing the bias.
122      * <p>
123      * For double numbers of the form 2<sup>x</sup>, the unbiased
124      * exponent is exactly x.
125      * </p>
126      * @return exponent for the instance, without bias
127      */
128     default int getExponent() {
129         return FastMath.getExponent(getReal());
130     }
131 
132     /**
133      * Multiply the instance by a power of 2.
134      * @param n power of 2
135      * @return this &times; 2<sup>n</sup>
136      */
137     T scalb(int n);
138 
139     /**
140      * Compute least significant bit (Unit in Last Position) for a number.
141      * @return ulp(this)
142      * @since 2.0
143      */
144     default T ulp() {
145         return newInstance(FastMath.ulp(getReal()));
146     }
147 
148     /**
149      * Returns the hypotenuse of a triangle with sides {@code this} and {@code y}
150      * - sqrt(<i>this</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
151      * avoiding intermediate overflow or underflow.
152      *
153      * <ul>
154      * <li> If either argument is infinite, then the result is positive infinity.</li>
155      * <li> else, if either argument is NaN then the result is NaN.</li>
156      * </ul>
157      *
158      * @param y a value
159      * @return sqrt(<i>this</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
160      * @exception MathIllegalArgumentException if number of free parameters or orders are inconsistent
161      */
162     T hypot(T y)
163         throws MathIllegalArgumentException;
164 
165     /** {@inheritDoc} */
166     @Override
167     default T divide(T a) {
168         return multiply(a.reciprocal());
169     }
170 
171     /** Square root.
172      * @return square root of the instance
173      */
174     default T sqrt() {
175         return rootN(2);
176     }
177 
178     /** Cubic root.
179      * @return cubic root of the instance
180      */
181     default T cbrt() {
182         return rootN(3);
183     }
184 
185     /** N<sup>th</sup> root.
186      * @param n order of the root
187      * @return n<sup>th</sup> root of the instance
188      */
189     default T rootN(int n) {
190         return pow(1. / n);
191     }
192 
193     /** Compute this &times; this.
194      * @return a new element representing this &times; this
195      * @since 3.1
196      */
197     default T square() {
198         return pow(2);
199     }
200 
201     /** Power operation.
202      * @param p power to apply
203      * @return this<sup>p</sup>
204      */
205     default T pow(double p) {
206         return pow(newInstance(p));
207     }
208 
209     /** Integer power operation.
210      * @param n power to apply
211      * @return this<sup>n</sup>
212      */
213     default T pow(int n) {
214         return pow((double) n);
215     }
216 
217     /** Power operation.
218      * @param e exponent
219      * @return this<sup>e</sup>
220      * @exception MathIllegalArgumentException if number of free parameters or orders are inconsistent
221      */
222     T pow(T e)
223         throws MathIllegalArgumentException;
224 
225     /** Exponential.
226      * @return exponential of the instance
227      */
228     T exp();
229 
230     /** Exponential minus 1.
231      * @return exponential minus one of the instance
232      */
233     T expm1();
234 
235     /** Natural logarithm.
236      * @return logarithm of the instance
237      */
238     T log();
239 
240     /** Shifted natural logarithm.
241      * @return logarithm of one plus the instance
242      */
243     T log1p();
244 
245     /** Base 10 logarithm.
246      * @return base 10 logarithm of the instance
247      */
248     T log10();
249 
250     /** Cosine operation.
251      * @return cos(this)
252      */
253     T cos();
254 
255     /** Sine operation.
256      * @return sin(this)
257      */
258     T sin();
259 
260     /** Combined Sine and Cosine operation.
261      * @return [sin(this), cos(this)]
262      * @since 1.4
263      */
264     default FieldSinCos<T> sinCos() {
265         return new FieldSinCos<>(sin(), cos());
266     }
267 
268     /** Tangent operation.
269      * @return tan(this)
270      */
271     default T tan() {
272         return sin().divide(cos());
273     }
274 
275     /** Arc cosine operation.
276      * @return acos(this)
277      */
278     T acos();
279 
280     /** Arc sine operation.
281      * @return asin(this)
282      */
283     T asin();
284 
285     /** Arc tangent operation.
286      * @return atan(this)
287      */
288     T atan();
289 
290     /** Two arguments arc tangent operation.
291      * <p>
292      * Beware of the order or arguments! As this is based on a
293      * two-arguments functions, in order to be consistent with
294      * arguments order, the instance is the <em>first</em> argument
295      * and the single provided argument is the <em>second</em> argument.
296      * In order to be consistent with programming languages {@code atan2},
297      * this method computes {@code atan2(this, x)}, i.e. the instance
298      * represents the {@code y} argument and the {@code x} argument is
299      * the one passed as a single argument. This may seem confusing especially
300      * for users of Wolfram alpha, as this site is <em>not</em> consistent
301      * with programming languages {@code atan2} two-arguments arc tangent
302      * and puts {@code x} as its first argument.
303      * </p>
304      * @param x second argument of the arc tangent
305      * @return atan2(this, x)
306      * @exception MathIllegalArgumentException if number of free parameters or orders are inconsistent
307      */
308     T atan2(T x)
309         throws MathIllegalArgumentException;
310 
311     /** Hyperbolic cosine operation.
312      * @return cosh(this)
313      */
314     T cosh();
315 
316     /** Hyperbolic sine operation.
317      * @return sinh(this)
318      */
319     T sinh();
320 
321     /** Combined hyperbolic sine and cosine operation.
322      * @return [sinh(this), cosh(this)]
323      * @since 2.0
324      */
325     default FieldSinhCosh<T> sinhCosh() {
326         return new FieldSinhCosh<>(sinh(), cosh());
327     }
328 
329     /** Hyperbolic tangent operation.
330      * @return tanh(this)
331      */
332     default T tanh() {
333         return sinh().divide(cosh());
334     }
335 
336     /** Inverse hyperbolic cosine operation.
337      * @return acosh(this)
338      */
339     T acosh();
340 
341     /** Inverse hyperbolic sine operation.
342      * @return asin(this)
343      */
344     T asinh();
345 
346     /** Inverse hyperbolic  tangent operation.
347      * @return atanh(this)
348      */
349     T atanh();
350 
351     /** Convert radians to degrees, with error of less than 0.5 ULP
352      *  @return instance converted into degrees
353      */
354     default T toDegrees() {
355         return multiply(FastMath.toDegrees(1.));
356     }
357 
358     /** Convert degrees to radians, with error of less than 0.5 ULP
359      *  @return instance converted into radians
360      */
361     default T toRadians() {
362         return multiply(FastMath.toRadians(1.));
363     }
364 
365     /**
366      * Compute a linear combination.
367      * @param a Factors.
368      * @param b Factors.
369      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
370      * @throws MathIllegalArgumentException if arrays dimensions don't match
371      */
372     T linearCombination(T[] a, T[] b)
373         throws MathIllegalArgumentException;
374 
375     /**
376      * Compute a linear combination.
377      * @param a Factors.
378      * @param b Factors.
379      * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
380      * @throws MathIllegalArgumentException if arrays dimensions don't match
381      */
382     default T linearCombination(double[] a, T[] b) throws MathIllegalArgumentException {
383         final T[] newInstances = MathArrays.buildArray(getField(), a.length);
384         for (int i = 0; i < a.length; i++) {
385             newInstances[i] = newInstance(a[i]);
386         }
387         return linearCombination(newInstances, b);
388     }
389 
390     /**
391      * Compute a linear combination.
392      * @param a1 first factor of the first term
393      * @param b1 second factor of the first term
394      * @param a2 first factor of the second term
395      * @param b2 second factor of the second term
396      * @return a<sub>1</sub>&times;b<sub>1</sub> +
397      * a<sub>2</sub>&times;b<sub>2</sub>
398      * @see #linearCombination(FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement)
399      * @see #linearCombination(FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement)
400      */
401     T linearCombination(T a1, T b1, T a2, T b2);
402 
403     /**
404      * Compute a linear combination.
405      * @param a1 first factor of the first term
406      * @param b1 second factor of the first term
407      * @param a2 first factor of the second term
408      * @param b2 second factor of the second term
409      * @return a<sub>1</sub>&times;b<sub>1</sub> +
410      * a<sub>2</sub>&times;b<sub>2</sub>
411      * @see #linearCombination(double, FieldElement, double, FieldElement, double, FieldElement)
412      * @see #linearCombination(double, FieldElement, double, FieldElement, double, FieldElement, double, FieldElement)
413      */
414     default T linearCombination(double a1, T b1, double a2, T b2) {
415         return linearCombination(newInstance(a1), b1, newInstance(a2), b2);
416     }
417 
418     /**
419      * Compute a linear combination.
420      * @param a1 first factor of the first term
421      * @param b1 second factor of the first term
422      * @param a2 first factor of the second term
423      * @param b2 second factor of the second term
424      * @param a3 first factor of the third term
425      * @param b3 second factor of the third term
426      * @return a<sub>1</sub>&times;b<sub>1</sub> +
427      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
428      * @see #linearCombination(FieldElement, FieldElement, FieldElement, FieldElement)
429      * @see #linearCombination(FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement)
430      */
431     T linearCombination(T a1, T b1, T a2, T b2, T a3, T b3);
432 
433     /**
434      * Compute a linear combination.
435      * @param a1 first factor of the first term
436      * @param b1 second factor of the first term
437      * @param a2 first factor of the second term
438      * @param b2 second factor of the second term
439      * @param a3 first factor of the third term
440      * @param b3 second factor of the third term
441      * @return a<sub>1</sub>&times;b<sub>1</sub> +
442      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
443      * @see #linearCombination(double, FieldElement, double, FieldElement)
444      * @see #linearCombination(double, FieldElement, double, FieldElement, double, FieldElement, double, FieldElement)
445      */
446     default T linearCombination(double a1, T b1, double a2, T b2, double a3, T b3) {
447         return linearCombination(newInstance(a1), b1, newInstance(a2), b2, newInstance(a3), b3);
448     }
449 
450     /**
451      * Compute a linear combination.
452      * @param a1 first factor of the first term
453      * @param b1 second factor of the first term
454      * @param a2 first factor of the second term
455      * @param b2 second factor of the second term
456      * @param a3 first factor of the third term
457      * @param b3 second factor of the third term
458      * @param a4 first factor of the fourth term
459      * @param b4 second factor of the fourth term
460      * @return a<sub>1</sub>&times;b<sub>1</sub> +
461      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
462      * a<sub>4</sub>&times;b<sub>4</sub>
463      * @see #linearCombination(FieldElement, FieldElement, FieldElement, FieldElement)
464      * @see #linearCombination(FieldElement, FieldElement, FieldElement, FieldElement, FieldElement, FieldElement)
465      */
466     T linearCombination(T a1, T b1, T a2, T b2, T a3, T b3, T a4, T b4);
467 
468     /**
469      * Compute a linear combination.
470      * @param a1 first factor of the first term
471      * @param b1 second factor of the first term
472      * @param a2 first factor of the second term
473      * @param b2 second factor of the second term
474      * @param a3 first factor of the third term
475      * @param b3 second factor of the third term
476      * @param a4 first factor of the fourth term
477      * @param b4 second factor of the fourth term
478      * @return a<sub>1</sub>&times;b<sub>1</sub> +
479      * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
480      * a<sub>4</sub>&times;b<sub>4</sub>
481      * @see #linearCombination(double, FieldElement, double, FieldElement)
482      * @see #linearCombination(double, FieldElement, double, FieldElement, double, FieldElement)
483      */
484     default T linearCombination(double a1, T b1, double a2, T b2, double a3, T b3, double a4, T b4) {
485         return linearCombination(newInstance(a1), b1, newInstance(a2), b2, newInstance(a3), b3,
486                 newInstance(a4), b4);
487     }
488 
489     /** Get the smallest whole number larger than instance.
490      * @return ceil(this)
491      */
492     default T ceil() {
493         return newInstance(FastMath.ceil(getReal()));
494     }
495 
496     /** Get the largest whole number smaller than instance.
497      * @return floor(this)
498      */
499     default T floor() {
500         return newInstance(FastMath.floor(getReal()));
501     }
502 
503     /** Get the whole number that is the nearest to the instance, or the even one if x is exactly half way between two integers.
504      * @return a double number r such that r is an integer r - 0.5 &le; this &le; r + 0.5
505      */
506     default T rint() {
507         return newInstance(FastMath.rint(getReal()));
508     }
509 
510     /** IEEE remainder operator.
511      * @param a right hand side parameter of the operator
512      * @return this - n &times; a where n is the closest integer to this/a
513      */
514     T remainder(double a);
515 
516     /** IEEE remainder operator.
517      * @param a right hand side parameter of the operator
518      * @return this - n &times; a where n is the closest integer to this/a
519      */
520     T remainder(T a);
521 
522     /** Compute the sign of the instance.
523      * The sign is -1 for negative numbers, +1 for positive numbers and 0 otherwise,
524      * for Complex number, it is extended on the unit circle (equivalent to z/|z|,
525      * with special handling for 0 and NaN)
526      * @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a
527      */
528     default T sign() {
529         return newInstance(FastMath.signum(getReal()));
530     }
531 
532     /**
533      * Returns the instance with the sign of the argument.
534      * A NaN {@code sign} argument is treated as positive.
535      *
536      * @param sign the sign for the returned value
537      * @return the instance with the same sign as the {@code sign} argument
538      */
539     T copySign(T sign);
540 
541     /**
542      * Returns the instance with the sign of the argument.
543      * A NaN {@code sign} argument is treated as positive.
544      *
545      * @param sign the sign for the returned value
546      * @return the instance with the same sign as the {@code sign} argument
547      */
548     default T copySign(double sign) {
549         return copySign(newInstance(sign));
550     }
551 
552     /**
553      * Check if the instance is infinite.
554      * @return true if the instance is infinite
555      */
556     default boolean isInfinite() {
557         return Double.isInfinite(getReal());
558     }
559 
560     /**
561      * Check if the instance is finite (neither infinite nor NaN).
562      * @return true if the instance is finite (neither infinite nor NaN)
563      * @since 2.0
564      */
565     default boolean isFinite() {
566         return Double.isFinite(getReal());
567     }
568 
569     /**
570      * Check if the instance is Not a Number.
571      * @return true if the instance is Not a Number
572      */
573     default boolean isNaN() {
574         return Double.isNaN(getReal());
575     }
576 
577     /** norm.
578      * @return norm(this)
579      * @since 2.0
580      */
581     default double norm() {
582         return abs().getReal();
583     }
584 
585     /** absolute value.
586      * @return abs(this)
587      */
588     T abs();
589 
590     /** Get the closest long to instance real value.
591      * @return closest long to {@link #getReal()}
592      */
593     default long round() {
594         return FastMath.round(getReal());
595     }
596 
597 }