github.com/seeker-insurance/kit@v0.0.13/imath/imath.go (about) 1 //Package imath contains tools for signed integer math. It largely corresponds with go's built in `math` library for float64s 2 package imath 3 4 import "math/rand" 5 import "github.com/seeker-insurance/kit/imath/operator" 6 7 const ( 8 is64bit = uint64(^uint(0)) == ^uint64(0) 9 ) 10 11 //Sum returns the sum of it's arguments. Sum() is 0 12 func Sum(a ...int) int { 13 return Reduce(operator.Add, 0, a...) 14 } 15 16 //Range returns the slice of integers in [start, stop) obtained by repeatedly adding step to start. 17 func Range(start, stop, step int) []int { 18 if (start > stop && step > 0) || 19 (start < stop && step < 0) || step == 0 { 20 return nil 21 } 22 a := make([]int, 0, Abs(start-stop)/Abs(step)) 23 if step < 0 { 24 for n := start; n > stop; n += step { 25 a = append(a, n) 26 } 27 return a 28 } 29 30 for n := start; n < stop; n += step { 31 a = append(a, n) 32 } 33 34 return a 35 } 36 37 //Product returns the product of it's arguments. Product() is 1. 38 func Product(a ...int) int { 39 return Reduce(operator.Mul, 1, a...) 40 } 41 42 //Max returns it's largest integer argument. 43 func Max(n int, a ...int) int { 44 return Reduce(Max2, n, a...) 45 } 46 47 //Max2 returns the largest of two integer arguments. 48 func Max2(a, b int) int { 49 if a > b { 50 return a 51 } 52 return b 53 } 54 55 //Min returns it's smallest integer argument. 56 func Min(n int, a ...int) int { 57 return Reduce(Min2, n, a...) 58 } 59 60 //Min2 returns the smallest of two integer arguments. 61 func Min2(a, b int) int { 62 if a < b { 63 return a 64 } 65 return b 66 } 67 68 //Abs returns the absolute value of n 69 func Abs(n int) int { 70 if n >= 0 { 71 return n 72 } 73 return -n 74 } 75 76 //RandSign returns -1 or 1 at random, using the default Source of math/rand. This is NOT crypto-safe, at all. 77 func RandSign() int { 78 if rand.Intn(2) > 0 { 79 return 1 80 } 81 return -1 82 } 83 84 //Clamp takes an int n, returns low if n < low, high if n > high, and n otherwise. 85 func Clamp(n, low, high int) int { 86 if n < low { 87 return low 88 } else if n > high { 89 return high 90 } 91 return n 92 } 93 94 //Sign returns the sign of the operand. The sign of zero is zero. 95 func Sign(n int) int { 96 switch { 97 case n < 0: 98 return -1 99 100 case n == 0: 101 return 0 102 103 default: 104 return 1 105 } 106 } 107 108 //Pow is an efficent implementation of exponentiation by squaring. 109 func Pow(base, exp int) int { 110 result := 1 111 for ; exp > 0; exp >>= 1 { 112 if exp&1 > 0 { 113 result *= base 114 } 115 base *= base 116 } 117 return result 118 } 119 120 func naivePow(base, exp int) int { 121 result := 1 122 for ; exp > 0; exp-- { 123 result *= base 124 } 125 return result 126 } 127 128 //TODO - test is broken 129 /* 130 func PowMod(base, exp, mod int) int { 131 base %= mod 132 exp %= mod 133 134 result := 1 135 for ; exp > 0; exp >>= 1 { 136 if exp&1 > 0 { 137 result = result * base % mod 138 } 139 base = base * base % mod 140 141 } 142 return result 143 } 144 145 146 func PowModSafe(base, exp, mod int) (int, bool) { 147 base %= mod 148 if exp < 0 { 149 return 0, false // negative exponent is unclear 150 } 151 exp %= mod 152 153 if is64bit && (math.MaxInt64/base) < base { 154 return 0, false 155 } else if math.MaxInt32/base < base { 156 return 0, false 157 } 158 // cannot exponentiate base because it will overflow int 159 result := 1 160 for ; exp > 0; exp >>= 1 { 161 if exp&1 > 0 { 162 result = result * base % mod 163 } 164 base = base * base % mod 165 } 166 return result, true 167 } 168 */