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