This source file includes following definitions.
- abs_i64
- bw_int_to_fixed_nonconst
- bw_frc_to_fixed
- bw_floor2
- bw_ceil2
- bw_mul
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 #include "dm_services.h"
  26 #include "bw_fixed.h"
  27 
  28 
  29 #define MIN_I64 \
  30         (int64_t)(-(1LL << 63))
  31 
  32 #define MAX_I64 \
  33         (int64_t)((1ULL << 63) - 1)
  34 
  35 #define FRACTIONAL_PART_MASK \
  36         ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1)
  37 
  38 #define GET_FRACTIONAL_PART(x) \
  39         (FRACTIONAL_PART_MASK & (x))
  40 
  41 static uint64_t abs_i64(int64_t arg)
  42 {
  43         if (arg >= 0)
  44                 return (uint64_t)(arg);
  45         else
  46                 return (uint64_t)(-arg);
  47 }
  48 
  49 struct bw_fixed bw_int_to_fixed_nonconst(int64_t value)
  50 {
  51         struct bw_fixed res;
  52         ASSERT(value < BW_FIXED_MAX_I32 && value > BW_FIXED_MIN_I32);
  53         res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART;
  54         return res;
  55 }
  56 
  57 struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
  58 {
  59         struct bw_fixed res;
  60         bool arg1_negative = numerator < 0;
  61         bool arg2_negative = denominator < 0;
  62         uint64_t arg1_value;
  63         uint64_t arg2_value;
  64         uint64_t remainder;
  65 
  66         
  67         uint64_t res_value;
  68 
  69         ASSERT(denominator != 0);
  70 
  71         arg1_value = abs_i64(numerator);
  72         arg2_value = abs_i64(denominator);
  73         res_value = div64_u64_rem(arg1_value, arg2_value, &remainder);
  74 
  75         ASSERT(res_value <= BW_FIXED_MAX_I32);
  76 
  77         
  78         {
  79                 uint32_t i = BW_FIXED_BITS_PER_FRACTIONAL_PART;
  80 
  81                 do
  82                 {
  83                         remainder <<= 1;
  84 
  85                         res_value <<= 1;
  86 
  87                         if (remainder >= arg2_value)
  88                         {
  89                                 res_value |= 1;
  90                                 remainder -= arg2_value;
  91                         }
  92                 } while (--i != 0);
  93         }
  94 
  95         
  96         {
  97                 uint64_t summand = (remainder << 1) >= arg2_value;
  98 
  99                 ASSERT(res_value <= MAX_I64 - summand);
 100 
 101                 res_value += summand;
 102         }
 103 
 104         res.value = (int64_t)(res_value);
 105 
 106         if (arg1_negative ^ arg2_negative)
 107                 res.value = -res.value;
 108         return res;
 109 }
 110 
 111 struct bw_fixed bw_floor2(
 112         const struct bw_fixed arg,
 113         const struct bw_fixed significance)
 114 {
 115         struct bw_fixed result;
 116         int64_t multiplicand;
 117 
 118         multiplicand = div64_s64(arg.value, abs_i64(significance.value));
 119         result.value = abs_i64(significance.value) * multiplicand;
 120         ASSERT(abs_i64(result.value) <= abs_i64(arg.value));
 121         return result;
 122 }
 123 
 124 struct bw_fixed bw_ceil2(
 125         const struct bw_fixed arg,
 126         const struct bw_fixed significance)
 127 {
 128         struct bw_fixed result;
 129         int64_t multiplicand;
 130 
 131         multiplicand = div64_s64(arg.value, abs_i64(significance.value));
 132         result.value = abs_i64(significance.value) * multiplicand;
 133         if (abs_i64(result.value) < abs_i64(arg.value)) {
 134                 if (arg.value < 0)
 135                         result.value -= abs_i64(significance.value);
 136                 else
 137                         result.value += abs_i64(significance.value);
 138         }
 139         return result;
 140 }
 141 
 142 struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2)
 143 {
 144         struct bw_fixed res;
 145 
 146         bool arg1_negative = arg1.value < 0;
 147         bool arg2_negative = arg2.value < 0;
 148 
 149         uint64_t arg1_value = abs_i64(arg1.value);
 150         uint64_t arg2_value = abs_i64(arg2.value);
 151 
 152         uint64_t arg1_int = BW_FIXED_GET_INTEGER_PART(arg1_value);
 153         uint64_t arg2_int = BW_FIXED_GET_INTEGER_PART(arg2_value);
 154 
 155         uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
 156         uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
 157 
 158         uint64_t tmp;
 159 
 160         res.value = arg1_int * arg2_int;
 161 
 162         ASSERT(res.value <= BW_FIXED_MAX_I32);
 163 
 164         res.value <<= BW_FIXED_BITS_PER_FRACTIONAL_PART;
 165 
 166         tmp = arg1_int * arg2_fra;
 167 
 168         ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
 169 
 170         res.value += tmp;
 171 
 172         tmp = arg2_int * arg1_fra;
 173 
 174         ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
 175 
 176         res.value += tmp;
 177 
 178         tmp = arg1_fra * arg2_fra;
 179 
 180         tmp = (tmp >> BW_FIXED_BITS_PER_FRACTIONAL_PART) +
 181                 (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value));
 182 
 183         ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
 184 
 185         res.value += tmp;
 186 
 187         if (arg1_negative ^ arg2_negative)
 188                 res.value = -res.value;
 189         return res;
 190 }
 191