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