Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: CPL 4 : * Purpose: Floating point conversion functions. Convert 16- and 24-bit 5 : * floating point numbers into the 32-bit IEEE 754 compliant ones. 6 : * Author: Andrey Kiselev, dron@remotesensing.org 7 : * 8 : ****************************************************************************** 9 : * Copyright (c) 2005, Andrey Kiselev <dron@remotesensing.org> 10 : * 11 : * This code is based on the code from OpenEXR project with the following 12 : * copyright: 13 : * 14 : * Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 15 : * Digital Ltd. LLC 16 : * 17 : * All rights reserved. 18 : * 19 : * Redistribution and use in source and binary forms, with or without 20 : * modification, are permitted provided that the following conditions are 21 : * met: 22 : * * Redistributions of source code must retain the above copyright 23 : * notice, this list of conditions and the following disclaimer. 24 : * * Redistributions in binary form must reproduce the above 25 : * copyright notice, this list of conditions and the following disclaimer 26 : * in the documentation and/or other materials provided with the 27 : * distribution. 28 : * * Neither the name of Industrial Light & Magic nor the names of 29 : * its contributors may be used to endorse or promote products derived 30 : * from this software without specific prior written permission. 31 : * 32 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 35 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 37 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 38 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 39 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 40 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 41 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 42 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 : * 44 : ****************************************************************************/ 45 : 46 : #include "cpl_float.h" 47 : #include "cpl_error.h" 48 : 49 : /************************************************************************/ 50 : /* HalfToFloat() */ 51 : /* */ 52 : /* 16-bit floating point number to 32-bit one. */ 53 : /************************************************************************/ 54 : 55 162024 : GUInt32 CPLHalfToFloat(GUInt16 iHalf) 56 : { 57 : 58 162024 : GUInt32 iSign = (iHalf >> 15) & 0x00000001; 59 162024 : int iExponent = (iHalf >> 10) & 0x0000001f; 60 162024 : GUInt32 iMantissa = iHalf & 0x000003ff; 61 : 62 162024 : if (iExponent == 0) 63 : { 64 261 : if (iMantissa == 0) 65 : { 66 : /* -------------------------------------------------------------------- 67 : */ 68 : /* Plus or minus zero. */ 69 : /* -------------------------------------------------------------------- 70 : */ 71 : 72 256 : return iSign << 31; 73 : } 74 : else 75 : { 76 : /* -------------------------------------------------------------------- 77 : */ 78 : /* Denormalized number -- renormalize it. */ 79 : /* -------------------------------------------------------------------- 80 : */ 81 : 82 37 : while (!(iMantissa & 0x00000400)) 83 : { 84 32 : iMantissa <<= 1; 85 32 : iExponent -= 1; 86 : } 87 : 88 5 : iExponent += 1; 89 5 : iMantissa &= ~0x00000400U; 90 : } 91 : } 92 161763 : else if (iExponent == 31) 93 : { 94 13 : if (iMantissa == 0) 95 : { 96 : /* -------------------------------------------------------------------- 97 : */ 98 : /* Positive or negative infinity. */ 99 : /* -------------------------------------------------------------------- 100 : */ 101 : 102 5 : return (iSign << 31) | 0x7f800000; 103 : } 104 : else 105 : { 106 : /* -------------------------------------------------------------------- 107 : */ 108 : /* NaN -- preserve sign and significand bits. */ 109 : /* -------------------------------------------------------------------- 110 : */ 111 : 112 8 : return (iSign << 31) | 0x7f800000 | (iMantissa << 13); 113 : } 114 : } 115 : 116 : /* -------------------------------------------------------------------- */ 117 : /* Normalized number. */ 118 : /* -------------------------------------------------------------------- */ 119 : 120 161755 : iExponent = iExponent + (127 - 15); 121 161755 : iMantissa = iMantissa << 13; 122 : 123 : /* -------------------------------------------------------------------- */ 124 : /* Assemble sign, exponent and mantissa. */ 125 : /* -------------------------------------------------------------------- */ 126 : 127 : /* coverity[overflow_sink] */ 128 161755 : return (iSign << 31) | (static_cast<GUInt32>(iExponent) << 23) | iMantissa; 129 : } 130 : 131 : /************************************************************************/ 132 : /* TripleToFloat() */ 133 : /* */ 134 : /* 24-bit floating point number to 32-bit one. */ 135 : /************************************************************************/ 136 : 137 400 : GUInt32 CPLTripleToFloat(GUInt32 iTriple) 138 : { 139 : 140 400 : GUInt32 iSign = (iTriple >> 23) & 0x00000001; 141 400 : int iExponent = (iTriple >> 16) & 0x0000007f; 142 400 : GUInt32 iMantissa = iTriple & 0x0000ffff; 143 : 144 400 : if (iExponent == 0) 145 : { 146 0 : if (iMantissa == 0) 147 : { 148 : /* -------------------------------------------------------------------- 149 : */ 150 : /* Plus or minus zero. */ 151 : /* -------------------------------------------------------------------- 152 : */ 153 : 154 0 : return iSign << 31; 155 : } 156 : else 157 : { 158 : /* -------------------------------------------------------------------- 159 : */ 160 : /* Denormalized number -- renormalize it. */ 161 : /* -------------------------------------------------------------------- 162 : */ 163 : 164 0 : while (!(iMantissa & 0x00010000)) 165 : { 166 0 : iMantissa <<= 1; 167 0 : iExponent -= 1; 168 : } 169 : 170 0 : iExponent += 1; 171 0 : iMantissa &= ~0x00010000U; 172 : } 173 : } 174 400 : else if (iExponent == 127) 175 : { 176 0 : if (iMantissa == 0) 177 : { 178 : /* -------------------------------------------------------------------- 179 : */ 180 : /* Positive or negative infinity. */ 181 : /* -------------------------------------------------------------------- 182 : */ 183 : 184 0 : return (iSign << 31) | 0x7f800000; 185 : } 186 : else 187 : { 188 : /* -------------------------------------------------------------------- 189 : */ 190 : /* NaN -- preserve sign and significand bits. */ 191 : /* -------------------------------------------------------------------- 192 : */ 193 : 194 0 : return (iSign << 31) | 0x7f800000 | (iMantissa << 7); 195 : } 196 : } 197 : 198 : /* -------------------------------------------------------------------- */ 199 : /* Normalized number. */ 200 : /* -------------------------------------------------------------------- */ 201 : 202 400 : iExponent = iExponent + (127 - 63); 203 400 : iMantissa = iMantissa << 7; 204 : 205 : /* -------------------------------------------------------------------- */ 206 : /* Assemble sign, exponent and mantissa. */ 207 : /* -------------------------------------------------------------------- */ 208 : 209 : /* coverity[overflow_sink] */ 210 400 : return (iSign << 31) | (static_cast<GUInt32>(iExponent) << 23) | iMantissa; 211 : } 212 : 213 : /************************************************************************/ 214 : /* FloatToHalf() */ 215 : /************************************************************************/ 216 : 217 240432 : GUInt16 CPLFloatToHalf(GUInt32 iFloat32, bool &bHasWarned) 218 : { 219 240432 : GUInt32 iSign = (iFloat32 >> 31) & 0x00000001; 220 240432 : GUInt32 iExponent = (iFloat32 >> 23) & 0x000000ff; 221 240432 : GUInt32 iMantissa = iFloat32 & 0x007fffff; 222 : 223 240432 : if (iExponent == 255) 224 : { 225 10 : if (iMantissa == 0) 226 : { 227 : /* -------------------------------------------------------------------- 228 : */ 229 : /* Positive or negative infinity. */ 230 : /* -------------------------------------------------------------------- 231 : */ 232 : 233 4 : return static_cast<GUInt16>((iSign << 15) | 0x7C00); 234 : } 235 : else 236 : { 237 : /* -------------------------------------------------------------------- 238 : */ 239 : /* NaN -- preserve sign and significand bits. */ 240 : /* -------------------------------------------------------------------- 241 : */ 242 6 : if (iMantissa >> 13) 243 4 : return static_cast<GUInt16>((iSign << 15) | 0x7C00 | 244 4 : (iMantissa >> 13)); 245 : 246 2 : return static_cast<GUInt16>((iSign << 15) | 0x7E00); 247 : } 248 : } 249 : 250 240422 : if (iExponent <= 127 - 15) 251 : { 252 : // Zero, float32 denormalized number or float32 too small normalized 253 : // number 254 302 : if (13 + 1 + 127 - 15 - iExponent >= 32) 255 297 : return static_cast<GUInt16>(iSign << 15); 256 : 257 : // Return a denormalized number 258 : return static_cast<GUInt16>( 259 5 : (iSign << 15) | 260 5 : ((iMantissa | 0x00800000) >> (13 + 1 + 127 - 15 - iExponent))); 261 : } 262 240120 : if (iExponent - (127 - 15) >= 31) 263 : { 264 1 : if (!bHasWarned) 265 : { 266 1 : bHasWarned = true; 267 1 : float fVal = 0.0f; 268 1 : memcpy(&fVal, &iFloat32, 4); 269 1 : CPLError( 270 : CE_Failure, CPLE_AppDefined, 271 : "Value %.8g is beyond range of float16. Converted to %sinf", 272 1 : fVal, (fVal > 0) ? "+" : "-"); 273 : } 274 1 : return static_cast<GUInt16>((iSign << 15) | 0x7C00); // Infinity 275 : } 276 : 277 : /* -------------------------------------------------------------------- */ 278 : /* Normalized number. */ 279 : /* -------------------------------------------------------------------- */ 280 : 281 240119 : iExponent = iExponent - (127 - 15); 282 240119 : iMantissa = iMantissa >> 13; 283 : 284 : /* -------------------------------------------------------------------- */ 285 : /* Assemble sign, exponent and mantissa. */ 286 : /* -------------------------------------------------------------------- */ 287 : 288 : // coverity[overflow_sink] 289 240119 : return static_cast<GUInt16>((iSign << 15) | (iExponent << 10) | iMantissa); 290 : }