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