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-03-28 14:25:54 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   1670055845 :   sreal () : m_sig (-1), m_exp (-1) {}
      45              : 
      46              :   /* Construct a sreal.  */
      47   3144678847 :   sreal (int64_t sig, int exp = 0)
      48   3144678847 :   {
      49   2700516505 :     normalize (sig, exp);
      50      1366165 :   }
      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    596617961 :   bool operator< (const sreal &other) const
      64              :   {
      65    596617961 :     if (m_exp == other.m_exp)
      66     35324172 :       return m_sig < other.m_sig;
      67              :     else
      68              :     {
      69    561293789 :       bool negative = m_sig < 0;
      70    561293789 :       bool other_negative = other.m_sig < 0;
      71              : 
      72    561293789 :       if (negative != other_negative)
      73     37249895 :         return negative > other_negative;
      74              : 
      75    524043894 :       bool r = m_exp < other.m_exp;
      76    524043894 :       return negative ? !r : r;
      77              :     }
      78              :   }
      79              : 
      80   1082275029 :   bool operator== (const sreal &other) const
      81              :   {
      82    253776436 :     return m_exp == other.m_exp && m_sig == other.m_sig;
      83              :   }
      84              : 
      85     10139287 :   sreal operator- () const
      86              :   {
      87     10139287 :     sreal tmp = *this;
      88     10139287 :     tmp.m_sig *= -1;
      89              : 
      90     10139287 :     return tmp;
      91              :   }
      92              : 
      93     62358174 :   sreal shift (int s) const
      94              :   {
      95              :     /* Zero needs no shifting.  */
      96     62358174 :     if (!m_sig)
      97      6753958 :       return *this;
      98     55604216 :     gcc_checking_assert (s <= SREAL_MAX_EXP);
      99     55604216 :     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     55604216 :     gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
     104     55604216 :     gcc_checking_assert (m_exp + s >= -SREAL_MAX_EXP);
     105              : 
     106     55604216 :     sreal tmp = *this;
     107     55604216 :     tmp.m_exp += s;
     108              : 
     109     55604216 :     return tmp;
     110              :   }
     111              : 
     112              :   /* Global minimum sreal can hold.  */
     113      1236808 :   inline static sreal min ()
     114              :   {
     115      1236808 :     sreal min;
     116              :     /* This never needs normalization.  */
     117      1236808 :     min.m_sig = -SREAL_MAX_SIG;
     118      1236808 :     min.m_exp = SREAL_MAX_EXP;
     119      1236808 :     return min;
     120              :   }
     121              : 
     122              :   /* Global minimum sreal can hold.  */
     123      2861038 :   inline static sreal max ()
     124              :   {
     125      2861038 :     sreal max;
     126              :     /* This never needs normalization.  */
     127      2861038 :     max.m_sig = SREAL_MAX_SIG;
     128      2861038 :     max.m_exp = SREAL_MAX_EXP;
     129       476963 :     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    655903818 : inline sreal &operator+= (sreal &a, const sreal &b)
     148              : {
     149    654491787 :   return a = a + b;
     150              : }
     151              : 
     152       479087 : inline sreal &operator-= (sreal &a, const sreal &b)
     153              : {
     154       479087 :   return a = a - b;
     155              : }
     156              : 
     157       483821 : inline sreal &operator/= (sreal &a, const sreal &b)
     158              : {
     159       483821 :   return a = a / b;
     160              : }
     161              : 
     162     18264728 : inline sreal &operator*= (sreal &a, const sreal &b)
     163              : {
     164     18264728 :   return a = a  * b;
     165              : }
     166              : 
     167     66581814 : inline bool operator!= (const sreal &a, const sreal &b)
     168              : {
     169    116440906 :   return !(a == b);
     170              : }
     171              : 
     172    441440200 : inline bool operator> (const sreal &a, const sreal &b)
     173              : {
     174    454896386 :   return !(a == b || a < b);
     175              : }
     176              : 
     177     12401530 : inline bool operator<= (const sreal &a, const sreal &b)
     178              : {
     179     12401530 :   return a < b || a == b;
     180              : }
     181              : 
     182    486008700 : inline bool operator>= (const sreal &a, const sreal &b)
     183              : {
     184    487876768 :   return a == b || a > b;
     185              : }
     186              : 
     187      2970373 : inline sreal operator<< (const sreal &a, int exp)
     188              : {
     189      2970373 :   return a.shift (exp);
     190              : }
     191              : 
     192     49541795 : inline sreal operator>> (const sreal &a, int exp)
     193              : {
     194     49541795 :   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   1152511276 : sreal::normalize_up (int64_t new_sig, signed int new_exp)
     203              : {
     204   1152511276 :   unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
     205   1152511276 :   int shift = SREAL_PART_BITS - 2 - floor_log2 (sig);
     206              : 
     207   1152511276 :   gcc_checking_assert (shift > 0);
     208   1152511276 :   sig <<= shift;
     209   1152511276 :   new_exp -= shift;
     210   1152511276 :   gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
     211              : 
     212              :   /* Check underflow.  */
     213   1152511276 :   if (new_exp < -SREAL_MAX_EXP)
     214              :     {
     215            0 :       new_exp = -SREAL_MAX_EXP;
     216            0 :       sig = 0;
     217              :     }
     218   1152511276 :   m_exp = new_exp;
     219   1152511276 :   if (SREAL_SIGN (new_sig) == -1)
     220     43452083 :     m_sig = -sig;
     221              :   else
     222   1109059193 :     m_sig = sig;
     223   1152511276 : }
     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    953123185 : sreal::normalize_down (int64_t new_sig, signed int new_exp)
     231              : {
     232    953123185 :   int last_bit;
     233    953123185 :   unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
     234    953123185 :   int shift = floor_log2 (sig) - SREAL_PART_BITS + 2;
     235              : 
     236    953123185 :   gcc_checking_assert (shift > 0);
     237    953123185 :   last_bit = (sig >> (shift-1)) & 1;
     238    953123185 :   sig >>= shift;
     239    953123185 :   new_exp += shift;
     240    953123185 :   gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
     241              : 
     242              :   /* Round the number.  */
     243    953123185 :   sig += last_bit;
     244    953123185 :   if (sig > SREAL_MAX_SIG)
     245              :     {
     246      3529838 :       sig >>= 1;
     247      3529838 :       new_exp++;
     248              :     }
     249              : 
     250              :   /* Check overflow.  */
     251    953123185 :   if (new_exp > SREAL_MAX_EXP)
     252              :     {
     253            0 :       new_exp = SREAL_MAX_EXP;
     254            0 :       sig = SREAL_MAX_SIG;
     255              :     }
     256    953123185 :   m_exp = new_exp;
     257    953123185 :   if (SREAL_SIGN (new_sig) == -1)
     258     16632407 :     m_sig = -sig;
     259              :   else
     260    936490778 :     m_sig = sig;
     261    953123185 : }
     262              : 
     263              : /* Normalize *this; the hot path.  */
     264              : 
     265              : inline void
     266   3634320527 : sreal::normalize (int64_t new_sig, signed int new_exp)
     267              : {
     268   3634320527 :   unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
     269              : 
     270   3634320527 :   if (sig == 0)
     271              :     {
     272   1118146747 :       m_sig = 0;
     273   1118146747 :       m_exp = -SREAL_MAX_EXP;
     274              :     }
     275   2516173780 :   else if (sig > SREAL_MAX_SIG)
     276    953123185 :     normalize_down (new_sig, new_exp);
     277   1563050595 :   else if (sig < SREAL_MIN_SIG)
     278   1152511276 :     normalize_up (new_sig, new_exp);
     279              :   else
     280              :     {
     281    410539319 :       m_sig = new_sig;
     282    410539319 :       m_exp = new_exp;
     283              :     }
     284   3634320527 : }
     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.