github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/natives/src/math/math.go (about) 1 //go:build js 2 // +build js 3 4 package math 5 6 import ( 7 "github.com/gopherjs/gopherjs/js" 8 ) 9 10 var ( 11 math = js.Global.Get("Math") 12 _zero float64 = 0 13 posInf = 1 / _zero 14 negInf = -1 / _zero 15 ) 16 17 // Usually, NaN can be obtained in JavaScript with `0 / 0` operation. However, 18 // in V8, `0 / _zero` yields a bitwise-different value of NaN compared to the 19 // default NaN or `0 / 0`. Unfortunately, Go compiler forbids division by zero, 20 // so we have to get this value from prelude. 21 var nan = js.Global.Get("$NaN").Float() 22 23 func Acos(x float64) float64 { 24 return math.Call("acos", x).Float() 25 } 26 27 func Acosh(x float64) float64 { 28 return math.Call("acosh", x).Float() 29 } 30 31 func Asin(x float64) float64 { 32 return math.Call("asin", x).Float() 33 } 34 35 func Asinh(x float64) float64 { 36 return math.Call("asinh", x).Float() 37 } 38 39 func Atan(x float64) float64 { 40 return math.Call("atan", x).Float() 41 } 42 43 func Atanh(x float64) float64 { 44 return math.Call("atanh", x).Float() 45 } 46 47 func Atan2(y, x float64) float64 { 48 return math.Call("atan2", y, x).Float() 49 } 50 51 func Cbrt(x float64) float64 { 52 return math.Call("cbrt", x).Float() 53 } 54 55 func Ceil(x float64) float64 { 56 return math.Call("ceil", x).Float() 57 } 58 59 func Copysign(x, y float64) float64 { 60 if (x < 0 || 1/x == negInf) != (y < 0 || 1/y == negInf) { 61 return -x 62 } 63 return x 64 } 65 66 func Cos(x float64) float64 { 67 return math.Call("cos", x).Float() 68 } 69 70 func Cosh(x float64) float64 { 71 return math.Call("cosh", x).Float() 72 } 73 74 func Erf(x float64) float64 { 75 return erf(x) 76 } 77 78 func Erfc(x float64) float64 { 79 return erfc(x) 80 } 81 82 func Exp(x float64) float64 { 83 return math.Call("exp", x).Float() 84 } 85 86 func Exp2(x float64) float64 { 87 return math.Call("pow", 2, x).Float() 88 } 89 90 func Expm1(x float64) float64 { 91 return expm1(x) 92 } 93 94 func Floor(x float64) float64 { 95 return math.Call("floor", x).Float() 96 } 97 98 func Frexp(f float64) (frac float64, exp int) { 99 return frexp(f) 100 } 101 102 func Hypot(p, q float64) float64 { 103 return hypot(p, q) 104 } 105 106 func Inf(sign int) float64 { 107 switch { 108 case sign >= 0: 109 return posInf 110 default: 111 return negInf 112 } 113 } 114 115 func IsInf(f float64, sign int) bool { 116 if f == posInf { 117 return sign >= 0 118 } 119 if f == negInf { 120 return sign <= 0 121 } 122 return false 123 } 124 125 func IsNaN(f float64) (is bool) { 126 return f != f 127 } 128 129 func Ldexp(frac float64, exp int) float64 { 130 if -1024 < exp && exp < 1024 { // Use Math.pow for small exp values where it's viable. For performance. 131 if frac == 0 { 132 return frac 133 } 134 return frac * math.Call("pow", 2, exp).Float() 135 } 136 return ldexp(frac, exp) 137 } 138 139 func Log(x float64) float64 { 140 if x != x { // workaround for optimizer bug in V8, remove at some point 141 return nan 142 } 143 return math.Call("log", x).Float() 144 } 145 146 func Log10(x float64) float64 { 147 return log10(x) 148 } 149 150 func Log1p(x float64) float64 { 151 return log1p(x) 152 } 153 154 func Log2(x float64) float64 { 155 return log2(x) 156 } 157 158 func Max(x, y float64) float64 { 159 return max(x, y) 160 } 161 162 func Min(x, y float64) float64 { 163 return min(x, y) 164 } 165 166 func Mod(x, y float64) float64 { 167 return js.Global.Call("$mod", x, y).Float() 168 } 169 170 func Modf(f float64) (float64, float64) { 171 if f == posInf || f == negInf { 172 return f, nan 173 } 174 if 1/f == negInf { 175 return f, f 176 } 177 frac := Mod(f, 1) 178 return f - frac, frac 179 } 180 181 func NaN() float64 { 182 return nan 183 } 184 185 func Pow(x, y float64) float64 { 186 if x == 1 || (x == -1 && (y == posInf || y == negInf)) { 187 return 1 188 } 189 return math.Call("pow", x, y).Float() 190 } 191 192 func Remainder(x, y float64) float64 { 193 return remainder(x, y) 194 } 195 196 func Signbit(x float64) bool { 197 return x < 0 || 1/x == negInf 198 } 199 200 func Sin(x float64) float64 { 201 return math.Call("sin", x).Float() 202 } 203 204 func Sinh(x float64) float64 { 205 return math.Call("sinh", x).Float() 206 } 207 208 func Sincos(x float64) (sin, cos float64) { 209 return Sin(x), Cos(x) 210 } 211 212 func Sqrt(x float64) float64 { 213 return math.Call("sqrt", x).Float() 214 } 215 216 func Tan(x float64) float64 { 217 return math.Call("tan", x).Float() 218 } 219 220 func Tanh(x float64) float64 { 221 return math.Call("tanh", x).Float() 222 } 223 224 func Trunc(x float64) float64 { 225 if x == posInf || x == negInf || x != x || 1/x == negInf { 226 return x 227 } 228 return Copysign(float64(int(x)), x) 229 } 230 231 var buf struct { 232 uint32array [2]uint32 233 float32array [2]float32 234 float64array [1]float64 235 } 236 237 func init() { 238 ab := js.Global.Get("ArrayBuffer").New(8) 239 js.InternalObject(buf).Set("uint32array", js.Global.Get("Uint32Array").New(ab)) 240 js.InternalObject(buf).Set("float32array", js.Global.Get("Float32Array").New(ab)) 241 js.InternalObject(buf).Set("float64array", js.Global.Get("Float64Array").New(ab)) 242 } 243 244 func Float32bits(f float32) uint32 { 245 buf.float32array[0] = f 246 return buf.uint32array[0] 247 } 248 249 func Float32frombits(b uint32) float32 { 250 buf.uint32array[0] = b 251 return buf.float32array[0] 252 } 253 254 func Float64bits(f float64) uint64 { 255 buf.float64array[0] = f 256 return uint64(buf.uint32array[1])<<32 + uint64(buf.uint32array[0]) 257 } 258 259 func Float64frombits(b uint64) float64 { 260 buf.uint32array[0] = uint32(b) 261 buf.uint32array[1] = uint32(b >> 32) 262 return buf.float64array[0] 263 }