| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef AVUTIL_SOFTFLOAT_H | ||
| 22 | #define AVUTIL_SOFTFLOAT_H | ||
| 23 | |||
| 24 | #include <stdint.h> | ||
| 25 | #include "common.h" | ||
| 26 | |||
| 27 | #include "avassert.h" | ||
| 28 | #include "softfloat_tables.h" | ||
| 29 | |||
| 30 | #define MIN_EXP -149 | ||
| 31 | #define MAX_EXP 126 | ||
| 32 | #define ONE_BITS 29 | ||
| 33 | |||
| 34 | typedef struct SoftFloat{ | ||
| 35 | int32_t mant; | ||
| 36 | int32_t exp; | ||
| 37 | }SoftFloat; | ||
| 38 | |||
| 39 | static const SoftFloat FLOAT_0 = { 0, MIN_EXP}; ///< 0.0 | ||
| 40 | static const SoftFloat FLOAT_05 = { 0x20000000, 0}; ///< 0.5 | ||
| 41 | static const SoftFloat FLOAT_1 = { 0x20000000, 1}; ///< 1.0 | ||
| 42 | static const SoftFloat FLOAT_EPSILON = { 0x29F16B12, -16}; ///< A small value | ||
| 43 | static const SoftFloat FLOAT_1584893192 = { 0x32B771ED, 1}; ///< 1.584893192 (10^.2) | ||
| 44 | static const SoftFloat FLOAT_100000 = { 0x30D40000, 17}; ///< 100000 | ||
| 45 | static const SoftFloat FLOAT_0999999 = { 0x3FFFFBCE, 0}; ///< 0.999999 | ||
| 46 | static const SoftFloat FLOAT_MIN = { 0x20000000, MIN_EXP}; | ||
| 47 | |||
| 48 | |||
| 49 | /** | ||
| 50 | * Convert a SoftFloat to a double precision float. | ||
| 51 | */ | ||
| 52 | static inline av_const double av_sf2double(SoftFloat v) { | ||
| 53 | v.exp -= ONE_BITS +1; | ||
| 54 | return ldexp(v.mant, v.exp); | ||
| 55 | } | ||
| 56 | |||
| 57 | 8669801 | static av_const SoftFloat av_normalize_sf(SoftFloat a){ | |
| 58 |
2/2✓ Branch 0 taken 8516501 times.
✓ Branch 1 taken 153300 times.
|
8669801 | if(a.mant){ |
| 59 | #if 1 | ||
| 60 |
2/2✓ Branch 0 taken 2600785 times.
✓ Branch 1 taken 8516501 times.
|
11117286 | while((a.mant + 0x1FFFFFFFU)<0x3FFFFFFFU){ |
| 61 | 2600785 | a.mant += a.mant; | |
| 62 | 2600785 | a.exp -= 1; | |
| 63 | } | ||
| 64 | #else | ||
| 65 | int s=ONE_BITS - av_log2(FFABS(a.mant)); | ||
| 66 | a.exp -= s; | ||
| 67 | a.mant <<= s; | ||
| 68 | #endif | ||
| 69 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8516501 times.
|
8516501 | if(a.exp < MIN_EXP){ |
| 70 | ✗ | a.exp = MIN_EXP; | |
| 71 | ✗ | a.mant= 0; | |
| 72 | } | ||
| 73 | }else{ | ||
| 74 | 153300 | a.exp= MIN_EXP; | |
| 75 | } | ||
| 76 | 8669801 | return a; | |
| 77 | } | ||
| 78 | |||
| 79 | 18108978 | static inline av_const SoftFloat av_normalize1_sf(SoftFloat a){ | |
| 80 | #if 1 | ||
| 81 |
2/2✓ Branch 0 taken 6405732 times.
✓ Branch 1 taken 11703246 times.
|
18108978 | if((int32_t)(a.mant + 0x40000000U) <= 0){ |
| 82 | 6405732 | a.exp++; | |
| 83 | 6405732 | a.mant>>=1; | |
| 84 | } | ||
| 85 | av_assert2(a.mant < 0x40000000 && a.mant > -0x40000000); | ||
| 86 | av_assert2(a.exp <= MAX_EXP); | ||
| 87 | 18108978 | return a; | |
| 88 | #elif 1 | ||
| 89 | int t= a.mant + 0x40000000 < 0; | ||
| 90 | return (SoftFloat){ a.mant>>t, a.exp+t}; | ||
| 91 | #else | ||
| 92 | int t= (a.mant + 0x3FFFFFFFU)>>31; | ||
| 93 | return (SoftFloat){a.mant>>t, a.exp+t}; | ||
| 94 | #endif | ||
| 95 | } | ||
| 96 | |||
| 97 | /** | ||
| 98 | * @return Will not be more denormalized than a*b. So if either input is | ||
| 99 | * normalized, then the output will not be worse then the other input. | ||
| 100 | * If both are normalized, then the output will be normalized. | ||
| 101 | */ | ||
| 102 | 8723947 | static inline av_const SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){ | |
| 103 | 8723947 | a.exp += b.exp; | |
| 104 | av_assert2((int32_t)((a.mant * (int64_t)b.mant) >> ONE_BITS) == (a.mant * (int64_t)b.mant) >> ONE_BITS); | ||
| 105 | 8723947 | a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS; | |
| 106 | 8723947 | a = av_normalize1_sf((SoftFloat){a.mant, a.exp - 1}); | |
| 107 |
3/4✓ Branch 0 taken 8327171 times.
✓ Branch 1 taken 396776 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8327171 times.
|
8723947 | if (!a.mant || a.exp < MIN_EXP) |
| 108 | 396776 | return FLOAT_0; | |
| 109 | 8327171 | return a; | |
| 110 | } | ||
| 111 | |||
| 112 | /** | ||
| 113 | * b has to be normalized and not zero. | ||
| 114 | * @return Will not be more denormalized than a. | ||
| 115 | */ | ||
| 116 | 715230 | static inline av_const SoftFloat av_div_sf(SoftFloat a, SoftFloat b){ | |
| 117 | 715230 | int64_t temp = (int64_t)a.mant * (1<<(ONE_BITS+1)); | |
| 118 | 715230 | temp /= b.mant; | |
| 119 | 715230 | a.exp -= b.exp; | |
| 120 | 715230 | a.mant = temp; | |
| 121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 715230 times.
|
715230 | while (a.mant != temp) { |
| 122 | ✗ | temp /= 2; | |
| 123 | ✗ | a.exp--; | |
| 124 | ✗ | a.mant = temp; | |
| 125 | } | ||
| 126 | 715230 | a = av_normalize1_sf(a); | |
| 127 |
3/4✓ Branch 0 taken 714012 times.
✓ Branch 1 taken 1218 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 714012 times.
|
715230 | if (!a.mant || a.exp < MIN_EXP) |
| 128 | 1218 | return FLOAT_0; | |
| 129 | 714012 | return a; | |
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Compares two SoftFloats. | ||
| 134 | * @returns < 0 if the first is less | ||
| 135 | * > 0 if the first is greater | ||
| 136 | * 0 if they are equal | ||
| 137 | */ | ||
| 138 | static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){ | ||
| 139 | int t= a.exp - b.exp; | ||
| 140 | if (t <-31) return - b.mant ; | ||
| 141 | else if (t < 0) return (a.mant >> (-t)) - b.mant ; | ||
| 142 | else if (t < 32) return a.mant - (b.mant >> t); | ||
| 143 | else return a.mant ; | ||
| 144 | } | ||
| 145 | |||
| 146 | /** | ||
| 147 | * Compares two SoftFloats. | ||
| 148 | * @returns 1 if a is greater than b, 0 otherwise | ||
| 149 | */ | ||
| 150 | 291082 | static inline av_const int av_gt_sf(SoftFloat a, SoftFloat b) | |
| 151 | { | ||
| 152 | 291082 | int t= a.exp - b.exp; | |
| 153 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 291082 times.
|
291082 | if (t <-31) return 0 > b.mant ; |
| 154 |
2/2✓ Branch 0 taken 163869 times.
✓ Branch 1 taken 127213 times.
|
291082 | else if (t < 0) return (a.mant >> (-t)) > b.mant ; |
| 155 |
1/2✓ Branch 0 taken 127213 times.
✗ Branch 1 not taken.
|
127213 | else if (t < 32) return a.mant > (b.mant >> t); |
| 156 | ✗ | else return a.mant > 0 ; | |
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * @returns the sum of 2 SoftFloats. | ||
| 161 | */ | ||
| 162 | 8247791 | static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){ | |
| 163 | 8247791 | int t= a.exp - b.exp; | |
| 164 |
2/2✓ Branch 0 taken 134526 times.
✓ Branch 1 taken 8113265 times.
|
8247791 | if (t <-31) return b; |
| 165 |
2/2✓ Branch 0 taken 1033624 times.
✓ Branch 1 taken 7079641 times.
|
8113265 | else if (t < 0) return av_normalize_sf(av_normalize1_sf((SoftFloat){ b.mant + (a.mant >> (-t)), b.exp})); |
| 166 |
2/2✓ Branch 0 taken 6820915 times.
✓ Branch 1 taken 258726 times.
|
7079641 | else if (t < 32) return av_normalize_sf(av_normalize1_sf((SoftFloat){ a.mant + (b.mant >> t ), a.exp})); |
| 167 | 258726 | else return a; | |
| 168 | } | ||
| 169 | |||
| 170 | /** | ||
| 171 | * @returns the difference of 2 SoftFloats. | ||
| 172 | */ | ||
| 173 | 333629 | static inline av_const SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){ | |
| 174 | 333629 | return av_add_sf(a, (SoftFloat){ -b.mant, b.exp}); | |
| 175 | } | ||
| 176 | |||
| 177 | //FIXME log, exp, pow | ||
| 178 | |||
| 179 | /** | ||
| 180 | * Converts a mantisse and exponent to a SoftFloat. | ||
| 181 | * This converts a fixed point value v with frac_bits fractional bits to a | ||
| 182 | * SoftFloat. | ||
| 183 | * @returns a SoftFloat with value v * 2^-frac_bits | ||
| 184 | */ | ||
| 185 | 815262 | static inline av_const SoftFloat av_int2sf(int v, int frac_bits){ | |
| 186 | 815262 | int exp_offset = 0; | |
| 187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 815262 times.
|
815262 | if(v <= INT_MIN + 1){ |
| 188 | ✗ | exp_offset = 1; | |
| 189 | ✗ | v>>=1; | |
| 190 | } | ||
| 191 | 815262 | return av_normalize_sf(av_normalize1_sf((SoftFloat){v, ONE_BITS + 1 - frac_bits + exp_offset})); | |
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Converts a SoftFloat to an integer. | ||
| 196 | * Rounding is to -inf. | ||
| 197 | */ | ||
| 198 | static inline av_const int av_sf2int(SoftFloat v, int frac_bits){ | ||
| 199 | v.exp += frac_bits - (ONE_BITS + 1); | ||
| 200 | if(v.exp >= 0) return v.mant << v.exp ; | ||
| 201 | else return v.mant >>(-v.exp); | ||
| 202 | } | ||
| 203 | |||
| 204 | /** | ||
| 205 | * Rounding-to-nearest used. | ||
| 206 | */ | ||
| 207 | 428135 | static av_always_inline SoftFloat av_sqrt_sf(SoftFloat val) | |
| 208 | { | ||
| 209 | int tabIndex, rem; | ||
| 210 | |||
| 211 |
2/2✓ Branch 0 taken 126160 times.
✓ Branch 1 taken 301975 times.
|
428135 | if (val.mant == 0) |
| 212 | 126160 | val.exp = MIN_EXP; | |
| 213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 301975 times.
|
301975 | else if (val.mant < 0) |
| 214 | ✗ | abort(); | |
| 215 | else | ||
| 216 | { | ||
| 217 | 301975 | tabIndex = (val.mant - 0x20000000) >> 20; | |
| 218 | |||
| 219 | 301975 | rem = val.mant & 0xFFFFF; | |
| 220 | 301975 | val.mant = (int)(((int64_t)av_sqrttbl_sf[tabIndex] * (0x100000 - rem) + | |
| 221 | 301975 | (int64_t)av_sqrttbl_sf[tabIndex + 1] * rem + | |
| 222 | 301975 | 0x80000) >> 20); | |
| 223 | 301975 | val.mant = (int)(((int64_t)av_sqr_exp_multbl_sf[val.exp & 1] * val.mant + | |
| 224 | 301975 | 0x10000000) >> 29); | |
| 225 | |||
| 226 |
2/2✓ Branch 0 taken 143712 times.
✓ Branch 1 taken 158263 times.
|
301975 | if (val.mant < 0x40000000) |
| 227 | 143712 | val.exp -= 2; | |
| 228 | else | ||
| 229 | 158263 | val.mant >>= 1; | |
| 230 | |||
| 231 | 301975 | val.exp = (val.exp >> 1) + 1; | |
| 232 | } | ||
| 233 | |||
| 234 | 428135 | return val; | |
| 235 | } | ||
| 236 | |||
| 237 | /** | ||
| 238 | * Rounding-to-nearest used. | ||
| 239 | * | ||
| 240 | * @param a angle in units of (1ULL<<30)/M_PI radians | ||
| 241 | * @param s pointer to where sine in units of (1<<30) is returned | ||
| 242 | * @param c pointer to where cosine in units of (1<<30) is returned | ||
| 243 | */ | ||
| 244 | 32256 | av_unused static void av_sincos_sf(int a, int *s, int *c) | |
| 245 | { | ||
| 246 | int idx, sign; | ||
| 247 | int sv, cv; | ||
| 248 | int st, ct; | ||
| 249 | |||
| 250 | 32256 | idx = a >> 26; | |
| 251 | 32256 | sign = (int32_t)((unsigned)idx << 27) >> 31; | |
| 252 | 32256 | cv = av_costbl_1_sf[idx & 0xf]; | |
| 253 | 32256 | cv = (cv ^ sign) - sign; | |
| 254 | |||
| 255 | 32256 | idx -= 8; | |
| 256 | 32256 | sign = (int32_t)((unsigned)idx << 27) >> 31; | |
| 257 | 32256 | sv = av_costbl_1_sf[idx & 0xf]; | |
| 258 | 32256 | sv = (sv ^ sign) - sign; | |
| 259 | |||
| 260 | 32256 | idx = a >> 21; | |
| 261 | 32256 | ct = av_costbl_2_sf[idx & 0x1f]; | |
| 262 | 32256 | st = av_sintbl_2_sf[idx & 0x1f]; | |
| 263 | |||
| 264 | 32256 | idx = (int)(((int64_t)cv * ct - (int64_t)sv * st + 0x20000000) >> 30); | |
| 265 | |||
| 266 | 32256 | sv = (int)(((int64_t)cv * st + (int64_t)sv * ct + 0x20000000) >> 30); | |
| 267 | |||
| 268 | 32256 | cv = idx; | |
| 269 | |||
| 270 | 32256 | idx = a >> 16; | |
| 271 | 32256 | ct = av_costbl_3_sf[idx & 0x1f]; | |
| 272 | 32256 | st = av_sintbl_3_sf[idx & 0x1f]; | |
| 273 | |||
| 274 | 32256 | idx = (int)(((int64_t)cv * ct - (int64_t)sv * st + 0x20000000) >> 30); | |
| 275 | |||
| 276 | 32256 | sv = (int)(((int64_t)cv * st + (int64_t)sv * ct + 0x20000000) >> 30); | |
| 277 | 32256 | cv = idx; | |
| 278 | |||
| 279 | 32256 | idx = a >> 11; | |
| 280 | |||
| 281 | 32256 | ct = (int)(((int64_t)av_costbl_4_sf[idx & 0x1f] * (0x800 - (a & 0x7ff)) + | |
| 282 | 32256 | (int64_t)av_costbl_4_sf[(idx & 0x1f)+1]*(a & 0x7ff) + | |
| 283 | 32256 | 0x400) >> 11); | |
| 284 | 32256 | st = (int)(((int64_t)av_sintbl_4_sf[idx & 0x1f] * (0x800 - (a & 0x7ff)) + | |
| 285 | 32256 | (int64_t)av_sintbl_4_sf[(idx & 0x1f) + 1] * (a & 0x7ff) + | |
| 286 | 32256 | 0x400) >> 11); | |
| 287 | |||
| 288 | 32256 | *c = (int)(((int64_t)cv * ct - (int64_t)sv * st + 0x20000000) >> 30); | |
| 289 | |||
| 290 | 32256 | *s = (int)(((int64_t)cv * st + (int64_t)sv * ct + 0x20000000) >> 30); | |
| 291 | 32256 | } | |
| 292 | |||
| 293 | #endif /* AVUTIL_SOFTFLOAT_H */ | ||
| 294 |