Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #ifndef __DAL_FIXED31_32_H__
0027 #define __DAL_FIXED31_32_H__
0028 
0029 #ifndef LLONG_MAX
0030 #define LLONG_MAX 9223372036854775807ll
0031 #endif
0032 #ifndef LLONG_MIN
0033 #define LLONG_MIN (-LLONG_MAX - 1ll)
0034 #endif
0035 
0036 #define FIXED31_32_BITS_PER_FRACTIONAL_PART 32
0037 #ifndef LLONG_MIN
0038 #define LLONG_MIN (1LL<<63)
0039 #endif
0040 #ifndef LLONG_MAX
0041 #define LLONG_MAX (-1LL>>1)
0042 #endif
0043 
0044 /*
0045  * @brief
0046  * Arithmetic operations on real numbers
0047  * represented as fixed-point numbers.
0048  * There are: 1 bit for sign,
0049  * 31 bit for integer part,
0050  * 32 bits for fractional part.
0051  *
0052  * @note
0053  * Currently, overflows and underflows are asserted;
0054  * no special result returned.
0055  */
0056 
0057 struct fixed31_32 {
0058     long long value;
0059 };
0060 
0061 
0062 /*
0063  * @brief
0064  * Useful constants
0065  */
0066 
0067 static const struct fixed31_32 dc_fixpt_zero = { 0 };
0068 static const struct fixed31_32 dc_fixpt_epsilon = { 1LL };
0069 static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL };
0070 static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL };
0071 
0072 /*
0073  * @brief
0074  * Initialization routines
0075  */
0076 
0077 /*
0078  * @brief
0079  * result = numerator / denominator
0080  */
0081 struct fixed31_32 dc_fixpt_from_fraction(long long numerator, long long denominator);
0082 
0083 /*
0084  * @brief
0085  * result = arg
0086  */
0087 static inline struct fixed31_32 dc_fixpt_from_int(int arg)
0088 {
0089     struct fixed31_32 res;
0090 
0091     res.value = (long long) arg << FIXED31_32_BITS_PER_FRACTIONAL_PART;
0092 
0093     return res;
0094 }
0095 
0096 /*
0097  * @brief
0098  * Unary operators
0099  */
0100 
0101 /*
0102  * @brief
0103  * result = -arg
0104  */
0105 static inline struct fixed31_32 dc_fixpt_neg(struct fixed31_32 arg)
0106 {
0107     struct fixed31_32 res;
0108 
0109     res.value = -arg.value;
0110 
0111     return res;
0112 }
0113 
0114 /*
0115  * @brief
0116  * result = abs(arg) := (arg >= 0) ? arg : -arg
0117  */
0118 static inline struct fixed31_32 dc_fixpt_abs(struct fixed31_32 arg)
0119 {
0120     if (arg.value < 0)
0121         return dc_fixpt_neg(arg);
0122     else
0123         return arg;
0124 }
0125 
0126 /*
0127  * @brief
0128  * Binary relational operators
0129  */
0130 
0131 /*
0132  * @brief
0133  * result = arg1 < arg2
0134  */
0135 static inline bool dc_fixpt_lt(struct fixed31_32 arg1, struct fixed31_32 arg2)
0136 {
0137     return arg1.value < arg2.value;
0138 }
0139 
0140 /*
0141  * @brief
0142  * result = arg1 <= arg2
0143  */
0144 static inline bool dc_fixpt_le(struct fixed31_32 arg1, struct fixed31_32 arg2)
0145 {
0146     return arg1.value <= arg2.value;
0147 }
0148 
0149 /*
0150  * @brief
0151  * result = arg1 == arg2
0152  */
0153 static inline bool dc_fixpt_eq(struct fixed31_32 arg1, struct fixed31_32 arg2)
0154 {
0155     return arg1.value == arg2.value;
0156 }
0157 
0158 /*
0159  * @brief
0160  * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
0161  */
0162 static inline struct fixed31_32 dc_fixpt_min(struct fixed31_32 arg1, struct fixed31_32 arg2)
0163 {
0164     if (arg1.value <= arg2.value)
0165         return arg1;
0166     else
0167         return arg2;
0168 }
0169 
0170 /*
0171  * @brief
0172  * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
0173  */
0174 static inline struct fixed31_32 dc_fixpt_max(struct fixed31_32 arg1, struct fixed31_32 arg2)
0175 {
0176     if (arg1.value <= arg2.value)
0177         return arg2;
0178     else
0179         return arg1;
0180 }
0181 
0182 /*
0183  * @brief
0184  *          | min_value, when arg <= min_value
0185  * result = | arg, when min_value < arg < max_value
0186  *          | max_value, when arg >= max_value
0187  */
0188 static inline struct fixed31_32 dc_fixpt_clamp(
0189     struct fixed31_32 arg,
0190     struct fixed31_32 min_value,
0191     struct fixed31_32 max_value)
0192 {
0193     if (dc_fixpt_le(arg, min_value))
0194         return min_value;
0195     else if (dc_fixpt_le(max_value, arg))
0196         return max_value;
0197     else
0198         return arg;
0199 }
0200 
0201 /*
0202  * @brief
0203  * Binary shift operators
0204  */
0205 
0206 /*
0207  * @brief
0208  * result = arg << shift
0209  */
0210 static inline struct fixed31_32 dc_fixpt_shl(struct fixed31_32 arg, unsigned char shift)
0211 {
0212     ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
0213         ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift))));
0214 
0215     arg.value = arg.value << shift;
0216 
0217     return arg;
0218 }
0219 
0220 /*
0221  * @brief
0222  * result = arg >> shift
0223  */
0224 static inline struct fixed31_32 dc_fixpt_shr(struct fixed31_32 arg, unsigned char shift)
0225 {
0226     bool negative = arg.value < 0;
0227 
0228     if (negative)
0229         arg.value = -arg.value;
0230     arg.value = arg.value >> shift;
0231     if (negative)
0232         arg.value = -arg.value;
0233     return arg;
0234 }
0235 
0236 /*
0237  * @brief
0238  * Binary additive operators
0239  */
0240 
0241 /*
0242  * @brief
0243  * result = arg1 + arg2
0244  */
0245 static inline struct fixed31_32 dc_fixpt_add(struct fixed31_32 arg1, struct fixed31_32 arg2)
0246 {
0247     struct fixed31_32 res;
0248 
0249     ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
0250         ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
0251 
0252     res.value = arg1.value + arg2.value;
0253 
0254     return res;
0255 }
0256 
0257 /*
0258  * @brief
0259  * result = arg1 + arg2
0260  */
0261 static inline struct fixed31_32 dc_fixpt_add_int(struct fixed31_32 arg1, int arg2)
0262 {
0263     return dc_fixpt_add(arg1, dc_fixpt_from_int(arg2));
0264 }
0265 
0266 /*
0267  * @brief
0268  * result = arg1 - arg2
0269  */
0270 static inline struct fixed31_32 dc_fixpt_sub(struct fixed31_32 arg1, struct fixed31_32 arg2)
0271 {
0272     struct fixed31_32 res;
0273 
0274     ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
0275         ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
0276 
0277     res.value = arg1.value - arg2.value;
0278 
0279     return res;
0280 }
0281 
0282 /*
0283  * @brief
0284  * result = arg1 - arg2
0285  */
0286 static inline struct fixed31_32 dc_fixpt_sub_int(struct fixed31_32 arg1, int arg2)
0287 {
0288     return dc_fixpt_sub(arg1, dc_fixpt_from_int(arg2));
0289 }
0290 
0291 
0292 /*
0293  * @brief
0294  * Binary multiplicative operators
0295  */
0296 
0297 /*
0298  * @brief
0299  * result = arg1 * arg2
0300  */
0301 struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2);
0302 
0303 
0304 /*
0305  * @brief
0306  * result = arg1 * arg2
0307  */
0308 static inline struct fixed31_32 dc_fixpt_mul_int(struct fixed31_32 arg1, int arg2)
0309 {
0310     return dc_fixpt_mul(arg1, dc_fixpt_from_int(arg2));
0311 }
0312 
0313 /*
0314  * @brief
0315  * result = square(arg) := arg * arg
0316  */
0317 struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg);
0318 
0319 /*
0320  * @brief
0321  * result = arg1 / arg2
0322  */
0323 static inline struct fixed31_32 dc_fixpt_div_int(struct fixed31_32 arg1, long long arg2)
0324 {
0325     return dc_fixpt_from_fraction(arg1.value, dc_fixpt_from_int((int)arg2).value);
0326 }
0327 
0328 /*
0329  * @brief
0330  * result = arg1 / arg2
0331  */
0332 static inline struct fixed31_32 dc_fixpt_div(struct fixed31_32 arg1, struct fixed31_32 arg2)
0333 {
0334     return dc_fixpt_from_fraction(arg1.value, arg2.value);
0335 }
0336 
0337 /*
0338  * @brief
0339  * Reciprocal function
0340  */
0341 
0342 /*
0343  * @brief
0344  * result = reciprocal(arg) := 1 / arg
0345  *
0346  * @note
0347  * No special actions taken in case argument is zero.
0348  */
0349 struct fixed31_32 dc_fixpt_recip(struct fixed31_32 arg);
0350 
0351 /*
0352  * @brief
0353  * Trigonometric functions
0354  */
0355 
0356 /*
0357  * @brief
0358  * result = sinc(arg) := sin(arg) / arg
0359  *
0360  * @note
0361  * Argument specified in radians,
0362  * internally it's normalized to [-2pi...2pi] range.
0363  */
0364 struct fixed31_32 dc_fixpt_sinc(struct fixed31_32 arg);
0365 
0366 /*
0367  * @brief
0368  * result = sin(arg)
0369  *
0370  * @note
0371  * Argument specified in radians,
0372  * internally it's normalized to [-2pi...2pi] range.
0373  */
0374 struct fixed31_32 dc_fixpt_sin(struct fixed31_32 arg);
0375 
0376 /*
0377  * @brief
0378  * result = cos(arg)
0379  *
0380  * @note
0381  * Argument specified in radians
0382  * and should be in [-2pi...2pi] range -
0383  * passing arguments outside that range
0384  * will cause incorrect result!
0385  */
0386 struct fixed31_32 dc_fixpt_cos(struct fixed31_32 arg);
0387 
0388 /*
0389  * @brief
0390  * Transcendent functions
0391  */
0392 
0393 /*
0394  * @brief
0395  * result = exp(arg)
0396  *
0397  * @note
0398  * Currently, function is verified for abs(arg) <= 1.
0399  */
0400 struct fixed31_32 dc_fixpt_exp(struct fixed31_32 arg);
0401 
0402 /*
0403  * @brief
0404  * result = log(arg)
0405  *
0406  * @note
0407  * Currently, abs(arg) should be less than 1.
0408  * No normalization is done.
0409  * Currently, no special actions taken
0410  * in case of invalid argument(s). Take care!
0411  */
0412 struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg);
0413 
0414 /*
0415  * @brief
0416  * Power function
0417  */
0418 
0419 /*
0420  * @brief
0421  * result = pow(arg1, arg2)
0422  *
0423  * @note
0424  * Currently, abs(arg1) should be less than 1. Take care!
0425  */
0426 static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)
0427 {
0428     if (arg1.value == 0)
0429         return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero;
0430 
0431     return dc_fixpt_exp(
0432         dc_fixpt_mul(
0433             dc_fixpt_log(arg1),
0434             arg2));
0435 }
0436 
0437 /*
0438  * @brief
0439  * Rounding functions
0440  */
0441 
0442 /*
0443  * @brief
0444  * result = floor(arg) := greatest integer lower than or equal to arg
0445  */
0446 static inline int dc_fixpt_floor(struct fixed31_32 arg)
0447 {
0448     unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
0449 
0450     if (arg.value >= 0)
0451         return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
0452     else
0453         return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
0454 }
0455 
0456 /*
0457  * @brief
0458  * result = round(arg) := integer nearest to arg
0459  */
0460 static inline int dc_fixpt_round(struct fixed31_32 arg)
0461 {
0462     unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
0463 
0464     const long long summand = dc_fixpt_half.value;
0465 
0466     ASSERT(LLONG_MAX - (long long)arg_value >= summand);
0467 
0468     arg_value += summand;
0469 
0470     if (arg.value >= 0)
0471         return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
0472     else
0473         return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
0474 }
0475 
0476 /*
0477  * @brief
0478  * result = ceil(arg) := lowest integer greater than or equal to arg
0479  */
0480 static inline int dc_fixpt_ceil(struct fixed31_32 arg)
0481 {
0482     unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
0483 
0484     const long long summand = dc_fixpt_one.value -
0485         dc_fixpt_epsilon.value;
0486 
0487     ASSERT(LLONG_MAX - (long long)arg_value >= summand);
0488 
0489     arg_value += summand;
0490 
0491     if (arg.value >= 0)
0492         return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
0493     else
0494         return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
0495 }
0496 
0497 /* the following two function are used in scaler hw programming to convert fixed
0498  * point value to format 2 bits from integer part and 19 bits from fractional
0499  * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
0500  * fractional
0501  */
0502 
0503 unsigned int dc_fixpt_u4d19(struct fixed31_32 arg);
0504 
0505 unsigned int dc_fixpt_u3d19(struct fixed31_32 arg);
0506 
0507 unsigned int dc_fixpt_u2d19(struct fixed31_32 arg);
0508 
0509 unsigned int dc_fixpt_u0d19(struct fixed31_32 arg);
0510 
0511 unsigned int dc_fixpt_clamp_u0d14(struct fixed31_32 arg);
0512 
0513 unsigned int dc_fixpt_clamp_u0d10(struct fixed31_32 arg);
0514 
0515 int dc_fixpt_s4d19(struct fixed31_32 arg);
0516 
0517 static inline struct fixed31_32 dc_fixpt_truncate(struct fixed31_32 arg, unsigned int frac_bits)
0518 {
0519     bool negative = arg.value < 0;
0520 
0521     if (frac_bits >= FIXED31_32_BITS_PER_FRACTIONAL_PART) {
0522         ASSERT(frac_bits == FIXED31_32_BITS_PER_FRACTIONAL_PART);
0523         return arg;
0524     }
0525 
0526     if (negative)
0527         arg.value = -arg.value;
0528     arg.value &= (~0LL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);
0529     if (negative)
0530         arg.value = -arg.value;
0531     return arg;
0532 }
0533 
0534 #endif