github.com/Aoi-hosizora/ahlib@v1.5.1-0.20230404072829-241b93cf91c7/xnumber/xnumber.go (about)

     1  package xnumber
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	_ "unsafe"
     7  )
     8  
     9  // ================
    10  // accuracy related
    11  // ================
    12  
    13  // Accuracy represents an accuracy with some compare methods in epsilon accuracy.
    14  type Accuracy func() float64
    15  
    16  // NewAccuracy creates an Accuracy, using eps as its accuracy.
    17  func NewAccuracy(eps float64) Accuracy {
    18  	return func() float64 {
    19  		return eps
    20  	}
    21  }
    22  
    23  // Equal checks equality (eq) between two float64.
    24  func (eps Accuracy) Equal(a, b float64) bool {
    25  	return math.Abs(a-b) < eps()
    26  }
    27  
    28  // NotEqual checks not-equality (ne) between two float64.
    29  func (eps Accuracy) NotEqual(a, b float64) bool {
    30  	return math.Abs(a-b) >= eps()
    31  }
    32  
    33  // Greater checks whether float `a` is greater than (gt) `b`.
    34  func (eps Accuracy) Greater(a, b float64) bool {
    35  	return math.Max(a, b) == a && math.Abs(a-b) > eps()
    36  }
    37  
    38  // Less checks whether float `a` is less than (lt) `b`.
    39  func (eps Accuracy) Less(a, b float64) bool {
    40  	return math.Max(a, b) == b && math.Abs(a-b) > eps()
    41  }
    42  
    43  // GreaterOrEqual checks whether float `a` is greater than or equals to (gte) `b`.
    44  func (eps Accuracy) GreaterOrEqual(a, b float64) bool {
    45  	return math.Max(a, b) == a || math.Abs(a-b) < eps()
    46  }
    47  
    48  // LessOrEqual checks whether float `a` is less than or equals to (lte) `b`.
    49  func (eps Accuracy) LessOrEqual(a, b float64) bool {
    50  	return math.Max(a, b) == b || math.Abs(a-b) < eps()
    51  }
    52  
    53  // _acc is a default Accuracy with 1e-3 eps.
    54  var _acc = NewAccuracy(1e-3)
    55  
    56  // EqualInAccuracy checks equality (eq) between two float64 with 1e-3 accuracy.
    57  func EqualInAccuracy(a, b float64) bool {
    58  	return _acc.Equal(a, b)
    59  }
    60  
    61  // NotEqualInAccuracy checks not-equality (ne) between two float64 with 1e-3 accuracy.
    62  func NotEqualInAccuracy(a, b float64) bool {
    63  	return _acc.NotEqual(a, b)
    64  }
    65  
    66  // GreaterInAccuracy checks whether float `a` is greater than (gt) `b` with 1e-3 accuracy.
    67  func GreaterInAccuracy(a, b float64) bool {
    68  	return _acc.Greater(a, b)
    69  }
    70  
    71  // LessInAccuracy checks whether float `a` is less than (lt) `b` with 1e-3 accuracy.
    72  func LessInAccuracy(a, b float64) bool {
    73  	return _acc.Less(a, b)
    74  }
    75  
    76  // GreaterOrEqualInAccuracy checks whether float `a` is greater than or equals to (gte) `b` with 1e-3 accuracy.
    77  func GreaterOrEqualInAccuracy(a, b float64) bool {
    78  	return _acc.GreaterOrEqual(a, b)
    79  }
    80  
    81  // LessOrEqualInAccuracy checks whether float `a` is less than or equals to (lte) `b` with 1e-3 accuracy.
    82  func LessOrEqualInAccuracy(a, b float64) bool {
    83  	return _acc.LessOrEqual(a, b)
    84  }
    85  
    86  // ==============
    87  // mass functions
    88  // ==============
    89  
    90  // FormatByteSize formats a byte size to string (using %.2f), supports `B` `KB` `MB` `GB` `TB` units.
    91  func FormatByteSize(bytes float64) string {
    92  	divisor := float64(1024)
    93  	minus := false
    94  	switch {
    95  	case bytes == 0:
    96  		return "0B"
    97  	case bytes < 0:
    98  		bytes = -bytes
    99  		minus = true
   100  	}
   101  	ret := func(s string) string {
   102  		if minus {
   103  			return "-" + s
   104  		}
   105  		return s
   106  	}
   107  
   108  	// [1B, 1024B)
   109  	b := bytes
   110  	if LessInAccuracy(b, divisor) {
   111  		return ret(fmt.Sprintf("%dB", int(b)))
   112  	}
   113  	// [1M, 1024K)
   114  	kb := b / divisor
   115  	if LessInAccuracy(kb, divisor) {
   116  		return ret(fmt.Sprintf("%.2fKB", kb))
   117  	}
   118  	// [1M, 1024M)
   119  	mb := kb / divisor
   120  	if LessInAccuracy(mb, divisor) {
   121  		return ret(fmt.Sprintf("%.2fMB", mb))
   122  	}
   123  	// [1G, 1024G)
   124  	gb := mb / divisor
   125  	if LessInAccuracy(gb, divisor) {
   126  		return ret(fmt.Sprintf("%.2fGB", gb))
   127  	}
   128  	// [1T, \inf)
   129  	tb := gb / divisor
   130  	return ret(fmt.Sprintf("%.2fTB", tb))
   131  }
   132  
   133  // Bool returns 1 if given value is true, otherwise returns 0.
   134  func Bool(b bool) int {
   135  	if b {
   136  		return 1
   137  	}
   138  	return 0
   139  }
   140  
   141  // intBitLength represents the int or uint bit-length, usually it equals to 32 or 64.
   142  var intBitLength = 32 << (^uint(0) >> 63) // <<< it should be `const` but use `var` for testing coverage
   143  
   144  // IntBitLength returns the int or uint bit-length, usually it equals to 32 or 64.
   145  func IntBitLength() int {
   146  	return intBitLength
   147  }
   148  
   149  //go:linkname FastrandUint32 runtime.fastrand
   150  
   151  // FastrandUint32 returns a random uint32 value using runtime.fastrand.
   152  func FastrandUint32() uint32
   153  
   154  // FastrandUint64 returns a random uint64 value using runtime.fastrand.
   155  func FastrandUint64() uint64 {
   156  	return (uint64(FastrandUint32()) << 32) | uint64(FastrandUint32())
   157  }
   158  
   159  // FastrandInt32 returns a random int32 value using runtime.fastrand.
   160  func FastrandInt32() int32 {
   161  	return int32(FastrandUint32() & (1<<31 - 1))
   162  }
   163  
   164  // FastrandInt64 returns a random int64 value using runtime.fastrand.
   165  func FastrandInt64() int64 {
   166  	return int64(FastrandUint64() & (1<<63 - 1))
   167  }
   168  
   169  // IsPowerOfTwo checks whether given integer is power of two.
   170  func IsPowerOfTwo(x int) bool {
   171  	return (x & (-x)) == x
   172  }
   173  
   174  // =====================
   175  // numeric range related
   176  // =====================
   177  
   178  const (
   179  	MinInt8   = int8(-128)                  // -1 << 7,  see math.MinInt8.
   180  	MinInt16  = int16(-32768)               // -1 << 15, see math.MinInt16.
   181  	MinInt32  = int32(-2147483648)          // -1 << 31, see math.MinInt32.
   182  	MinInt64  = int64(-9223372036854775808) // -1 << 63, see math.MinInt64.
   183  	MinUint8  = uint8(0)                    // 0.
   184  	MinUint16 = uint16(0)                   // 0.
   185  	MinUint32 = uint32(0)                   // 0.
   186  	MinUint64 = uint64(0)                   // 0.
   187  
   188  	MaxInt8   = int8(127)                    // 1 << 7  - 1, see math.MaxInt8.
   189  	MaxInt16  = int16(32767)                 // 1 << 15 - 1, see math.MaxInt16.
   190  	MaxInt32  = int32(2147483647)            // 1 << 31 - 1, see math.MaxInt32.
   191  	MaxInt64  = int64(9223372036854775807)   // 1 << 63 - 1, see math.MaxInt64.
   192  	MaxUint8  = uint8(255)                   // 1 << 8  - 1, see math.MaxUint8.
   193  	MaxUint16 = uint16(65535)                // 1 << 16 - 1, see math.MaxUint16.
   194  	MaxUint32 = uint32(4294967295)           // 1 << 32 - 1, see math.MaxUint32.
   195  	MaxUint64 = uint64(18446744073709551615) // 1 << 64 - 1, see math.MaxUint64.
   196  
   197  	MaxFloat32             = float32(math.MaxFloat32)             // 2**127 * (2**24 - 1) / 2**23, see math.MaxFloat32.
   198  	SmallestNonzeroFloat32 = float32(math.SmallestNonzeroFloat32) // 1 / 2**(127 - 1 + 23), see math.SmallestNonzeroFloat32.
   199  	MaxFloat64             = float64(math.MaxFloat64)             // 2**1023 * (2**53 - 1) / 2**52, see math.MaxFloat64.
   200  	SmallestNonzeroFloat64 = float64(math.SmallestNonzeroFloat64) // 1 / 2**(1023 - 1 + 52), see math.SmallestNonzeroFloat64.
   201  )
   202  
   203  // OverflowWhenAddInt8 checks whether overflow will happen when add int8 addend to int8 augend.
   204  func OverflowWhenAddInt8(augend, addend int8) bool {
   205  	return (augend > 0 && addend > 0 && augend > MaxInt8-addend) || (augend < 0 && addend < 0 && augend < MinInt8-addend)
   206  }
   207  
   208  // OverflowWhenAddInt16 checks whether overflow will happen when add int16 addend to int16 augend.
   209  func OverflowWhenAddInt16(augend, addend int16) bool {
   210  	return (augend > 0 && addend > 0 && augend > MaxInt16-addend) || (augend < 0 && addend < 0 && augend < MinInt16-addend)
   211  }
   212  
   213  // OverflowWhenAddInt32 checks whether overflow will happen when add int32 addend to int32 augend.
   214  func OverflowWhenAddInt32(augend, addend int32) bool {
   215  	return (augend > 0 && addend > 0 && augend > MaxInt32-addend) || (augend < 0 && addend < 0 && augend < MinInt32-addend)
   216  }
   217  
   218  // OverflowWhenAddInt64 checks whether overflow will happen when add int64 addend to int64 augend.
   219  func OverflowWhenAddInt64(augend, addend int64) bool {
   220  	return (augend > 0 && addend > 0 && augend > MaxInt64-addend) || (augend < 0 && addend < 0 && augend < MinInt64-addend)
   221  }
   222  
   223  // OverflowWhenAddInt checks whether overflow will happen when add int addend to int augend.
   224  func OverflowWhenAddInt(augend, addend int) bool {
   225  	if intBitLength <= 32 {
   226  		return OverflowWhenAddInt32(int32(augend), int32(addend))
   227  	}
   228  	return OverflowWhenAddInt64(int64(augend), int64(addend))
   229  }
   230  
   231  // OverflowWhenSubtractInt8 checks whether overflow will happen when subtract int8 subtrahend from int8 minuend.
   232  func OverflowWhenSubtractInt8(minuend, subtrahend int8) bool {
   233  	return OverflowWhenAddInt8(minuend, -subtrahend)
   234  }
   235  
   236  // OverflowWhenSubtractInt16 checks whether overflow will happen when subtract int16 subtrahend from int16 minuend.
   237  func OverflowWhenSubtractInt16(minuend, subtrahend int16) bool {
   238  	return OverflowWhenAddInt16(minuend, -subtrahend)
   239  }
   240  
   241  // OverflowWhenSubtractInt32 checks whether overflow will happen when subtract int32 subtrahend from int32 minuend.
   242  func OverflowWhenSubtractInt32(minuend, subtrahend int32) bool {
   243  	return OverflowWhenAddInt32(minuend, -subtrahend)
   244  }
   245  
   246  // OverflowWhenSubtractInt64 checks whether overflow will happen when subtract int64 subtrahend from int64 minuend.
   247  func OverflowWhenSubtractInt64(minuend, subtrahend int64) bool {
   248  	return OverflowWhenAddInt64(minuend, -subtrahend)
   249  }
   250  
   251  // OverflowWhenSubtractInt checks whether overflow will happen when subtract int subtrahend from int minuend.
   252  func OverflowWhenSubtractInt(minuend, subtrahend int) bool {
   253  	if intBitLength <= 32 {
   254  		return OverflowWhenSubtractInt32(int32(minuend), int32(subtrahend))
   255  	}
   256  	return OverflowWhenSubtractInt64(int64(minuend), int64(subtrahend))
   257  }
   258  
   259  // OverflowWhenAddUint8 checks whether overflow will happen when add uint8 addend to uint8 augend.
   260  func OverflowWhenAddUint8(augend, addend uint8) bool {
   261  	return augend > 0 && addend > 0 && augend > MaxUint8-addend
   262  }
   263  
   264  // OverflowWhenAddUint16 checks whether overflow will happen when add uint16 addend to uint16 augend.
   265  func OverflowWhenAddUint16(augend, addend uint16) bool {
   266  	return augend > 0 && addend > 0 && augend > MaxUint16-addend
   267  }
   268  
   269  // OverflowWhenAddUint32 checks whether overflow will happen when add uint32 addend to uint32 augend.
   270  func OverflowWhenAddUint32(augend, addend uint32) bool {
   271  	return augend > 0 && addend > 0 && augend > MaxUint32-addend
   272  }
   273  
   274  // OverflowWhenAddUint64 checks whether overflow will happen when add uint64 addend to uint64 augend.
   275  func OverflowWhenAddUint64(augend, addend uint64) bool {
   276  	return augend > 0 && addend > 0 && augend > MaxUint64-addend
   277  }
   278  
   279  // OverflowWhenAddUint checks whether overflow will happen when add uint addend to uint augend.
   280  func OverflowWhenAddUint(augend, addend uint) bool {
   281  	if intBitLength <= 32 {
   282  		return OverflowWhenAddUint32(uint32(augend), uint32(addend))
   283  	}
   284  	return OverflowWhenAddUint64(uint64(augend), uint64(addend))
   285  }
   286  
   287  // OverflowWhenSubtractUint8 checks whether overflow will happen when subtract uint8 subtrahend from uint8 minuend.
   288  func OverflowWhenSubtractUint8(minuend, subtrahend uint8) bool {
   289  	return minuend > 0 && subtrahend > 0 && minuend < subtrahend
   290  }
   291  
   292  // OverflowWhenSubtractUint16 checks whether overflow will happen when subtract uint16 subtrahend from uint16 minuend.
   293  func OverflowWhenSubtractUint16(minuend, subtrahend uint16) bool {
   294  	return minuend > 0 && subtrahend > 0 && minuend < subtrahend
   295  }
   296  
   297  // OverflowWhenSubtractUint32 checks whether overflow will happen when subtract uint32 subtrahend from uint32 minuend.
   298  func OverflowWhenSubtractUint32(minuend, subtrahend uint32) bool {
   299  	return minuend > 0 && subtrahend > 0 && minuend < subtrahend
   300  }
   301  
   302  // OverflowWhenSubtractUint64 checks whether overflow will happen when subtract uint64 subtrahend from uint64 minuend.
   303  func OverflowWhenSubtractUint64(minuend, subtrahend uint64) bool {
   304  	return minuend > 0 && subtrahend > 0 && minuend < subtrahend
   305  }
   306  
   307  // OverflowWhenSubtractUint checks whether overflow will happen when subtract uint subtrahend from uint minuend.
   308  func OverflowWhenSubtractUint(minuend, subtrahend uint) bool {
   309  	if intBitLength <= 32 {
   310  		return OverflowWhenSubtractUint32(uint32(minuend), uint32(subtrahend))
   311  	}
   312  	return OverflowWhenSubtractUint64(uint64(minuend), uint64(subtrahend))
   313  }