xref: /aosp_15_r20/external/mesa3d/src/amd/vpelib/src/utils/inc/fixed31_32.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* Copyright 2022 Advanced Micro Devices, Inc.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
17  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19  * OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Authors: AMD
22  *
23  */
24 
25 #pragma once
26 
27 #include <stdint.h>
28 #include <stdbool.h>
29 #include <limits.h>
30 #include <stddef.h>
31 #include "vpe_assert.h"
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 #ifndef LLONG_MAX
38 #define LLONG_MAX 9223372036854775807ll
39 #endif
40 #ifndef LLONG_MIN
41 #define LLONG_MIN (-LLONG_MAX - 1ll)
42 #endif
43 
44 #define FIXED31_32_BITS_PER_FRACTIONAL_PART 32
45 #ifndef LLONG_MIN
46 #define LLONG_MIN (1LL << 63)
47 #endif
48 #ifndef LLONG_MAX
49 #define LLONG_MAX (-1LL >> 1)
50 #endif
51 
52 #ifndef ASSERT
53 #define ASSERT assert
54 #endif
55 
56 /*
57  * @brief
58  * Arithmetic operations on real numbers
59  * represented as fixed-point numbers.
60  * There are: 1 bit for sign,
61  * 31 bit for integer part,
62  * 32 bits for fractional part.
63  *
64  * @note
65  * Currently, overflows and underflows are asserted;
66  * no special result returned.
67  */
68 
69 struct fixed31_32 {
70     long long value;
71 };
72 
73 /*
74  * @brief
75  * Useful constants
76  */
77 
78 static const struct fixed31_32 vpe_fixpt_zero    = {0};
79 static const struct fixed31_32 vpe_fixpt_epsilon = {1LL};
80 static const struct fixed31_32 vpe_fixpt_half    = {0x80000000LL};
81 static const struct fixed31_32 vpe_fixpt_one     = {0x100000000LL};
82 
83 static const struct fixed31_32 vpe_fixpt_pi        = {13493037705LL};
84 static const struct fixed31_32 vpe_fixpt_two_pi    = {26986075409LL};
85 static const struct fixed31_32 vpe_fixpt_e         = {11674931555LL};
86 static const struct fixed31_32 vpe_fixpt_ln2       = {2977044471LL};
87 static const struct fixed31_32 vpe_fixpt_ln2_div_2 = {1488522236LL};
88 
89 /*
90  * @brief
91  * Initialization routines
92  */
93 
94 /*
95  * @brief
96  * result = numerator / denominator
97  */
98 struct fixed31_32 vpe_fixpt_from_fraction(long long numerator, long long denominator);
99 
100 /*
101  * @brief
102  * result = arg
103  */
vpe_fixpt_from_int(long long arg)104 static inline struct fixed31_32 vpe_fixpt_from_int(long long arg)
105 {
106     struct fixed31_32 res;
107 
108     res.value = (long long)arg << FIXED31_32_BITS_PER_FRACTIONAL_PART;
109 
110     return res;
111 }
112 
113 /*
114  * @brief
115  * Unary operators
116  */
117 
118 /*
119  * @brief
120  * result = -arg
121  */
vpe_fixpt_neg(struct fixed31_32 arg)122 static inline struct fixed31_32 vpe_fixpt_neg(struct fixed31_32 arg)
123 {
124     struct fixed31_32 res;
125 
126     res.value = -arg.value;
127 
128     return res;
129 }
130 
131 /*
132  * @brief
133  * result = abs(arg) := (arg >= 0) ? arg : -arg
134  */
vpe_fixpt_abs(struct fixed31_32 arg)135 static inline struct fixed31_32 vpe_fixpt_abs(struct fixed31_32 arg)
136 {
137     if (arg.value < 0)
138         return vpe_fixpt_neg(arg);
139     else
140         return arg;
141 }
142 
143 /*
144  * @brief
145  * Binary relational operators
146  */
147 
148 /*
149  * @brief
150  * result = arg1 < arg2
151  */
vpe_fixpt_lt(struct fixed31_32 arg1,struct fixed31_32 arg2)152 static inline bool vpe_fixpt_lt(struct fixed31_32 arg1, struct fixed31_32 arg2)
153 {
154     return arg1.value < arg2.value;
155 }
156 
157 /*
158  * @brief
159  * result = arg1 <= arg2
160  */
vpe_fixpt_le(struct fixed31_32 arg1,struct fixed31_32 arg2)161 static inline bool vpe_fixpt_le(struct fixed31_32 arg1, struct fixed31_32 arg2)
162 {
163     return arg1.value <= arg2.value;
164 }
165 
166 /*
167  * @brief
168  * result = arg1 == arg2
169  */
vpe_fixpt_eq(struct fixed31_32 arg1,struct fixed31_32 arg2)170 static inline bool vpe_fixpt_eq(struct fixed31_32 arg1, struct fixed31_32 arg2)
171 {
172     return arg1.value == arg2.value;
173 }
174 
175 /*
176  * @brief
177  * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
178  */
vpe_fixpt_min(struct fixed31_32 arg1,struct fixed31_32 arg2)179 static inline struct fixed31_32 vpe_fixpt_min(struct fixed31_32 arg1, struct fixed31_32 arg2)
180 {
181     if (arg1.value <= arg2.value)
182         return arg1;
183     else
184         return arg2;
185 }
186 
187 /*
188  * @brief
189  * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
190  */
vpe_fixpt_max(struct fixed31_32 arg1,struct fixed31_32 arg2)191 static inline struct fixed31_32 vpe_fixpt_max(struct fixed31_32 arg1, struct fixed31_32 arg2)
192 {
193     if (arg1.value <= arg2.value)
194         return arg2;
195     else
196         return arg1;
197 }
198 
199 /*
200  * @brief
201  *          | min_value, when arg <= min_value
202  * result = | arg, when min_value < arg < max_value
203  *          | max_value, when arg >= max_value
204  */
vpe_fixpt_clamp(struct fixed31_32 arg,struct fixed31_32 min_value,struct fixed31_32 max_value)205 static inline struct fixed31_32 vpe_fixpt_clamp(
206     struct fixed31_32 arg, struct fixed31_32 min_value, struct fixed31_32 max_value)
207 {
208     if (vpe_fixpt_le(arg, min_value))
209         return min_value;
210     else if (vpe_fixpt_le(max_value, arg))
211         return max_value;
212     else
213         return arg;
214 }
215 
216 /*
217  * @brief
218  * Binary shift operators
219  */
220 
221 /*
222  * @brief
223  * result = arg << shift
224  */
vpe_fixpt_shl(struct fixed31_32 arg,unsigned char shift)225 static inline struct fixed31_32 vpe_fixpt_shl(struct fixed31_32 arg, unsigned char shift)
226 {
227     VPE_ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
228                ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift))));
229 
230     arg.value = arg.value << shift;
231 
232     return arg;
233 }
234 
235 /*
236  * @brief
237  * result = arg >> shift
238  */
vpe_fixpt_shr(struct fixed31_32 arg,unsigned char shift)239 static inline struct fixed31_32 vpe_fixpt_shr(struct fixed31_32 arg, unsigned char shift)
240 {
241     bool negative = arg.value < 0;
242 
243     if (negative)
244         arg.value = -arg.value;
245     arg.value = arg.value >> shift;
246     if (negative)
247         arg.value = -arg.value;
248     return arg;
249 }
250 
251 /*
252  * @brief
253  * Binary additive operators
254  */
255 
256 /*
257  * @brief
258  * result = arg1 + arg2
259  */
vpe_fixpt_add(struct fixed31_32 arg1,struct fixed31_32 arg2)260 static inline struct fixed31_32 vpe_fixpt_add(struct fixed31_32 arg1, struct fixed31_32 arg2)
261 {
262     struct fixed31_32 res;
263 
264     VPE_ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
265                ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
266 
267     res.value = arg1.value + arg2.value;
268 
269     return res;
270 }
271 
272 /*
273  * @brief
274  * result = arg1 + arg2
275  */
vpe_fixpt_add_int(struct fixed31_32 arg1,int arg2)276 static inline struct fixed31_32 vpe_fixpt_add_int(struct fixed31_32 arg1, int arg2)
277 {
278     return vpe_fixpt_add(arg1, vpe_fixpt_from_int(arg2));
279 }
280 
281 /*
282  * @brief
283  * result = arg1 - arg2
284  */
vpe_fixpt_sub(struct fixed31_32 arg1,struct fixed31_32 arg2)285 static inline struct fixed31_32 vpe_fixpt_sub(struct fixed31_32 arg1, struct fixed31_32 arg2)
286 {
287     struct fixed31_32 res;
288 
289     VPE_ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
290                ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
291 
292     res.value = arg1.value - arg2.value;
293 
294     return res;
295 }
296 
297 /*
298  * @brief
299  * result = arg1 - arg2
300  */
vpe_fixpt_sub_int(struct fixed31_32 arg1,int arg2)301 static inline struct fixed31_32 vpe_fixpt_sub_int(struct fixed31_32 arg1, int arg2)
302 {
303     return vpe_fixpt_sub(arg1, vpe_fixpt_from_int(arg2));
304 }
305 
306 /*
307  * @brief
308  * Binary multiplicative operators
309  */
310 
311 /*
312  * @brief
313  * result = arg1 * arg2
314  */
315 struct fixed31_32 vpe_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2);
316 
317 /*
318  * @brief
319  * result = arg1 * arg2
320  */
vpe_fixpt_mul_int(struct fixed31_32 arg1,int arg2)321 static inline struct fixed31_32 vpe_fixpt_mul_int(struct fixed31_32 arg1, int arg2)
322 {
323     return vpe_fixpt_mul(arg1, vpe_fixpt_from_int(arg2));
324 }
325 
326 /*
327  * @brief
328  * result = square(arg) := arg * arg
329  */
330 struct fixed31_32 vpe_fixpt_sqr(struct fixed31_32 arg);
331 
332 /*
333  * @brief
334  * result = arg1 / arg2
335  */
vpe_fixpt_div_int(struct fixed31_32 arg1,long long arg2)336 static inline struct fixed31_32 vpe_fixpt_div_int(struct fixed31_32 arg1, long long arg2)
337 {
338     return vpe_fixpt_from_fraction(arg1.value, vpe_fixpt_from_int(arg2).value);
339 }
340 
341 /*
342  * @brief
343  * result = arg1 / arg2
344  */
vpe_fixpt_div(struct fixed31_32 arg1,struct fixed31_32 arg2)345 static inline struct fixed31_32 vpe_fixpt_div(struct fixed31_32 arg1, struct fixed31_32 arg2)
346 {
347     return vpe_fixpt_from_fraction(arg1.value, arg2.value);
348 }
349 
350 /*
351  * @brief
352  * Reciprocal function
353  */
354 
355 /*
356  * @brief
357  * result = reciprocal(arg) := 1 / arg
358  *
359  * @note
360  * No special actions taken in case argument is zero.
361  */
362 struct fixed31_32 vpe_fixpt_recip(struct fixed31_32 arg);
363 
364 /*
365  * @brief
366  * Trigonometric functions
367  */
368 
369 /*
370  * @brief
371  * result = sinc(arg) := sin(arg) / arg
372  *
373  * @note
374  * Argument specified in radians,
375  * internally it's normalized to [-2pi...2pi] range.
376  */
377 struct fixed31_32 vpe_fixpt_sinc(struct fixed31_32 arg);
378 
379 /*
380  * @brief
381  * result = sin(arg)
382  *
383  * @note
384  * Argument specified in radians,
385  * internally it's normalized to [-2pi...2pi] range.
386  */
387 struct fixed31_32 vpe_fixpt_sin(struct fixed31_32 arg);
388 
389 /*
390  * @brief
391  * result = cos(arg)
392  *
393  * @note
394  * Argument specified in radians
395  * and should be in [-2pi...2pi] range -
396  * passing arguments outside that range
397  * will cause incorrect result!
398  */
399 struct fixed31_32 vpe_fixpt_cos(struct fixed31_32 arg);
400 
401 /*
402  * @brief
403  * Transcendent functions
404  */
405 
406 /*
407  * @brief
408  * result = exp(arg)
409  *
410  * @note
411  * Currently, function is verified for abs(arg) <= 1.
412  */
413 struct fixed31_32 vpe_fixpt_exp(struct fixed31_32 arg);
414 
415 /*
416  * @brief
417  * result = log(arg)
418  *
419  * @note
420  * Currently, abs(arg) should be less than 1.
421  * No normalization is done.
422  * Currently, no special actions taken
423  * in case of invalid argument(s). Take care!
424  */
425 struct fixed31_32 vpe_fixpt_log(struct fixed31_32 arg);
426 
427 /*
428  * @brief
429  * Power function
430  */
431 
432 /*
433  * @brief
434  * result = pow(arg1, arg2)
435  *
436  * @note
437  * Currently, abs(arg1) should be less than 1. Take care!
438  */
vpe_fixpt_pow(struct fixed31_32 arg1,struct fixed31_32 arg2)439 static inline struct fixed31_32 vpe_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)
440 {
441     if (arg1.value == 0)
442         return arg2.value == 0 ? vpe_fixpt_one : vpe_fixpt_zero;
443 
444     return vpe_fixpt_exp(vpe_fixpt_mul(vpe_fixpt_log(arg1), arg2));
445 }
446 
447 /*
448  * @brief
449  * Rounding functions
450  */
451 
452 /*
453  * @brief
454  * result = floor(arg) := greatest integer lower than or equal to arg
455  */
vpe_fixpt_floor(struct fixed31_32 arg)456 static inline int vpe_fixpt_floor(struct fixed31_32 arg)
457 {
458     unsigned long long arg_value = (unsigned long long)(arg.value > 0 ? arg.value : -arg.value);
459 
460     if (arg.value >= 0)
461         return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
462     else
463         return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
464 }
465 
466 /*
467  * @brief
468  * result = round(arg) := integer nearest to arg
469  */
vpe_fixpt_round(struct fixed31_32 arg)470 static inline int vpe_fixpt_round(struct fixed31_32 arg)
471 {
472     unsigned long long arg_value = (unsigned long long)(arg.value > 0 ? arg.value : -arg.value);
473 
474     const long long summand = vpe_fixpt_half.value;
475 
476     VPE_ASSERT(LLONG_MAX - (long long)arg_value >= summand);
477 
478     arg_value += (unsigned long long)summand;
479 
480     if (arg.value >= 0)
481         return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
482     else
483         return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
484 }
485 
486 /*
487  * @brief
488  * result = ceil(arg) := lowest integer greater than or equal to arg
489  */
vpe_fixpt_ceil(struct fixed31_32 arg)490 static inline int vpe_fixpt_ceil(struct fixed31_32 arg)
491 {
492     unsigned long long arg_value = (unsigned long long)(arg.value > 0 ? arg.value : -arg.value);
493 
494     const long long summand = vpe_fixpt_one.value - vpe_fixpt_epsilon.value;
495 
496     VPE_ASSERT(LLONG_MAX - (long long)arg_value >= summand);
497 
498     arg_value += (unsigned long long)summand;
499 
500     if (arg.value >= 0)
501         return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
502     else
503         return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
504 }
505 
506 /* the following two function are used in scaler hw programming to convert fixed
507  * point value to format 2 bits from integer part and 19 bits from fractional
508  * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
509  * fractional
510  */
511 
512 unsigned int vpe_fixpt_u4d19(struct fixed31_32 arg);
513 
514 unsigned int vpe_fixpt_u3d19(struct fixed31_32 arg);
515 
516 unsigned int vpe_fixpt_u2d19(struct fixed31_32 arg);
517 
518 unsigned int vpe_fixpt_u0d19(struct fixed31_32 arg);
519 
520 unsigned int vpe_fixpt_clamp_u0d14(struct fixed31_32 arg);
521 
522 unsigned int vpe_fixpt_clamp_u0d10(struct fixed31_32 arg);
523 
524 int vpe_fixpt_s4d19(struct fixed31_32 arg);
525 
vpe_fixpt_truncate(struct fixed31_32 arg,unsigned int frac_bits)526 static inline struct fixed31_32 vpe_fixpt_truncate(struct fixed31_32 arg, unsigned int frac_bits)
527 {
528     bool negative = arg.value < 0;
529 
530     if (frac_bits >= FIXED31_32_BITS_PER_FRACTIONAL_PART) {
531         VPE_ASSERT(frac_bits == FIXED31_32_BITS_PER_FRACTIONAL_PART);
532         return arg;
533     }
534 
535     if (negative)
536         arg.value = -arg.value;
537     arg.value &= (~0ULL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);
538     if (negative)
539         arg.value = -arg.value;
540     return arg;
541 }
542 
543 unsigned int vpe_to_fixed_point(
544     unsigned int decimalBits, double value, unsigned int mask, double d_pix);
545 
546 #ifdef __cplusplus
547 }
548 #endif
549