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