Source file src/internal/strconv/math.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package strconv
     6  
     7  import "math/bits"
     8  
     9  // A uint128 is a 128-bit uint.
    10  // The fields are exported to make them visible to package strconv_test.
    11  type uint128 struct {
    12  	Hi uint64
    13  	Lo uint64
    14  }
    15  
    16  // umul128 returns the 128-bit product x*y.
    17  func umul128(x, y uint64) uint128 {
    18  	hi, lo := bits.Mul64(x, y)
    19  	return uint128{hi, lo}
    20  }
    21  
    22  // umul192 returns the 192-bit product x*y in three uint64s.
    23  func umul192(x uint64, y uint128) (hi, mid, lo uint64) {
    24  	mid1, lo := bits.Mul64(x, y.Lo)
    25  	hi, mid2 := bits.Mul64(x, y.Hi)
    26  	mid, carry := bits.Add64(mid1, mid2, 0)
    27  	return hi + carry, mid, lo
    28  }
    29  
    30  // pow10 returns the 128-bit mantissa and binary exponent of 10**e.
    31  // That is, 10^e = mant/2^128 * 2**exp.
    32  // If e is out of range, pow10 returns ok=false.
    33  func pow10(e int) (mant uint128, exp int, ok bool) {
    34  	if e < pow10Min || e > pow10Max {
    35  		return
    36  	}
    37  	return pow10Tab[e-pow10Min], 1 + mulLog2_10(e), true
    38  }
    39  
    40  // mulLog10_2 returns math.Floor(x * log(2)/log(10)) for an integer x in
    41  // the range -1600 <= x && x <= +1600.
    42  //
    43  // The range restriction lets us work in faster integer arithmetic instead of
    44  // slower floating point arithmetic. Correctness is verified by unit tests.
    45  func mulLog10_2(x int) int {
    46  	// log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18
    47  	return (x * 78913) >> 18
    48  }
    49  
    50  // mulLog2_10 returns math.Floor(x * log(10)/log(2)) for an integer x in
    51  // the range -500 <= x && x <= +500.
    52  //
    53  // The range restriction lets us work in faster integer arithmetic instead of
    54  // slower floating point arithmetic. Correctness is verified by unit tests.
    55  func mulLog2_10(x int) int {
    56  	// log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15
    57  	return (x * 108853) >> 15
    58  }
    59  

View as plain text