This repository has been archived by the owner on Aug 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmath.go
116 lines (110 loc) · 1.96 KB
/
math.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package goal
import "math"
// vfNaN implements the nan variadic verb.
func vfNaN(ctx *Context, args []V) V {
switch len(args) {
case 1:
r := isNaN(args[0])
return r
case 2:
return fillNaN(args[1], args[0])
default:
return panicRank("nan")
}
}
func isNaN(x V) V {
if x.IsI() {
return NewI(b2I(false))
}
if x.IsF() {
return NewI(b2I(math.IsNaN(x.F())))
}
switch xv := x.bv.(type) {
case *AB:
r := xv.reuse()
for i := range r.elts {
r.elts[i] = 0
}
r.flags = flagBool
return NewV(r)
case *AI:
r := make([]byte, xv.Len())
return newABb(r)
case *AF:
r := make([]byte, xv.Len())
for i, xi := range xv.elts {
r[i] = b2B(math.IsNaN(xi))
}
return newABb(r)
case *AV:
return mapAV(xv, isNaN)
case *D:
return newDictValues(xv.keys, isNaN(NewV(xv.values)))
default:
return panicType("NaN x", "x", x)
}
}
func fillNaN(x V, y V) V {
var fill float64
if x.IsI() {
fill = float64(x.I())
} else if x.IsF() {
fill = x.F()
} else {
return panicType("x NaN y", "x", x)
}
r := fillNaNf(fill, y)
return r
}
func fillNaNf(fill float64, y V) V {
if y.IsI() {
return y
}
if y.IsF() {
if math.IsNaN(y.F()) {
return NewF(fill)
}
return y
}
switch yv := y.bv.(type) {
case *AB:
return y
case *AI:
return y
case *AF:
var r []float64
if yv.reusable() {
r = yv.elts
} else {
r = make([]float64, yv.Len())
copy(r, yv.elts)
}
for i, ri := range r {
if math.IsNaN(ri) {
r[i] = fill
}
}
return NewAF(r)
case *AV:
return mapAV(yv, func(yi V) V { return fillNaNf(fill, yi) })
case *D:
return newDictValues(yv.keys, fillNaNf(fill, NewV(yv.values)))
default:
return panicType("x NaN y", "y", y)
}
}
// vfAtan implements the atan variadic verb.
func vfAtan(ctx *Context, args []V) V {
switch len(args) {
case 1:
r := mathm(args[0], math.Atan)
if r.IsPanic() {
return ppanic("tan x : ", r)
}
return r
case 2:
return arctan2(args[1], args[0])
default:
return panicRank("+")
}
}