qxLib
easing_functions.inl
Go to the documentation of this file.
1 /**
2 
3  @file easing_functions.inl
4  @author Khrapov
5  @date 14.10.2026
6  @copyright (c) Nick Khrapov, 2026. All right reserved.
7 
8 **/
9 
10 namespace qx::easing
11 {
12 
13 template<class T>
14 constexpr T eps()
15 {
16  return T(1e-14f);
17 }
18 
19 template<>
20 constexpr float eps()
21 {
22  return 1e-6f;
23 }
24 
25 template<class T>
26 constexpr T linear_func(T x) noexcept
27 {
28  return x;
29 }
30 
31 template<class T>
32 constexpr T step_func(T x) noexcept
33 {
34  return x < T(0.5f) ? T(0.0f) : T(1.0f);
35 }
36 
37 template<class T>
38 inline T smooth_step_func(T x) noexcept
39 {
40  if (epsilon_less_equal(x, T(0.0f)))
41  return T(0.0f);
42  else if (epsilon_greater_equal(x, T(1.0f)))
43  return T(1.0f);
44  else
45  return (T(3.0f) - T(2.0f) * x) * std::pow(x, T(2.0f));
46 }
47 
48 template<class T>
49 inline T smoother_step_func(T x) noexcept
50 {
51  if (epsilon_less_equal(x, T(0.0f)))
52  return T(0.0f);
53  else if (epsilon_greater_equal(x, T(1.0f)))
54  return T(1.0f);
55  else
56  return std::pow(x, T(3.0f)) * (x * (x * T(6.0f) - T(15.0f)) + T(10.0f));
57 }
58 
59 template<class T>
60 inline T quadratic_in_func(T x) noexcept
61 {
62  return std::pow(x, T(2.0f));
63 }
64 
65 template<class T>
66 constexpr T quadratic_out_func(T x) noexcept
67 {
68  return -x * (x - T(2.0f));
69 }
70 
71 template<class T>
72 inline T quadratic_in_out_func(T x) noexcept
73 {
74  if (x < T(0.5f))
75  return T(2.0f) * std::pow(x, T(2.0f));
76  else
77  return T(1.0f) - T(2.0f) * std::pow(T(1.0f) - x, T(2.0f));
78 }
79 
80 template<class T>
81 inline T cubic_in_func(T x) noexcept
82 {
83  return std::pow(x, T(3.0f));
84 }
85 
86 template<class T>
87 inline T cubic_out_func(T x) noexcept
88 {
89  return std::pow(x - T(1.0f), T(3.0f)) + T(1.0f);
90 }
91 
92 template<class T>
93 inline T cubic_in_out_func(T x) noexcept
94 {
95  if (x < T(0.5f))
96  return T(4.0f) * std::pow(x, T(3.0f));
97  else
98  return T(1.0f) - T(4.0f) * std::pow(T(1.0f) - x, T(3.0f));
99 }
100 
101 template<class T>
102 inline T quartic_in_func(T x) noexcept
103 {
104  return std::pow(x, T(4.0f));
105 }
106 
107 template<class T>
108 inline T quartic_out_func(T x) noexcept
109 {
110  return T(1.0f) - std::pow(T(1.0f) - x, T(4.0f));
111 }
112 
113 template<class T>
114 inline T quartic_in_out_func(T x) noexcept
115 {
116  if (x < T(0.5f))
117  return 8 * std::pow(x, T(4.0f));
118  else
119  return T(1.0f) - T(8.0f) * std::pow(T(1.0f) - x, T(4.0f));
120 }
121 
122 template<class T>
123 inline T quintic_in_func(T x) noexcept
124 {
125  return std::pow(x, T(5.0f));
126 }
127 
128 template<class T>
129 inline T quintic_out_func(T x) noexcept
130 {
131  return T(1.0f) + std::pow(x - T(1.0f), T(5.0f));
132 }
133 
134 template<class T>
135 inline T quintic_in_out_func(T x) noexcept
136 {
137  if (x < T(0.5f))
138  return T(16.0f) * std::pow(x, T(5.0f));
139  else
140  return T(1.0f) - T(16.0f) * std::pow(T(1.0f) - x, T(5.0f));
141 }
142 
143 template<class T>
144 inline T sine_in_func(T x) noexcept
145 {
146  return T(1.0f) + static_cast<T>(std::sin(std::numbers::pi_v<T> / T(2.0f) * (x - T(1.0f))));
147 }
148 
149 template<class T>
150 inline T sine_out_func(T x) noexcept
151 {
152  return static_cast<T>(std::sin(std::numbers::pi_v<T> / T(2.0f) * x));
153 }
154 
155 template<class T>
156 inline T sine_in_out_func(T x) noexcept
157 {
158  return T(0.5f) * (T(1.0f) - static_cast<T>(std::cos(x * std::numbers::pi_v<T>)));
159 }
160 
161 template<class T>
162 inline T circular_in_func(T x) noexcept
163 {
164  return T(1.0f) - std::sqrt(T(1.0f) - std::pow(x, T(2.0f)));
165 }
166 
167 template<class T>
168 inline T circular_out_func(T x) noexcept
169 {
170  return std::sqrt((T(2.0f) - x) * x);
171 }
172 
173 template<class T>
174 inline T circular_in_out_func(T x) noexcept
175 {
176  if (x < T(0.5f))
177  {
178  return T(0.5f) * (T(1.0f) - std::sqrt(T(1.0f) - T(4.0f) * std::pow(x, T(2.0f))));
179  }
180  else
181  {
182  return T(0.5f) * (T(1.0f) + std::sqrt(-T(4.0f) * std::pow(x, T(2.0f)) + T(8.0f) * x - T(3.0f)));
183  }
184 }
185 
186 template<class T>
187 inline T exponential_in_func(T x) noexcept
188 {
189  return x <= T(0.0f) ? T(0.0f) : std::pow(T(2.0f), T(10.0f) * (x - T(1.0f)));
190 }
191 
192 template<class T>
193 inline T exponential_out_func(T x) noexcept
194 {
195  return x >= T(1.0f) ? T(1.0f) : T(1.0f) - std::pow(T(2.0f), -T(10.0f) * x);
196 }
197 
198 template<class T>
199 inline T exponential_in_out_func(T x) noexcept
200 {
201  if (x <= T(0.0f))
202  return T(0.0f);
203  else if (x < T(0.5f))
204  return T(0.5f) * std::pow(T(2.0f), T(20.0f) * x - T(10.0f));
205  else if (x < T(1.0f))
206  return T(1.0f) - T(0.5f) * std::pow(T(2.0f), T(10.0f) - T(20.0f) * x);
207  else
208  return T(1.0f);
209 }
210 
211 template<class T>
212 inline T elastic_in_func(T x) noexcept
213 {
214  return std::pow(T(2.0f), T(10.0f) * (x - T(1.0f)))
215  * static_cast<T>(std::sin(T(13.0f) * std::numbers::pi_v<T> / T(2.0f) * x));
216 }
217 
218 template<class T>
219 inline T elastic_out_func(T x) noexcept
220 {
221  return T(1.0f)
222  - std::pow(T(2.0f), -T(10.0f) * x)
223  * static_cast<T>(std::sin(T(13.0f) * std::numbers::pi_v<T> / T(2.0f) * (x + T(1.0f))));
224 }
225 
226 template<class T>
227 inline T elastic_in_out_func(T x) noexcept
228 {
229  if (x < T(0.5f))
230  {
231  return T(0.5f) * std::pow(T(2.0f), T(10.0f) * (T(2.0f) * x - T(1.0f)))
232  * static_cast<T>(std::sin(T(13.0f) * std::numbers::pi_v<T> * x));
233  }
234  else
235  {
236  return T(1.0f)
237  - T(0.5f) * std::pow(T(2.0f), T(10.0f) * (T(1.0f) - T(2.0f) * x))
238  * static_cast<T>(std::sin(T(13.0f) * std::numbers::pi_v<T> * x));
239  }
240 }
241 
242 template<class T>
243 inline T back_in_func(T x) noexcept
244 {
245  return x * (std::pow(x, T(2.0f)) - static_cast<T>(std::sin(std::numbers::pi_v<T> * x)));
246 }
247 
248 template<class T>
249 inline T back_out_func(T x) noexcept
250 {
251  const T fInv = T(1.0f) - x;
252  return T(1.0f) - fInv * (fInv * fInv - static_cast<T>(std::sin(std::numbers::pi_v<T> * fInv)));
253 }
254 
255 template<class T>
256 inline T back_in_out_func(T x) noexcept
257 {
258  if (x < T(0.5f))
259  {
260  const T f2t = T(2.0f) * x;
261  return T(0.5f) * f2t * (f2t * f2t - static_cast<T>(std::sin(std::numbers::pi_v<T> * f2t)));
262  }
263  else
264  {
265  const T fInv = T(2.0f) - T(2.0f) * x;
266  return T(1.0f) - T(0.5f) * fInv * (fInv * fInv - static_cast<T>(std::sin(std::numbers::pi_v<T> * fInv)));
267  }
268 }
269 
270 template<class T>
271 inline T bounce_out_func(T x) noexcept
272 {
273  if (x < T(4.0f) / T(11.0f))
274  {
275  return (T(121.0f) * std::pow(x, T(2.0f))) / T(16.0f);
276  }
277  else if (x < T(8.0f) / T(11.0f))
278  {
279  return T(363.0f) / T(40.0f) * std::pow(x, T(2.0f)) - T(99.0f) / T(10.0f) * x + T(17.0f) / T(5.0f);
280  }
281  else if (x < T(9.0f) / T(10.0f))
282  {
283  return T(4356.0f) / T(361.0f) * std::pow(x, T(2.0f)) - T(35442.0f) / T(1805.0f) * x + T(16061.0f) / T(1805.0f);
284  }
285  else
286  {
287  return T(54.0f) / T(5.0f) * std::pow(x, T(2.0f)) - T(513.0f) / T(25.0f) * x + T(268.0f) / T(25.0f);
288  }
289 }
290 
291 template<class T>
292 inline T bounce_in_func(T x) noexcept
293 {
294  return T(1.0f) - bounce_out_func<T>(T(1.0f) - x);
295 }
296 
297 template<class T>
298 inline T bounce_in_out_func(T x) noexcept
299 {
300  if (x < T(0.5f))
301  return T(0.5f) * bounce_in_func<T>(T(2.0f) * x);
302  else
303  return T(0.5f) * bounce_out_func<T>(T(2.0f) * x - T(1.0f)) + T(0.5f);
304 }
305 
306 } // namespace qx::easing
constexpr bool epsilon_greater_equal(T left, T right, T eps=std::numeric_limits< T >::epsilon())
Constexpr comparison function for a user defined epsilon values.
constexpr bool epsilon_less_equal(T left, T right, T eps=std::numeric_limits< T >::epsilon())
Constexpr comparison function for a user defined epsilon values.
constexpr double pow(T number, int nPower)
Power function for integer power.
Definition: common.inl:58