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 | static av_unused 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 |