github.com/iEvan-lhr/exciting-tool@v0.0.0-20230504054234-8e983f73cdd2/float.go (about) 1 package tools 2 3 import ( 4 "math" 5 ) 6 7 var float32info = floatInfo{23, 8, -127} 8 var float64info = floatInfo{52, 11, -1023} 9 var optimize = true // set to false to force slow-path conversions for testing 10 11 func genericFtoa(dst *[]byte, val float64, fmt byte, prec, bitSize int) { 12 var bits uint64 13 var flt *floatInfo 14 switch bitSize { 15 case 32: 16 bits = uint64(math.Float32bits(float32(val))) 17 flt = &float32info 18 case 64: 19 bits = math.Float64bits(val) 20 flt = &float64info 21 default: 22 panic("strconv: illegal AppendFloat/FormatFloat bitSize") 23 } 24 25 neg := bits>>(flt.expbits+flt.mantbits) != 0 26 exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1) 27 mant := bits & (uint64(1)<<flt.mantbits - 1) 28 29 switch exp { 30 case 1<<flt.expbits - 1: 31 // Inf, NaN 32 switch { 33 case mant != 0: 34 *dst = append(*dst, []byte("NaN")...) 35 case neg: 36 *dst = append(*dst, []byte("-Inf")...) 37 default: 38 *dst = append(*dst, []byte("+Inf")...) 39 } 40 return 41 case 0: 42 // denormalized 43 exp++ 44 45 default: 46 // add implicit top bit 47 mant |= uint64(1) << flt.mantbits 48 } 49 exp += flt.bias 50 51 // Pick off easy binary, hex formats. 52 if fmt == 'b' { 53 fmtB(dst, neg, mant, exp, flt) 54 return 55 } 56 if fmt == 'x' || fmt == 'X' { 57 fmtX(dst, prec, fmt, neg, mant, exp, flt) 58 return 59 } 60 61 if !optimize { 62 bigFtoa(dst, prec, fmt, neg, mant, exp, flt) 63 return 64 } 65 66 var digs decimalSlice 67 ok := false 68 // Negative precision means "only as much as needed to be exact." 69 shortest := prec < 0 70 if shortest { 71 // Use Ryu algorithm. 72 var buf [32]byte 73 digs.d = buf[:] 74 ryuFtoaShortest(&digs, mant, exp-int(flt.mantbits), flt) 75 ok = true 76 // Precision for shortest representation mode. 77 switch fmt { 78 case 'e', 'E': 79 prec = max(digs.nd-1, 0) 80 case 'f': 81 prec = max(digs.nd-digs.dp, 0) 82 case 'g', 'G': 83 prec = digs.nd 84 } 85 } else if fmt != 'f' { 86 // Fixed number of digits. 87 digits := prec 88 switch fmt { 89 case 'e', 'E': 90 digits++ 91 case 'g', 'G': 92 if prec == 0 { 93 prec = 1 94 } 95 digits = prec 96 default: 97 // Invalid mode. 98 digits = 1 99 } 100 var buf [24]byte 101 if bitSize == 32 && digits <= 9 { 102 digs.d = buf[:] 103 ryuFtoaFixed32(&digs, uint32(mant), exp-int(flt.mantbits), digits) 104 ok = true 105 } else if digits <= 18 { 106 digs.d = buf[:] 107 ryuFtoaFixed64(&digs, mant, exp-int(flt.mantbits), digits) 108 ok = true 109 } 110 } 111 if !ok { 112 bigFtoa(dst, prec, fmt, neg, mant, exp, flt) 113 return 114 } 115 formatDigits(dst, shortest, neg, digs, prec, fmt) 116 } 117 118 // bigFtoa uses multiprecision computations to format a float. 119 func bigFtoa(dst *[]byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) { 120 d := new(decimal) 121 d.Assign(mant) 122 d.Shift(exp - int(flt.mantbits)) 123 var digs decimalSlice 124 shortest := prec < 0 125 if shortest { 126 roundShortest(d, mant, exp, flt) 127 digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp} 128 // Precision for shortest representation mode. 129 switch fmt { 130 case 'e', 'E': 131 prec = digs.nd - 1 132 case 'f': 133 prec = max(digs.nd-digs.dp, 0) 134 case 'g', 'G': 135 prec = digs.nd 136 } 137 } else { 138 // Round appropriately. 139 switch fmt { 140 case 'e', 'E': 141 d.Round(prec + 1) 142 case 'f': 143 d.Round(d.dp + prec) 144 case 'g', 'G': 145 if prec == 0 { 146 prec = 1 147 } 148 d.Round(prec) 149 } 150 digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp} 151 } 152 formatDigits(dst, shortest, neg, digs, prec, fmt) 153 } 154 155 // TODO: move elsewhere? 156 type floatInfo struct { 157 mantbits uint 158 expbits uint 159 bias int 160 } 161 162 func formatDigits(dst *[]byte, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) { 163 switch fmt { 164 case 'e', 'E': 165 fmtE(dst, neg, digs, prec, fmt) 166 return 167 case 'f': 168 fmtF(dst, neg, digs, prec) 169 return 170 case 'g', 'G': 171 // trailing fractional zeros in 'e' form will be trimmed. 172 eprec := prec 173 if eprec > digs.nd && digs.nd >= digs.dp { 174 eprec = digs.nd 175 } 176 // %e is used if the exponent from the conversion 177 // is less than -4 or greater than or equal to the precision. 178 // if precision was the shortest possible, use precision 6 for this decision. 179 if shortest { 180 eprec = 6 181 } 182 exp := digs.dp - 1 183 if exp < -4 || exp >= eprec { 184 if prec > digs.nd { 185 prec = digs.nd 186 } 187 fmtE(dst, neg, digs, prec-1, fmt+'e'-'g') 188 return 189 } 190 if prec > digs.dp { 191 prec = digs.nd 192 } 193 fmtF(dst, neg, digs, max(prec-digs.dp, 0)) 194 return 195 } 196 197 // unknown format 198 *dst = append(*dst, '%', fmt) 199 } 200 201 // roundShortest rounds d (= mant * 2^exp) to the shortest number of digits 202 // that will let the original floating point value be precisely reconstructed. 203 func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { 204 // If mantissa is zero, the number is zero; stop now. 205 if mant == 0 { 206 d.nd = 0 207 return 208 } 209 210 // Compute upper and lower such that any decimal number 211 // between upper and lower (possibly inclusive) 212 // will round to the original floating point number. 213 214 // We may see at once that the number is already shortest. 215 // 216 // Suppose d is not denormal, so that 2^exp <= d < 10^dp. 217 // The closest shorter number is at least 10^(dp-nd) away. 218 // The lower/upper bounds computed below are at distance 219 // at most 2^(exp-mantbits). 220 // 221 // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), 222 // or equivalently log2(10)*(dp-nd) > exp-mantbits. 223 // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). 224 minexp := flt.bias + 1 // minimum possible exponent 225 if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { 226 // The number is already shortest. 227 return 228 } 229 230 // d = mant << (exp - mantbits) 231 // Next highest floating point number is mant+1 << exp-mantbits. 232 // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1. 233 upper := new(decimal) 234 upper.Assign(mant*2 + 1) 235 upper.Shift(exp - int(flt.mantbits) - 1) 236 237 // d = mant << (exp - mantbits) 238 // Next lowest floating point number is mant-1 << exp-mantbits, 239 // unless mant-1 drops the significant bit and exp is not the minimum exp, 240 // in which case the next lowest is mant*2-1 << exp-mantbits-1. 241 // Either way, call it mantlo << explo-mantbits. 242 // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1. 243 var mantlo uint64 244 var explo int 245 if mant > 1<<flt.mantbits || exp == minexp { 246 mantlo = mant - 1 247 explo = exp 248 } else { 249 mantlo = mant*2 - 1 250 explo = exp - 1 251 } 252 lower := new(decimal) 253 lower.Assign(mantlo*2 + 1) 254 lower.Shift(explo - int(flt.mantbits) - 1) 255 256 // The upper and lower bounds are possible outputs only if 257 // the original mantissa is even, so that IEEE round-to-even 258 // would round to the original mantissa and not the neighbors. 259 inclusive := mant%2 == 0 260 261 // As we walk the digits we want to know whether rounding up would fall 262 // within the upper bound. This is tracked by upperdelta: 263 // 264 // If upperdelta == 0, the digits of d and upper are the same so far. 265 // 266 // If upperdelta == 1, we saw a difference of 1 between d and upper on a 267 // previous digit and subsequently only 9s for d and 0s for upper. 268 // (Thus rounding up may fall outside the bound, if it is exclusive.) 269 // 270 // If upperdelta == 2, then the difference is greater than 1 271 // and we know that rounding up falls within the bound. 272 var upperdelta uint8 273 274 // Now we can figure out the minimum number of digits required. 275 // Walk along until d has distinguished itself from upper and lower. 276 for ui := 0; ; ui++ { 277 // lower, d, and upper may have the decimal points at different 278 // places. In this case upper is the longest, so we iterate from 279 // ui==0 and start li and mi at (possibly) -1. 280 mi := ui - upper.dp + d.dp 281 if mi >= d.nd { 282 break 283 } 284 li := ui - upper.dp + lower.dp 285 l := byte('0') // lower digit 286 if li >= 0 && li < lower.nd { 287 l = lower.d[li] 288 } 289 m := byte('0') // middle digit 290 if mi >= 0 { 291 m = d.d[mi] 292 } 293 u := byte('0') // upper digit 294 if ui < upper.nd { 295 u = upper.d[ui] 296 } 297 298 // Okay to round down (truncate) if lower has a different digit 299 // or if lower is inclusive and is exactly the result of rounding 300 // down (i.e., and we have reached the final digit of lower). 301 okdown := l != m || inclusive && li+1 == lower.nd 302 303 switch { 304 case upperdelta == 0 && m+1 < u: 305 // Example: 306 // m = 12345xxx 307 // u = 12347xxx 308 upperdelta = 2 309 case upperdelta == 0 && m != u: 310 // Example: 311 // m = 12345xxx 312 // u = 12346xxx 313 upperdelta = 1 314 case upperdelta == 1 && (m != '9' || u != '0'): 315 // Example: 316 // m = 1234598x 317 // u = 1234600x 318 upperdelta = 2 319 } 320 // Okay to round up if upper has a different digit and either upper 321 // is inclusive or upper is bigger than the result of rounding up. 322 okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd) 323 324 // If it's okay to do either, then round to the nearest one. 325 // If it's okay to do only one, do it. 326 switch { 327 case okdown && okup: 328 d.Round(mi + 1) 329 return 330 case okdown: 331 d.RoundDown(mi + 1) 332 return 333 case okup: 334 d.RoundUp(mi + 1) 335 return 336 } 337 } 338 } 339 340 type decimalSlice struct { 341 d []byte 342 nd, dp int 343 neg bool 344 } 345 346 // %e: -d.ddddde±dd 347 func fmtE(dst *[]byte, neg bool, d decimalSlice, prec int, fmt byte) { 348 // sign 349 if neg { 350 *dst = append(*dst, '-') 351 } 352 353 // first digit 354 ch := byte('0') 355 if d.nd != 0 { 356 ch = d.d[0] 357 } 358 *dst = append(*dst, ch) 359 360 // .moredigits 361 if prec > 0 { 362 *dst = append(*dst, '.') 363 i := 1 364 m := min(d.nd, prec+1) 365 if i < m { 366 *dst = append(*dst, d.d[i:m]...) 367 i = m 368 } 369 for ; i <= prec; i++ { 370 *dst = append(*dst, '0') 371 } 372 } 373 374 // e± 375 *dst = append(*dst, fmt) 376 exp := d.dp - 1 377 if d.nd == 0 { // special case: 0 has exponent 0 378 exp = 0 379 } 380 if exp < 0 { 381 ch = '-' 382 exp = -exp 383 } else { 384 ch = '+' 385 } 386 *dst = append(*dst, ch) 387 388 // dd or ddd 389 switch { 390 case exp < 10: 391 *dst = append(*dst, '0', byte(exp)+'0') 392 case exp < 100: 393 *dst = append(*dst, byte(exp/10)+'0', byte(exp%10)+'0') 394 default: 395 *dst = append(*dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0') 396 } 397 398 } 399 400 // %f: -ddddddd.ddddd 401 func fmtF(dst *[]byte, neg bool, d decimalSlice, prec int) { 402 // sign 403 if neg { 404 *dst = append(*dst, '-') 405 } 406 407 // integer, padded with zeros as needed. 408 if d.dp > 0 { 409 m := min(d.nd, d.dp) 410 *dst = append(*dst, d.d[:m]...) 411 for ; m < d.dp; m++ { 412 *dst = append(*dst, '0') 413 } 414 } else { 415 *dst = append(*dst, '0') 416 } 417 418 // fraction 419 if prec > 0 { 420 *dst = append(*dst, '.') 421 for i := 0; i < prec; i++ { 422 ch := byte('0') 423 if j := d.dp + i; 0 <= j && j < d.nd { 424 ch = d.d[j] 425 } 426 *dst = append(*dst, ch) 427 } 428 } 429 430 } 431 432 // %b: -ddddddddp±ddd 433 func fmtB(dst *[]byte, neg bool, mant uint64, exp int, flt *floatInfo) { 434 // sign 435 if neg { 436 *dst = append(*dst, '-') 437 } 438 439 // mantissa 440 formatBits(dst, mant, 10, false) 441 442 // p 443 *dst = append(*dst, 'p') 444 445 // ±exponent 446 exp -= int(flt.mantbits) 447 if exp >= 0 { 448 *dst = append(*dst, '+') 449 } 450 formatBits(dst, uint64(exp), 10, exp < 0) 451 } 452 453 // %x: -0x1.yyyyyyyyp±ddd or -0x0p+0. (y is hex digit, d is decimal digit) 454 func fmtX(dst *[]byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) { 455 if mant == 0 { 456 exp = 0 457 } 458 459 // Shift digits so leading 1 (if any) is at bit 1<<60. 460 mant <<= 60 - flt.mantbits 461 for mant != 0 && mant&(1<<60) == 0 { 462 mant <<= 1 463 exp-- 464 } 465 466 // Round if requested. 467 if prec >= 0 && prec < 15 { 468 shift := uint(prec * 4) 469 extra := (mant << shift) & (1<<60 - 1) 470 mant >>= 60 - shift 471 if extra|(mant&1) > 1<<59 { 472 mant++ 473 } 474 mant <<= 60 - shift 475 if mant&(1<<61) != 0 { 476 // Wrapped around. 477 mant >>= 1 478 exp++ 479 } 480 } 481 482 hex := lowerhex 483 if fmt == 'X' { 484 hex = upperhex 485 } 486 487 // sign, 0x, leading digit 488 if neg { 489 *dst = append(*dst, '-') 490 } 491 *dst = append(*dst, '0', fmt, '0'+byte((mant>>60)&1)) 492 493 // .fraction 494 mant <<= 4 // remove leading 0 or 1 495 if prec < 0 && mant != 0 { 496 *dst = append(*dst, '.') 497 for mant != 0 { 498 *dst = append(*dst, hex[(mant>>60)&15]) 499 mant <<= 4 500 } 501 } else if prec > 0 { 502 *dst = append(*dst, '.') 503 for i := 0; i < prec; i++ { 504 *dst = append(*dst, hex[(mant>>60)&15]) 505 mant <<= 4 506 } 507 } 508 509 // p± 510 ch := byte('P') 511 if fmt == lower(fmt) { 512 ch = 'p' 513 } 514 *dst = append(*dst, ch) 515 if exp < 0 { 516 ch = '-' 517 exp = -exp 518 } else { 519 ch = '+' 520 } 521 *dst = append(*dst, ch) 522 523 // dd or ddd or dddd 524 switch { 525 case exp < 100: 526 *dst = append(*dst, byte(exp/10)+'0', byte(exp%10)+'0') 527 case exp < 1000: 528 *dst = append(*dst, byte(exp/100)+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') 529 default: 530 *dst = append(*dst, byte(exp/1000)+'0', byte(exp/100)%10+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') 531 } 532 } 533 534 func min(a, b int) int { 535 if a < b { 536 return a 537 } 538 return b 539 } 540 541 func max(a, b int) int { 542 if a > b { 543 return a 544 } 545 return b 546 } 547 548 const ( 549 lowerhex = "0123456789abcdef" 550 upperhex = "0123456789ABCDEF" 551 ) 552 553 func lower(c byte) byte { 554 return c | ('x' - 'X') 555 }