LCOV - code coverage report
Current view: top level - gcc - sreal.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.3 % 108 104
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Definitions for simple data type for real numbers.
       2              :    Copyright (C) 2002-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #ifndef GCC_SREAL_H
      21              : #define GCC_SREAL_H
      22              : 
      23              : #define SREAL_PART_BITS 31
      24              : 
      25              : #define UINT64_BITS     64
      26              : 
      27              : #define SREAL_MIN_SIG ((int64_t) 1 << (SREAL_PART_BITS - 2))
      28              : #define SREAL_MAX_SIG (((int64_t) 1 << (SREAL_PART_BITS - 1)) - 1)
      29              : #define SREAL_MAX_EXP (INT_MAX / 4)
      30              : 
      31              : #define SREAL_BITS SREAL_PART_BITS
      32              : 
      33              : #define SREAL_SIGN(v) (v < 0 ? -1 : 1)
      34              : #define SREAL_ABS(v) (v < 0 ? -v : v)
      35              : 
      36              : struct output_block;
      37              : class lto_input_block;
      38              : 
      39              : /* Structure for holding a simple real number.  */
      40              : class sreal
      41              : {
      42              : public:
      43              :   /* Construct an uninitialized sreal.  */
      44   1683672038 :   sreal () : m_sig (-1), m_exp (-1) {}
      45              : 
      46              :   /* Construct a sreal.  */
      47   3177889432 :   sreal (int64_t sig, int exp = 0)
      48   3177889432 :   {
      49   2728375623 :     normalize (sig, exp);
      50      1369626 :   }
      51              : 
      52              :   void dump (FILE *) const;
      53              :   int64_t to_int () const;
      54              :   int64_t to_nearest_int () const;
      55              :   double to_double () const;
      56              :   void stream_out (struct output_block *);
      57              :   static sreal stream_in (class lto_input_block *);
      58              :   sreal operator+ (const sreal &other) const;
      59              :   sreal operator- (const sreal &other) const;
      60              :   sreal operator* (const sreal &other) const;
      61              :   sreal operator/ (const sreal &other) const;
      62              : 
      63    601700467 :   bool operator< (const sreal &other) const
      64              :   {
      65    601700467 :     if (m_exp == other.m_exp)
      66     36176090 :       return m_sig < other.m_sig;
      67              :     else
      68              :     {
      69    565524377 :       bool negative = m_sig < 0;
      70    565524377 :       bool other_negative = other.m_sig < 0;
      71              : 
      72    565524377 :       if (negative != other_negative)
      73     37887838 :         return negative > other_negative;
      74              : 
      75    527636539 :       bool r = m_exp < other.m_exp;
      76    527636539 :       return negative ? !r : r;
      77              :     }
      78              :   }
      79              : 
      80   1093612082 :   bool operator== (const sreal &other) const
      81              :   {
      82    257045918 :     return m_exp == other.m_exp && m_sig == other.m_sig;
      83              :   }
      84              : 
      85     10542244 :   sreal operator- () const
      86              :   {
      87     10542244 :     sreal tmp = *this;
      88     10542244 :     tmp.m_sig *= -1;
      89              : 
      90     10542244 :     return tmp;
      91              :   }
      92              : 
      93     62798390 :   sreal shift (int s) const
      94              :   {
      95              :     /* Zero needs no shifting.  */
      96     62798390 :     if (!m_sig)
      97      6804507 :       return *this;
      98     55993883 :     gcc_checking_assert (s <= SREAL_MAX_EXP);
      99     55993883 :     gcc_checking_assert (s >= -SREAL_MAX_EXP);
     100              : 
     101              :     /* Overflows/drop to 0 could be handled gracefully, but hopefully we do not
     102              :        need to do so.  */
     103     55993883 :     gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
     104     55993883 :     gcc_checking_assert (m_exp + s >= -SREAL_MAX_EXP);
     105              : 
     106     55993883 :     sreal tmp = *this;
     107     55993883 :     tmp.m_exp += s;
     108              : 
     109     55993883 :     return tmp;
     110              :   }
     111              : 
     112              :   /* Global minimum sreal can hold.  */
     113      1225614 :   inline static sreal min ()
     114              :   {
     115      1225614 :     sreal min;
     116              :     /* This never needs normalization.  */
     117      1225614 :     min.m_sig = -SREAL_MAX_SIG;
     118      1225614 :     min.m_exp = SREAL_MAX_EXP;
     119      1225614 :     return min;
     120              :   }
     121              : 
     122              :   /* Global minimum sreal can hold.  */
     123      2836662 :   inline static sreal max ()
     124              :   {
     125      2836662 :     sreal max;
     126              :     /* This never needs normalization.  */
     127      2836662 :     max.m_sig = SREAL_MAX_SIG;
     128      2836662 :     max.m_exp = SREAL_MAX_EXP;
     129       472732 :     return max;
     130              :   }
     131              : 
     132              : private:
     133              :   inline void normalize (int64_t new_sig, signed int new_exp);
     134              :   inline void normalize_up (int64_t new_sig, signed int new_exp);
     135              :   inline void normalize_down (int64_t new_sig, signed int new_exp);
     136              :   void shift_right (int amount);
     137              :   static sreal signedless_plus (const sreal &a, const sreal &b, bool negative);
     138              :   static sreal signedless_minus (const sreal &a, const sreal &b, bool negative);
     139              : 
     140              :   int32_t m_sig;                        /* Significant.  */
     141              :   signed int m_exp;                     /* Exponent.  */
     142              : };
     143              : 
     144              : extern void debug (const sreal &ref);
     145              : extern void debug (const sreal *ptr);
     146              : 
     147    660778839 : inline sreal &operator+= (sreal &a, const sreal &b)
     148              : {
     149    659377108 :   return a = a + b;
     150              : }
     151              : 
     152       452373 : inline sreal &operator-= (sreal &a, const sreal &b)
     153              : {
     154       452373 :   return a = a - b;
     155              : }
     156              : 
     157       483023 : inline sreal &operator/= (sreal &a, const sreal &b)
     158              : {
     159       483023 :   return a = a / b;
     160              : }
     161              : 
     162     18991847 : inline sreal &operator*= (sreal &a, const sreal &b)
     163              : {
     164     18991847 :   return a = a  * b;
     165              : }
     166              : 
     167     68437766 : inline bool operator!= (const sreal &a, const sreal &b)
     168              : {
     169    119866881 :   return !(a == b);
     170              : }
     171              : 
     172    445787336 : inline bool operator> (const sreal &a, const sreal &b)
     173              : {
     174    459600784 :   return !(a == b || a < b);
     175              : }
     176              : 
     177     12767226 : inline bool operator<= (const sreal &a, const sreal &b)
     178              : {
     179     12767226 :   return a < b || a == b;
     180              : }
     181              : 
     182    489334291 : inline bool operator>= (const sreal &a, const sreal &b)
     183              : {
     184    491305725 :   return a == b || a > b;
     185              : }
     186              : 
     187      2978332 : inline sreal operator<< (const sreal &a, int exp)
     188              : {
     189      2978332 :   return a.shift (exp);
     190              : }
     191              : 
     192     49600990 : inline sreal operator>> (const sreal &a, int exp)
     193              : {
     194     49600990 :   return a.shift (-exp);
     195              : }
     196              : 
     197              : /* Make significant to be >= SREAL_MIN_SIG.
     198              : 
     199              :    Make this separate method so inliner can handle hot path better.  */
     200              : 
     201              : inline void
     202   1164912047 : sreal::normalize_up (int64_t new_sig, signed int new_exp)
     203              : {
     204   1164912047 :   unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
     205   1164912047 :   int shift = SREAL_PART_BITS - 2 - floor_log2 (sig);
     206              : 
     207   1164912047 :   gcc_checking_assert (shift > 0);
     208   1164912047 :   sig <<= shift;
     209   1164912047 :   new_exp -= shift;
     210   1164912047 :   gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
     211              : 
     212              :   /* Check underflow.  */
     213   1164912047 :   if (new_exp < -SREAL_MAX_EXP)
     214              :     {
     215            0 :       new_exp = -SREAL_MAX_EXP;
     216            0 :       sig = 0;
     217              :     }
     218   1164912047 :   m_exp = new_exp;
     219   1164912047 :   if (SREAL_SIGN (new_sig) == -1)
     220     44130218 :     m_sig = -sig;
     221              :   else
     222   1120781829 :     m_sig = sig;
     223   1164912047 : }
     224              : 
     225              : /* Make significant to be <= SREAL_MAX_SIG.
     226              : 
     227              :    Make this separate method so inliner can handle hot path better.  */
     228              : 
     229              : inline void
     230    968378702 : sreal::normalize_down (int64_t new_sig, signed int new_exp)
     231              : {
     232    968378702 :   int last_bit;
     233    968378702 :   unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
     234    968378702 :   int shift = floor_log2 (sig) - SREAL_PART_BITS + 2;
     235              : 
     236    968378702 :   gcc_checking_assert (shift > 0);
     237    968378702 :   last_bit = (sig >> (shift-1)) & 1;
     238    968378702 :   sig >>= shift;
     239    968378702 :   new_exp += shift;
     240    968378702 :   gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
     241              : 
     242              :   /* Round the number.  */
     243    968378702 :   sig += last_bit;
     244    968378702 :   if (sig > SREAL_MAX_SIG)
     245              :     {
     246      3603328 :       sig >>= 1;
     247      3603328 :       new_exp++;
     248              :     }
     249              : 
     250              :   /* Check overflow.  */
     251    968378702 :   if (new_exp > SREAL_MAX_EXP)
     252              :     {
     253            0 :       new_exp = SREAL_MAX_EXP;
     254            0 :       sig = SREAL_MAX_SIG;
     255              :     }
     256    968378702 :   m_exp = new_exp;
     257    968378702 :   if (SREAL_SIGN (new_sig) == -1)
     258     17034663 :     m_sig = -sig;
     259              :   else
     260    951344039 :     m_sig = sig;
     261    968378702 : }
     262              : 
     263              : /* Normalize *this; the hot path.  */
     264              : 
     265              : inline void
     266   3672961769 : sreal::normalize (int64_t new_sig, signed int new_exp)
     267              : {
     268   3672961769 :   unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
     269              : 
     270   3672961769 :   if (sig == 0)
     271              :     {
     272   1124855948 :       m_sig = 0;
     273   1124855948 :       m_exp = -SREAL_MAX_EXP;
     274              :     }
     275   2548105821 :   else if (sig > SREAL_MAX_SIG)
     276    968378702 :     normalize_down (new_sig, new_exp);
     277   1579727119 :   else if (sig < SREAL_MIN_SIG)
     278   1164912047 :     normalize_up (new_sig, new_exp);
     279              :   else
     280              :     {
     281    414815072 :       m_sig = new_sig;
     282    414815072 :       m_exp = new_exp;
     283              :     }
     284   3672961769 : }
     285              : 
     286              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.