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 /** '×' operator.
99 * @param a right hand side parameter of the operator
100 * @return this×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 /** '÷' operator.
113 * @param a right hand side parameter of the operator
114 * @return this÷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 × 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> +<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> +<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 × this.
194 * @return a new element representing this × 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>Σ<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>Σ<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>×b<sub>1</sub> +
397 * a<sub>2</sub>×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>×b<sub>1</sub> +
410 * a<sub>2</sub>×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>×b<sub>1</sub> +
427 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×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>×b<sub>1</sub> +
442 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×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>×b<sub>1</sub> +
461 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×b<sub>3</sub> +
462 * a<sub>4</sub>×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>×b<sub>1</sub> +
479 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×b<sub>3</sub> +
480 * a<sub>4</sub>×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 ≤ this ≤ 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 × 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 × 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 }