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 }