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: 2024-04-28 18:08:58 Functions: 3 3 100.0 %

          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      160882 : GUInt32 CPLHalfToFloat(GUInt16 iHalf)
      57             : {
      58             : 
      59      160882 :     GUInt32 iSign = (iHalf >> 15) & 0x00000001;
      60      160882 :     int iExponent = (iHalf >> 10) & 0x0000001f;
      61      160882 :     GUInt32 iMantissa = iHalf & 0x000003ff;
      62             : 
      63      160882 :     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      160621 :     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      160613 :     iExponent = iExponent + (127 - 15);
     122      160613 :     iMantissa = iMantissa << 13;
     123             : 
     124             :     /* -------------------------------------------------------------------- */
     125             :     /*       Assemble sign, exponent and mantissa.                          */
     126             :     /* -------------------------------------------------------------------- */
     127             : 
     128             :     /* coverity[overflow_sink] */
     129      160613 :     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      240032 : GUInt16 CPLFloatToHalf(GUInt32 iFloat32, bool &bHasWarned)
     219             : {
     220      240032 :     GUInt32 iSign = (iFloat32 >> 31) & 0x00000001;
     221      240032 :     GUInt32 iExponent = (iFloat32 >> 23) & 0x000000ff;
     222      240032 :     GUInt32 iMantissa = iFloat32 & 0x007fffff;
     223             : 
     224      240032 :     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      240022 :     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      239720 :     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      239719 :     iExponent = iExponent - (127 - 15);
     283      239719 :     iMantissa = iMantissa >> 13;
     284             : 
     285             :     /* -------------------------------------------------------------------- */
     286             :     /*       Assemble sign, exponent and mantissa.                          */
     287             :     /* -------------------------------------------------------------------- */
     288             : 
     289             :     // coverity[overflow_sink]
     290      239719 :     return static_cast<GUInt16>((iSign << 15) | (iExponent << 10) | iMantissa);
     291             : }

Generated by: LCOV version 1.14