LCOV - code coverage report
Current view: top level - port - cpl_float.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 55 73 75.3 %
Date: 2025-02-20 10:14:44 Functions: 3 5 60.0 %

          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             : #include <cstring>
      50             : 
      51             : /************************************************************************/
      52             : /*                           HalfToFloat()                              */
      53             : /*                                                                      */
      54             : /*  16-bit floating point number to 32-bit one.                         */
      55             : /************************************************************************/
      56             : 
      57      162020 : GUInt32 CPLHalfToFloat(GUInt16 iHalf)
      58             : {
      59             : 
      60      162020 :     GUInt32 iSign = (iHalf >> 15) & 0x00000001;
      61      162020 :     int iExponent = (iHalf >> 10) & 0x0000001f;
      62      162020 :     GUInt32 iMantissa = iHalf & 0x000003ff;
      63             : 
      64      162020 :     if (iExponent == 0)
      65             :     {
      66         261 :         if (iMantissa == 0)
      67             :         {
      68             :             /* --------------------------------------------------------------------
      69             :              */
      70             :             /*      Plus or minus zero. */
      71             :             /* --------------------------------------------------------------------
      72             :              */
      73             : 
      74         256 :             return iSign << 31;
      75             :         }
      76             :         else
      77             :         {
      78             :             /* --------------------------------------------------------------------
      79             :              */
      80             :             /*      Denormalized number -- renormalize it. */
      81             :             /* --------------------------------------------------------------------
      82             :              */
      83             : 
      84          37 :             while (!(iMantissa & 0x00000400))
      85             :             {
      86          32 :                 iMantissa <<= 1;
      87          32 :                 iExponent -= 1;
      88             :             }
      89             : 
      90           5 :             iExponent += 1;
      91           5 :             iMantissa &= ~0x00000400U;
      92             :         }
      93             :     }
      94      161759 :     else if (iExponent == 31)
      95             :     {
      96          11 :         if (iMantissa == 0)
      97             :         {
      98             :             /* --------------------------------------------------------------------
      99             :              */
     100             :             /*       Positive or negative infinity. */
     101             :             /* --------------------------------------------------------------------
     102             :              */
     103             : 
     104           5 :             return (iSign << 31) | 0x7f800000;
     105             :         }
     106             :         else
     107             :         {
     108             :             /* --------------------------------------------------------------------
     109             :              */
     110             :             /*       NaN -- preserve sign and significand bits. */
     111             :             /* --------------------------------------------------------------------
     112             :              */
     113             : 
     114           6 :             return (iSign << 31) | 0x7f800000 | (iMantissa << 13);
     115             :         }
     116             :     }
     117             : 
     118             :     /* -------------------------------------------------------------------- */
     119             :     /*       Normalized number.                                             */
     120             :     /* -------------------------------------------------------------------- */
     121             : 
     122      161753 :     iExponent = iExponent + (127 - 15);
     123      161753 :     iMantissa = iMantissa << 13;
     124             : 
     125             :     /* -------------------------------------------------------------------- */
     126             :     /*       Assemble sign, exponent and mantissa.                          */
     127             :     /* -------------------------------------------------------------------- */
     128             : 
     129             :     /* coverity[overflow_sink] */
     130      161753 :     return (iSign << 31) | (static_cast<GUInt32>(iExponent) << 23) | iMantissa;
     131             : }
     132             : 
     133             : /************************************************************************/
     134             : /*                           TripleToFloat()                            */
     135             : /*                                                                      */
     136             : /*  24-bit floating point number to 32-bit one.                         */
     137             : /************************************************************************/
     138             : 
     139         400 : GUInt32 CPLTripleToFloat(GUInt32 iTriple)
     140             : {
     141             : 
     142         400 :     GUInt32 iSign = (iTriple >> 23) & 0x00000001;
     143         400 :     int iExponent = (iTriple >> 16) & 0x0000007f;
     144         400 :     GUInt32 iMantissa = iTriple & 0x0000ffff;
     145             : 
     146         400 :     if (iExponent == 0)
     147             :     {
     148           0 :         if (iMantissa == 0)
     149             :         {
     150             :             /* --------------------------------------------------------------------
     151             :              */
     152             :             /*      Plus or minus zero. */
     153             :             /* --------------------------------------------------------------------
     154             :              */
     155             : 
     156           0 :             return iSign << 31;
     157             :         }
     158             :         else
     159             :         {
     160             :             /* --------------------------------------------------------------------
     161             :              */
     162             :             /*      Denormalized number -- renormalize it. */
     163             :             /* --------------------------------------------------------------------
     164             :              */
     165             : 
     166           0 :             while (!(iMantissa & 0x00010000))
     167             :             {
     168           0 :                 iMantissa <<= 1;
     169           0 :                 iExponent -= 1;
     170             :             }
     171             : 
     172           0 :             iExponent += 1;
     173           0 :             iMantissa &= ~0x00010000U;
     174             :         }
     175             :     }
     176         400 :     else if (iExponent == 127)
     177             :     {
     178           0 :         if (iMantissa == 0)
     179             :         {
     180             :             /* --------------------------------------------------------------------
     181             :              */
     182             :             /*       Positive or negative infinity. */
     183             :             /* --------------------------------------------------------------------
     184             :              */
     185             : 
     186           0 :             return (iSign << 31) | 0x7f800000;
     187             :         }
     188             :         else
     189             :         {
     190             :             /* --------------------------------------------------------------------
     191             :              */
     192             :             /*       NaN -- preserve sign and significand bits. */
     193             :             /* --------------------------------------------------------------------
     194             :              */
     195             : 
     196           0 :             return (iSign << 31) | 0x7f800000 | (iMantissa << 7);
     197             :         }
     198             :     }
     199             : 
     200             :     /* -------------------------------------------------------------------- */
     201             :     /*       Normalized number.                                             */
     202             :     /* -------------------------------------------------------------------- */
     203             : 
     204         400 :     iExponent = iExponent + (127 - 63);
     205         400 :     iMantissa = iMantissa << 7;
     206             : 
     207             :     /* -------------------------------------------------------------------- */
     208             :     /*       Assemble sign, exponent and mantissa.                          */
     209             :     /* -------------------------------------------------------------------- */
     210             : 
     211             :     /* coverity[overflow_sink] */
     212         400 :     return (iSign << 31) | (static_cast<GUInt32>(iExponent) << 23) | iMantissa;
     213             : }
     214             : 
     215             : /************************************************************************/
     216             : /*                            FloatToHalf()                             */
     217             : /************************************************************************/
     218             : 
     219      240432 : GUInt16 CPLFloatToHalf(GUInt32 iFloat32, bool &bHasWarned)
     220             : {
     221      240432 :     GUInt32 iSign = (iFloat32 >> 31) & 0x00000001;
     222      240432 :     GUInt32 iExponent = (iFloat32 >> 23) & 0x000000ff;
     223      240432 :     GUInt32 iMantissa = iFloat32 & 0x007fffff;
     224             : 
     225      240432 :     if (iExponent == 255)
     226             :     {
     227          10 :         if (iMantissa == 0)
     228             :         {
     229             :             /* --------------------------------------------------------------------
     230             :              */
     231             :             /*       Positive or negative infinity. */
     232             :             /* --------------------------------------------------------------------
     233             :              */
     234             : 
     235           4 :             return static_cast<GUInt16>((iSign << 15) | 0x7C00);
     236             :         }
     237             :         else
     238             :         {
     239             :             /* --------------------------------------------------------------------
     240             :              */
     241             :             /*       NaN -- preserve sign and significand bits. */
     242             :             /* --------------------------------------------------------------------
     243             :              */
     244           6 :             if (iMantissa >> 13)
     245           4 :                 return static_cast<GUInt16>((iSign << 15) | 0x7C00 |
     246           4 :                                             (iMantissa >> 13));
     247             : 
     248           2 :             return static_cast<GUInt16>((iSign << 15) | 0x7E00);
     249             :         }
     250             :     }
     251             : 
     252      240422 :     if (iExponent <= 127 - 15)
     253             :     {
     254             :         // Zero, float32 denormalized number or float32 too small normalized
     255             :         // number
     256         302 :         if (13 + 1 + 127 - 15 - iExponent >= 32)
     257         297 :             return static_cast<GUInt16>(iSign << 15);
     258             : 
     259             :         // Return a denormalized number
     260             :         return static_cast<GUInt16>(
     261           5 :             (iSign << 15) |
     262           5 :             ((iMantissa | 0x00800000) >> (13 + 1 + 127 - 15 - iExponent)));
     263             :     }
     264      240120 :     if (iExponent - (127 - 15) >= 31)
     265             :     {
     266           1 :         if (!bHasWarned)
     267             :         {
     268           1 :             bHasWarned = true;
     269           1 :             float fVal = 0.0f;
     270           1 :             memcpy(&fVal, &iFloat32, 4);
     271           1 :             CPLError(
     272             :                 CE_Failure, CPLE_AppDefined,
     273             :                 "Value %.8g is beyond range of float16. Converted to %sinf",
     274           1 :                 fVal, (fVal > 0) ? "+" : "-");
     275             :         }
     276           1 :         return static_cast<GUInt16>((iSign << 15) | 0x7C00);  // Infinity
     277             :     }
     278             : 
     279             :     /* -------------------------------------------------------------------- */
     280             :     /*       Normalized number.                                             */
     281             :     /* -------------------------------------------------------------------- */
     282             : 
     283      240119 :     iExponent = iExponent - (127 - 15);
     284      240119 :     iMantissa = iMantissa >> 13;
     285             : 
     286             :     /* -------------------------------------------------------------------- */
     287             :     /*       Assemble sign, exponent and mantissa.                          */
     288             :     /* -------------------------------------------------------------------- */
     289             : 
     290             :     // coverity[overflow_sink]
     291      240119 :     return static_cast<GUInt16>((iSign << 15) | (iExponent << 10) | iMantissa);
     292             : }
     293             : 
     294           0 : GUInt16 CPLConvertFloatToHalf(float fFloat32)
     295             : {
     296             :     GUInt32 nFloat32;
     297           0 :     std::memcpy(&nFloat32, &fFloat32, sizeof nFloat32);
     298           0 :     bool bHasWarned = true;
     299           0 :     return CPLFloatToHalf(nFloat32, bHasWarned);
     300             : }
     301             : 
     302           0 : float CPLConvertHalfToFloat(GUInt16 nHalf)
     303             : {
     304           0 :     GUInt32 nFloat32 = CPLHalfToFloat(nHalf);
     305             :     float fFloat32;
     306           0 :     std::memcpy(&fFloat32, &nFloat32, sizeof fFloat32);
     307           0 :     return fFloat32;
     308             : }

Generated by: LCOV version 1.14