LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - rational_cln_imp.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 63 75 84.0 %
Date: 2026-05-13 10:48:54 Functions: 7 7 100.0 %
Branches: 27 46 58.7 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * A multi-precision rational constant.
      11                 :            :  */
      12                 :            : #include <cln/integer_io.h>
      13                 :            : 
      14                 :            : #include <sstream>
      15                 :            : #include <string>
      16                 :            : 
      17                 :            : #include "base/cvc5config.h"
      18                 :            : #include "util/rational.h"
      19                 :            : 
      20                 :            : #ifndef CVC5_CLN_IMP
      21                 :            : #error "This source should only ever be built if CVC5_CLN_IMP is on !"
      22                 :            : #endif /* CVC5_CLN_IMP */
      23                 :            : 
      24                 :            : #include "base/check.h"
      25                 :            : 
      26                 :            : using namespace std;
      27                 :            : 
      28                 :            : namespace cvc5::internal {
      29                 :            : 
      30                 :            : /* Computes a rational given a decimal string. The rational
      31                 :            :  * version of <code>xxx.yyy</code> is <code>xxxyyy/(10^3)</code>.
      32                 :            :  */
      33                 :     910765 : Rational Rational::fromDecimal(const std::string& dec)
      34                 :            : {
      35                 :            :   // Find the decimal point, if there is one
      36                 :     910765 :   string::size_type i(dec.find("."));
      37         [ +  + ]:     910765 :   if (i != string::npos)
      38                 :            :   {
      39                 :            :     /* Erase the decimal point, so we have just the numerator. */
      40                 :      66394 :     Integer numerator(string(dec).erase(i, 1));
      41                 :            : 
      42                 :            :     /* Compute the denominator: 10 raise to the number of decimal places */
      43                 :      66390 :     int decPlaces = dec.size() - (i + 1);
      44                 :      66390 :     Integer denominator(Integer(10).pow(decPlaces));
      45                 :            : 
      46                 :      66390 :     return Rational(numerator, denominator);
      47                 :      66390 :   }
      48                 :            :   else
      49                 :            :   {
      50                 :            :     /* No decimal point, assume it's just an integer. */
      51                 :     844373 :     return Rational(dec);
      52                 :            :   }
      53                 :            : }
      54                 :            : 
      55                 :     890321 : Rational::Rational(const char* s, uint32_t base)
      56                 :            : {
      57                 :            :   try
      58                 :            :   {
      59                 :            :     cln::cl_read_flags flags;
      60                 :     890321 :     flags.rational_base = base;
      61                 :     890321 :     flags.lsyntax = cln::lsyntax_standard;
      62                 :            : 
      63                 :     890321 :     const char* p = strchr(s, '/');
      64                 :            :     /* read_rational() does not support the case where the denominator is
      65                 :            :      * negative.  In this case we read the numerator and denominator via
      66                 :            :      * read_integer() and build a rational out of two integers. */
      67         [ +  + ]:     890321 :     if (p)
      68                 :            :     {
      69                 :      45302 :       flags.syntax = cln::syntax_integer;
      70                 :      45302 :       auto num = cln::read_integer(flags, s, p, nullptr);
      71                 :      45296 :       auto den = cln::read_integer(flags, p + 1, nullptr, nullptr);
      72                 :      45296 :       d_value = num / den;
      73                 :      45296 :     }
      74                 :            :     else
      75                 :            :     {
      76                 :     845019 :       flags.syntax = cln::syntax_rational;
      77                 :     845019 :       d_value = read_rational(flags, s, NULL, NULL);
      78                 :            :     }
      79                 :            :   }
      80                 :        388 :   catch (...)
      81                 :            :   {
      82                 :        388 :     std::stringstream ss;
      83                 :        388 :     ss << "Rational() failed to parse value \"" << s << "\" in base=" << base;
      84                 :        388 :     throw std::invalid_argument(ss.str());
      85                 :        776 :   }
      86                 :     890321 : }
      87                 :            : 
      88                 :     845842 : Rational::Rational(const std::string& s, uint32_t base)
      89                 :     845842 :     : Rational(s.c_str(), base)
      90                 :            : {
      91                 :     845454 : }
      92                 :            : 
      93                 :  650546497 : int Rational::sgn() const
      94                 :            : {
      95         [ +  + ]:  650546497 :   if (cln::zerop(d_value))
      96                 :            :   {
      97                 :   64492229 :     return 0;
      98                 :            :   }
      99         [ +  + ]:  586054268 :   else if (cln::minusp(d_value))
     100                 :            :   {
     101                 :  347944604 :     return -1;
     102                 :            :   }
     103                 :            :   else
     104                 :            :   {
     105 [ -  + ][ -  + ]:  238109664 :     Assert(cln::plusp(d_value));
                 [ -  - ]
     106                 :  238109664 :     return 1;
     107                 :            :   }
     108                 :            : }
     109                 :            : 
     110                 :    1825003 : std::ostream& operator<<(std::ostream& os, const Rational& q)
     111                 :            : {
     112                 :    1825003 :   return os << q.toString();
     113                 :            : }
     114                 :            : 
     115                 :            : /** Equivalent to calling (this->abs()).cmp(b.abs()) */
     116                 :    9881930 : int Rational::absCmp(const Rational& q) const
     117                 :            : {
     118                 :    9881930 :   const Rational& r = *this;
     119                 :    9881930 :   int rsgn = r.sgn();
     120                 :    9881930 :   int qsgn = q.sgn();
     121         [ -  + ]:    9881930 :   if (rsgn == 0)
     122                 :            :   {
     123         [ -  - ]:          0 :     return (qsgn == 0) ? 0 : -1;
     124                 :            :   }
     125         [ -  + ]:    9881930 :   else if (qsgn == 0)
     126                 :            :   {
     127                 :          0 :     Assert(rsgn != 0);
     128                 :          0 :     return 1;
     129                 :            :   }
     130 [ +  + ][ +  + ]:    9881930 :   else if ((rsgn > 0) && (qsgn > 0))
     131                 :            :   {
     132                 :    6951739 :     return r.cmp(q);
     133                 :            :   }
     134 [ +  + ][ +  + ]:    2930191 :   else if ((rsgn < 0) && (qsgn < 0))
     135                 :            :   {
     136                 :            :     // if r < q < 0, q.cmp(r) = +1, (r.abs()).cmp(q.abs()) = +1
     137                 :            :     // if q < r < 0, q.cmp(r) = -1, (r.abs()).cmp(q.abs()) = -1
     138                 :            :     // if q = r < 0, q.cmp(r) =  0, (r.abs()).cmp(q.abs()) =  0
     139                 :     530518 :     return q.cmp(r);
     140                 :            :   }
     141 [ +  + ][ +  - ]:    2399673 :   else if ((rsgn < 0) && (qsgn > 0))
     142                 :            :   {
     143                 :    1517239 :     Rational rpos = -r;
     144                 :    1517239 :     return rpos.cmp(q);
     145                 :    1517239 :   }
     146                 :            :   else
     147                 :            :   {
     148 [ +  - ][ +  - ]:     882434 :     Assert(rsgn > 0 && (qsgn < 0));
         [ -  + ][ -  + ]
                 [ -  - ]
     149                 :     882434 :     Rational qpos = -q;
     150                 :     882434 :     return r.cmp(qpos);
     151                 :     882434 :   }
     152                 :            : }
     153                 :            : 
     154                 :         16 : std::optional<Rational> Rational::fromDouble(double d)
     155                 :            : {
     156                 :            :   try
     157                 :            :   {
     158                 :         16 :     cln::cl_DF fromD = d;
     159                 :         16 :     Rational q;
     160                 :         16 :     q.d_value = cln::rationalize(fromD);
     161                 :         16 :     return q;
     162                 :         16 :   }
     163 [ -  - ][ -  - ]:          0 :   catch (cln::floating_point_underflow_exception& fpue)
     164                 :            :   {
     165                 :          0 :     return std::optional<Rational>();
     166                 :          0 :   }
     167                 :          0 :   catch (cln::floating_point_nan_exception& fpne)
     168                 :            :   {
     169                 :          0 :     return std::optional<Rational>();
     170                 :          0 :   }
     171                 :          0 :   catch (cln::floating_point_overflow_exception& fpoe)
     172                 :            :   {
     173                 :          0 :     return std::optional<Rational>();
     174                 :          0 :   }
     175                 :            : }
     176                 :            : 
     177                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14