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 /** '×' operator. 79 * @param a right hand side parameter of the operator 80 * @return this×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 /** '÷' operator. 93 * @param a right hand side parameter of the operator 94 * @return this÷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 × 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> +<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> +<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 × this. 174 * @return a new element representing this × 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>Σ<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>Σ<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>×b<sub>1</sub> + 377 * a<sub>2</sub>×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>×b<sub>1</sub> + 390 * a<sub>2</sub>×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>×b<sub>1</sub> + 407 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×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>×b<sub>1</sub> + 422 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×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>×b<sub>1</sub> + 441 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×b<sub>3</sub> + 442 * a<sub>4</sub>×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>×b<sub>1</sub> + 459 * a<sub>2</sub>×b<sub>2</sub> + a<sub>3</sub>×b<sub>3</sub> + 460 * a<sub>4</sub>×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 ≤ this ≤ 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 × 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 × 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 }