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