LCOV - code coverage report
Current view: top level - port - cpl_float.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 55 65 84.6 %
Date: 2025-01-18 12:42:00 Functions: 3 3 100.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             : /************************************************************************/
      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             : }

Generated by: LCOV version 1.14