LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - floatingpoint.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 151 175 86.3 %
Date: 2026-05-13 10:48:54 Functions: 52 58 89.7 %
Branches: 22 28 78.6 %

           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 floating-point value.
      11                 :            :  *
      12                 :            :  * This file contains the data structures used by the constant and parametric
      13                 :            :  * types of the floating point theory.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "util/floatingpoint.h"
      17                 :            : 
      18                 :            : #include <math.h>
      19                 :            : 
      20                 :            : #include "base/check.h"
      21                 :            : #include "util/floatingpoint_literal.h"
      22                 :            : #include "util/integer.h"
      23                 :            : 
      24                 :            : /* -------------------------------------------------------------------------- */
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : 
      28                 :            : /* -------------------------------------------------------------------------- */
      29                 :            : 
      30                 :        198 : uint32_t FloatingPoint::getUnpackedExponentWidth(FloatingPointSize& size)
      31                 :            : {
      32                 :        198 :   return FloatingPointLiteral::getUnpackedExponentWidth(size);
      33                 :            : }
      34                 :            : 
      35                 :        198 : uint32_t FloatingPoint::getUnpackedSignificandWidth(FloatingPointSize& size)
      36                 :            : {
      37                 :        198 :   return FloatingPointLiteral::getUnpackedSignificandWidth(size);
      38                 :            : }
      39                 :            : 
      40                 :       6074 : FloatingPoint::FloatingPoint(uint32_t d_exp_size,
      41                 :            :                              uint32_t d_sig_size,
      42                 :       6074 :                              const BitVector& bv)
      43                 :       6074 :     : d_fpl(FloatingPointLiteral::create(d_exp_size, d_sig_size, bv))
      44                 :            : {
      45                 :       6074 : }
      46                 :            : 
      47                 :         34 : FloatingPoint::FloatingPoint(const FloatingPointSize& size, const BitVector& bv)
      48                 :         34 :     : d_fpl(FloatingPointLiteral::create(size, bv))
      49                 :            : {
      50                 :         34 : }
      51                 :            : 
      52                 :        165 : FloatingPoint::FloatingPoint(const FloatingPointSize& size,
      53                 :            :                              const RoundingMode& rm,
      54                 :            :                              const BitVector& bv,
      55                 :        165 :                              bool signedBV)
      56                 :        165 :     : d_fpl(FloatingPointLiteral::create(size, rm, bv, signedBV))
      57                 :            : {
      58                 :        165 : }
      59                 :            : 
      60                 :      14093 : FloatingPoint::FloatingPoint(std::unique_ptr<FloatingPointLiteral>&& fpl)
      61                 :      14093 :     : d_fpl(std::move(fpl))
      62                 :            : {
      63                 :      14093 : }
      64                 :            : 
      65                 :         77 : FloatingPoint::FloatingPoint(const FloatingPointSize& size,
      66                 :            :                              const RoundingMode& rm,
      67                 :         77 :                              const Rational& r)
      68                 :         77 :     : d_fpl(FloatingPointLiteral::createFromRational(size, rm, r))
      69                 :            : {
      70                 :         77 : }
      71                 :            : 
      72                 :      28194 : FloatingPoint::FloatingPoint(const FloatingPoint& fp) : d_fpl(fp.d_fpl->clone())
      73                 :            : {
      74                 :      28194 : }
      75                 :            : 
      76                 :          2 : FloatingPoint::FloatingPoint(FloatingPoint&& fp) noexcept
      77                 :          2 :     : d_fpl(std::move(fp.d_fpl))
      78                 :            : {
      79                 :          2 : }
      80                 :            : 
      81                 :          0 : FloatingPoint& FloatingPoint::operator=(const FloatingPoint& other)
      82                 :            : {
      83         [ -  - ]:          0 :   if (this != &other)
      84                 :            :   {
      85                 :          0 :     d_fpl = other.d_fpl->clone();
      86                 :            :   }
      87                 :          0 :   return *this;
      88                 :            : }
      89                 :            : 
      90                 :          1 : FloatingPoint& FloatingPoint::operator=(FloatingPoint&& other) noexcept
      91                 :            : {
      92         [ +  - ]:          1 :   if (this != &other)
      93                 :            :   {
      94                 :          1 :     d_fpl = std::move(other.d_fpl);
      95                 :            :   }
      96                 :          1 :   return *this;
      97                 :            : }
      98                 :            : 
      99                 :      48593 : FloatingPoint::~FloatingPoint() {}
     100                 :            : 
     101                 :      76798 : const FloatingPointSize& FloatingPoint::getSize() const
     102                 :            : {
     103                 :      76798 :   return d_fpl->getSize();
     104                 :            : }
     105                 :            : 
     106                 :        237 : FloatingPoint FloatingPoint::makeNaN(const FloatingPointSize& size)
     107                 :            : {
     108                 :        474 :   return FloatingPoint(FloatingPointLiteral::create(
     109                 :        474 :       size, FloatingPointLiteral::SpecialConstKind::FPNAN));
     110                 :            : }
     111                 :            : 
     112                 :        392 : FloatingPoint FloatingPoint::makeInf(const FloatingPointSize& size, bool sign)
     113                 :            : {
     114                 :        784 :   return FloatingPoint(FloatingPointLiteral::create(
     115                 :        784 :       size, FloatingPointLiteral::SpecialConstKind::FPINF, sign));
     116                 :            : }
     117                 :            : 
     118                 :        430 : FloatingPoint FloatingPoint::makeZero(const FloatingPointSize& size, bool sign)
     119                 :            : {
     120                 :        860 :   return FloatingPoint(FloatingPointLiteral::create(
     121                 :        860 :       size, FloatingPointLiteral::SpecialConstKind::FPZERO, sign));
     122                 :            : }
     123                 :            : 
     124                 :          8 : FloatingPoint FloatingPoint::makeMinSubnormal(const FloatingPointSize& size,
     125                 :            :                                               bool sign)
     126                 :            : {
     127         [ +  + ]:          8 :   BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     128                 :          8 :   BitVector bvexp = BitVector::mkZero(size.packedExponentWidth());
     129                 :          8 :   BitVector bvsig = BitVector::mkOne(size.packedSignificandWidth());
     130                 :         24 :   return FloatingPoint(size, bvsign.concat(bvexp).concat(bvsig));
     131                 :          8 : }
     132                 :            : 
     133                 :          8 : FloatingPoint FloatingPoint::makeMaxSubnormal(const FloatingPointSize& size,
     134                 :            :                                               bool sign)
     135                 :            : {
     136         [ +  + ]:          8 :   BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     137                 :          8 :   BitVector bvexp = BitVector::mkZero(size.packedExponentWidth());
     138                 :          8 :   BitVector bvsig = BitVector::mkOnes(size.packedSignificandWidth());
     139                 :         24 :   return FloatingPoint(size, bvsign.concat(bvexp).concat(bvsig));
     140                 :          8 : }
     141                 :            : 
     142                 :          8 : FloatingPoint FloatingPoint::makeMinNormal(const FloatingPointSize& size,
     143                 :            :                                            bool sign)
     144                 :            : {
     145         [ +  + ]:          8 :   BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     146                 :          8 :   BitVector bvexp = BitVector::mkOne(size.packedExponentWidth());
     147                 :          8 :   BitVector bvsig = BitVector::mkZero(size.packedSignificandWidth());
     148                 :         24 :   return FloatingPoint(size, bvsign.concat(bvexp).concat(bvsig));
     149                 :          8 : }
     150                 :            : 
     151                 :          8 : FloatingPoint FloatingPoint::makeMaxNormal(const FloatingPointSize& size,
     152                 :            :                                            bool sign)
     153                 :            : {
     154         [ +  + ]:          8 :   BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     155                 :          8 :   BitVector bvexp = BitVector::mkOnes(size.packedExponentWidth());
     156                 :          8 :   bvexp.setBit(0, false);
     157                 :          8 :   BitVector bvsig = BitVector::mkOnes(size.packedSignificandWidth());
     158                 :         24 :   return FloatingPoint(size, bvsign.concat(bvexp).concat(bvsig));
     159                 :          8 : }
     160                 :            : 
     161                 :        222 : FloatingPoint FloatingPoint::absolute(void) const
     162                 :            : {
     163                 :        444 :   return FloatingPoint(d_fpl->absolute());
     164                 :            : }
     165                 :            : 
     166                 :        672 : FloatingPoint FloatingPoint::negate(void) const
     167                 :            : {
     168                 :       1344 :   return FloatingPoint(d_fpl->negate());
     169                 :            : }
     170                 :            : 
     171                 :       4736 : FloatingPoint FloatingPoint::add(const RoundingMode& rm,
     172                 :            :                                  const FloatingPoint& arg) const
     173                 :            : {
     174                 :       9472 :   return FloatingPoint(d_fpl->add(rm, *arg.d_fpl));
     175                 :            : }
     176                 :            : 
     177                 :          0 : FloatingPoint FloatingPoint::sub(const RoundingMode& rm,
     178                 :            :                                  const FloatingPoint& arg) const
     179                 :            : {
     180                 :          0 :   return FloatingPoint(d_fpl->sub(rm, *arg.d_fpl));
     181                 :            : }
     182                 :            : 
     183                 :       2418 : FloatingPoint FloatingPoint::mult(const RoundingMode& rm,
     184                 :            :                                   const FloatingPoint& arg) const
     185                 :            : {
     186                 :       4836 :   return FloatingPoint(d_fpl->mult(rm, *arg.d_fpl));
     187                 :            : }
     188                 :            : 
     189                 :          2 : FloatingPoint FloatingPoint::fma(const RoundingMode& rm,
     190                 :            :                                  const FloatingPoint& arg1,
     191                 :            :                                  const FloatingPoint& arg2) const
     192                 :            : {
     193                 :          4 :   return FloatingPoint(d_fpl->fma(rm, *arg1.d_fpl, *arg2.d_fpl));
     194                 :            : }
     195                 :            : 
     196                 :       2605 : FloatingPoint FloatingPoint::div(const RoundingMode& rm,
     197                 :            :                                  const FloatingPoint& arg) const
     198                 :            : {
     199                 :       5210 :   return FloatingPoint(d_fpl->div(rm, *arg.d_fpl));
     200                 :            : }
     201                 :            : 
     202                 :       1180 : FloatingPoint FloatingPoint::sqrt(const RoundingMode& rm) const
     203                 :            : {
     204                 :       2360 :   return FloatingPoint(d_fpl->sqrt(rm));
     205                 :            : }
     206                 :            : 
     207                 :        210 : FloatingPoint FloatingPoint::rti(const RoundingMode& rm) const
     208                 :            : {
     209                 :        420 :   return FloatingPoint(d_fpl->rti(rm));
     210                 :            : }
     211                 :            : 
     212                 :        525 : FloatingPoint FloatingPoint::rem(const FloatingPoint& arg) const
     213                 :            : {
     214                 :       1050 :   return FloatingPoint(d_fpl->rem(*arg.d_fpl));
     215                 :            : }
     216                 :            : 
     217                 :        424 : FloatingPoint FloatingPoint::maxTotal(const FloatingPoint& arg,
     218                 :            :                                       bool zeroCaseLeft) const
     219                 :            : {
     220                 :        848 :   return FloatingPoint(d_fpl->maxTotal(*arg.d_fpl, zeroCaseLeft));
     221                 :            : }
     222                 :            : 
     223                 :         18 : FloatingPoint FloatingPoint::minTotal(const FloatingPoint& arg,
     224                 :            :                                       bool zeroCaseLeft) const
     225                 :            : {
     226                 :         36 :   return FloatingPoint(d_fpl->minTotal(*arg.d_fpl, zeroCaseLeft));
     227                 :            : }
     228                 :            : 
     229                 :            : // Suppress clang-analyzer-core.uninitialized.Assign for the
     230                 :            : // following functions as a workaround for a false positive
     231                 :            : // in clang-tidy 18.
     232                 :            : // NOLINTBEGIN(clang-analyzer-core.uninitialized.Assign)
     233                 :        212 : FloatingPoint::PartialFloatingPoint FloatingPoint::max(
     234                 :            :     const FloatingPoint& arg) const
     235                 :            : {
     236                 :        212 :   FloatingPoint tmp(maxTotal(arg, true));
     237                 :        636 :   return PartialFloatingPoint(tmp, tmp == maxTotal(arg, false));
     238                 :        212 : }
     239                 :            : 
     240                 :          8 : FloatingPoint::PartialFloatingPoint FloatingPoint::min(
     241                 :            :     const FloatingPoint& arg) const
     242                 :            : {
     243                 :          8 :   FloatingPoint tmp(minTotal(arg, true));
     244                 :         24 :   return PartialFloatingPoint(tmp, tmp == minTotal(arg, false));
     245                 :          8 : }
     246                 :            : // NOLINTEND(clang-analyzer-core.uninitialized.Assign)
     247                 :            : 
     248                 :      26009 : bool FloatingPoint::operator==(const FloatingPoint& fp) const
     249                 :            : {
     250                 :      26009 :   return *d_fpl == *fp.d_fpl;
     251                 :            : }
     252                 :            : 
     253                 :         45 : bool FloatingPoint::operator<=(const FloatingPoint& fp) const
     254                 :            : {
     255                 :         45 :   return *d_fpl <= *fp.d_fpl;
     256                 :            : }
     257                 :            : 
     258                 :         42 : bool FloatingPoint::operator<(const FloatingPoint& fp) const
     259                 :            : {
     260                 :         42 :   return *d_fpl < *fp.d_fpl;
     261                 :            : }
     262                 :            : 
     263                 :         26 : BitVector FloatingPoint::getUnpackedExponent() const
     264                 :            : {
     265                 :         26 :   return d_fpl->getUnpackedExponent();
     266                 :            : }
     267                 :            : 
     268                 :         26 : BitVector FloatingPoint::getUnpackedSignificand() const
     269                 :            : {
     270                 :         26 :   return d_fpl->getUnpackedSignificand();
     271                 :            : }
     272                 :            : 
     273                 :         26 : bool FloatingPoint::getSign() const { return d_fpl->getSign(); }
     274                 :            : 
     275                 :         42 : bool FloatingPoint::isNormal(void) const { return d_fpl->isNormal(); }
     276                 :            : 
     277                 :         29 : bool FloatingPoint::isSubnormal(void) const { return d_fpl->isSubnormal(); }
     278                 :            : 
     279                 :        514 : bool FloatingPoint::isZero(void) const { return d_fpl->isZero(); }
     280                 :            : 
     281                 :        249 : bool FloatingPoint::isInfinite(void) const { return d_fpl->isInfinite(); }
     282                 :            : 
     283                 :        260 : bool FloatingPoint::isNaN(void) const { return d_fpl->isNaN(); }
     284                 :            : 
     285                 :        112 : bool FloatingPoint::isNegative(void) const { return d_fpl->isNegative(); }
     286                 :            : 
     287                 :        113 : bool FloatingPoint::isPositive(void) const { return d_fpl->isPositive(); }
     288                 :            : 
     289                 :         22 : FloatingPoint FloatingPoint::convert(const FloatingPointSize& target,
     290                 :            :                                      const RoundingMode& rm) const
     291                 :            : {
     292                 :         44 :   return FloatingPoint(d_fpl->convert(target, rm));
     293                 :            : }
     294                 :            : 
     295                 :         12 : BitVector FloatingPoint::convertToBVTotal(BitVectorSize width,
     296                 :            :                                           const RoundingMode& rm,
     297                 :            :                                           bool signedBV,
     298                 :            :                                           BitVector undefinedCase) const
     299                 :            : {
     300         [ +  + ]:         12 :   if (signedBV)
     301                 :            :   {
     302                 :          4 :     return d_fpl->convertToSBVTotal(width, rm, undefinedCase);
     303                 :            :   }
     304                 :          8 :   return d_fpl->convertToUBVTotal(width, rm, undefinedCase);
     305                 :            : }
     306                 :            : 
     307                 :         33 : Rational FloatingPoint::convertToRationalTotal(Rational undefinedCase) const
     308                 :            : {
     309                 :         33 :   PartialRational p(convertToRational());
     310                 :            : 
     311         [ +  + ]:         66 :   return p.second ? p.first : undefinedCase;
     312                 :         33 : }
     313                 :            : 
     314                 :          0 : FloatingPoint::PartialBitVector FloatingPoint::convertToBV(
     315                 :            :     BitVectorSize width, const RoundingMode& rm, bool signedBV) const
     316                 :            : {
     317                 :          0 :   BitVector tmp(convertToBVTotal(width, rm, signedBV, BitVector(width, 0U)));
     318                 :            :   BitVector confirm(
     319                 :          0 :       convertToBVTotal(width, rm, signedBV, BitVector(width, 1U)));
     320                 :            : 
     321                 :          0 :   return PartialBitVector(tmp, tmp == confirm);
     322                 :          0 : }
     323                 :            : 
     324                 :         41 : FloatingPoint::PartialRational FloatingPoint::convertToRational(void) const
     325                 :            : {
     326                 :         41 :   return d_fpl->convertToRational();
     327                 :            : }
     328                 :            : 
     329                 :      40931 : BitVector FloatingPoint::pack(void) const { return d_fpl->pack(); }
     330                 :            : 
     331                 :        570 : void FloatingPoint::getIEEEBitvectors(BitVector& sign,
     332                 :            :                                       BitVector& exp,
     333                 :            :                                       BitVector& sig) const
     334                 :            : {
     335                 :            :   // retrieve BV value
     336                 :        570 :   BitVector bv(pack());
     337                 :            :   uint32_t largestSignificandBit =
     338                 :        570 :       getSize().significandWidth() - 2;  // -1 for -inclusive, -1 for hidden
     339                 :            :   uint32_t largestExponentBit =
     340                 :        570 :       (getSize().exponentWidth() - 1) + (largestSignificandBit + 1);
     341                 :        570 :   sign = bv.extract(largestExponentBit + 1, largestExponentBit + 1);
     342                 :        570 :   exp = bv.extract(largestExponentBit, largestSignificandBit + 1);
     343                 :        570 :   sig = bv.extract(largestSignificandBit, 0);
     344                 :        570 : }
     345                 :            : 
     346                 :        551 : std::string FloatingPoint::toString(bool printAsIndexed) const
     347                 :            : {
     348                 :        551 :   std::string str;
     349                 :            :   // retrive BV value
     350         [ +  + ]:       4408 :   BitVector v[3];
     351                 :        551 :   getIEEEBitvectors(v[0], v[1], v[2]);
     352                 :        551 :   str.append("(fp ");
     353         [ +  + ]:       2204 :   for (uint32_t i = 0; i < 3; ++i)
     354                 :            :   {
     355         [ -  + ]:       1653 :     if (printAsIndexed)
     356                 :            :     {
     357                 :          0 :       str.append("(_ bv");
     358                 :          0 :       str.append(v[i].getValue().toString());
     359                 :          0 :       str.append(" ");
     360                 :          0 :       str.append(std::to_string(v[i].getSize()));
     361                 :          0 :       str.append(")");
     362                 :            :     }
     363                 :            :     else
     364                 :            :     {
     365                 :       1653 :       str.append("#b");
     366                 :       1653 :       str.append(v[i].toString());
     367                 :            :     }
     368         [ +  + ]:       1653 :     if (i < 2)
     369                 :            :     {
     370                 :       1102 :       str.append(" ");
     371                 :            :     }
     372                 :            :   }
     373                 :        551 :   str.append(")");
     374                 :       1102 :   return str;
     375 [ +  + ][ -  - ]:       2204 : }
     376                 :            : 
     377                 :          0 : std::ostream& operator<<(std::ostream& os, const FloatingPoint& fp)
     378                 :            : {
     379                 :            :   // print in binary notation
     380                 :          0 :   return os << fp.toString();
     381                 :            : }
     382                 :            : 
     383                 :          0 : std::ostream& operator<<(std::ostream& os, const FloatingPointSize& fps)
     384                 :            : {
     385                 :          0 :   return os << "(_ FloatingPoint " << fps.exponentWidth() << " "
     386                 :          0 :             << fps.significandWidth() << ")";
     387                 :            : }
     388                 :            : 
     389                 :          0 : std::ostream& operator<<(std::ostream& os, const FloatingPointConvertSort& fpcs)
     390                 :            : {
     391                 :          0 :   return os << "(_ to_fp " << fpcs.getSize().exponentWidth() << " "
     392                 :          0 :             << fpcs.getSize().significandWidth() << ")";
     393                 :            : }
     394                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14