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