Home | History | Annotate | Line # | Download | only in include
      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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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