github.com/richardwilkes/toolbox@v1.121.0/xmath/math.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package xmath 11 12 import ( 13 "math" 14 "reflect" 15 16 "golang.org/x/exp/constraints" 17 ) 18 19 // Numeric is a constraint that permits any integer or float type. 20 type Numeric interface { 21 constraints.Float | constraints.Integer 22 } 23 24 // Abs returns the absolute value of x. 25 // 26 // Special cases are: 27 // 28 // Abs(±Inf) = +Inf 29 // Abs(NaN) = NaN 30 func Abs[T Numeric](x T) T { 31 switch reflect.TypeOf(x).Kind() { 32 case reflect.Float32: 33 return T(math.Float32frombits(math.Float32bits(float32(x)) &^ (1 << 31))) 34 case reflect.Float64: 35 return T(math.Abs(float64(x))) 36 default: 37 if x < 0 { 38 return -x 39 } 40 return x 41 } 42 } 43 44 // Acos returns the arccosine of x. 45 func Acos[T constraints.Float](x T) T { 46 return T(math.Acos(float64(x))) 47 } 48 49 // Acosh returns the inverse hyperbolic cosine of x. 50 // 51 // Special cases are: 52 // 53 // Acosh(+Inf) = +Inf 54 // Acosh(x) = NaN if x < 1 55 // Acosh(NaN) = NaN 56 func Acosh[T constraints.Float](x T) T { 57 return T(math.Acosh(float64(x))) 58 } 59 60 // Asin returns the arcsine, in radians, of x. 61 // 62 // Special cases are: 63 // 64 // Asin(±0) = ±0 65 // Asin(x) = NaN if x < -1 or x > 1 66 func Asin[T constraints.Float](x T) T { 67 return T(math.Asin(float64(x))) 68 } 69 70 // Asinh returns the inverse hyperbolic sine of x. 71 // 72 // Special cases are: 73 // 74 // Asinh(±0) = ±0 75 // Asinh(±Inf) = ±Inf 76 // Asinh(NaN) = NaN 77 func Asinh[T constraints.Float](x T) T { 78 return T(math.Asinh(float64(x))) 79 } 80 81 // Atan2 returns the arc tangent of y/x, using the signs of the two to determine the quadrant of the return value. 82 // 83 // Special cases are (in order): 84 // 85 // Atan2(y, NaN) = NaN 86 // Atan2(NaN, x) = NaN 87 // Atan2(+0, x>=0) = +0 88 // Atan2(-0, x>=0) = -0 89 // Atan2(+0, x<=-0) = +Pi 90 // Atan2(-0, x<=-0) = -Pi 91 // Atan2(y>0, 0) = +Pi/2 92 // Atan2(y<0, 0) = -Pi/2 93 // Atan2(+Inf, +Inf) = +Pi/4 94 // Atan2(-Inf, +Inf) = -Pi/4 95 // Atan2(+Inf, -Inf) = 3Pi/4 96 // Atan2(-Inf, -Inf) = -3Pi/4 97 // Atan2(y, +Inf) = 0 98 // Atan2(y>0, -Inf) = +Pi 99 // Atan2(y<0, -Inf) = -Pi 100 // Atan2(+Inf, x) = +Pi/2 101 // Atan2(-Inf, x) = -Pi/2 102 func Atan2[T constraints.Float](y, x T) T { 103 return T(math.Atan2(float64(y), float64(x))) 104 } 105 106 // Atan returns the arctangent, in radians, of x. 107 // 108 // Special cases are: 109 // 110 // Atan(±0) = ±0 111 // Atan(±Inf) = ±Pi/2 112 func Atan[T constraints.Float](x T) T { 113 return T(math.Atan(float64(x))) 114 } 115 116 // Atanh returns the inverse hyperbolic tangent of x. 117 // 118 // Special cases are: 119 // 120 // Atanh(1) = +Inf 121 // Atanh(±0) = ±0 122 // Atanh(-1) = -Inf 123 // Atanh(x) = NaN if x < -1 or x > 1 124 // Atanh(NaN) = NaN 125 func Atanh[T constraints.Float](x T) T { 126 return T(math.Atanh(float64(x))) 127 } 128 129 // Cbrt returns the cube root of x. 130 func Cbrt[T constraints.Float](x T) T { 131 return T(math.Cbrt(float64(x))) 132 } 133 134 // Ceil returns the smallest integer value greater than or equal to x. 135 func Ceil[T Numeric](x T) T { 136 switch reflect.TypeOf(x).Kind() { 137 case reflect.Float32, reflect.Float64: 138 return T(math.Ceil(float64(x))) 139 default: 140 return x 141 } 142 } 143 144 // Copysign returns a value with the magnitude of x and the sign of y. 145 func Copysign[T constraints.Float](x, y T) T { 146 if reflect.TypeOf(x).Kind() == reflect.Float32 { 147 const sign = 1 << 31 148 return T(math.Float32frombits(math.Float32bits(float32(x))&^sign | math.Float32bits(float32(y))&sign)) 149 } 150 return T(math.Copysign(float64(x), float64(y))) 151 } 152 153 // Cos returns the cosine of the radian argument x. 154 // 155 // Special cases are: 156 // 157 // Cos(±Inf) = NaN 158 // Cos(NaN) = NaN 159 func Cos[T constraints.Float](x T) T { 160 return T(math.Cos(float64(x))) 161 } 162 163 // Cosh returns the hyperbolic cosine of x. 164 // 165 // Special cases are: 166 // 167 // Cosh(±0) = 1 168 // Cosh(±Inf) = +Inf 169 // Cosh(NaN) = NaN 170 func Cosh[T constraints.Float](x T) T { 171 return T(math.Cosh(float64(x))) 172 } 173 174 // Dim returns the maximum of x-y or 0. 175 // 176 // Special cases are: 177 // 178 // Dim(+Inf, +Inf) = NaN 179 // Dim(-Inf, -Inf) = NaN 180 // Dim(x, NaN) = Dim(NaN, x) = NaN 181 func Dim[T constraints.Float](x, y T) T { 182 if v := x - y; v > 0 { 183 return v 184 } 185 return 0 186 } 187 188 // Erf returns the error function of x. 189 // 190 // Special cases are: 191 // 192 // Erf(+Inf) = 1 193 // Erf(-Inf) = -1 194 // Erf(NaN) = NaN 195 func Erf[T constraints.Float](x T) T { 196 return T(math.Erf(float64(x))) 197 } 198 199 // Erfc returns the complementary error function of x. 200 // 201 // Special cases are: 202 // 203 // Erfc(+Inf) = 0 204 // Erfc(-Inf) = 2 205 // Erfc(NaN) = NaN 206 func Erfc[T constraints.Float](x T) T { 207 return T(math.Erfc(float64(x))) 208 } 209 210 // Erfinv returns the inverse error function of x. 211 // 212 // Special cases are: 213 // 214 // Erfinv(1) = +Inf 215 // Erfinv(-1) = -Inf 216 // Erfinv(x) = NaN if x < -1 or x > 1 217 // Erfinv(NaN) = NaN 218 func Erfinv[T constraints.Float](x T) T { 219 return T(math.Erfinv(float64(x))) 220 } 221 222 // Erfcinv returns the inverse of Erfc(x). 223 // 224 // Special cases are: 225 // 226 // Erfcinv(0) = +Inf 227 // Erfcinv(2) = -Inf 228 // Erfcinv(x) = NaN if x < 0 or x > 2 229 // Erfcinv(NaN) = NaN 230 func Erfcinv[T constraints.Float](x T) T { 231 return Erfinv(1 - x) 232 } 233 234 // Exp returns e**x, the base-e exponential of x. 235 // 236 // Special cases are: 237 // 238 // Exp(+Inf) = +Inf 239 // Exp(NaN) = NaN 240 // 241 // Very large values overflow to 0 or +Inf. 242 // Very small values underflow to 1. 243 func Exp[T constraints.Float](x T) T { 244 return T(math.Exp(float64(x))) 245 } 246 247 // Exp2 returns 2**x, the base-2 exponential of x. 248 // 249 // Special cases are the same as Exp. 250 func Exp2[T constraints.Float](x T) T { 251 return T(math.Exp2(float64(x))) 252 } 253 254 // Expm1 returns e**x - 1, the base-e exponential of x minus 1. 255 // It is more accurate than Exp(x) - 1 when x is near zero. 256 // 257 // Special cases are: 258 // 259 // Expm1(+Inf) = +Inf 260 // Expm1(-Inf) = -1 261 // Expm1(NaN) = NaN 262 // 263 // Very large values overflow to -1 or +Inf. 264 func Expm1[T constraints.Float](x T) T { 265 return T(math.Expm1(float64(x))) 266 } 267 268 // Floor returns the greatest integer value less than or equal to x. 269 func Floor[T Numeric](x T) T { 270 switch reflect.TypeOf(x).Kind() { 271 case reflect.Float32, reflect.Float64: 272 return T(math.Floor(float64(x))) 273 default: 274 return x 275 } 276 } 277 278 // FMA returns x * y + z, computed with only one rounding. 279 // (That is, FMA returns the fused multiply-add of x, y, and z.) 280 func FMA[T constraints.Float](x, y, z T) T { 281 return T(math.FMA(float64(x), float64(y), float64(z))) 282 } 283 284 // Frexp breaks f into a normalized fraction 285 // and an integral power of two. 286 // It returns frac and exp satisfying f == frac × 2**exp, 287 // with the absolute value of frac in the interval [½, 1). 288 // 289 // Special cases are: 290 // 291 // Frexp(±0) = ±0, 0 292 // Frexp(±Inf) = ±Inf, 0 293 // Frexp(NaN) = NaN, 0 294 func Frexp[T constraints.Float](f T) (frac T, exp int) { 295 fr, e := math.Frexp(float64(f)) 296 return T(fr), e 297 } 298 299 // Gamma returns the Gamma function of x. 300 // 301 // Special cases are: 302 // 303 // Gamma(+Inf) = +Inf 304 // Gamma(+0) = +Inf 305 // Gamma(-0) = -Inf 306 // Gamma(x) = NaN for integer x < 0 307 // Gamma(-Inf) = NaN 308 // Gamma(NaN) = NaN 309 func Gamma[T constraints.Float](x T) T { 310 return T(math.Gamma(float64(x))) 311 } 312 313 // Hypot returns Sqrt(p*p + q*q), taking care to avoid 314 // unnecessary overflow and underflow. 315 // 316 // Special cases are: 317 // 318 // Hypot(±Inf, q) = +Inf 319 // Hypot(p, ±Inf) = +Inf 320 // Hypot(NaN, q) = NaN 321 // Hypot(p, NaN) = NaN 322 func Hypot[T constraints.Float](p, q T) T { 323 return T(math.Hypot(float64(p), float64(q))) 324 } 325 326 // Ilogb returns the binary exponent of x as an integer. 327 // 328 // Special cases are: 329 // 330 // Ilogb(±Inf) = MaxInt32 331 // Ilogb(0) = MinInt32 332 // Ilogb(NaN) = MaxInt32 333 func Ilogb[T constraints.Float](x T) int { 334 return math.Ilogb(float64(x)) 335 } 336 337 // Inf returns positive infinity if sign >= 0, negative infinity if sign < 0. 338 func Inf[T constraints.Float](sign int) T { 339 var t T 340 if reflect.TypeOf(t).Kind() == reflect.Float32 { 341 var v uint32 342 if sign >= 0 { 343 v = 0x7F800000 344 } else { 345 v = 0xFF800000 346 } 347 return T(math.Float32frombits(v)) 348 } 349 return T(math.Inf(sign)) 350 } 351 352 // IsInf reports whether f is an infinity, according to sign. 353 // If sign > 0, IsInf reports whether f is positive infinity. 354 // If sign < 0, IsInf reports whether f is negative infinity. 355 // If sign == 0, IsInf reports whether f is either infinity. 356 func IsInf[T constraints.Float](f T, sign int) bool { 357 if reflect.TypeOf(f).Kind() == reflect.Float32 { 358 return sign >= 0 && f > math.MaxFloat32 || sign <= 0 && f < -math.MaxFloat32 359 } 360 return math.IsInf(float64(f), sign) 361 } 362 363 // IsNaN reports whether f is a "not-a-number" value. 364 func IsNaN[T constraints.Float](f T) bool { 365 //nolint:gocritic // Only NaNs satisfy f != f, which is what we are looking for 366 return f != f 367 } 368 369 // J0 returns the order-zero Bessel function of the first kind. 370 // 371 // Special cases are: 372 // 373 // J0(±Inf) = 0 374 // J0(0) = 1 375 // J0(NaN) = NaN 376 func J0[T constraints.Float](x T) T { 377 return T(math.J0(float64(x))) 378 } 379 380 // J1 returns the order-one Bessel function of the first kind. 381 // 382 // Special cases are: 383 // 384 // J1(±Inf) = 0 385 // J1(NaN) = NaN 386 func J1[T constraints.Float](x T) T { 387 return T(math.J1(float64(x))) 388 } 389 390 // Jn returns the order-n Bessel function of the first kind. 391 // 392 // Special cases are: 393 // 394 // Jn(n, ±Inf) = 0 395 // Jn(n, NaN) = NaN 396 func Jn[T constraints.Float](n int, x T) T { 397 return T(math.Jn(n, float64(x))) 398 } 399 400 // Ldexp is the inverse of Frexp. 401 // It returns frac × 2**exp. 402 // 403 // Special cases are: 404 // 405 // Ldexp(±0, exp) = ±0 406 // Ldexp(±Inf, exp) = ±Inf 407 // Ldexp(NaN, exp) = NaN 408 func Ldexp[T constraints.Float](frac T, exp int) T { 409 return T(math.Ldexp(float64(frac), exp)) 410 } 411 412 // Lgamma returns the natural logarithm and sign (-1 or +1) of Gamma(x). 413 // 414 // Special cases are: 415 // 416 // Lgamma(+Inf) = +Inf 417 // Lgamma(0) = +Inf 418 // Lgamma(-integer) = +Inf 419 // Lgamma(-Inf) = -Inf 420 // Lgamma(NaN) = NaN 421 func Lgamma[T constraints.Float](x T) (lgamma T, sign int) { 422 f64, s := math.Lgamma(float64(x)) 423 return T(f64), s 424 } 425 426 // Log returns the natural logarithm of x. 427 // 428 // Special cases are: 429 // 430 // Log(+Inf) = +Inf 431 // Log(0) = -Inf 432 // Log(x < 0) = NaN 433 // Log(NaN) = NaN 434 func Log[T constraints.Float](x T) T { 435 return T(math.Log(float64(x))) 436 } 437 438 // Log10 returns the decimal logarithm of x. The special cases are the same as for Log. 439 func Log10[T constraints.Float](x T) T { 440 return T(math.Log10(float64(x))) 441 } 442 443 // Log1p returns the natural logarithm of 1 plus its argument x. It is more accurate than Log(1 + x) when x is near 444 // zero. 445 // 446 // Special cases are: 447 // 448 // Log1p(+Inf) = +Inf 449 // Log1p(±0) = ±0 450 // Log1p(-1) = -Inf 451 // Log1p(x < -1) = NaN 452 // Log1p(NaN) = NaN 453 func Log1p[T constraints.Float](x T) T { 454 return T(math.Log1p(float64(x))) 455 } 456 457 // Log2 returns the binary logarithm of x. The special cases are the same as for Log. 458 func Log2[T constraints.Float](x T) T { 459 return T(math.Log2(float64(x))) 460 } 461 462 // Logb returns the binary exponent of x. 463 // 464 // Special cases are: 465 // 466 // Logb(±Inf) = +Inf 467 // Logb(0) = -Inf 468 // Logb(NaN) = NaN 469 func Logb[T constraints.Float](x T) T { 470 return T(math.Logb(float64(x))) 471 } 472 473 // MaxValue returns the maximum value for the type. 474 func MaxValue[T Numeric]() T { 475 var t T 476 v := reflect.Indirect(reflect.ValueOf(&t)) 477 switch reflect.TypeOf(t).Kind() { 478 case reflect.Int: 479 v.SetInt(math.MaxInt) 480 case reflect.Int8: 481 v.SetInt(math.MaxInt8) 482 case reflect.Int16: 483 v.SetInt(math.MaxInt16) 484 case reflect.Int32: 485 v.SetInt(math.MaxInt32) 486 case reflect.Int64: 487 v.SetInt(math.MaxInt64) 488 case reflect.Uint: 489 v.SetUint(math.MaxUint) 490 case reflect.Uint8: 491 v.SetUint(math.MaxUint8) 492 case reflect.Uint16: 493 v.SetUint(math.MaxUint16) 494 case reflect.Uint32: 495 v.SetUint(math.MaxUint32) 496 case reflect.Uint64: 497 v.SetUint(math.MaxUint64) 498 case reflect.Uintptr: 499 v.SetUint(math.MaxUint64) 500 case reflect.Float32: 501 v.SetFloat(math.MaxFloat32) 502 case reflect.Float64: 503 v.SetFloat(math.MaxFloat64) 504 default: 505 panic("unhandled type") 506 } 507 return t 508 } 509 510 // MinValue returns the minimum value for the type. 511 func MinValue[T Numeric]() T { 512 var t T 513 v := reflect.Indirect(reflect.ValueOf(&t)) 514 switch reflect.TypeOf(t).Kind() { 515 case reflect.Int: 516 v.SetInt(MinInt) 517 case reflect.Int8: 518 v.SetInt(MinInt8) 519 case reflect.Int16: 520 v.SetInt(MinInt16) 521 case reflect.Int32: 522 v.SetInt(MinInt32) 523 case reflect.Int64: 524 v.SetInt(MinInt64) 525 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 526 // 0 527 case reflect.Float32: 528 v.SetFloat(-MaxFloat32) 529 case reflect.Float64: 530 v.SetFloat(-MaxFloat64) 531 default: 532 panic("unhandled type") 533 } 534 return t 535 } 536 537 // SmallestPositiveNonZeroValue returns the smallest, positive, non-zero value for the type. 538 func SmallestPositiveNonZeroValue[T Numeric]() T { 539 var t T 540 v := reflect.Indirect(reflect.ValueOf(&t)) 541 switch reflect.TypeOf(t).Kind() { 542 case reflect.Float32: 543 v.SetFloat(SmallestNonzeroFloat32) 544 case reflect.Float64: 545 v.SetFloat(SmallestNonzeroFloat64) 546 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 547 v.SetInt(1) 548 default: 549 panic("unhandled type") 550 } 551 return t 552 } 553 554 // Mod returns the floating-point remainder of x/y. The magnitude of the result is less than y and its sign agrees with 555 // that of x. 556 // 557 // Special cases are: 558 // 559 // Mod(±Inf, y) = NaN 560 // Mod(NaN, y) = NaN 561 // Mod(x, 0) = NaN 562 // Mod(x, ±Inf) = x 563 // Mod(x, NaN) = NaN 564 func Mod[T constraints.Float](x, y T) T { 565 return T(math.Mod(float64(x), float64(y))) 566 } 567 568 // Modf returns integer and fractional floating-point numbers 569 // that sum to f. Both values have the same sign as f. 570 // 571 // Special cases are: 572 // 573 // Modf(±Inf) = ±Inf, NaN 574 // Modf(NaN) = NaN, NaN 575 func Modf[T constraints.Float](f T) (i, frac T) { 576 i64, f64 := math.Modf(float64(f)) 577 return T(i64), T(f64) 578 } 579 580 // NaN returns the "not-a-number" value. 581 func NaN[T constraints.Float]() T { 582 var t T 583 if reflect.TypeOf(t).Kind() == reflect.Float32 { 584 return T(math.Float32frombits(0x7FF80001)) 585 } 586 return T(math.NaN()) 587 } 588 589 // Nextafter returns the next representable float32 value after x towards y. 590 // 591 // Special cases are: 592 // 593 // Nextafter(x, x) = x 594 // Nextafter(NaN, y) = NaN 595 // Nextafter(x, NaN) = NaN 596 func Nextafter[T constraints.Float](x, y T) (r T) { 597 if reflect.TypeOf(x).Kind() == reflect.Float32 { 598 return T(math.Nextafter32(float32(x), float32(y))) 599 } 600 return T(math.Nextafter(float64(x), float64(y))) 601 } 602 603 // Pow returns x**y, the base-x exponential of y. 604 // 605 // Special cases are (in order): 606 // 607 // Pow(x, ±0) = 1 for any x 608 // Pow(1, y) = 1 for any y 609 // Pow(x, 1) = x for any x 610 // Pow(NaN, y) = NaN 611 // Pow(x, NaN) = NaN 612 // Pow(±0, y) = ±Inf for y an odd integer < 0 613 // Pow(±0, -Inf) = +Inf 614 // Pow(±0, +Inf) = +0 615 // Pow(±0, y) = +Inf for finite y < 0 and not an odd integer 616 // Pow(±0, y) = ±0 for y an odd integer > 0 617 // Pow(±0, y) = +0 for finite y > 0 and not an odd integer 618 // Pow(-1, ±Inf) = 1 619 // Pow(x, +Inf) = +Inf for |x| > 1 620 // Pow(x, -Inf) = +0 for |x| > 1 621 // Pow(x, +Inf) = +0 for |x| < 1 622 // Pow(x, -Inf) = +Inf for |x| < 1 623 // Pow(+Inf, y) = +Inf for y > 0 624 // Pow(+Inf, y) = +0 for y < 0 625 // Pow(-Inf, y) = Pow(-0, -y) 626 // Pow(x, y) = NaN for finite x < 0 and finite non-integer y 627 func Pow[T constraints.Float](x, y T) T { 628 return T(math.Pow(float64(x), float64(y))) 629 } 630 631 // Pow10 returns 10**n, the base-10 exponential of n. 632 // 633 // Special cases are: 634 // 635 // Pow10(n) = 0 for n < -323 636 // Pow10(n) = +Inf for n > 308 637 func Pow10[T constraints.Float](n int) T { 638 return T(math.Pow10(n)) 639 } 640 641 // Remainder returns the IEEE 754 floating-point remainder of x/y. 642 // 643 // Special cases are: 644 // 645 // Remainder(±Inf, y) = NaN 646 // Remainder(NaN, y) = NaN 647 // Remainder(x, 0) = NaN 648 // Remainder(x, ±Inf) = x 649 // Remainder(x, NaN) = NaN 650 func Remainder[T constraints.Float](x, y T) T { 651 return T(math.Remainder(float64(x), float64(y))) 652 } 653 654 // Round returns the nearest integer, rounding half away from zero. 655 // 656 // Special cases are: 657 // 658 // Round(±0) = ±0 659 // Round(±Inf) = ±Inf 660 // Round(NaN) = NaN 661 func Round[T constraints.Float](x T) T { 662 return T(math.Round(float64(x))) 663 } 664 665 // RoundToEven returns the nearest integer, rounding ties to even. 666 // 667 // Special cases are: 668 // 669 // RoundToEven(±0) = ±0 670 // RoundToEven(±Inf) = ±Inf 671 // RoundToEven(NaN) = NaN 672 func RoundToEven[T constraints.Float](x T) T { 673 return T(math.RoundToEven(float64(x))) 674 } 675 676 // Signbit reports whether x is negative or negative zero. 677 func Signbit[T constraints.Float](x T) bool { 678 if reflect.TypeOf(x).Kind() == reflect.Float32 { 679 return math.Float32bits(float32(x))&(1<<31) != 0 680 } 681 return math.Signbit(float64(x)) 682 } 683 684 // Sin returns the sine of the radian argument x. 685 // 686 // Special cases are: 687 // 688 // Sin(±0) = ±0 689 // Sin(±Inf) = NaN 690 // Sin(NaN) = NaN 691 func Sin[T constraints.Float](x T) T { 692 return T(math.Sin(float64(x))) 693 } 694 695 // Sincos returns Sin(x), Cos(x). 696 // 697 // Special cases are: 698 // 699 // Sincos(±0) = ±0, 1 700 // Sincos(±Inf) = NaN, NaN 701 // Sincos(NaN) = NaN, NaN 702 func Sincos[T constraints.Float](x T) (sin, cos T) { 703 s, c := math.Sincos(float64(x)) 704 return T(s), T(c) 705 } 706 707 // Sinh returns the hyperbolic sine of x. 708 // 709 // Special cases are: 710 // 711 // Sinh(±0) = ±0 712 // Sinh(±Inf) = ±Inf 713 // Sinh(NaN) = NaN 714 func Sinh[T constraints.Float](x T) T { 715 return T(math.Sinh(float64(x))) 716 } 717 718 // Sqrt returns the square root of x. 719 // 720 // Special cases are: 721 // 722 // Sqrt(+Inf) = +Inf 723 // Sqrt(±0) = ±0 724 // Sqrt(x < 0) = NaN 725 // Sqrt(NaN) = NaN 726 func Sqrt[T constraints.Float](x T) T { 727 return T(math.Sqrt(float64(x))) 728 } 729 730 // Tan returns the tangent of the radian argument x. 731 // 732 // Special cases are: 733 // 734 // Tan(±0) = ±0 735 // Tan(±Inf) = NaN 736 // Tan(NaN) = NaN 737 func Tan[T constraints.Float](x T) T { 738 return T(math.Tan(float64(x))) 739 } 740 741 // Tanh returns the hyperbolic tangent of x. 742 // 743 // Special cases are: 744 // 745 // Tanh(±0) = ±0 746 // Tanh(±Inf) = ±1 747 // Tanh(NaN) = NaN 748 func Tanh[T constraints.Float](x T) T { 749 return T(math.Tanh(float64(x))) 750 } 751 752 // Trunc returns the integer value of x. 753 // 754 // Special cases are: 755 // 756 // Trunc(±0) = ±0 757 // Trunc(±Inf) = ±Inf 758 // Trunc(NaN) = NaN 759 func Trunc[T constraints.Float](x T) T { 760 return T(math.Trunc(float64(x))) 761 } 762 763 // Y0 returns the order-zero Bessel function of the second kind. 764 // 765 // Special cases are: 766 // 767 // Y0(+Inf) = 0 768 // Y0(0) = -Inf 769 // Y0(x < 0) = NaN 770 // Y0(NaN) = NaN 771 func Y0[T constraints.Float](x T) T { 772 return T(math.Y0(float64(x))) 773 } 774 775 // Y1 returns the order-one Bessel function of the second kind. 776 // 777 // Special cases are: 778 // 779 // Y1(+Inf) = 0 780 // Y1(0) = -Inf 781 // Y1(x < 0) = NaN 782 // Y1(NaN) = NaN 783 func Y1[T constraints.Float](x T) T { 784 return T(math.Y1(float64(x))) 785 } 786 787 // Yn returns the order-n Bessel function of the second kind. 788 // 789 // Special cases are: 790 // 791 // Yn(n, +Inf) = 0 792 // Yn(n ≥ 0, 0) = -Inf 793 // Yn(n < 0, 0) = +Inf if n is odd, -Inf if n is even 794 // Yn(n, x < 0) = NaN 795 // Yn(n, NaN) = NaN 796 func Yn[T constraints.Float](n int, x T) T { 797 return T(math.Yn(n, float64(x))) 798 } 799 800 // EqualWithin returns true if a and b are within the given tolerance of each other. 801 func EqualWithin[T Numeric](a, b, tolerance T) bool { 802 return Abs(a-b) <= tolerance 803 }