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  }