LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - rational_cln_imp.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 80 83 96.4 %
Date: 2024-08-28 11:13:27 Functions: 45 47 95.7 %
Branches: 4 4 100.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Tim King, Gereon Kremer, Aina Niemetz
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * Multiprecision rational constants; wraps a CLN multiprecision rational.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "cvc5_public.h"
      17                 :            : 
      18                 :            : #ifndef CVC5__RATIONAL_H
      19                 :            : #define CVC5__RATIONAL_H
      20                 :            : 
      21                 :            : #include <cln/dfloat.h>
      22                 :            : #include <cln/input.h>
      23                 :            : #include <cln/io.h>
      24                 :            : #include <cln/number_io.h>
      25                 :            : #include <cln/output.h>
      26                 :            : #include <cln/rational.h>
      27                 :            : #include <cln/rational_io.h>
      28                 :            : #include <cln/real.h>
      29                 :            : 
      30                 :            : #include <optional>
      31                 :            : #include <sstream>
      32                 :            : #include <string>
      33                 :            : 
      34                 :            : #include "base/exception.h"
      35                 :            : #include "util/integer.h"
      36                 :            : 
      37                 :            : namespace cvc5::internal {
      38                 :            : 
      39                 :            : /**
      40                 :            :  * A multi-precision rational constant.
      41                 :            :  * This stores the rational as a pair of multi-precision integers,
      42                 :            :  * one for the numerator and one for the denominator.
      43                 :            :  * The number is always stored so that the gcd of the numerator and denominator
      44                 :            :  * is 1.  (This is referred to as referred to as canonical form in GMP's
      45                 :            :  * literature.) A consequence is that that the numerator and denominator may be
      46                 :            :  * different than the values used to construct the Rational.
      47                 :            :  *
      48                 :            :  * NOTE: The correct way to create a Rational from an int is to use one of the
      49                 :            :  * int numerator/int denominator constructors with the denominator 1.  Trying
      50                 :            :  * to construct a Rational with a single int, e.g., Rational(0), will put you
      51                 :            :  * in danger of invoking the char* constructor, from whence you will segfault.
      52                 :            :  */
      53                 :            : 
      54                 :            : class Rational
      55                 :            : {
      56                 :            :  public:
      57                 :            :   /**
      58                 :            :    * Constructs a Rational from a cln::cl_RA object.
      59                 :            :    * Does a deep copy.
      60                 :            :    */
      61                 :  319807073 :   Rational(const cln::cl_RA& val) : d_value(val) {}
      62                 :            : 
      63                 :            :   /**
      64                 :            :    * Creates a rational from a decimal string (e.g., <code>"1.5"</code>).
      65                 :            :    *
      66                 :            :    * @param dec a string encoding a decimal number in the format
      67                 :            :    * <code>[0-9]*\.[0-9]*</code>
      68                 :            :    */
      69                 :            :   static Rational fromDecimal(const std::string& dec);
      70                 :            : 
      71                 :            :   /** Constructs a rational with the value 0/1. */
      72                 :   19796403 :   Rational() : d_value(0) {}
      73                 :            :   /**
      74                 :            :    * Constructs a Rational from a C string in a given base (defaults to 10).
      75                 :            :    *
      76                 :            :    * Throws std::invalid_argument if the string is not a valid rational, i.e.,
      77                 :            :    * if it does not match sign{digit}+/sign{digit}+.
      78                 :            :    */
      79                 :            :   explicit Rational(const char* s, uint32_t base = 10);
      80                 :            :   Rational(const std::string& s, uint32_t base = 10);
      81                 :            : 
      82                 :            :   /**
      83                 :            :    * Creates a Rational from another Rational, q, by performing a deep copy.
      84                 :            :    */
      85                 :  394023196 :   Rational(const Rational& q) : d_value(q.d_value) {}
      86                 :            : 
      87                 :            :   /**
      88                 :            :    * Constructs a canonical Rational from a numerator.
      89                 :            :    */
      90                 :  797454778 :   Rational(signed int n) : d_value((signed long int)n) {}
      91                 :    8586392 :   Rational(unsigned int n) : d_value((unsigned long int)n) {}
      92                 :     117741 :   Rational(signed long int n) : d_value(n) {}
      93                 :    2069768 :   Rational(unsigned long int n) : d_value(n) {}
      94                 :            : 
      95                 :            : #ifdef CVC5_NEED_INT64_T_OVERLOADS
      96                 :            :   Rational(int64_t n) : d_value(n) {}
      97                 :            :   Rational(uint64_t n) : d_value(n) {}
      98                 :            : #endif /* CVC5_NEED_INT64_T_OVERLOADS */
      99                 :            : 
     100                 :            :   /**
     101                 :            :    * Constructs a canonical Rational from a numerator and denominator.
     102                 :            :    */
     103                 :   25367722 :   Rational(signed int n, signed int d) : d_value((signed long int)n)
     104                 :            :   {
     105                 :   25367722 :     d_value /= cln::cl_I(d);
     106                 :   25367722 :   }
     107                 :         15 :   Rational(unsigned int n, unsigned int d) : d_value((unsigned long int)n)
     108                 :            :   {
     109                 :         15 :     d_value /= cln::cl_I(d);
     110                 :         15 :   }
     111                 :        411 :   Rational(signed long int n, signed long int d) : d_value(n)
     112                 :            :   {
     113                 :        411 :     d_value /= cln::cl_I(d);
     114                 :        411 :   }
     115                 :          1 :   Rational(unsigned long int n, unsigned long int d) : d_value(n)
     116                 :            :   {
     117                 :          1 :     d_value /= cln::cl_I(d);
     118                 :          1 :   }
     119                 :            : 
     120                 :            : #ifdef CVC5_NEED_INT64_T_OVERLOADS
     121                 :            :   Rational(int64_t n, int64_t d) : d_value(n) { d_value /= cln::cl_I(d); }
     122                 :            :   Rational(uint64_t n, uint64_t d) : d_value(n) { d_value /= cln::cl_I(d); }
     123                 :            : #endif /* CVC5_NEED_INT64_T_OVERLOADS */
     124                 :            : 
     125                 :    3624501 :   Rational(const Integer& n, const Integer& d) : d_value(n.get_cl_I())
     126                 :            :   {
     127                 :    3624501 :     d_value /= d.get_cl_I();
     128                 :    3624501 :   }
     129                 :   37845500 :   Rational(const Integer& n) : d_value(n.get_cl_I()) {}
     130                 :            : 
     131                 : 1609522126 :   ~Rational() {}
     132                 :            : 
     133                 :            :   /**
     134                 :            :    * Returns a copy of d_value to enable public access of CLN data.
     135                 :            :    */
     136                 :            :   const cln::cl_RA& getValue() const { return d_value; }
     137                 :            : 
     138                 :            :   /**
     139                 :            :    * Returns the value of numerator of the Rational.
     140                 :            :    * Note that this makes a deep copy of the numerator.
     141                 :            :    */
     142                 :  206902029 :   Integer getNumerator() const { return Integer(cln::numerator(d_value)); }
     143                 :            : 
     144                 :            :   /**
     145                 :            :    * Returns the value of denominator of the Rational.
     146                 :            :    * Note that this makes a deep copy of the denominator.
     147                 :            :    */
     148                 :   39517321 :   Integer getDenominator() const { return Integer(cln::denominator(d_value)); }
     149                 :            : 
     150                 :            :   /** Return an exact rational for a double d. */
     151                 :            :   static std::optional<Rational> fromDouble(double d);
     152                 :            : 
     153                 :            :   /**
     154                 :            :    * Get a double representation of this Rational, which is
     155                 :            :    * approximate: truncation may occur, overflow may result in
     156                 :            :    * infinity, and underflow may result in zero.
     157                 :            :    */
     158                 :         92 :   double getDouble() const { return cln::double_approx(d_value); }
     159                 :            : 
     160                 :    1253360 :   Rational inverse() const { return Rational(cln::recip(d_value)); }
     161                 :            : 
     162                 :  185476000 :   int cmp(const Rational& x) const
     163                 :            :   {
     164                 :            :     // Don't use mpq_class's cmp() function.
     165                 :            :     // The name ends up conflicting with this function.
     166                 :  185476000 :     return cln::compare(d_value, x.d_value);
     167                 :            :   }
     168                 :            : 
     169                 :            :   int sgn() const;
     170                 :            : 
     171                 :   78391100 :   bool isZero() const { return cln::zerop(d_value); }
     172                 :            : 
     173                 :   27253300 :   bool isOne() const { return d_value == 1; }
     174                 :            : 
     175                 :      75418 :   bool isNegativeOne() const { return d_value == -1; }
     176                 :            : 
     177                 :     650034 :   Rational abs() const
     178                 :            :   {
     179         [ +  + ]:     650034 :     if (sgn() < 0)
     180                 :            :     {
     181                 :     131613 :       return -(*this);
     182                 :            :     }
     183                 :            :     else
     184                 :            :     {
     185                 :     518421 :       return *this;
     186                 :            :     }
     187                 :            :   }
     188                 :            : 
     189                 :  431950000 :   bool isIntegral() const { return cln::denominator(d_value) == 1; }
     190                 :            : 
     191                 :       7406 :   Integer floor() const { return Integer(cln::floor1(d_value)); }
     192                 :            : 
     193                 :    3507170 :   Integer ceiling() const { return Integer(cln::ceiling1(d_value)); }
     194                 :            : 
     195                 :          0 :   Rational floor_frac() const { return (*this) - Rational(floor()); }
     196                 :            : 
     197                 :  192739003 :   Rational& operator=(const Rational& x)
     198                 :            :   {
     199         [ +  + ]:  192739003 :     if (this == &x) return *this;
     200                 :  192739003 :     d_value = x.d_value;
     201                 :  192739003 :     return *this;
     202                 :            :   }
     203                 :            : 
     204                 :   24072600 :   Rational operator-() const { return Rational(-(d_value)); }
     205                 :            : 
     206                 :  768767249 :   bool operator==(const Rational& y) const { return d_value == y.d_value; }
     207                 :            : 
     208                 :  109729016 :   bool operator!=(const Rational& y) const { return d_value != y.d_value; }
     209                 :            : 
     210                 :    2300460 :   bool operator<(const Rational& y) const { return d_value < y.d_value; }
     211                 :            : 
     212                 :   59231000 :   bool operator<=(const Rational& y) const { return d_value <= y.d_value; }
     213                 :            : 
     214                 :     707416 :   bool operator>(const Rational& y) const { return d_value > y.d_value; }
     215                 :            : 
     216                 :     487256 :   bool operator>=(const Rational& y) const { return d_value >= y.d_value; }
     217                 :            : 
     218                 :   65479509 :   Rational operator+(const Rational& y) const
     219                 :            :   {
     220                 :  130959009 :     return Rational(d_value + y.d_value);
     221                 :            :   }
     222                 :     359582 :   Rational operator-(const Rational& y) const
     223                 :            :   {
     224                 :     719155 :     return Rational(d_value - y.d_value);
     225                 :            :   }
     226                 :            : 
     227                 :  236178009 :   Rational operator*(const Rational& y) const
     228                 :            :   {
     229                 :  472357009 :     return Rational(d_value * y.d_value);
     230                 :            :   }
     231                 :    5126232 :   Rational operator/(const Rational& y) const
     232                 :            :   {
     233                 :   10252412 :     return Rational(d_value / y.d_value);
     234                 :            :   }
     235                 :            : 
     236                 :   93082500 :   Rational& operator+=(const Rational& y)
     237                 :            :   {
     238                 :   93082500 :     d_value += y.d_value;
     239                 :   93082500 :     return (*this);
     240                 :            :   }
     241                 :            : 
     242                 :      34822 :   Rational& operator-=(const Rational& y)
     243                 :            :   {
     244                 :      34822 :     d_value -= y.d_value;
     245                 :      34822 :     return (*this);
     246                 :            :   }
     247                 :            : 
     248                 :    8137840 :   Rational& operator*=(const Rational& y)
     249                 :            :   {
     250                 :    8137840 :     d_value *= y.d_value;
     251                 :    8137840 :     return (*this);
     252                 :            :   }
     253                 :            : 
     254                 :       1959 :   Rational& operator/=(const Rational& y)
     255                 :            :   {
     256                 :       1959 :     d_value /= y.d_value;
     257                 :       1959 :     return (*this);
     258                 :            :   }
     259                 :            : 
     260                 :            :   /** Returns a string representing the rational in the given base. */
     261                 :     770469 :   std::string toString(int base = 10) const
     262                 :            :   {
     263                 :    1540934 :     cln::cl_print_flags flags;
     264                 :     770469 :     flags.rational_base = base;
     265                 :     770469 :     flags.rational_readably = false;
     266                 :    1540934 :     std::stringstream ss;
     267                 :     770469 :     print_rational(ss, flags, d_value);
     268                 :    1540934 :     return ss.str();
     269                 :            :   }
     270                 :            : 
     271                 :            :   /**
     272                 :            :    * Computes the hash of the rational from hashes of the numerator and the
     273                 :            :    * denominator.
     274                 :            :    */
     275                 :  219078000 :   size_t hash() const { return equal_hashcode(d_value); }
     276                 :            : 
     277                 :          0 :   uint32_t complexity() const
     278                 :            :   {
     279                 :          0 :     return getNumerator().length() + getDenominator().length();
     280                 :            :   }
     281                 :            : 
     282                 :            :   /** Equivalent to calling (this->abs()).cmp(b.abs()) */
     283                 :            :   int absCmp(const Rational& q) const;
     284                 :            : 
     285                 :            :  private:
     286                 :            :   /**
     287                 :            :    * Stores the value of the rational in a C++ CLN rational class.
     288                 :            :    */
     289                 :            :   cln::cl_RA d_value;
     290                 :            : 
     291                 :            : }; /* class Rational */
     292                 :            : 
     293                 :            : struct RationalHashFunction
     294                 :            : {
     295                 :  219078000 :   inline size_t operator()(const cvc5::internal::Rational& r) const { return r.hash(); }
     296                 :            : }; /* struct RationalHashFunction */
     297                 :            : 
     298                 :            : std::ostream& operator<<(std::ostream& os, const Rational& n);
     299                 :            : 
     300                 :            : }  // namespace cvc5::internal
     301                 :            : 
     302                 :            : #endif /* CVC5__RATIONAL_H */

Generated by: LCOV version 1.14