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