-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtape.h
225 lines (204 loc) · 4.64 KB
/
tape.h
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#ifndef TAPE_H
#define TAPE_H
#include <vector>
#include <cmath>
#ifndef uint
#define uint unsigned int
struct Tape;
struct Grad;
struct Node
{
float w1, w2;
uint a, b;
Node(const float = 0, const uint = 0, const float = 0, const uint = 0);
inline void set(const float w1, const float w2)
{
this->w1 = w1;
this->w2 = w2;
}
};
struct Var
{
Tape* tape;
uint id;
float val;
Var(Tape* const, const uint = 0, const float = 0);
void grad(Grad&);
Grad grad();
Var& operator=(const Var&);
Var& operator+=(const Var&);
Var& operator-=(const Var&);
Var& operator*=(const Var&);
Var& operator/=(const Var&);
Var& operator^=(const Var&);
Var& operator=(const float);
Var& operator+=(const float);
Var& operator-=(const float);
Var& operator*=(const float);
Var& operator/=(const float);
Var& operator^=(const float);
};
struct Tape
{
std::vector<Node> nodes;
Tape();
Var var(const float, const float = 0, const uint = 0, const float = 0, const uint = 0);
uint push(const float = 0, const uint = 0, const float = 0, const uint = 0);
inline Node* get(const uint id) {return &nodes[id];}
inline uint size() {return nodes.size();}
inline void clear() {nodes.resize(1);} // I don't know why, but this doesn't work correctly without an initial dummy node
};
struct Grad
{
std::vector<float> d;
inline float wrt(const Var& x) {return (x.id < d.size())? d[x.id] : 0;}
};
inline Var operator+(Var lhs, const Var& rhs)
{
lhs += rhs;
return lhs;
}
inline Var operator-(Var lhs, const Var& rhs)
{
lhs -= rhs;
return lhs;
}
inline Var operator*(Var lhs, const Var& rhs)
{
lhs *= rhs;
return lhs;
}
inline Var operator/(Var lhs, const Var& rhs)
{
lhs /= rhs;
return lhs;
}
inline Var operator^(Var lhs, const Var& rhs)
{
lhs ^= rhs;
return lhs;
}
inline Var operator+(Var lhs, const float rhs)
{
lhs += rhs;
return lhs;
}
inline Var operator-(Var lhs, const float rhs)
{
lhs -= rhs;
return lhs;
}
inline Var operator*(Var lhs, const float rhs)
{
lhs *= rhs;
return lhs;
}
inline Var operator/(Var lhs, const float rhs)
{
lhs /= rhs;
return lhs;
}
inline Var operator^(Var lhs, const float rhs)
{
lhs ^= rhs;
return lhs;
}
inline Var sin(const Var& x)
{
return x.tape->var(sin(x.val), cos(x.val), x.id);
}
inline Var cos(const Var& x)
{
return x.tape->var(cos(x.val), -sin(x.val), x.id);
}
inline Var tan(const Var& x)
{
return x.tape->var(tan(x.val), 1/pow(cos(x.val), 2), x.id);
}
inline Var sec(const Var& x)
{
return x.tape->var(1/cos(x.val), tan(x.val)/cos(x.val), x.id);
}
inline Var csc(const Var& x)
{
return x.tape->var(1/sin(x.val), -1/(sin(x.val) * tan(x.val)), x.id);
}
inline Var cot(const Var& x)
{
return x.tape->var(1/tan(x.val), -1/pow(sin(x.val), 2), x.id);
}
inline Var asin(const Var& x)
{
return x.tape->var(asin(x.val), 1/sqrt(1 - x.val * x.val), x.id);
}
inline Var acos(const Var& x)
{
return x.tape->var(acos(x.val), -1/sqrt(1 - x.val * x.val), x.id);
}
inline Var atan(const Var& x)
{
return x.tape->var(atan(x.val), 1/(1 + x.val * x.val), x.id);
}
inline Var sinh(const Var& x)
{
const float ex = exp(x.val);
const float y = (ex - 1/ex)/2;
return x.tape->var(y, y + 2/ex, x.id);
}
inline Var cosh(const Var& x)
{
const float ex = exp(x.val);
const float y = (ex + 1/ex)/2;
return x.tape->var(y, y - 2/ex, x.id);
}
inline Var tanh(const Var& x)
{
const float ex = exp(x.val);
const float y = (ex - 1/ex)/(ex + 1/ex);
return x.tape->var(y, 1 - y * y, x.id);
}
inline Var sech(const Var& x)
{
const float ex = exp(x.val);
const float y = 2/(ex + 1/ex);
return x.tape->var(y, -y * y * (ex - 1/ex)/2, x.id);
}
inline Var csch(const Var& x)
{
const float ex = exp(x.val);
const float y = 2/(ex - 1/ex);
return x.tape->var(y, -y * y * (ex + 1/ex)/2, x.id);
}
inline Var coth(const Var& x)
{
const float ex = exp(x.val);
const float y = (ex + 1/ex)/(ex - 1/ex);
return x.tape->var(y, -pow(y * 2/(ex + 1/ex), 2), x.id);
}
inline Var sinc(const Var& x)
{
if (x.val == 0)
return x.tape->var(1, 0, x.id);
else
return x.tape->var(sin(x.val)/x.val, cos(x.val)/x.val - sin(x.val)/(x.val * x.val), x.id);
}
inline Var exp(const Var& x)
{
return x.tape->var(exp(x.val), exp(x.val), x.id);
}
inline Var log(const Var& x)
{
return x.tape->var(log(x.val), 1/x.val, x.id);
}
inline Var log(const Var& x, const float a)
{
return x.tape->var(log10(x.val) / log10(a), 1/(x.val * log(a)), x.id);
}
inline Var sigmoid(const Var& x)
{
const float y = 1/(1 + 1/exp(x.val));
return x.tape->var(y, y * (1 - y), x.id);
}
#undef uint
#endif
#endif