1 #include "a/trajbell.h"
4 #if A_PREREQ_GNUC(3, 0) || __has_warning("-Wfloat-equal")
5 #pragma GCC diagnostic ignored "-Wfloat-equal"
6 #endif /* -Wfloat-equal */
8 a_float
a_trajbell_gen(a_trajbell
*ctx
, a_float jm
, a_float am
, a_float vm
,
9 a_float p0
, a_float p1
, a_float v0
, a_float v1
)
11 a_float p
, ac
, tj
, _2tj
, _2v0
, _2v1
, _tmp
, temp
, v0pv1
, _2v02pv12
;
12 if (jm
< 0) { jm
= -jm
; }
13 if (am
< 0) { am
= -am
; }
14 if (vm
< 0) { vm
= -vm
; }
15 if (v0
< -vm
) { v0
= -vm
; }
16 else if (v0
> vm
) { v0
= vm
; }
17 if (v1
< -vm
) { v1
= -vm
; }
18 else if (v1
> vm
) { v1
= vm
; }
36 ctx
->taj
= a_float_sqrt(_2v0
/ jm
);
37 ctx
->ta
= 2 * ctx
->taj
;
38 ctx
->am
= +jm
* ctx
->taj
;
43 ctx
->ta
= ctx
->taj
+ _2v0
/ am
;
49 ctx
->tdj
= a_float_sqrt(_2v1
/ jm
);
50 ctx
->td
= 2 * ctx
->tdj
;
51 ctx
->dm
= -jm
* ctx
->tdj
;
56 ctx
->td
= ctx
->tdj
+ _2v1
/ am
;
60 ctx
->tv
= p
/ vm
- A_FLOAT_C(0.5) * ctx
->ta
* (1 + v0
/ vm
) - A_FLOAT_C(0.5) * ctx
->td
* (1 + v1
/ vm
);
61 if (ctx
->tv
> 0) { goto out
; }
67 ctx
->dm
= ac
* A_FLOAT_C(0.0625);
68 _2v02pv12
= 2 * (v0
* v0
+ v1
* v1
);
75 temp
= _tmp
* _tmp
+ _2v02pv12
+ (4 * p
- _2tj
* v0pv1
) * am
;
76 _tmp
+= a_float_sqrt(temp
);
78 ctx
->ta
= (_tmp
- _2v0
) / temp
;
81 if (am
== ctx
->am
|| ac
< ctx
->dm
)
85 ctx
->td
= 2 * p
/ v0pv1
;
87 temp
= jm
* (_tmp
* p
+ (v1
- v0
) * v0pv1
* v0pv1
);
88 if (temp
< 0) { goto fail
; }
89 ctx
->tdj
= (_tmp
- a_float_sqrt(temp
)) / (jm
* v0pv1
);
91 ctx
->dm
= -jm
* ctx
->tdj
;
99 ctx
->td
= (_tmp
- _2v1
) / temp
;
102 if (am
== ctx
->am
|| ac
< ctx
->dm
)
106 ctx
->ta
= 2 * p
/ v0pv1
;
108 temp
= jm
* (_tmp
* p
+ (v0
- v1
) * v0pv1
* v0pv1
);
109 if (temp
< 0) { goto fail
; }
110 ctx
->taj
= (_tmp
- a_float_sqrt(temp
)) / (jm
* v0pv1
);
111 ctx
->am
= +jm
* ctx
->taj
;
113 ctx
->vm
= v0
+ ctx
->am
* (ctx
->ta
- ctx
->taj
);
116 ac
*= A_FLOAT_C(0.5);
120 if (ctx
->ta
>= _2tj
&& ctx
->td
>= _2tj
)
122 if (am
== ctx
->am
|| ac
< ctx
->dm
)
126 ctx
->vm
= v0
+ ctx
->am
* (ctx
->ta
- tj
);
129 ac
*= A_FLOAT_C(0.5);
133 ac
*= A_FLOAT_C(0.5);
135 } while (ac
> A_FLOAT_EPSILON
);
140 ctx
->t
= ctx
->ta
+ ctx
->tv
+ ctx
->td
;
144 a_float
a_trajbell_pos(a_trajbell
const *ctx
, a_float dt
)
147 a_float p0
= ctx
->p0
;
148 a_float p1
= ctx
->p1
;
149 a_float v0
= ctx
->v0
;
150 a_float v1
= ctx
->v1
;
151 a_bool
const rev
= ctx
->p0
> ctx
->p1
;
163 if (dt
<= 0) { return ctx
->p0
; }
164 out
= p0
+ v0
* dt
+ ctx
->jm
* dt
* dt
* dt
/ 6;
167 if (dt
< ctx
->ta
- ctx
->taj
)
169 out
= p0
+ v0
* dt
+ ctx
->am
* (3 * dt
* dt
- 3 * dt
* ctx
->taj
+ ctx
->taj
* ctx
->taj
) / 6;
173 out
= p0
+ A_FLOAT_C(0.5) * (ctx
->vm
+ v0
) * ctx
->ta
- ctx
->vm
* dt
+ ctx
->jm
* dt
* dt
* dt
/ 6;
176 if (dt
< ctx
->t
- ctx
->td
+ ctx
->tdj
)
178 if (dt
< ctx
->ta
+ ctx
->tv
)
180 out
= p0
+ A_FLOAT_C(0.5) * (ctx
->vm
+ v0
) * ctx
->ta
+ ctx
->vm
* (dt
- ctx
->ta
);
183 dt
-= ctx
->t
- ctx
->td
;
184 out
= p1
- A_FLOAT_C(0.5) * (ctx
->vm
+ v1
) * ctx
->td
+ ctx
->vm
* dt
- ctx
->jm
* dt
* dt
* dt
/ 6;
189 if (dt
< ctx
->t
- ctx
->tdj
)
191 dt
-= ctx
->t
- ctx
->td
;
192 out
= p1
- A_FLOAT_C(0.5) * (ctx
->vm
+ v1
) * ctx
->td
+ ctx
->vm
* dt
+
193 ctx
->dm
* (3 * dt
* dt
- 3 * dt
* ctx
->tdj
+ ctx
->tdj
* ctx
->tdj
) / 6;
197 out
= p1
- v1
* dt
- ctx
->jm
* dt
* dt
* dt
/ 6;
202 return rev
? -out
: out
;
205 a_float
a_trajbell_vel(a_trajbell
const *ctx
, a_float dt
)
208 a_float v0
= ctx
->v0
;
209 a_float v1
= ctx
->v1
;
210 a_bool
const rev
= ctx
->p0
> ctx
->p1
;
220 if (dt
<= 0) { return ctx
->v0
; }
221 out
= v0
+ A_FLOAT_C(0.5) * ctx
->jm
* dt
* dt
;
224 if (dt
< ctx
->ta
- ctx
->taj
)
226 out
= v0
+ ctx
->am
* (dt
- A_FLOAT_C(0.5) * ctx
->taj
);
230 out
= ctx
->vm
- A_FLOAT_C(0.5) * ctx
->jm
* dt
* dt
;
233 if (dt
< ctx
->t
- ctx
->td
+ ctx
->tdj
)
235 if (dt
< ctx
->ta
+ ctx
->tv
)
240 dt
-= ctx
->t
- ctx
->td
;
241 out
= ctx
->vm
- A_FLOAT_C(0.5) * ctx
->jm
* dt
* dt
;
246 if (dt
< ctx
->t
- ctx
->tdj
)
248 out
= ctx
->vm
+ ctx
->dm
* (dt
- ctx
->t
+ ctx
->td
- A_FLOAT_C(0.5) * ctx
->tdj
);
252 out
= v1
+ A_FLOAT_C(0.5) * ctx
->jm
* dt
* dt
;
257 return rev
? -out
: out
;
260 a_float
a_trajbell_acc(a_trajbell
const *ctx
, a_float dt
)
267 if (dt
< ctx
->ta
- ctx
->taj
)
272 out
= ctx
->jm
* (ctx
->ta
- dt
);
281 else if (dt
< ctx
->t
- ctx
->td
+ ctx
->tdj
)
283 if (dt
>= ctx
->ta
+ ctx
->tv
)
285 out
= -ctx
->jm
* (dt
- ctx
->t
+ ctx
->td
);
289 else if (dt
< ctx
->t
)
291 if (dt
< ctx
->t
- ctx
->tdj
)
296 out
= -ctx
->jm
* (ctx
->t
- dt
);
301 if (ctx
->p0
> ctx
->p1
)
308 a_float
a_trajbell_jer(a_trajbell
const *ctx
, a_float dt
)
313 if (dt
>= ctx
->ta
- ctx
->taj
)
318 if (dt
< ctx
->taj
&& dt
>= 0)
324 else if (dt
< ctx
->t
- ctx
->td
+ ctx
->tdj
)
326 if (dt
>= ctx
->ta
+ ctx
->tv
)
332 else if (dt
<= ctx
->t
)
334 if (dt
>= ctx
->t
- ctx
->tdj
)
342 if (ctx
->p0
> ctx
->p1
)