LCOV - code coverage report
Current view: top level - snapwebsites - floats.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 29 0.0 %
Date: 2019-12-15 17:13:15 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Snap Websites Server -- handle the basic display of the website content
       2             : // Copyright (c) 2011-2019  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // This program is free software; you can redistribute it and/or modify
       5             : // it under the terms of the GNU General Public License as published by
       6             : // the Free Software Foundation; either version 2 of the License, or
       7             : // (at your option) any later version.
       8             : //
       9             : // This program is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : // GNU General Public License for more details.
      13             : //
      14             : // You should have received a copy of the GNU General Public License
      15             : // along with this program; if not, write to the Free Software
      16             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      17             : 
      18             : 
      19             : // self
      20             : //
      21             : #include "snapwebsites/floats.h"
      22             : 
      23             : 
      24             : // C++ lib
      25             : //
      26             : #include <cstdint>
      27             : 
      28             : 
      29             : // last include
      30             : //
      31             : #include <snapdev/poison.h>
      32             : 
      33             : 
      34             : 
      35             : namespace snap
      36             : {
      37             : 
      38             : /** \brief Compare two floating points together.
      39             :  *
      40             :  * Comparing two floating point numbers requires some work if you want to
      41             :  * make sure that you do get true when the floats are (nearly) equal, then
      42             :  * you want to compare the mantissa and not the floats as is.
      43             :  *
      44             :  * The function compares the signs, unless a and b are +0.0 and -0.0 if the
      45             :  * signs are different the floating points are considered different.
      46             :  *
      47             :  * Next the function extracts the mantissa and shifts it before comparing
      48             :  * the absolute value of the difference against the value defined in
      49             :  * epsilon.
      50             :  *
      51             :  * \note
      52             :  * At this time the compare ignores whether one of the input is a NaN.
      53             :  *
      54             :  * \param[in] a  The left hand side floating point value.
      55             :  * \param[in] b  The right hand side floating point value.
      56             :  * \param[in] epsilon  The maximum delta between a and b.
      57             :  *
      58             :  * \return true if a and b are considered equal.
      59             :  */
      60             : template<typename T, typename I, int mantissa, int exponent, I epsilon>
      61           0 : bool almost_equal(T a, T b)
      62             : {
      63             : #pragma GCC diagnostic push
      64             : #pragma GCC diagnostic ignored "-Wfloat-equal"
      65             :     // quick test as is first (works great for 0.0 == 0.0)
      66             :     // (so the warning is okay, we're under control)
      67           0 :     if(a == b)
      68             : #pragma GCC diagnostic pop
      69             :     {
      70           0 :         return true;
      71             :     }
      72             :  
      73             :     // different signs means they do not match.
      74           0 :     bool const sa(a < static_cast<T>(0.0));
      75           0 :     bool const sb(b < static_cast<T>(0.0));
      76           0 :     if(sa ^ sb)
      77             :     {
      78             :         // we already checked for +0.0 == -0.0
      79           0 :         return false;
      80             :     }
      81             : 
      82             :     union float_t
      83             :     {
      84             :         T   f_float;
      85             :         I   f_integer;
      86             :     };
      87             :     float_t fa, fb;
      88           0 :     fa.f_float = a;
      89           0 :     fb.f_float = b;
      90             : 
      91             :     // retrieve the mantissa
      92           0 :     I ia(fa.f_integer & (static_cast<I>(-1) >> (sizeof(I) * 8 - mantissa)));
      93           0 :     I ib(fb.f_integer & (static_cast<I>(-1) >> (sizeof(I) * 8 - mantissa)));
      94             : 
      95             :     // retrieve the exponent
      96           0 :     I ea((fa.f_integer >> mantissa) & (static_cast<I>(-1) >> (sizeof(I) * 8 - exponent)));
      97           0 :     I eb((fb.f_integer >> mantissa) & (static_cast<I>(-1) >> (sizeof(I) * 8 - exponent)));
      98             : 
      99             :     // adjust the mantissa with the exponent
     100             :     // TBD: ameliorate to try to keep as many bits as possible?
     101           0 :     if(ea < eb)
     102             :     {
     103           0 :         I d(eb - ea);
     104           0 :         ib >>= d;
     105             :     }
     106           0 :     else if(ea > eb)
     107             :     {
     108           0 :         I d(eb - ea);
     109           0 :         ia >>= d;
     110             :     }
     111             : 
     112             :     // Compare the mantissa
     113           0 :     I p(ia > ib ? ia - ib : ib - ia);
     114           0 :     return p < epsilon;
     115             : }
     116             :  
     117             : 
     118             : /** \brief Compare two float numbers against each others.
     119             :  *
     120             :  * This function compares two float numbers against each others and return
     121             :  * true if they are considered equal.
     122             :  *
     123             :  * \param[in] a  The left hand side floating point value.
     124             :  * \param[in] b  The right hand side floating point value.
     125             :  *
     126             :  * \return true if the two floats are close.
     127             :  */
     128           0 : bool compare_floats(float a, float b)
     129             : {
     130           0 :     return almost_equal<float, int32_t, 23, 8, 0x20>(a, b);
     131             : }
     132             : 
     133             : 
     134             : /** \brief Compare two double numbers against each others.
     135             :  *
     136             :  * This function compares two double numbers against each others and return
     137             :  * true if they are considered equal.
     138             :  *
     139             :  * \param[in] a  The left hand side floating point value.
     140             :  * \param[in] b  The right hand side floating point value.
     141             :  *
     142             :  * \return true if the two floats are close.
     143             :  */
     144           0 : bool compare_floats(double a, double b)
     145             : {
     146           0 :     return almost_equal<double, int64_t, 52, 11, 0x80>(a, b);
     147             : }
     148             : 
     149             : 
     150             : /** \fn compare_floats(double a, float b)
     151             :  * \brief Compare two floating point numbers against each others.
     152             :  *
     153             :  * This function compares a float with a double number after converting
     154             :  * the float to a double. The function returns true if they are
     155             :  * considered equal.
     156             :  *
     157             :  * \param[in] a  The left hand side floating point value.
     158             :  * \param[in] b  The right hand side floating point value.
     159             :  *
     160             :  * \return true if the two floats are close.
     161             :  */
     162           0 : bool compare_floats(double a, float b)
     163             : {
     164           0 :     return compare_floats(a, static_cast<double>(b));
     165             : }
     166             : 
     167             : 
     168             : /** \fn compare_floats(float a, double b)
     169             :  * \brief Compare two floating point numbers against each others.
     170             :  *
     171             :  * This function compares a float with a double number after converting
     172             :  * the float to a double. The function returns true if they are
     173             :  * considered equal.
     174             :  *
     175             :  * \param[in] a  The left hand side floating point value.
     176             :  * \param[in] b  The right hand side floating point value.
     177             :  *
     178             :  * \return true if the two floats are close.
     179             :  */
     180           0 : bool compare_floats(float a, double b)
     181             : {
     182           0 :     return compare_floats(static_cast<double>(a), b);
     183             : }
     184             : 
     185             : 
     186             : } // namespace snap
     187             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13