Commit | Line | Data |
---|---|---|
4562236b HW |
1 | /* |
2 | * Copyright 2012-15 Advanced Micro Devices, Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | * | |
22 | * Authors: AMD | |
23 | * | |
24 | */ | |
25 | ||
26 | #ifndef __DAL_FIXED31_32_H__ | |
27 | #define __DAL_FIXED31_32_H__ | |
28 | ||
29 | #include "os_types.h" | |
30 | ||
31 | /* | |
32 | * @brief | |
33 | * Arithmetic operations on real numbers | |
34 | * represented as fixed-point numbers. | |
35 | * There are: 1 bit for sign, | |
36 | * 31 bit for integer part, | |
37 | * 32 bits for fractional part. | |
38 | * | |
39 | * @note | |
40 | * Currently, overflows and underflows are asserted; | |
41 | * no special result returned. | |
42 | */ | |
43 | ||
44 | struct fixed31_32 { | |
45 | int64_t value; | |
46 | }; | |
47 | ||
48 | /* | |
49 | * @brief | |
50 | * Useful constants | |
51 | */ | |
52 | ||
53 | static const struct fixed31_32 dal_fixed31_32_zero = { 0 }; | |
54 | static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL }; | |
55 | static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL }; | |
56 | static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL }; | |
57 | ||
58 | static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL }; | |
59 | static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL }; | |
60 | static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL }; | |
61 | static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL }; | |
62 | static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL }; | |
63 | ||
64 | /* | |
65 | * @brief | |
66 | * Initialization routines | |
67 | */ | |
68 | ||
69 | /* | |
70 | * @brief | |
71 | * result = numerator / denominator | |
72 | */ | |
73 | struct fixed31_32 dal_fixed31_32_from_fraction( | |
74 | int64_t numerator, | |
75 | int64_t denominator); | |
76 | ||
77 | /* | |
78 | * @brief | |
79 | * result = arg | |
80 | */ | |
81 | struct fixed31_32 dal_fixed31_32_from_int( | |
82 | int64_t arg); | |
83 | ||
84 | /* | |
85 | * @brief | |
86 | * Unary operators | |
87 | */ | |
88 | ||
89 | /* | |
90 | * @brief | |
91 | * result = -arg | |
92 | */ | |
204de25f DA |
93 | static inline struct fixed31_32 dal_fixed31_32_neg(struct fixed31_32 arg) |
94 | { | |
95 | struct fixed31_32 res; | |
96 | ||
97 | res.value = -arg.value; | |
98 | ||
99 | return res; | |
100 | } | |
4562236b HW |
101 | |
102 | /* | |
103 | * @brief | |
104 | * result = abs(arg) := (arg >= 0) ? arg : -arg | |
105 | */ | |
204de25f DA |
106 | static inline struct fixed31_32 dal_fixed31_32_abs(struct fixed31_32 arg) |
107 | { | |
108 | if (arg.value < 0) | |
109 | return dal_fixed31_32_neg(arg); | |
110 | else | |
111 | return arg; | |
112 | } | |
4562236b HW |
113 | |
114 | /* | |
115 | * @brief | |
116 | * Binary relational operators | |
117 | */ | |
118 | ||
119 | /* | |
120 | * @brief | |
121 | * result = arg1 < arg2 | |
122 | */ | |
204de25f DA |
123 | static inline bool dal_fixed31_32_lt(struct fixed31_32 arg1, |
124 | struct fixed31_32 arg2) | |
125 | { | |
126 | return arg1.value < arg2.value; | |
127 | } | |
4562236b HW |
128 | |
129 | /* | |
130 | * @brief | |
131 | * result = arg1 <= arg2 | |
132 | */ | |
204de25f DA |
133 | static inline bool dal_fixed31_32_le(struct fixed31_32 arg1, |
134 | struct fixed31_32 arg2) | |
135 | { | |
136 | return arg1.value <= arg2.value; | |
137 | } | |
4562236b HW |
138 | |
139 | /* | |
140 | * @brief | |
141 | * result = arg1 == arg2 | |
142 | */ | |
204de25f DA |
143 | static inline bool dal_fixed31_32_eq(struct fixed31_32 arg1, |
144 | struct fixed31_32 arg2) | |
145 | { | |
146 | return arg1.value == arg2.value; | |
147 | } | |
4562236b HW |
148 | |
149 | /* | |
150 | * @brief | |
151 | * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 | |
152 | */ | |
204de25f DA |
153 | static inline struct fixed31_32 dal_fixed31_32_min(struct fixed31_32 arg1, |
154 | struct fixed31_32 arg2) | |
155 | { | |
156 | if (arg1.value <= arg2.value) | |
157 | return arg1; | |
158 | else | |
159 | return arg2; | |
160 | } | |
4562236b HW |
161 | |
162 | /* | |
163 | * @brief | |
164 | * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 | |
165 | */ | |
204de25f DA |
166 | static inline struct fixed31_32 dal_fixed31_32_max(struct fixed31_32 arg1, |
167 | struct fixed31_32 arg2) | |
168 | { | |
169 | if (arg1.value <= arg2.value) | |
170 | return arg2; | |
171 | else | |
172 | return arg1; | |
173 | } | |
4562236b HW |
174 | |
175 | /* | |
176 | * @brief | |
177 | * | min_value, when arg <= min_value | |
178 | * result = | arg, when min_value < arg < max_value | |
179 | * | max_value, when arg >= max_value | |
180 | */ | |
204de25f | 181 | static inline struct fixed31_32 dal_fixed31_32_clamp( |
4562236b HW |
182 | struct fixed31_32 arg, |
183 | struct fixed31_32 min_value, | |
204de25f DA |
184 | struct fixed31_32 max_value) |
185 | { | |
186 | if (dal_fixed31_32_le(arg, min_value)) | |
187 | return min_value; | |
188 | else if (dal_fixed31_32_le(max_value, arg)) | |
189 | return max_value; | |
190 | else | |
191 | return arg; | |
192 | } | |
4562236b HW |
193 | |
194 | /* | |
195 | * @brief | |
196 | * Binary shift operators | |
197 | */ | |
198 | ||
199 | /* | |
200 | * @brief | |
201 | * result = arg << shift | |
202 | */ | |
203 | struct fixed31_32 dal_fixed31_32_shl( | |
204 | struct fixed31_32 arg, | |
205 | uint8_t shift); | |
206 | ||
207 | /* | |
208 | * @brief | |
209 | * result = arg >> shift | |
210 | */ | |
204de25f | 211 | static inline struct fixed31_32 dal_fixed31_32_shr( |
4562236b | 212 | struct fixed31_32 arg, |
204de25f DA |
213 | uint8_t shift) |
214 | { | |
215 | struct fixed31_32 res; | |
216 | res.value = arg.value >> shift; | |
217 | return res; | |
218 | } | |
4562236b HW |
219 | |
220 | /* | |
221 | * @brief | |
222 | * Binary additive operators | |
223 | */ | |
224 | ||
225 | /* | |
226 | * @brief | |
227 | * result = arg1 + arg2 | |
228 | */ | |
229 | struct fixed31_32 dal_fixed31_32_add( | |
230 | struct fixed31_32 arg1, | |
231 | struct fixed31_32 arg2); | |
232 | ||
fcd2f4bf AZ |
233 | /* |
234 | * @brief | |
235 | * result = arg1 + arg2 | |
236 | */ | |
204de25f DA |
237 | static inline struct fixed31_32 dal_fixed31_32_add_int(struct fixed31_32 arg1, |
238 | int32_t arg2) | |
239 | { | |
240 | return dal_fixed31_32_add(arg1, | |
241 | dal_fixed31_32_from_int(arg2)); | |
242 | } | |
fcd2f4bf | 243 | |
4562236b HW |
244 | /* |
245 | * @brief | |
246 | * result = arg1 - arg2 | |
247 | */ | |
204de25f | 248 | struct fixed31_32 dal_fixed31_32_sub( |
4562236b | 249 | struct fixed31_32 arg1, |
204de25f | 250 | struct fixed31_32 arg2); |
4562236b HW |
251 | |
252 | /* | |
253 | * @brief | |
254 | * result = arg1 - arg2 | |
255 | */ | |
204de25f DA |
256 | static inline struct fixed31_32 dal_fixed31_32_sub_int(struct fixed31_32 arg1, |
257 | int32_t arg2) | |
258 | { | |
259 | return dal_fixed31_32_sub(arg1, | |
260 | dal_fixed31_32_from_int(arg2)); | |
261 | } | |
262 | ||
4562236b HW |
263 | |
264 | /* | |
265 | * @brief | |
266 | * Binary multiplicative operators | |
267 | */ | |
268 | ||
269 | /* | |
270 | * @brief | |
271 | * result = arg1 * arg2 | |
272 | */ | |
204de25f | 273 | struct fixed31_32 dal_fixed31_32_mul( |
4562236b | 274 | struct fixed31_32 arg1, |
204de25f DA |
275 | struct fixed31_32 arg2); |
276 | ||
4562236b HW |
277 | |
278 | /* | |
279 | * @brief | |
280 | * result = arg1 * arg2 | |
281 | */ | |
204de25f DA |
282 | static inline struct fixed31_32 dal_fixed31_32_mul_int(struct fixed31_32 arg1, |
283 | int32_t arg2) | |
284 | { | |
285 | return dal_fixed31_32_mul(arg1, | |
286 | dal_fixed31_32_from_int(arg2)); | |
287 | } | |
4562236b HW |
288 | |
289 | /* | |
290 | * @brief | |
291 | * result = square(arg) := arg * arg | |
292 | */ | |
293 | struct fixed31_32 dal_fixed31_32_sqr( | |
294 | struct fixed31_32 arg); | |
295 | ||
296 | /* | |
297 | * @brief | |
298 | * result = arg1 / arg2 | |
299 | */ | |
300 | struct fixed31_32 dal_fixed31_32_div_int( | |
301 | struct fixed31_32 arg1, | |
302 | int64_t arg2); | |
303 | ||
304 | /* | |
305 | * @brief | |
306 | * result = arg1 / arg2 | |
307 | */ | |
204de25f DA |
308 | static inline struct fixed31_32 dal_fixed31_32_div(struct fixed31_32 arg1, |
309 | struct fixed31_32 arg2) | |
310 | { | |
311 | return dal_fixed31_32_from_fraction(arg1.value, | |
312 | arg2.value); | |
313 | } | |
4562236b HW |
314 | |
315 | /* | |
316 | * @brief | |
317 | * Reciprocal function | |
318 | */ | |
319 | ||
320 | /* | |
321 | * @brief | |
322 | * result = reciprocal(arg) := 1 / arg | |
323 | * | |
324 | * @note | |
325 | * No special actions taken in case argument is zero. | |
326 | */ | |
327 | struct fixed31_32 dal_fixed31_32_recip( | |
328 | struct fixed31_32 arg); | |
329 | ||
330 | /* | |
331 | * @brief | |
332 | * Trigonometric functions | |
333 | */ | |
334 | ||
335 | /* | |
336 | * @brief | |
337 | * result = sinc(arg) := sin(arg) / arg | |
338 | * | |
339 | * @note | |
340 | * Argument specified in radians, | |
341 | * internally it's normalized to [-2pi...2pi] range. | |
342 | */ | |
343 | struct fixed31_32 dal_fixed31_32_sinc( | |
344 | struct fixed31_32 arg); | |
345 | ||
346 | /* | |
347 | * @brief | |
348 | * result = sin(arg) | |
349 | * | |
350 | * @note | |
351 | * Argument specified in radians, | |
352 | * internally it's normalized to [-2pi...2pi] range. | |
353 | */ | |
354 | struct fixed31_32 dal_fixed31_32_sin( | |
355 | struct fixed31_32 arg); | |
356 | ||
357 | /* | |
358 | * @brief | |
359 | * result = cos(arg) | |
360 | * | |
361 | * @note | |
362 | * Argument specified in radians | |
363 | * and should be in [-2pi...2pi] range - | |
364 | * passing arguments outside that range | |
365 | * will cause incorrect result! | |
366 | */ | |
367 | struct fixed31_32 dal_fixed31_32_cos( | |
368 | struct fixed31_32 arg); | |
369 | ||
370 | /* | |
371 | * @brief | |
372 | * Transcendent functions | |
373 | */ | |
374 | ||
375 | /* | |
376 | * @brief | |
377 | * result = exp(arg) | |
378 | * | |
379 | * @note | |
380 | * Currently, function is verified for abs(arg) <= 1. | |
381 | */ | |
382 | struct fixed31_32 dal_fixed31_32_exp( | |
383 | struct fixed31_32 arg); | |
384 | ||
385 | /* | |
386 | * @brief | |
387 | * result = log(arg) | |
388 | * | |
389 | * @note | |
390 | * Currently, abs(arg) should be less than 1. | |
391 | * No normalization is done. | |
392 | * Currently, no special actions taken | |
393 | * in case of invalid argument(s). Take care! | |
394 | */ | |
395 | struct fixed31_32 dal_fixed31_32_log( | |
396 | struct fixed31_32 arg); | |
397 | ||
398 | /* | |
399 | * @brief | |
400 | * Power function | |
401 | */ | |
402 | ||
403 | /* | |
404 | * @brief | |
405 | * result = pow(arg1, arg2) | |
406 | * | |
407 | * @note | |
408 | * Currently, abs(arg1) should be less than 1. Take care! | |
409 | */ | |
410 | struct fixed31_32 dal_fixed31_32_pow( | |
411 | struct fixed31_32 arg1, | |
412 | struct fixed31_32 arg2); | |
413 | ||
414 | /* | |
415 | * @brief | |
416 | * Rounding functions | |
417 | */ | |
418 | ||
419 | /* | |
420 | * @brief | |
421 | * result = floor(arg) := greatest integer lower than or equal to arg | |
422 | */ | |
423 | int32_t dal_fixed31_32_floor( | |
424 | struct fixed31_32 arg); | |
425 | ||
426 | /* | |
427 | * @brief | |
428 | * result = round(arg) := integer nearest to arg | |
429 | */ | |
430 | int32_t dal_fixed31_32_round( | |
431 | struct fixed31_32 arg); | |
432 | ||
433 | /* | |
434 | * @brief | |
435 | * result = ceil(arg) := lowest integer greater than or equal to arg | |
436 | */ | |
437 | int32_t dal_fixed31_32_ceil( | |
438 | struct fixed31_32 arg); | |
439 | ||
440 | /* the following two function are used in scaler hw programming to convert fixed | |
441 | * point value to format 2 bits from integer part and 19 bits from fractional | |
442 | * part. The same applies for u0d19, 0 bits from integer part and 19 bits from | |
443 | * fractional | |
444 | */ | |
445 | ||
446 | uint32_t dal_fixed31_32_u2d19( | |
447 | struct fixed31_32 arg); | |
448 | ||
449 | uint32_t dal_fixed31_32_u0d19( | |
450 | struct fixed31_32 arg); | |
451 | ||
452 | #endif |