github.com/prysmaticlabs/prysm@v1.4.4/shared/mathutil/math_helper.go (about)

     1  // Package mathutil includes important helpers for Ethereum such as fast integer square roots.
     2  package mathutil
     3  
     4  import (
     5  	"errors"
     6  	"math"
     7  	"math/bits"
     8  
     9  	"github.com/thomaso-mirodin/intmath/u64"
    10  )
    11  
    12  // Common square root values.
    13  var squareRootTable = map[uint64]uint64{
    14  	4:       2,
    15  	16:      4,
    16  	64:      8,
    17  	256:     16,
    18  	1024:    32,
    19  	4096:    64,
    20  	16384:   128,
    21  	65536:   256,
    22  	262144:  512,
    23  	1048576: 1024,
    24  	4194304: 2048,
    25  }
    26  
    27  // IntegerSquareRoot defines a function that returns the
    28  // largest possible integer root of a number using go's standard library.
    29  func IntegerSquareRoot(n uint64) uint64 {
    30  	if v, ok := squareRootTable[n]; ok {
    31  		return v
    32  	}
    33  
    34  	// Golang floating point precision may be lost above 52 bits, so we use a
    35  	// non floating point method. u64.Sqrt is about x2.5 slower than math.Sqrt.
    36  	if n >= 1<<52 {
    37  		return u64.Sqrt(n)
    38  	}
    39  
    40  	return uint64(math.Sqrt(float64(n)))
    41  }
    42  
    43  // CeilDiv8 divides the input number by 8
    44  // and takes the ceiling of that number.
    45  func CeilDiv8(n int) int {
    46  	ret := n / 8
    47  	if n%8 > 0 {
    48  		ret++
    49  	}
    50  
    51  	return ret
    52  }
    53  
    54  // IsPowerOf2 returns true if n is an
    55  // exact power of two. False otherwise.
    56  func IsPowerOf2(n uint64) bool {
    57  	return n != 0 && (n&(n-1)) == 0
    58  }
    59  
    60  // PowerOf2 returns an integer that is the provided
    61  // exponent of 2. Can only return powers of 2 till 63,
    62  // after that it overflows
    63  func PowerOf2(n uint64) uint64 {
    64  	if n >= 64 {
    65  		panic("integer overflow")
    66  	}
    67  	return 1 << n
    68  }
    69  
    70  // Max returns the larger integer of the two
    71  // given ones.This is used over the Max function
    72  // in the standard math library because that max function
    73  // has to check for some special floating point cases
    74  // making it slower by a magnitude of 10.
    75  func Max(a, b uint64) uint64 {
    76  	if a > b {
    77  		return a
    78  	}
    79  	return b
    80  }
    81  
    82  // Min returns the smaller integer of the two
    83  // given ones. This is used over the Min function
    84  // in the standard math library because that min function
    85  // has to check for some special floating point cases
    86  // making it slower by a magnitude of 10.
    87  func Min(a, b uint64) uint64 {
    88  	if a < b {
    89  		return a
    90  	}
    91  	return b
    92  }
    93  
    94  // Mul64 multiples 2 64-bit unsigned integers and checks if they
    95  // lead to an overflow. If they do not, it returns the result
    96  // without an error.
    97  func Mul64(a, b uint64) (uint64, error) {
    98  	overflows, val := bits.Mul64(a, b)
    99  	if overflows > 0 {
   100  		return 0, errors.New("multiplication overflows")
   101  	}
   102  	return val, nil
   103  }
   104  
   105  // Add64 adds 2 64-bit unsigned integers and checks if they
   106  // lead to an overflow. If they do not, it returns the result
   107  // without an error.
   108  func Add64(a, b uint64) (uint64, error) {
   109  	res, carry := bits.Add64(a, b, 0 /* carry */)
   110  	if carry > 0 {
   111  		return 0, errors.New("addition overflows")
   112  	}
   113  	return res, nil
   114  }