1// SPDX-License-Identifier: Apache-2.0
2// ----------------------------------------------------------------------------
3// Copyright 2011-2021 Arm Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License"); you may not
6// use this file except in compliance with the License. You may obtain a copy
7// of the License at:
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14// License for the specific language governing permissions and limitations
15// under the License.
16// ----------------------------------------------------------------------------
17
18/**
19 * @brief Soft-float library for IEEE-754.
20 */
21#if (ASTCENC_F16C == 0) && (ASTCENC_NEON == 0)
22
23#include "astcenc_mathlib.h"
24
25/* sized soft-float types. These are mapped to the sized integer
26 types of C99, instead of C's floating-point types; this is because
27 the library needs to maintain exact, bit-level control on all
28 operations on these data types. */
29typedef uint16_t sf16;
30typedef uint32_t sf32;
31
32/******************************************
33 helper functions and their lookup tables
34 ******************************************/
35/* count leading zeros functions. Only used when the input is nonzero. */
36
37#if defined(__GNUC__) && (defined(__i386) || defined(__amd64))
38#elif defined(__arm__) && defined(__ARMCC_VERSION)
39#elif defined(__arm__) && defined(__GNUC__)
40#else
41 /* table used for the slow default versions. */
42 static const uint8_t clz_table[256] =
43 {
44 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
45 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
46 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
47 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
48 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
49 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
50 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
51 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
60 };
61#endif
62
63/*
64 32-bit count-leading-zeros function: use the Assembly instruction whenever possible. */
65static uint32_t clz32(uint32_t inp)
66{
67 #if defined(__GNUC__) && (defined(__i386) || defined(__amd64))
68 uint32_t bsr;
69 __asm__("bsrl %1, %0": "=r"(bsr):"r"(inp | 1));
70 return 31 - bsr;
71 #else
72 #if defined(__arm__) && defined(__ARMCC_VERSION)
73 return __clz(inp); /* armcc builtin */
74 #else
75 #if defined(__arm__) && defined(__GNUC__)
76 uint32_t lz;
77 __asm__("clz %0, %1": "=r"(lz):"r"(inp));
78 return lz;
79 #else
80 /* slow default version */
81 uint32_t summa = 24;
82 if (inp >= UINT32_C(0x10000))
83 {
84 inp >>= 16;
85 summa -= 16;
86 }
87 if (inp >= UINT32_C(0x100))
88 {
89 inp >>= 8;
90 summa -= 8;
91 }
92 return summa + clz_table[inp];
93 #endif
94 #endif
95 #endif
96}
97
98/* the five rounding modes that IEEE-754r defines */
99typedef enum
100{
101 SF_UP = 0, /* round towards positive infinity */
102 SF_DOWN = 1, /* round towards negative infinity */
103 SF_TOZERO = 2, /* round towards zero */
104 SF_NEARESTEVEN = 3, /* round toward nearest value; if mid-between, round to even value */
105 SF_NEARESTAWAY = 4 /* round toward nearest value; if mid-between, round away from zero */
106} roundmode;
107
108
109static uint32_t rtne_shift32(uint32_t inp, uint32_t shamt)
110{
111 uint32_t vl1 = UINT32_C(1) << shamt;
112 uint32_t inp2 = inp + (vl1 >> 1); /* added 0.5 ULP */
113 uint32_t msk = (inp | UINT32_C(1)) & vl1; /* nonzero if odd. '| 1' forces it to 1 if the shamt is 0. */
114 msk--; /* negative if even, nonnegative if odd. */
115 inp2 -= (msk >> 31); /* subtract epsilon before shift if even. */
116 inp2 >>= shamt;
117 return inp2;
118}
119
120static uint32_t rtna_shift32(uint32_t inp, uint32_t shamt)
121{
122 uint32_t vl1 = (UINT32_C(1) << shamt) >> 1;
123 inp += vl1;
124 inp >>= shamt;
125 return inp;
126}
127
128static uint32_t rtup_shift32(uint32_t inp, uint32_t shamt)
129{
130 uint32_t vl1 = UINT32_C(1) << shamt;
131 inp += vl1;
132 inp--;
133 inp >>= shamt;
134 return inp;
135}
136
137/* convert from FP16 to FP32. */
138static sf32 sf16_to_sf32(sf16 inp)
139{
140 uint32_t inpx = inp;
141
142 /*
143 This table contains, for every FP16 sign/exponent value combination,
144 the difference between the input FP16 value and the value obtained
145 by shifting the correct FP32 result right by 13 bits.
146 This table allows us to handle every case except denormals and NaN
147 with just 1 table lookup, 2 shifts and 1 add.
148 */
149
150 #define WITH_MSB(a) (UINT32_C(a) | (1u << 31))
151 static const uint32_t tbl[64] =
152 {
153 WITH_MSB(0x00000), 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000,
154 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000,
155 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000,
156 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, WITH_MSB(0x38000),
157 WITH_MSB(0x38000), 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000,
158 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000,
159 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000,
160 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, 0x54000, WITH_MSB(0x70000)
161 };
162
163 uint32_t res = tbl[inpx >> 10];
164 res += inpx;
165
166 /* Normal cases: MSB of 'res' not set. */
167 if ((res & WITH_MSB(0)) == 0)
168 {
169 return res << 13;
170 }
171
172 /* Infinity and Zero: 10 LSB of 'res' not set. */
173 if ((res & 0x3FF) == 0)
174 {
175 return res << 13;
176 }
177
178 /* NaN: the exponent field of 'inp' is non-zero. */
179 if ((inpx & 0x7C00) != 0)
180 {
181 /* All NaNs are quietened. */
182 return (res << 13) | 0x400000;
183 }
184
185 /* Denormal cases */
186 uint32_t sign = (inpx & 0x8000) << 16;
187 uint32_t mskval = inpx & 0x7FFF;
188 uint32_t leadingzeroes = clz32(mskval);
189 mskval <<= leadingzeroes;
190 return (mskval >> 8) + ((0x85 - leadingzeroes) << 23) + sign;
191}
192
193/* Conversion routine that converts from FP32 to FP16. It supports denormals and all rounding modes. If a NaN is given as input, it is quietened. */
194static sf16 sf32_to_sf16(sf32 inp, roundmode rmode)
195{
196 /* for each possible sign/exponent combination, store a case index. This gives a 512-byte table */
197 static const uint8_t tab[512] {
198 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
199 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
200 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
201 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
202 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
203 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
204 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
205 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
206 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 40,
207 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
208 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
209 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
210 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
211 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
212 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
213 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 50,
214
215 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
216 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
217 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
218 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
219 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
220 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
221 15, 15, 15, 15, 15, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
222 25, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
223 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 45,
224 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
225 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
226 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
227 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
228 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
229 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
230 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 55,
231 };
232
233 /* many of the cases below use a case-dependent magic constant. So we look up a magic constant before actually performing the switch. This table allows us to group cases, thereby minimizing code
234 size. */
235 static const uint32_t tabx[60] {
236 UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0x8000), UINT32_C(0x80000000), UINT32_C(0x8000), UINT32_C(0x8000), UINT32_C(0x8000),
237 UINT32_C(1), UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0x8000), UINT32_C(0x8001), UINT32_C(0x8000), UINT32_C(0x8000), UINT32_C(0x8000),
238 UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0), UINT32_C(0x8000), UINT32_C(0x8000), UINT32_C(0x8000), UINT32_C(0x8000), UINT32_C(0x8000),
239 UINT32_C(0xC8001FFF), UINT32_C(0xC8000000), UINT32_C(0xC8000000), UINT32_C(0xC8000FFF), UINT32_C(0xC8001000),
240 UINT32_C(0x58000000), UINT32_C(0x38001FFF), UINT32_C(0x58000000), UINT32_C(0x58000FFF), UINT32_C(0x58001000),
241 UINT32_C(0x7C00), UINT32_C(0x7BFF), UINT32_C(0x7BFF), UINT32_C(0x7C00), UINT32_C(0x7C00),
242 UINT32_C(0xFBFF), UINT32_C(0xFC00), UINT32_C(0xFBFF), UINT32_C(0xFC00), UINT32_C(0xFC00),
243 UINT32_C(0x90000000), UINT32_C(0x90000000), UINT32_C(0x90000000), UINT32_C(0x90000000), UINT32_C(0x90000000),
244 UINT32_C(0x20000000), UINT32_C(0x20000000), UINT32_C(0x20000000), UINT32_C(0x20000000), UINT32_C(0x20000000)
245 };
246
247 uint32_t p;
248 uint32_t idx = rmode + tab[inp >> 23];
249 uint32_t vlx = tabx[idx];
250 switch (idx)
251 {
252 /*
253 Positive number which may be Infinity or NaN.
254 We need to check whether it is NaN; if it is, quieten it by setting the top bit of the mantissa.
255 (If we don't do this quieting, then a NaN that is distinguished only by having
256 its low-order bits set, would be turned into an INF. */
257 case 50:
258 case 51:
259 case 52:
260 case 53:
261 case 54:
262 case 55:
263 case 56:
264 case 57:
265 case 58:
266 case 59:
267 /*
268 the input value is 0x7F800000 or 0xFF800000 if it is INF.
269 By subtracting 1, we get 7F7FFFFF or FF7FFFFF, that is, bit 23 becomes zero.
270 For NaNs, however, this operation will keep bit 23 with the value 1.
271 We can then extract bit 23, and logical-OR bit 9 of the result with this
272 bit in order to quieten the NaN (a Quiet NaN is a NaN where the top bit
273 of the mantissa is set.)
274 */
275 p = (inp - 1) & UINT32_C(0x800000); /* zero if INF, nonzero if NaN. */
276 return static_cast<sf16>(((inp + vlx) >> 13) | (p >> 14));
277 /*
278 positive, exponent = 0, round-mode == UP; need to check whether number actually is 0.
279 If it is, then return 0, else return 1 (the smallest representable nonzero number)
280 */
281 case 0:
282 /*
283 -inp will set the MSB if the input number is nonzero.
284 Thus (-inp) >> 31 will turn into 0 if the input number is 0 and 1 otherwise.
285 */
286 return static_cast<sf16>(static_cast<uint32_t>((-static_cast<int32_t>(inp))) >> 31);
287
288 /*
289 negative, exponent = , round-mode == DOWN, need to check whether number is
290 actually 0. If it is, return 0x8000 ( float -0.0 )
291 Else return the smallest negative number ( 0x8001 ) */
292 case 6:
293 /*
294 in this case 'vlx' is 0x80000000. By subtracting the input value from it,
295 we obtain a value that is 0 if the input value is in fact zero and has
296 the MSB set if it isn't. We then right-shift the value by 31 places to
297 get a value that is 0 if the input is -0.0 and 1 otherwise.
298 */
299 return static_cast<sf16>(((vlx - inp) >> 31) + UINT32_C(0x8000));
300
301 /*
302 for all other cases involving underflow/overflow, we don't need to
303 do actual tests; we just return 'vlx'.
304 */
305 case 1:
306 case 2:
307 case 3:
308 case 4:
309 case 5:
310 case 7:
311 case 8:
312 case 9:
313 case 10:
314 case 11:
315 case 12:
316 case 13:
317 case 14:
318 case 15:
319 case 16:
320 case 17:
321 case 18:
322 case 19:
323 case 40:
324 case 41:
325 case 42:
326 case 43:
327 case 44:
328 case 45:
329 case 46:
330 case 47:
331 case 48:
332 case 49:
333 return static_cast<sf16>(vlx);
334
335 /*
336 for normal numbers, 'vlx' is the difference between the FP32 value of a number and the
337 FP16 representation of the same number left-shifted by 13 places. In addition, a rounding constant is
338 baked into 'vlx': for rounding-away-from zero, the constant is 2^13 - 1, causing roundoff away
339 from zero. for round-to-nearest away, the constant is 2^12, causing roundoff away from zero.
340 for round-to-nearest-even, the constant is 2^12 - 1. This causes correct round-to-nearest-even
341 except for odd input numbers. For odd input numbers, we need to add 1 to the constant. */
342
343 /* normal number, all rounding modes except round-to-nearest-even: */
344 case 30:
345 case 31:
346 case 32:
347 case 34:
348 case 35:
349 case 36:
350 case 37:
351 case 39:
352 return static_cast<sf16>((inp + vlx) >> 13);
353
354 /* normal number, round-to-nearest-even. */
355 case 33:
356 case 38:
357 p = inp + vlx;
358 p += (inp >> 13) & 1;
359 return static_cast<sf16>(p >> 13);
360
361 /*
362 the various denormal cases. These are not expected to be common, so their performance is a bit
363 less important. For each of these cases, we need to extract an exponent and a mantissa
364 (including the implicit '1'!), and then right-shift the mantissa by a shift-amount that
365 depends on the exponent. The shift must apply the correct rounding mode. 'vlx' is used to supply the
366 sign of the resulting denormal number.
367 */
368 case 21:
369 case 22:
370 case 25:
371 case 27:
372 /* denormal, round towards zero. */
373 p = 126 - ((inp >> 23) & 0xFF);
374 return static_cast<sf16>((((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000)) >> p) | vlx);
375 case 20:
376 case 26:
377 /* denormal, round away from zero. */
378 p = 126 - ((inp >> 23) & 0xFF);
379 return static_cast<sf16>(rtup_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx);
380 case 24:
381 case 29:
382 /* denormal, round to nearest-away */
383 p = 126 - ((inp >> 23) & 0xFF);
384 return static_cast<sf16>(rtna_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx);
385 case 23:
386 case 28:
387 /* denormal, round to nearest-even. */
388 p = 126 - ((inp >> 23) & 0xFF);
389 return static_cast<sf16>(rtne_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx);
390 }
391
392 return 0;
393}
394
395/* convert from soft-float to native-float */
396float sf16_to_float(uint16_t p)
397{
398 if32 i;
399 i.u = sf16_to_sf32(p);
400 return i.f;
401}
402
403/* convert from native-float to soft-float */
404uint16_t float_to_sf16(float p)
405{
406 if32 i;
407 i.f = p;
408 return sf32_to_sf16(i.u, SF_NEARESTEVEN);
409}
410
411#endif
412