1*1c60b9acSAndroid Build Coastguard Worker /******************************************************************************
2*1c60b9acSAndroid Build Coastguard Worker *
3*1c60b9acSAndroid Build Coastguard Worker * Filename: ieeehalfprecision.c
4*1c60b9acSAndroid Build Coastguard Worker * Programmer: James Tursa
5*1c60b9acSAndroid Build Coastguard Worker * Version: 1.0
6*1c60b9acSAndroid Build Coastguard Worker * Date: March 3, 2009
7*1c60b9acSAndroid Build Coastguard Worker * Copyright: (c) 2009 by James Tursa, All Rights Reserved
8*1c60b9acSAndroid Build Coastguard Worker *
9*1c60b9acSAndroid Build Coastguard Worker * This code uses the BSD License:
10*1c60b9acSAndroid Build Coastguard Worker *
11*1c60b9acSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
12*1c60b9acSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are
13*1c60b9acSAndroid Build Coastguard Worker * met:
14*1c60b9acSAndroid Build Coastguard Worker *
15*1c60b9acSAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright
16*1c60b9acSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
17*1c60b9acSAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright
18*1c60b9acSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in
19*1c60b9acSAndroid Build Coastguard Worker * the documentation and/or other materials provided with the distribution
20*1c60b9acSAndroid Build Coastguard Worker *
21*1c60b9acSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*1c60b9acSAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*1c60b9acSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*1c60b9acSAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*1c60b9acSAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*1c60b9acSAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*1c60b9acSAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*1c60b9acSAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*1c60b9acSAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30*1c60b9acSAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31*1c60b9acSAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
32*1c60b9acSAndroid Build Coastguard Worker *
33*1c60b9acSAndroid Build Coastguard Worker * This file contains C code to convert between IEEE double, single, and half
34*1c60b9acSAndroid Build Coastguard Worker * precision floating point formats. The intended use is for standalone C code
35*1c60b9acSAndroid Build Coastguard Worker * that does not rely on MATLAB mex.h. The bit pattern for the half precision
36*1c60b9acSAndroid Build Coastguard Worker * floating point format is stored in a 16-bit unsigned int variable. The half
37*1c60b9acSAndroid Build Coastguard Worker * precision bit pattern definition is:
38*1c60b9acSAndroid Build Coastguard Worker *
39*1c60b9acSAndroid Build Coastguard Worker * 1 bit sign bit
40*1c60b9acSAndroid Build Coastguard Worker * 5 bits exponent, biased by 15
41*1c60b9acSAndroid Build Coastguard Worker * 10 bits mantissa, hidden leading bit, normalized to 1.0
42*1c60b9acSAndroid Build Coastguard Worker *
43*1c60b9acSAndroid Build Coastguard Worker * Special floating point bit patterns recognized and supported:
44*1c60b9acSAndroid Build Coastguard Worker *
45*1c60b9acSAndroid Build Coastguard Worker * All exponent bits zero:
46*1c60b9acSAndroid Build Coastguard Worker * - If all mantissa bits are zero, then number is zero (possibly signed)
47*1c60b9acSAndroid Build Coastguard Worker * - Otherwise, number is a denormalized bit pattern
48*1c60b9acSAndroid Build Coastguard Worker *
49*1c60b9acSAndroid Build Coastguard Worker * All exponent bits set to 1:
50*1c60b9acSAndroid Build Coastguard Worker * - If all mantissa bits are zero, then number is +Infinity or -Infinity
51*1c60b9acSAndroid Build Coastguard Worker * - Otherwise, number is NaN (Not a Number)
52*1c60b9acSAndroid Build Coastguard Worker *
53*1c60b9acSAndroid Build Coastguard Worker * For the denormalized cases, note that 2^(-24) is the smallest number that can
54*1c60b9acSAndroid Build Coastguard Worker * be represented in half precision exactly. 2^(-25) will convert to 2^(-24)
55*1c60b9acSAndroid Build Coastguard Worker * because of the rounding algorithm used, and 2^(-26) is too small and
56*1c60b9acSAndroid Build Coastguard Worker * underflows to zero.
57*1c60b9acSAndroid Build Coastguard Worker *
58*1c60b9acSAndroid Build Coastguard Worker ******************************************************************************/
59*1c60b9acSAndroid Build Coastguard Worker
60*1c60b9acSAndroid Build Coastguard Worker /*
61*1c60b9acSAndroid Build Coastguard Worker changes by K. Rogovin:
62*1c60b9acSAndroid Build Coastguard Worker - changed macros UINT16_TYPE, etc to types from stdint.h
63*1c60b9acSAndroid Build Coastguard Worker (i.e. UINT16_TYPE-->uint16_t, INT16_TYPE-->int16_t, etc)
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker - removed double conversion routines.
66*1c60b9acSAndroid Build Coastguard Worker
67*1c60b9acSAndroid Build Coastguard Worker - changed run time checks of endianness to compile time macro.
68*1c60b9acSAndroid Build Coastguard Worker
69*1c60b9acSAndroid Build Coastguard Worker - removed return value from routines
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker - changed source parameter type from * to const *
72*1c60b9acSAndroid Build Coastguard Worker
73*1c60b9acSAndroid Build Coastguard Worker - changed pointer types from void ot uint16_t and uint32_t
74*1c60b9acSAndroid Build Coastguard Worker */
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker /*
77*1c60b9acSAndroid Build Coastguard Worker * [email protected]:
78*1c60b9acSAndroid Build Coastguard Worker *
79*1c60b9acSAndroid Build Coastguard Worker * - clean style and indenting
80*1c60b9acSAndroid Build Coastguard Worker * - convert to single operation
81*1c60b9acSAndroid Build Coastguard Worker * - export as lws_
82*1c60b9acSAndroid Build Coastguard Worker */
83*1c60b9acSAndroid Build Coastguard Worker
84*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
85*1c60b9acSAndroid Build Coastguard Worker #include <stdint.h>
86*1c60b9acSAndroid Build Coastguard Worker
87*1c60b9acSAndroid Build Coastguard Worker void
lws_singles2halfp(uint16_t * hp,uint32_t x)88*1c60b9acSAndroid Build Coastguard Worker lws_singles2halfp(uint16_t *hp, uint32_t x)
89*1c60b9acSAndroid Build Coastguard Worker {
90*1c60b9acSAndroid Build Coastguard Worker uint32_t xs, xe, xm;
91*1c60b9acSAndroid Build Coastguard Worker uint16_t hs, he, hm;
92*1c60b9acSAndroid Build Coastguard Worker int hes;
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker if (!(x & 0x7FFFFFFFu)) {
95*1c60b9acSAndroid Build Coastguard Worker /* Signed zero */
96*1c60b9acSAndroid Build Coastguard Worker *hp = (uint16_t)(x >> 16);
97*1c60b9acSAndroid Build Coastguard Worker
98*1c60b9acSAndroid Build Coastguard Worker return;
99*1c60b9acSAndroid Build Coastguard Worker }
100*1c60b9acSAndroid Build Coastguard Worker
101*1c60b9acSAndroid Build Coastguard Worker xs = x & 0x80000000u; // Pick off sign bit
102*1c60b9acSAndroid Build Coastguard Worker xe = x & 0x7F800000u; // Pick off exponent bits
103*1c60b9acSAndroid Build Coastguard Worker xm = x & 0x007FFFFFu; // Pick off mantissa bits
104*1c60b9acSAndroid Build Coastguard Worker
105*1c60b9acSAndroid Build Coastguard Worker if (xe == 0) { // Denormal will underflow, return a signed zero
106*1c60b9acSAndroid Build Coastguard Worker *hp = (uint16_t) (xs >> 16);
107*1c60b9acSAndroid Build Coastguard Worker return;
108*1c60b9acSAndroid Build Coastguard Worker }
109*1c60b9acSAndroid Build Coastguard Worker
110*1c60b9acSAndroid Build Coastguard Worker if (xe == 0x7F800000u) { // Inf or NaN (all the exponent bits are set)
111*1c60b9acSAndroid Build Coastguard Worker if (!xm) { // If mantissa is zero ...
112*1c60b9acSAndroid Build Coastguard Worker *hp = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf
113*1c60b9acSAndroid Build Coastguard Worker return;
114*1c60b9acSAndroid Build Coastguard Worker }
115*1c60b9acSAndroid Build Coastguard Worker
116*1c60b9acSAndroid Build Coastguard Worker *hp = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker return;
119*1c60b9acSAndroid Build Coastguard Worker }
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker /* Normalized number */
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker hs = (uint16_t) (xs >> 16); // Sign bit
124*1c60b9acSAndroid Build Coastguard Worker /* Exponent unbias the single, then bias the halfp */
125*1c60b9acSAndroid Build Coastguard Worker hes = ((int)(xe >> 23)) - 127 + 15;
126*1c60b9acSAndroid Build Coastguard Worker
127*1c60b9acSAndroid Build Coastguard Worker if (hes >= 0x1F) { // Overflow
128*1c60b9acSAndroid Build Coastguard Worker *hp = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf
129*1c60b9acSAndroid Build Coastguard Worker return;
130*1c60b9acSAndroid Build Coastguard Worker }
131*1c60b9acSAndroid Build Coastguard Worker
132*1c60b9acSAndroid Build Coastguard Worker if (hes <= 0) { // Underflow
133*1c60b9acSAndroid Build Coastguard Worker if ((14 - hes) > 24)
134*1c60b9acSAndroid Build Coastguard Worker /*
135*1c60b9acSAndroid Build Coastguard Worker * Mantissa shifted all the way off & no
136*1c60b9acSAndroid Build Coastguard Worker * rounding possibility
137*1c60b9acSAndroid Build Coastguard Worker */
138*1c60b9acSAndroid Build Coastguard Worker hm = (uint16_t) 0u; // Set mantissa to zero
139*1c60b9acSAndroid Build Coastguard Worker else {
140*1c60b9acSAndroid Build Coastguard Worker xm |= 0x00800000u; // Add the hidden leading bit
141*1c60b9acSAndroid Build Coastguard Worker hm = (uint16_t) (xm >> (14 - hes)); // Mantissa
142*1c60b9acSAndroid Build Coastguard Worker if ((xm >> (13 - hes)) & 1u) // Check for rounding
143*1c60b9acSAndroid Build Coastguard Worker /* Round, might overflow into exp bit,
144*1c60b9acSAndroid Build Coastguard Worker * but this is OK */
145*1c60b9acSAndroid Build Coastguard Worker hm = (uint16_t)(hm + 1u);
146*1c60b9acSAndroid Build Coastguard Worker }
147*1c60b9acSAndroid Build Coastguard Worker /* Combine sign bit and mantissa bits, biased exponent is 0 */
148*1c60b9acSAndroid Build Coastguard Worker *hp = hs | hm;
149*1c60b9acSAndroid Build Coastguard Worker
150*1c60b9acSAndroid Build Coastguard Worker return;
151*1c60b9acSAndroid Build Coastguard Worker }
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker he = (uint16_t)(hes << 10); // Exponent
154*1c60b9acSAndroid Build Coastguard Worker hm = (uint16_t)(xm >> 13); // Mantissa
155*1c60b9acSAndroid Build Coastguard Worker
156*1c60b9acSAndroid Build Coastguard Worker if (xm & 0x00001000u) // Check for rounding
157*1c60b9acSAndroid Build Coastguard Worker /* Round, might overflow to inf, this is OK */
158*1c60b9acSAndroid Build Coastguard Worker *hp = (uint16_t)((hs | he | hm) + (uint16_t)1u);
159*1c60b9acSAndroid Build Coastguard Worker else
160*1c60b9acSAndroid Build Coastguard Worker *hp = hs | he | hm; // No rounding
161*1c60b9acSAndroid Build Coastguard Worker }
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker void
lws_halfp2singles(uint32_t * xp,uint16_t h)164*1c60b9acSAndroid Build Coastguard Worker lws_halfp2singles(uint32_t *xp, uint16_t h)
165*1c60b9acSAndroid Build Coastguard Worker {
166*1c60b9acSAndroid Build Coastguard Worker uint16_t hs, he, hm;
167*1c60b9acSAndroid Build Coastguard Worker uint32_t xs, xe, xm;
168*1c60b9acSAndroid Build Coastguard Worker int32_t xes;
169*1c60b9acSAndroid Build Coastguard Worker int e;
170*1c60b9acSAndroid Build Coastguard Worker
171*1c60b9acSAndroid Build Coastguard Worker if (!(h & 0x7FFFu)) { // Signed zero
172*1c60b9acSAndroid Build Coastguard Worker *xp = ((uint32_t)h) << 16; // Return the signed zero
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker return;
175*1c60b9acSAndroid Build Coastguard Worker }
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker hs = h & 0x8000u; // Pick off sign bit
178*1c60b9acSAndroid Build Coastguard Worker he = h & 0x7C00u; // Pick off exponent bits
179*1c60b9acSAndroid Build Coastguard Worker hm = h & 0x03FFu; // Pick off mantissa bits
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker if (!he) { // Denormal will convert to normalized
182*1c60b9acSAndroid Build Coastguard Worker e = -1;
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker /* figure out how much extra to adjust the exponent */
185*1c60b9acSAndroid Build Coastguard Worker do {
186*1c60b9acSAndroid Build Coastguard Worker e++;
187*1c60b9acSAndroid Build Coastguard Worker hm = (uint16_t)(hm << 1);
188*1c60b9acSAndroid Build Coastguard Worker /* Shift until leading bit overflows into exponent */
189*1c60b9acSAndroid Build Coastguard Worker } while (!(hm & 0x0400u));
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker xs = ((uint32_t) hs) << 16; // Sign bit
192*1c60b9acSAndroid Build Coastguard Worker
193*1c60b9acSAndroid Build Coastguard Worker /* Exponent unbias the halfp, then bias the single */
194*1c60b9acSAndroid Build Coastguard Worker xes = ((int32_t)(he >> 10)) - 15 + 127 - e;
195*1c60b9acSAndroid Build Coastguard Worker xe = (uint32_t)(xes << 23); // Exponent
196*1c60b9acSAndroid Build Coastguard Worker xm = ((uint32_t)(hm & 0x03FFu)) << 13; // Mantissa
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker *xp = xs | xe | xm;
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker return;
201*1c60b9acSAndroid Build Coastguard Worker }
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker if (he == 0x7C00u) { /* Inf or NaN (all the exponent bits are set) */
204*1c60b9acSAndroid Build Coastguard Worker if (!hm) { /* If mantissa is zero ...
205*1c60b9acSAndroid Build Coastguard Worker * Signed Inf
206*1c60b9acSAndroid Build Coastguard Worker */
207*1c60b9acSAndroid Build Coastguard Worker *xp = (((uint32_t)hs) << 16) | ((uint32_t)0x7F800000u);
208*1c60b9acSAndroid Build Coastguard Worker
209*1c60b9acSAndroid Build Coastguard Worker return;
210*1c60b9acSAndroid Build Coastguard Worker }
211*1c60b9acSAndroid Build Coastguard Worker
212*1c60b9acSAndroid Build Coastguard Worker /* ... NaN, only 1st mantissa bit set */
213*1c60b9acSAndroid Build Coastguard Worker *xp = (uint32_t)0xFFC00000u;
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker return;
216*1c60b9acSAndroid Build Coastguard Worker }
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker /* Normalized number */
219*1c60b9acSAndroid Build Coastguard Worker
220*1c60b9acSAndroid Build Coastguard Worker xs = ((uint32_t)hs) << 16; // Sign bit
221*1c60b9acSAndroid Build Coastguard Worker /* Exponent unbias the halfp, then bias the single */
222*1c60b9acSAndroid Build Coastguard Worker xes = ((int32_t)(he >> 10)) - 15 + 127;
223*1c60b9acSAndroid Build Coastguard Worker xe = (uint32_t)(xes << 23); // Exponent
224*1c60b9acSAndroid Build Coastguard Worker xm = ((uint32_t)hm) << 13; // Mantissa
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker /* Combine sign bit, exponent bits, and mantissa bits */
227*1c60b9acSAndroid Build Coastguard Worker *xp = xs | xe | xm;
228*1c60b9acSAndroid Build Coastguard Worker }
229