LCOV - code coverage report
Current view: top level - buildbot/coverage/build/test/unit/util - floatingpoint_black.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 405 535 75.7 %
Date: 2026-09-28 09:33:01 Functions: 158 175 90.3 %
Branches: 384 846 45.4 %

           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                 :            :  * Black box testing of cvc5::FloatingPoint.
      11                 :            :  *
      12                 :            :  * Cross-checks the MPFR and SymFPU floating-point literal backends.
      13                 :            :  * Ported from Bitwuzla's FP unit tests, see
      14                 :            :  * https://github.com/bitwuzla/bitwuzla/tree/main/test/unit/fp
      15                 :            :  * (Copyright (C) 2022 by the Bitwuzla authors, MIT license).
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "base/check.h"
      19                 :            : #include "test.h"
      20                 :            : #include "util/floatingpoint.h"
      21                 :            : #ifdef CVC5_USE_MPFR
      22                 :            : #include "util/floatingpoint_literal_mpfr.h"
      23                 :            : #endif
      24                 :            : #include "util/floatingpoint_literal_symfpu.h"
      25                 :            : #include "util/random.h"
      26                 :            : 
      27                 :            : namespace cvc5::internal {
      28                 :            : namespace test {
      29                 :            : 
      30                 :            : /* -------------------------------------------------------------------------- */
      31                 :            : 
      32                 :            : class TestUtilBlackFloatingPoint : public TestInternal
      33                 :            : {
      34                 :            :  protected:
      35                 :            :   // With CVC5_SLOW_TESTS, these complement the exhaustive Float16 testing
      36                 :            :   // below and we can afford a large number of them. Without it, they run on
      37                 :            :   // every CI and nightly build, where the cross-checks are otherwise by far
      38                 :            :   // the slowest unit test, so we use lower counts.
      39                 :            : #ifdef CVC5_SLOW_TESTS
      40                 :            :   /** Default number of random tests when not exhaustively testing. */
      41                 :            :   static constexpr uint32_t N_TESTS = 1000;
      42                 :            :   /** Number of tests fp.rem (significantly slower than other operators). */
      43                 :            :   static constexpr uint32_t N_TESTS_REM = 500;
      44                 :            : #else
      45                 :            :   /** Default number of random tests when not exhaustively testing. */
      46                 :            :   static constexpr uint32_t N_TESTS = 100;
      47                 :            :   /** Number of tests fp.rem (significantly slower than other operators). */
      48                 :            :   static constexpr uint32_t N_TESTS_REM = 50;
      49                 :            : #endif
      50                 :            :   /** Min/max bit-vector width used in convertToBV cross-checks. */
      51                 :            :   static constexpr uint32_t MIN_SIZE_TO_BV = 4;
      52                 :            :   static constexpr uint32_t MAX_SIZE_TO_BV = 64;
      53                 :            : 
      54                 :         32 :   TestUtilBlackFloatingPoint()
      55                 :         96 :       : d_rng(Random::getRandom()),
      56                 :         32 :         d_fp16(5, 11),
      57                 :         32 :         d_fp32(8, 24),
      58                 :         32 :         d_fp64(11, 53),
      59                 :         32 :         d_fp128(15, 113),
      60                 :         32 :         d_all_formats({d_fp16, d_fp32, d_fp64, d_fp128}),
      61                 :         32 :         d_formats_32_128({d_fp32, d_fp64, d_fp128}),
      62                 :            :   // If slow tests are enabled (CVC5_SLOW_TESTS), we exhaustively test
      63                 :            :   // for Float16, and randomly for other formats. Else, we test randomly
      64                 :            :   // for all formats, for N_TESTS each.
      65                 :            : #ifdef CVC5_SLOW_TESTS
      66                 :            :         d_test_formats(d_formats_32_128)
      67                 :            : #else
      68                 :         64 :         d_test_formats(d_all_formats)
      69                 :            : #endif
      70                 :            :   {
      71                 :         32 :   }
      72                 :            : 
      73                 :         32 :   void SetUp() override
      74                 :            :   {
      75                 :         32 :     TestInternal::SetUp();
      76                 :         64 :     d_all_rms = {RoundingMode::ROUND_NEAREST_TIES_TO_EVEN,
      77                 :            :                  RoundingMode::ROUND_NEAREST_TIES_TO_AWAY,
      78                 :            :                  RoundingMode::ROUND_TOWARD_POSITIVE,
      79                 :            :                  RoundingMode::ROUND_TOWARD_NEGATIVE,
      80                 :         32 :                  RoundingMode::ROUND_TOWARD_ZERO};
      81                 :         32 :   }
      82                 :            : 
      83                 :            :   /** @return A random boolean. */
      84                 :          0 :   bool pickBool() { return d_rng.pick<uint32_t>(0, 1) != 0; }
      85                 :            : 
      86                 :            :   /** @return A random rounding mode. */
      87                 :       2400 :   RoundingMode pickRm()
      88                 :            :   {
      89                 :       2400 :     return d_all_rms[d_rng.pick<size_t>() % d_all_rms.size()];
      90                 :            :   }
      91                 :            : 
      92                 :            :   /** @return A random floating-point format. */
      93                 :        300 :   FloatingPointSize pickFormat()
      94                 :            :   {
      95                 :        300 :     return d_all_formats[d_rng.pick<size_t>() % d_all_formats.size()];
      96                 :            :   }
      97                 :            : 
      98                 :            :   /**
      99                 :            :    * Test `fun` exhaustively for all Float16 values.
     100                 :            :    * Does nothing unless compiled with CVC5_SLOW_TESTS.
     101                 :            :    */
     102                 :         16 :   void testForFloat16(
     103                 :            :       [[maybe_unused]] std::function<void(const BitVector&, const BitVector&)>
     104                 :            :           fun)
     105                 :            :   {
     106                 :            : #ifdef CVC5_SLOW_TESTS
     107                 :            :     uint32_t expSize = 5;
     108                 :            :     uint32_t sigBits = 10;  // significand width minus hidden bit
     109                 :            :     for (uint32_t i = 0; i < (1u << expSize); ++i)
     110                 :            :     {
     111                 :            :       BitVector bvexp(expSize, i);
     112                 :            :       for (uint32_t j = 0; j < (1u << sigBits); ++j)
     113                 :            :       {
     114                 :            :         BitVector bvsig(sigBits, j);
     115                 :            :         fun(bvexp, bvsig);
     116                 :            :       }
     117                 :            :     }
     118                 :            : #endif
     119                 :         16 :   }
     120                 :            : 
     121                 :            :   /** Test `fun` for given formats. */
     122                 :         21 :   void testForFormats(
     123                 :            :       const std::vector<FloatingPointSize>& formats,
     124                 :            :       uint32_t nTests,
     125                 :            :       std::function<void(const FloatingPointSize&, const BitVector&)> fun)
     126                 :            :   {
     127         [ +  + ]:        105 :     for (const auto& f : formats)
     128                 :            :     {
     129                 :         84 :       uint32_t bvSize = f.exponentWidth() + f.significandWidth();
     130         [ +  + ]:       8084 :       for (uint32_t i = 0; i < nTests; ++i)
     131                 :            :       {
     132                 :       8000 :         BitVector bv = BitVector::mkRandom(bvSize);
     133                 :       8000 :         fun(f, bv);
     134                 :       8000 :       }
     135                 :            :     }
     136                 :         21 :   }
     137                 :            : 
     138                 :            :   /**
     139                 :            :    * Check the nextUp/nextDown round trips for the value with packed
     140                 :            :    * representation bv: nextDown(nextUp(fp)) and nextUp(nextDown(fp)) are fp
     141                 :            :    * again (up to the sign of zero, since the two zeros compare equal),
     142                 :            :    * unless the first step reaches an infinity. Does nothing for NaN and the
     143                 :            :    * infinities.
     144                 :            :    */
     145                 :        400 :   void checkNextUpDownRoundTrip(const FloatingPointSize& fmt,
     146                 :            :                                 const BitVector& bv)
     147                 :            :   {
     148                 :        400 :     FloatingPoint fp(fmt, bv);
     149 [ +  + ][ -  + ]:        400 :     if (fp.isNaN() || fp.isInfinite())
                 [ +  + ]
     150                 :            :     {
     151                 :          6 :       return;
     152                 :            :     }
     153                 :            : 
     154                 :        394 :     FloatingPoint up = FloatingPoint::nextUp(fp);
     155 [ -  + ][ +  - ]:        394 :     ASSERT_FALSE(up.isNaN());
     156         [ -  + ]:        394 :     if (up.isInfinite())
     157                 :            :     {
     158                 :          0 :       ASSERT_TRUE(up.isPositive());
     159                 :            :     }
     160                 :            :     else
     161                 :            :     {
     162                 :        394 :       FloatingPoint back = FloatingPoint::nextDown(up);
     163         [ -  + ]:        394 :       if (fp.isZero())
     164                 :            :       {
     165                 :          0 :         ASSERT_TRUE(back.isZero());
     166                 :            :       }
     167                 :            :       else
     168                 :            :       {
     169 [ -  + ][ +  - ]:        788 :         ASSERT_EQ(back.pack(), bv);
     170                 :            :       }
     171         [ +  - ]:        394 :     }
     172                 :            : 
     173                 :        394 :     FloatingPoint down = FloatingPoint::nextDown(fp);
     174 [ -  + ][ +  - ]:        394 :     ASSERT_FALSE(down.isNaN());
     175         [ -  + ]:        394 :     if (down.isInfinite())
     176                 :            :     {
     177                 :          0 :       ASSERT_TRUE(down.isNegative());
     178                 :            :     }
     179                 :            :     else
     180                 :            :     {
     181                 :        394 :       FloatingPoint back = FloatingPoint::nextUp(down);
     182         [ -  + ]:        394 :       if (fp.isZero())
     183                 :            :       {
     184                 :          0 :         ASSERT_TRUE(back.isZero());
     185                 :            :       }
     186                 :            :       else
     187                 :            :       {
     188 [ -  + ][ +  - ]:        788 :         ASSERT_EQ(back.pack(), bv);
     189                 :            :       }
     190         [ +  - ]:        394 :     }
     191 [ +  - ][ +  + ]:        400 :   }
     192                 :            : 
     193                 :            :   Random& d_rng;
     194                 :            : 
     195                 :            :   FloatingPointSize d_fp16;
     196                 :            :   FloatingPointSize d_fp32;
     197                 :            :   FloatingPointSize d_fp64;
     198                 :            :   FloatingPointSize d_fp128;
     199                 :            : 
     200                 :            :   std::vector<FloatingPointSize> d_all_formats;
     201                 :            :   std::vector<FloatingPointSize> d_formats_32_128;
     202                 :            :   std::vector<RoundingMode> d_all_rms;
     203                 :            :   const std::vector<FloatingPointSize>& d_test_formats;
     204                 :            : };
     205                 :            : 
     206                 :            : /* -------------------------------------------------------------------------- */
     207                 :            : 
     208                 :          4 : TEST_F(TestUtilBlackFloatingPoint, move)
     209                 :            : {
     210                 :          1 :   BitVector bv1 = BitVector::mkRandom(d_fp16.packedWidth());
     211                 :          1 :   BitVector bv2 = BitVector::mkRandom(d_fp128.packedWidth());
     212                 :          1 :   FloatingPoint fp1(d_fp16, bv1);
     213                 :          1 :   FloatingPoint fp2(d_fp128, bv2);
     214                 :            : 
     215                 :          1 :   fp1 = std::move(fp2);
     216 [ -  + ][ +  - ]:          2 :   ASSERT_EQ(fp1.pack(), bv2);
     217 [ -  + ][ +  - ]:          1 :   ASSERT_EQ(fp1.getSize(), d_fp128);
     218                 :            : 
     219                 :          1 :   auto fp3 = std::move(fp1);
     220 [ -  + ][ +  - ]:          2 :   ASSERT_EQ(fp3.pack(), bv2);
     221 [ -  + ][ +  - ]:          1 :   ASSERT_EQ(fp3.getSize(), d_fp128);
     222                 :            : 
     223                 :          1 :   FloatingPoint fp4(std::move(fp3));
     224 [ -  + ][ +  - ]:          2 :   ASSERT_EQ(fp4.pack(), bv2);
     225 [ -  + ][ +  - ]:          1 :   ASSERT_EQ(fp4.getSize(), d_fp128);
     226 [ +  - ][ +  - ]:          1 : }
         [ +  - ][ +  - ]
                 [ +  - ]
     227                 :            : 
     228                 :          4 : TEST_F(TestUtilBlackFloatingPoint, makeMinSubnormal)
     229                 :            : {
     230         [ +  + ]:          5 :   for (const auto& size : d_all_formats)
     231                 :            :   {
     232                 :          4 :     FloatingPoint fp = FloatingPoint::makeMinSubnormal(size, true);
     233 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(fp.isSubnormal());
     234                 :          4 :     FloatingPoint mfp = FloatingPoint::makeMinSubnormal(size, false);
     235 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(mfp.isSubnormal());
     236         [ +  - ]:          4 :   }
     237                 :            : }
     238                 :            : 
     239                 :          4 : TEST_F(TestUtilBlackFloatingPoint, makeMaxSubnormal)
     240                 :            : {
     241         [ +  + ]:          5 :   for (const auto& size : d_all_formats)
     242                 :            :   {
     243                 :          4 :     FloatingPoint fp = FloatingPoint::makeMaxSubnormal(size, true);
     244 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(fp.isSubnormal());
     245                 :          4 :     FloatingPoint mfp = FloatingPoint::makeMaxSubnormal(size, false);
     246 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(mfp.isSubnormal());
     247         [ +  - ]:          4 :   }
     248                 :            : }
     249                 :            : 
     250                 :          4 : TEST_F(TestUtilBlackFloatingPoint, makeMinNormal)
     251                 :            : {
     252         [ +  + ]:          5 :   for (const auto& size : d_all_formats)
     253                 :            :   {
     254                 :          4 :     FloatingPoint fp = FloatingPoint::makeMinNormal(size, true);
     255 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(fp.isNormal());
     256                 :          4 :     FloatingPoint mfp = FloatingPoint::makeMinNormal(size, false);
     257 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(mfp.isNormal());
     258         [ +  - ]:          4 :   }
     259                 :            : }
     260                 :            : 
     261                 :          4 : TEST_F(TestUtilBlackFloatingPoint, makeMaxNormal)
     262                 :            : {
     263         [ +  + ]:          5 :   for (const auto& size : d_all_formats)
     264                 :            :   {
     265                 :          4 :     FloatingPoint fp = FloatingPoint::makeMaxNormal(size, true);
     266 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(fp.isNormal());
     267                 :          4 :     FloatingPoint mfp = FloatingPoint::makeMaxNormal(size, false);
     268 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(mfp.isNormal());
     269         [ +  - ]:          4 :   }
     270                 :            : }
     271                 :            : 
     272                 :          4 : TEST_F(TestUtilBlackFloatingPoint, fromSbv1)
     273                 :            : {
     274                 :          1 :   BitVector bv0(1, 0u);
     275                 :          1 :   BitVector bv1(1, 1u);
     276         [ +  + ]:          5 :   for (const auto& bv : {bv0, bv1})
     277                 :            :   {
     278         [ +  + ]:          6 :     for (bool sign : {true, false})
     279                 :            :     {
     280                 :          0 :       FloatingPoint fp(FloatingPointSize(5, 11),
     281                 :          0 :                        RoundingMode::ROUND_NEAREST_TIES_TO_AWAY,
     282                 :            :                        bv,
     283                 :          4 :                        sign);
     284                 :          4 :     }
     285 [ +  + ][ -  - ]:          3 :   }
     286                 :          1 : }
     287                 :            : 
     288                 :          4 : TEST_F(TestUtilBlackFloatingPoint, nextUpNextDownSpecial)
     289                 :            : {
     290         [ +  + ]:          5 :   for (const auto& size : d_all_formats)
     291                 :            :   {
     292                 :          4 :     FloatingPoint nan = FloatingPoint::makeNaN(size);
     293                 :          4 :     FloatingPoint pinf = FloatingPoint::makeInf(size, false);
     294                 :          4 :     FloatingPoint ninf = FloatingPoint::makeInf(size, true);
     295                 :          4 :     FloatingPoint pzero = FloatingPoint::makeZero(size, false);
     296                 :          4 :     FloatingPoint nzero = FloatingPoint::makeZero(size, true);
     297                 :          4 :     FloatingPoint minSub = FloatingPoint::makeMinSubnormal(size, false);
     298                 :          4 :     FloatingPoint nminSub = FloatingPoint::makeMinSubnormal(size, true);
     299                 :          4 :     FloatingPoint maxSub = FloatingPoint::makeMaxSubnormal(size, false);
     300                 :          4 :     FloatingPoint nmaxSub = FloatingPoint::makeMaxSubnormal(size, true);
     301                 :          4 :     FloatingPoint minNorm = FloatingPoint::makeMinNormal(size, false);
     302                 :          4 :     FloatingPoint nminNorm = FloatingPoint::makeMinNormal(size, true);
     303                 :          4 :     FloatingPoint maxNorm = FloatingPoint::makeMaxNormal(size, false);
     304                 :          4 :     FloatingPoint nmaxNorm = FloatingPoint::makeMaxNormal(size, true);
     305                 :            : 
     306                 :            :     // nextUp(NaN) and nextDown(NaN) are NaN
     307 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(FloatingPoint::nextUp(nan).isNaN());
     308 [ -  + ][ +  - ]:          4 :     ASSERT_TRUE(FloatingPoint::nextDown(nan).isNaN());
     309                 :            :     // the infinities are the extremes of the order, stepping away from them
     310                 :            :     // reaches the largest finite value of the respective sign
     311 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(pinf).pack(), pinf.pack());
     312 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(ninf).pack(), nmaxNorm.pack());
     313 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(ninf).pack(), ninf.pack());
     314 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(pinf).pack(), maxNorm.pack());
     315                 :            :     // nextUp of the zero class is the smallest positive subnormal, its
     316                 :            :     // nextDown the negative subnormal of smallest magnitude
     317 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(pzero).pack(), minSub.pack());
     318 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(nzero).pack(), minSub.pack());
     319 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(pzero).pack(), nminSub.pack());
     320 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(nzero).pack(), nminSub.pack());
     321                 :            :     // when the result is the zero class, its sign is the sign of the argument
     322 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(nminSub).pack(), nzero.pack());
     323 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(minSub).pack(), pzero.pack());
     324                 :            :     // crossing the subnormal/normal boundary
     325 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(maxSub).pack(), minNorm.pack());
     326 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(minNorm).pack(), maxSub.pack());
     327 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(nminNorm).pack(), nmaxSub.pack());
     328 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(nmaxSub).pack(), nminNorm.pack());
     329                 :            :     // stepping beyond the largest normals reaches the infinities
     330 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextUp(maxNorm).pack(), pinf.pack());
     331 [ -  + ][ +  - ]:          8 :     ASSERT_EQ(FloatingPoint::nextDown(nmaxNorm).pack(), ninf.pack());
     332 [ +  - ][ +  - ]:          4 :   }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     333                 :            : }
     334                 :            : 
     335                 :          4 : TEST_F(TestUtilBlackFloatingPoint, nextUpNextDownRoundTrip)
     336                 :            : {
     337                 :            :   // Round trips through nextUp/nextDown. Exhaustive for Float16 if
     338                 :            :   // CVC5_SLOW_TESTS is enabled, else only a random subset is tested for
     339                 :            :   // Float16 (as with the other formats). The exhaustive run additionally
     340                 :            :   // establishes adjacency in the value order: if nextUp skipped over a
     341                 :            :   // value b, the round trip starting at b would not return to b.
     342                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     343         [ -  - ]:          0 :     for (bool sign : {false, true})
     344                 :            :     {
     345         [ -  - ]:          0 :       BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     346                 :          0 :       checkNextUpDownRoundTrip(d_fp16, bvsign.concat(bvexp).concat(bvsig));
     347                 :          0 :     }
     348                 :          1 :   };
     349                 :          1 :   testForFloat16(fun16);
     350                 :          1 :   testForFormats(d_test_formats,
     351                 :            :                  N_TESTS,
     352                 :        400 :                  [this](const FloatingPointSize& fmt, const BitVector& bv) {
     353                 :        400 :                    checkNextUpDownRoundTrip(fmt, bv);
     354                 :        400 :                  });
     355                 :          1 : }
     356                 :            : 
     357                 :          4 : TEST_F(TestUtilBlackFloatingPoint, nextUpNextDownOrder)
     358                 :            : {
     359                 :            :   // nextUp and nextDown are strictly above resp. below in the value order
     360                 :            :   // (checked on the exact rationals the values denote), for random values of
     361                 :            :   // all formats.
     362                 :          1 :   Rational zero(0);
     363                 :          1 :   testForFormats(d_all_formats,
     364                 :            :                  N_TESTS,
     365                 :        400 :                  [&](const FloatingPointSize& fmt, const BitVector& bv) {
     366                 :        400 :                    FloatingPoint fp(fmt, bv);
     367 [ +  + ][ -  + ]:        400 :                    if (fp.isNaN() || fp.isInfinite())
                 [ +  + ]
     368                 :            :                    {
     369                 :          2 :                      return;
     370                 :            :                    }
     371                 :        398 :                    Rational rfp = fp.convertToRationalTotal(zero);
     372                 :        398 :                    FloatingPoint up = FloatingPoint::nextUp(fp);
     373         [ +  - ]:        398 :                    if (!up.isInfinite())
     374                 :            :                    {
     375 [ -  + ][ +  - ]:        398 :                      ASSERT_TRUE(rfp < up.convertToRationalTotal(zero));
     376                 :            :                    }
     377                 :        398 :                    FloatingPoint down = FloatingPoint::nextDown(fp);
     378         [ +  - ]:        398 :                    if (!down.isInfinite())
     379                 :            :                    {
     380 [ -  + ][ +  - ]:        398 :                      ASSERT_TRUE(down.convertToRationalTotal(zero) < rfp);
     381                 :            :                    }
     382 [ +  - ][ +  - ]:        400 :                  });
                 [ +  + ]
     383                 :          1 : }
     384                 :            : 
     385                 :            : /* -------------------------------------------------------------------------- */
     386                 :            : /* Crosscheck MPFR and SymFPU back ends.                                      */
     387                 :            : /* -------------------------------------------------------------------------- */
     388                 :            : 
     389                 :            : #ifdef CVC5_USE_MPFR
     390                 :            : namespace {
     391                 :            : /** @return An FP literal with MPFR as the back end. */
     392                 :      12800 : FloatingPointLiteralMPFR fpMPFR(const FloatingPointSize& fmt,
     393                 :            :                                 const BitVector& bv)
     394                 :            : {
     395                 :      12800 :   return FloatingPointLiteralMPFR(fmt, bv);
     396                 :            : }
     397                 :            : 
     398                 :            : /** @return An FP literal with SymFPU as the back end. */
     399                 :      12800 : FloatingPointLiteralSymFPU fpSymFPU(const FloatingPointSize& fmt,
     400                 :            :                                     const BitVector& bv)
     401                 :            : {
     402                 :      12800 :   return FloatingPointLiteralSymFPU(fmt, bv);
     403                 :            : }
     404                 :            : }  // namespace
     405                 :            : 
     406                 :          4 : TEST_F(TestUtilBlackFloatingPoint, pack)
     407                 :            : {
     408                 :            :   // Exhaustive for Float16 if CVC5_SLOW_TESTS is enabled, else only a random
     409                 :            :   // subset is tested for Float16 (as with the other formats).
     410                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     411         [ -  - ]:          0 :     for (bool sign : {false, true})
     412                 :            :     {
     413         [ -  - ]:          0 :       BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     414                 :          0 :       BitVector bv = bvsign.concat(bvexp).concat(bvsig);
     415                 :            : 
     416                 :          0 :       auto mpfr = fpMPFR(d_fp16, bv);
     417                 :          0 :       auto sym = fpSymFPU(d_fp16, bv);
     418                 :            : 
     419                 :          0 :       BitVector packedMpfr = mpfr.pack();
     420                 :          0 :       BitVector packedSym = sym.pack();
     421                 :            : 
     422                 :            :       // Both backends must produce the same packed representation.
     423         [ -  - ]:          0 :       ASSERT_EQ(packedMpfr, packedSym)
     424         [ -  - ]:          0 :           << "pack mismatch for bv=" << bv.toString();
     425 [ -  - ][ -  - ]:          0 :     }
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     426                 :          1 :   };
     427                 :          1 :   testForFloat16(fun16);
     428                 :          1 :   testForFormats(d_test_formats,
     429                 :            :                  N_TESTS,
     430                 :        400 :                  [](const FloatingPointSize& fmt, const BitVector& bv) {
     431                 :        400 :                    auto mpfr = fpMPFR(fmt, bv);
     432                 :        400 :                    auto sym = fpSymFPU(fmt, bv);
     433 [ -  + ][ +  - ]:        800 :                    ASSERT_EQ(mpfr.pack(), sym.pack());
     434 [ +  - ][ +  - ]:        400 :                  });
     435                 :          1 : }
     436                 :            : 
     437                 :          4 : TEST_F(TestUtilBlackFloatingPoint, classification)
     438                 :            : {
     439                 :          1 :   BitVector ezero = BitVector::mkZero(5);
     440                 :          1 :   BitVector eones = BitVector::mkOnes(5);
     441                 :          1 :   BitVector szero = BitVector::mkZero(10);
     442                 :          0 :   auto fun16 = [&, this](const BitVector& bvexp, const BitVector& bvsig) {
     443         [ -  - ]:          0 :     for (bool sign : {false, true})
     444                 :            :     {
     445         [ -  - ]:          0 :       BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     446                 :          0 :       BitVector bv = bvsign.concat(bvexp).concat(bvsig);
     447                 :            : 
     448                 :          0 :       auto mpfr = fpMPFR(d_fp16, bv);
     449                 :          0 :       auto sym = fpSymFPU(d_fp16, bv);
     450                 :            : 
     451                 :          0 :       ASSERT_EQ(mpfr.isNormal(), sym.isNormal());
     452                 :          0 :       ASSERT_EQ(mpfr.isSubnormal(), sym.isSubnormal());
     453                 :          0 :       ASSERT_EQ(mpfr.isZero(), sym.isZero());
     454                 :          0 :       ASSERT_EQ(mpfr.isInfinite(), sym.isInfinite());
     455                 :          0 :       ASSERT_EQ(mpfr.isNaN(), sym.isNaN());
     456                 :          0 :       ASSERT_EQ(mpfr.isNegative(), sym.isNegative());
     457                 :          0 :       ASSERT_EQ(mpfr.isPositive(), sym.isPositive());
     458                 :          0 :       ASSERT_EQ(mpfr.getSign(), sym.getSign());
     459                 :            : 
     460         [ -  - ]:          0 :       if (bvexp != ezero)
     461                 :            :       {
     462         [ -  - ]:          0 :         if (bvexp != eones)
     463                 :            :         {
     464                 :          0 :           ASSERT_TRUE(mpfr.isNormal());
     465                 :          0 :           ASSERT_FALSE(mpfr.isSubnormal());
     466                 :          0 :           ASSERT_FALSE(mpfr.isInfinite());
     467                 :          0 :           ASSERT_FALSE(mpfr.isNaN());
     468                 :          0 :           ASSERT_FALSE(mpfr.isZero());
     469                 :            :         }
     470                 :            :         else
     471                 :            :         {
     472         [ -  - ]:          0 :           if (bvsig == szero)
     473                 :            :           {
     474                 :          0 :             ASSERT_TRUE(mpfr.isInfinite());
     475                 :          0 :             ASSERT_FALSE(mpfr.isNormal());
     476                 :          0 :             ASSERT_FALSE(mpfr.isSubnormal());
     477                 :          0 :             ASSERT_FALSE(mpfr.isNaN());
     478                 :          0 :             ASSERT_FALSE(mpfr.isZero());
     479                 :            :           }
     480                 :            :           else
     481                 :            :           {
     482                 :          0 :             ASSERT_TRUE(mpfr.isNaN());
     483                 :          0 :             ASSERT_FALSE(mpfr.isNormal());
     484                 :          0 :             ASSERT_FALSE(mpfr.isSubnormal());
     485                 :          0 :             ASSERT_FALSE(mpfr.isInfinite());
     486                 :          0 :             ASSERT_FALSE(mpfr.isZero());
     487                 :            :           }
     488                 :            :         }
     489                 :            :       }
     490                 :            :       else
     491                 :            :       {
     492         [ -  - ]:          0 :         if (bvsig == szero)
     493                 :            :         {
     494                 :          0 :           ASSERT_TRUE(mpfr.isZero());
     495                 :          0 :           ASSERT_FALSE(mpfr.isNormal());
     496                 :          0 :           ASSERT_FALSE(mpfr.isSubnormal());
     497                 :          0 :           ASSERT_FALSE(mpfr.isInfinite());
     498                 :          0 :           ASSERT_FALSE(mpfr.isNaN());
     499                 :            :         }
     500                 :            :         else
     501                 :            :         {
     502                 :          0 :           ASSERT_TRUE(mpfr.isSubnormal());
     503                 :          0 :           ASSERT_FALSE(mpfr.isNormal());
     504                 :          0 :           ASSERT_FALSE(mpfr.isInfinite());
     505                 :          0 :           ASSERT_FALSE(mpfr.isNaN());
     506                 :          0 :           ASSERT_FALSE(mpfr.isZero());
     507                 :            :         }
     508                 :            :       }
     509 [ -  - ][ -  - ]:          0 :     }
         [ -  - ][ -  - ]
     510                 :          1 :   };
     511                 :          1 :   testForFloat16(fun16);
     512                 :          1 :   testForFormats(d_test_formats,
     513                 :            :                  N_TESTS,
     514                 :        400 :                  [](const FloatingPointSize& fmt, const BitVector& bv1) {
     515                 :        400 :                    auto mpfr = fpMPFR(fmt, bv1);
     516                 :        400 :                    auto sym = fpSymFPU(fmt, bv1);
     517 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr.isNormal(), sym.isNormal());
     518 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr.isSubnormal(), sym.isSubnormal());
     519 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr.isZero(), sym.isZero());
     520 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr.isNaN(), sym.isNaN());
     521 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr.isInfinite(), sym.isInfinite());
     522 [ +  - ][ +  - ]:        400 :                  });
     523                 :          1 : }
     524                 :            : 
     525                 :          4 : TEST_F(TestUtilBlackFloatingPoint, components)
     526                 :            : {
     527                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     528         [ -  - ]:          0 :     for (bool sign : {false, true})
     529                 :            :     {
     530         [ -  - ]:          0 :       BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     531                 :          0 :       BitVector bv = bvsign.concat(bvexp).concat(bvsig);
     532                 :            : 
     533                 :          0 :       auto mpfr = fpMPFR(d_fp16, bv);
     534                 :          0 :       auto sym = fpSymFPU(d_fp16, bv);
     535                 :            : 
     536                 :          0 :       ASSERT_EQ(mpfr.getUnpackedExponent(), sym.getUnpackedExponent());
     537                 :          0 :       ASSERT_EQ(mpfr.getUnpackedSignificand(), sym.getUnpackedSignificand());
     538 [ -  - ][ -  - ]:          0 :     }
         [ -  - ][ -  - ]
     539                 :          1 :   };
     540                 :          1 :   testForFloat16(fun16);
     541                 :          1 :   testForFormats(
     542                 :            :       d_test_formats,
     543                 :            :       N_TESTS,
     544                 :        400 :       [](const FloatingPointSize& fmt, const BitVector& bv) {
     545                 :        400 :         auto mpfr = fpMPFR(fmt, bv);
     546                 :        400 :         auto sym = fpSymFPU(fmt, bv);
     547 [ -  + ][ +  - ]:        800 :         ASSERT_EQ(mpfr.getUnpackedExponent(), sym.getUnpackedExponent());
     548 [ -  + ][ +  - ]:        800 :         ASSERT_EQ(mpfr.getUnpackedSignificand(), sym.getUnpackedSignificand());
     549 [ +  - ][ +  - ]:        400 :       });
     550                 :          1 : }
     551                 :            : 
     552                 :          4 : TEST_F(TestUtilBlackFloatingPoint, specialConstants)
     553                 :            : {
     554         [ +  + ]:          5 :   for (const auto& size : d_all_formats)
     555                 :            :   {
     556                 :            :     using SCKind = FloatingPointLiteral::SpecialConstKind;
     557                 :            :     // NaN
     558                 :            :     {
     559                 :          4 :       auto mpfr = FloatingPointLiteralMPFR(size, SCKind::FPNAN);
     560                 :          4 :       auto sym = FloatingPointLiteralSymFPU(size, SCKind::FPNAN);
     561 [ -  + ][ +  - ]:          8 :       ASSERT_EQ(mpfr.pack(), sym.pack());
     562 [ -  + ][ +  - ]:          4 :       ASSERT_TRUE(mpfr.isNaN());
     563 [ -  + ][ +  - ]:          4 :       ASSERT_FALSE(mpfr.isInfinite());
     564 [ -  + ][ +  - ]:          4 :       ASSERT_FALSE(mpfr.isNormal());
     565 [ -  + ][ +  - ]:          4 :       ASSERT_FALSE(mpfr.isSubnormal());
     566 [ -  + ][ +  - ]:          4 :       ASSERT_FALSE(mpfr.isZero());
     567 [ +  - ][ +  - ]:          4 :     }
     568         [ +  + ]:         12 :     for (bool sign : {false, true})
     569                 :            :     {
     570                 :            :       // +inf, -inf
     571                 :            :       {
     572                 :          8 :         auto mpfr = FloatingPointLiteralMPFR(size, SCKind::FPINF, sign);
     573                 :          8 :         auto sym = FloatingPointLiteralSymFPU(size, SCKind::FPINF, sign);
     574 [ -  + ][ +  - ]:         16 :         ASSERT_EQ(mpfr.pack(), sym.pack());
     575 [ -  + ][ +  - ]:          8 :         ASSERT_TRUE(mpfr.isInfinite());
     576 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isNaN());
     577 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isNormal());
     578 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isSubnormal());
     579 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isZero());
     580 [ +  - ][ +  - ]:          8 :       }
     581                 :            :       // +zero, -zero
     582                 :            :       {
     583                 :          8 :         auto mpfr = FloatingPointLiteralMPFR(size, SCKind::FPZERO, sign);
     584                 :          8 :         auto sym = FloatingPointLiteralSymFPU(size, SCKind::FPZERO, sign);
     585 [ -  + ][ +  - ]:         16 :         ASSERT_EQ(mpfr.pack(), sym.pack());
     586 [ -  + ][ +  - ]:          8 :         ASSERT_TRUE(mpfr.isZero());
     587 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isInfinite());
     588 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isNaN());
     589 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isNormal());
     590 [ -  + ][ +  - ]:          8 :         ASSERT_FALSE(mpfr.isSubnormal());
     591 [ +  - ][ +  - ]:          8 :       }
     592                 :            :     }
     593                 :            :   }
     594                 :            : }
     595                 :            : 
     596                 :          4 : TEST_F(TestUtilBlackFloatingPoint, fromUbvSbv)
     597                 :            : {
     598                 :            : #ifdef CVC5_SLOW_TESTS
     599                 :            :   // Test exhaustively for Float16.
     600                 :            :   for (uint64_t bw = 2; bw <= 16; ++bw)
     601                 :            :   {
     602                 :            :     for (uint64_t i = 0; i < (1ul << bw); ++i)
     603                 :            :     {
     604                 :            :       BitVector bv = BitVector(bw, i);
     605                 :            :       for (RoundingMode rm : d_all_rms)
     606                 :            :       {
     607                 :            :         for (bool sign : {false, true})
     608                 :            :         {
     609                 :            :           FloatingPointLiteralMPFR mpfr(d_fp16, rm, bv, sign);
     610                 :            :           FloatingPointLiteralSymFPU symfpu(d_fp16, rm, bv, sign);
     611                 :            :           ASSERT_EQ(mpfr.pack(), symfpu.pack());
     612                 :            :         }
     613                 :            :       }
     614                 :            :     }
     615                 :            :   }
     616                 :            : #endif
     617                 :            :   // Test randomly for all formats if CVC5_SLOW_TESTS is not defined, else
     618                 :            :   // only for larger formats since we already tested Float16 exhaustively.
     619         [ +  + ]:          5 :   for (const auto& f : d_test_formats)
     620                 :            :   {
     621         [ +  + ]:         68 :     for (uint64_t bw = 1; bw <= 16; ++bw)
     622                 :            :     {
     623         [ +  + ]:        704 :       for (uint64_t i = 0; i < 10; ++i)
     624                 :            :       {
     625                 :        640 :         auto bv = BitVector::mkRandom(bw);
     626         [ +  + ]:       3840 :         for (RoundingMode rm : d_all_rms)
     627                 :            :         {
     628         [ +  + ]:       9600 :           for (auto sign : {false, true})
     629                 :            :           {
     630                 :       6400 :             FloatingPointLiteralMPFR mpfr(f, rm, bv, sign);
     631                 :       6400 :             FloatingPointLiteralSymFPU symfpu(f, rm, bv, sign);
     632 [ -  + ][ +  - ]:      12800 :             ASSERT_EQ(mpfr.pack(), symfpu.pack());
     633 [ +  - ][ +  - ]:       6400 :           }
     634                 :            :         }
     635         [ +  - ]:        640 :       }
     636                 :            :     }
     637                 :            :   }
     638                 :            : }
     639                 :            : 
     640                 :            : /* -------------------------------------------------------------------------- */
     641                 :            : /* Unary operators without FM: fp.abs, fp.neg */
     642                 :            : /* -------------------------------------------------------------------------- */
     643                 :            : 
     644                 :            : #define TEST_UNARY_OP(NAME, METHOD)                                           \
     645                 :            :   TEST_F(TestUtilBlackFloatingPoint, NAME)                                    \
     646                 :            :   {                                                                           \
     647                 :            :     auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {     \
     648                 :            :       for (bool sign : {false, true})                                         \
     649                 :            :       {                                                                       \
     650                 :            :         BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1); \
     651                 :            :         BitVector bv = bvsign.concat(bvexp).concat(bvsig);                    \
     652                 :            :         auto mpfr = fpMPFR(d_fp16, bv);                                       \
     653                 :            :         auto sym = fpSymFPU(d_fp16, bv);                                      \
     654                 :            :         ASSERT_EQ(mpfr.METHOD()->pack(), sym.METHOD()->pack());               \
     655                 :            :       }                                                                       \
     656                 :            :     };                                                                        \
     657                 :            :     testForFloat16(fun16);                                                    \
     658                 :            :     testForFormats(d_test_formats,                                            \
     659                 :            :                    N_TESTS,                                                   \
     660                 :            :                    [](const FloatingPointSize& fmt, const BitVector& bv) {    \
     661                 :            :                      auto mpfr = fpMPFR(fmt, bv);                             \
     662                 :            :                      auto sym = fpSymFPU(fmt, bv);                            \
     663                 :            :                      ASSERT_EQ(mpfr.METHOD()->pack(), sym.METHOD()->pack());  \
     664                 :            :                    });                                                        \
     665                 :            :   }
     666                 :            : 
     667 [ -  + ][ +  - ]:       1204 : TEST_UNARY_OP(absolute, absolute)
         [ +  - ][ +  - ]
     668 [ -  + ][ +  - ]:       1204 : TEST_UNARY_OP(negate, negate)
         [ +  - ][ +  - ]
     669                 :            : 
     670                 :            : #undef TEST_UNARY_OP
     671                 :            : 
     672                 :            : /* -------------------------------------------------------------------------- */
     673                 :            : /* Unary operators with RM: fp.sqrt, fp.rti                                   */
     674                 :            : /* -------------------------------------------------------------------------- */
     675                 :            : 
     676                 :            : #define TEST_UNARY_RM_OP(NAME, METHOD)                                         \
     677                 :            :   TEST_F(TestUtilBlackFloatingPoint, NAME)                                     \
     678                 :            :   {                                                                            \
     679                 :            :     auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {      \
     680                 :            :       for (bool sign : {false, true})                                          \
     681                 :            :       {                                                                        \
     682                 :            :         BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);  \
     683                 :            :         BitVector bv = bvsign.concat(bvexp).concat(bvsig);                     \
     684                 :            :         auto mpfr = fpMPFR(d_fp16, bv);                                        \
     685                 :            :         auto sym = fpSymFPU(d_fp16, bv);                                       \
     686                 :            :         for (auto rm : d_all_rms)                                              \
     687                 :            :         {                                                                      \
     688                 :            :           ASSERT_EQ(mpfr.METHOD(rm)->pack(), sym.METHOD(rm)->pack());          \
     689                 :            :         }                                                                      \
     690                 :            :       }                                                                        \
     691                 :            :     };                                                                         \
     692                 :            :     testForFloat16(fun16);                                                     \
     693                 :            :     testForFormats(d_test_formats,                                             \
     694                 :            :                    N_TESTS,                                                    \
     695                 :            :                    [this](const FloatingPointSize& fmt, const BitVector& bv) { \
     696                 :            :                      auto mpfr = fpMPFR(fmt, bv);                              \
     697                 :            :                      auto sym = fpSymFPU(fmt, bv);                             \
     698                 :            :                      for (auto rm : d_all_rms)                                 \
     699                 :            :                      {                                                         \
     700                 :            :                        ASSERT_EQ(mpfr.METHOD(rm)->pack(),                      \
     701                 :            :                                  sym.METHOD(rm)->pack());                      \
     702                 :            :                      }                                                         \
     703                 :            :                    });                                                         \
     704                 :            :   }
     705                 :            : 
     706 [ -  + ][ +  - ]:       4404 : TEST_UNARY_RM_OP(fpSqrt, sqrt)
         [ +  + ][ +  - ]
                 [ +  - ]
     707 [ -  + ][ +  - ]:       4404 : TEST_UNARY_RM_OP(fpRti, rti)
         [ +  + ][ +  - ]
                 [ +  - ]
     708                 :            : 
     709                 :            : #undef TEST_UNARY_RM_OP
     710                 :            : 
     711                 :            : /* -------------------------------------------------------------------------- */
     712                 :            : /* Binary operator without RM: fp.rem                                         */
     713                 :            : /* -------------------------------------------------------------------------- */
     714                 :            : 
     715                 :          4 : TEST_F(TestUtilBlackFloatingPoint, fpRem)
     716                 :            : {
     717                 :            :   // Exhaustive for Float16 (one operand exhaustive, other random) if
     718                 :            :   // CVC5_SLOW_TESTS is not enabled, else only a random subset is tested for
     719                 :            :   // Float16 (as with the other formats).
     720                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     721                 :          0 :     bool sign = pickBool();
     722         [ -  - ]:          0 :     BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     723                 :          0 :     BitVector bv1 = bvsign.concat(bvexp).concat(bvsig);
     724                 :          0 :     BitVector bv2 = BitVector::mkRandom(d_fp16.packedWidth());
     725                 :            : 
     726                 :          0 :     auto mpfr1 = fpMPFR(d_fp16, bv1);
     727                 :          0 :     auto mpfr2 = fpMPFR(d_fp16, bv2);
     728                 :          0 :     auto sym1 = fpSymFPU(d_fp16, bv1);
     729                 :          0 :     auto sym2 = fpSymFPU(d_fp16, bv2);
     730                 :            : 
     731                 :          0 :     ASSERT_EQ(mpfr1.rem(mpfr2)->pack(), sym1.rem(sym2)->pack());
     732 [ -  - ][ -  - ]:          1 :   };
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     733                 :          1 :   testForFloat16(fun16);
     734                 :          1 :   testForFormats(d_test_formats,
     735                 :            :                  N_TESTS_REM,
     736                 :        200 :                  [](const FloatingPointSize& fmt, const BitVector& bv1) {
     737                 :        200 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
     738                 :        200 :                    auto mpfr1 = fpMPFR(fmt, bv1);
     739                 :        200 :                    auto mpfr2 = fpMPFR(fmt, bv2);
     740                 :        200 :                    auto sym1 = fpSymFPU(fmt, bv1);
     741                 :        200 :                    auto sym2 = fpSymFPU(fmt, bv2);
     742 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1.rem(mpfr2)->pack(), sym1.rem(sym2)->pack());
     743 [ +  - ][ +  - ]:        200 :                  });
         [ +  - ][ +  - ]
                 [ +  - ]
     744                 :          1 : }
     745                 :            : 
     746                 :            : /* -------------------------------------------------------------------------- */
     747                 :            : /* Binary operators with RM: fp.add, fp.sub, fp.mult, fp.div                  */
     748                 :            : /* -------------------------------------------------------------------------- */
     749                 :            : 
     750                 :            : #define TEST_BINARY_RM_OP(NAME, METHOD)                                     \
     751                 :            :   TEST_F(TestUtilBlackFloatingPoint, NAME)                                  \
     752                 :            :   {                                                                         \
     753                 :            :     auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {   \
     754                 :            :       bool sign = pickBool();                                               \
     755                 :            :       BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1); \
     756                 :            :       BitVector bv1 = bvsign.concat(bvexp).concat(bvsig);                   \
     757                 :            :       BitVector bv2 = BitVector::mkRandom(d_fp16.packedWidth());            \
     758                 :            :       auto mpfr1 = fpMPFR(d_fp16, bv1);                                     \
     759                 :            :       auto mpfr2 = fpMPFR(d_fp16, bv2);                                     \
     760                 :            :       auto sym1 = fpSymFPU(d_fp16, bv1);                                    \
     761                 :            :       auto sym2 = fpSymFPU(d_fp16, bv2);                                    \
     762                 :            :       for (auto rm : d_all_rms)                                             \
     763                 :            :       {                                                                     \
     764                 :            :         ASSERT_EQ(mpfr1.METHOD(rm, mpfr2)->pack(),                          \
     765                 :            :                   sym1.METHOD(rm, sym2)->pack());                           \
     766                 :            :       }                                                                     \
     767                 :            :     };                                                                      \
     768                 :            :     testForFloat16(fun16);                                                  \
     769                 :            :     testForFormats(                                                         \
     770                 :            :         d_test_formats,                                                     \
     771                 :            :         N_TESTS,                                                            \
     772                 :            :         [this](const FloatingPointSize& fmt, const BitVector& bv1) {        \
     773                 :            :           BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());           \
     774                 :            :           auto mpfr1 = fpMPFR(fmt, bv1);                                    \
     775                 :            :           auto mpfr2 = fpMPFR(fmt, bv2);                                    \
     776                 :            :           auto sym1 = fpSymFPU(fmt, bv1);                                   \
     777                 :            :           auto sym2 = fpSymFPU(fmt, bv2);                                   \
     778                 :            :           for (auto rm : d_all_rms)                                         \
     779                 :            :           {                                                                 \
     780                 :            :             ASSERT_EQ(mpfr1.METHOD(rm, mpfr2)->pack(),                      \
     781                 :            :                       sym1.METHOD(rm, sym2)->pack());                       \
     782                 :            :           }                                                                 \
     783                 :            :         });                                                                 \
     784                 :            :   }
     785                 :            : 
     786 [ -  + ][ +  - ]:       4404 : TEST_BINARY_RM_OP(fpAdd, add)
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     787 [ -  + ][ +  - ]:       4404 : TEST_BINARY_RM_OP(fpSub, sub)
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     788 [ -  + ][ +  - ]:       4404 : TEST_BINARY_RM_OP(fpMult, mult)
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     789 [ -  + ][ +  - ]:       4404 : TEST_BINARY_RM_OP(fpDiv, div)
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     790                 :            : 
     791                 :            : #undef TEST_BINARY_RM_OP
     792                 :            : 
     793                 :            : /* -------------------------------------------------------------------------- */
     794                 :            : /* Ternary operator with RM: fp.fma                                           */
     795                 :            : /* -------------------------------------------------------------------------- */
     796                 :            : 
     797                 :          4 : TEST_F(TestUtilBlackFloatingPoint, fpFma)
     798                 :            : {
     799                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     800                 :          0 :     bool sign = pickBool();
     801         [ -  - ]:          0 :     BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     802                 :          0 :     BitVector bv1 = bvsign.concat(bvexp).concat(bvsig);
     803                 :          0 :     BitVector bv2 = BitVector::mkRandom(d_fp16.packedWidth());
     804                 :          0 :     BitVector bv3 = BitVector::mkRandom(d_fp16.packedWidth());
     805                 :            : 
     806                 :          0 :     auto mpfr1 = fpMPFR(d_fp16, bv1);
     807                 :          0 :     auto mpfr2 = fpMPFR(d_fp16, bv2);
     808                 :          0 :     auto mpfr3 = fpMPFR(d_fp16, bv3);
     809                 :          0 :     auto sym1 = fpSymFPU(d_fp16, bv1);
     810                 :          0 :     auto sym2 = fpSymFPU(d_fp16, bv2);
     811                 :          0 :     auto sym3 = fpSymFPU(d_fp16, bv3);
     812                 :            : 
     813         [ -  - ]:          0 :     for (auto rm : d_all_rms)
     814                 :            :     {
     815         [ -  - ]:          0 :       ASSERT_EQ(mpfr1.fma(rm, mpfr2, mpfr3)->pack(),
     816         [ -  - ]:          0 :                 sym1.fma(rm, sym2, sym3)->pack());
     817                 :            :     }
     818 [ -  - ][ -  - ]:          1 :   };
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     819                 :          1 :   testForFloat16(fun16);
     820                 :          1 :   testForFormats(d_test_formats,
     821                 :            :                  N_TESTS,
     822                 :        800 :                  [this](const FloatingPointSize& fmt, const BitVector& bv1) {
     823                 :        400 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
     824                 :        400 :                    BitVector bv3 = BitVector::mkRandom(fmt.packedWidth());
     825                 :        400 :                    auto mpfr1 = fpMPFR(fmt, bv1);
     826                 :        400 :                    auto mpfr2 = fpMPFR(fmt, bv2);
     827                 :        400 :                    auto mpfr3 = fpMPFR(fmt, bv3);
     828                 :        400 :                    auto sym1 = fpSymFPU(fmt, bv1);
     829                 :        400 :                    auto sym2 = fpSymFPU(fmt, bv2);
     830                 :        400 :                    auto sym3 = fpSymFPU(fmt, bv3);
     831         [ +  + ]:       2400 :                    for (auto rm : d_all_rms)
     832                 :            :                    {
     833         [ -  + ]:       4000 :                      ASSERT_EQ(mpfr1.fma(rm, mpfr2, mpfr3)->pack(),
     834         [ +  - ]:       2000 :                                sym1.fma(rm, sym2, sym3)->pack());
     835                 :            :                    }
     836 [ +  - ][ +  - ]:        400 :                  });
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     837                 :          1 : }
     838                 :            : 
     839                 :            : /* -------------------------------------------------------------------------- */
     840                 :            : /* Min/Max                                                                    */
     841                 :            : /* -------------------------------------------------------------------------- */
     842                 :            : 
     843                 :          4 : TEST_F(TestUtilBlackFloatingPoint, fpMinMax)
     844                 :            : {
     845                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     846                 :          0 :     bool sign = pickBool();
     847         [ -  - ]:          0 :     BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     848                 :          0 :     BitVector bv1 = bvsign.concat(bvexp).concat(bvsig);
     849                 :          0 :     BitVector bv2 = BitVector::mkRandom(d_fp16.packedWidth());
     850                 :            : 
     851                 :          0 :     auto mpfr1 = fpMPFR(d_fp16, bv1);
     852                 :          0 :     auto mpfr2 = fpMPFR(d_fp16, bv2);
     853                 :          0 :     auto sym1 = fpSymFPU(d_fp16, bv1);
     854                 :          0 :     auto sym2 = fpSymFPU(d_fp16, bv2);
     855                 :            : 
     856         [ -  - ]:          0 :     for (bool zeroCaseLeft : {false, true})
     857                 :            :     {
     858         [ -  - ]:          0 :       ASSERT_EQ(mpfr1.maxTotal(mpfr2, zeroCaseLeft)->pack(),
     859         [ -  - ]:          0 :                 sym1.maxTotal(sym2, zeroCaseLeft)->pack());
     860         [ -  - ]:          0 :       ASSERT_EQ(mpfr1.minTotal(mpfr2, zeroCaseLeft)->pack(),
     861         [ -  - ]:          0 :                 sym1.minTotal(sym2, zeroCaseLeft)->pack());
     862                 :            :     }
     863 [ -  - ][ -  - ]:          1 :   };
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     864                 :          1 :   testForFloat16(fun16);
     865                 :          1 :   testForFormats(d_test_formats,
     866                 :            :                  N_TESTS,
     867                 :        400 :                  [](const FloatingPointSize& fmt, const BitVector& bv1) {
     868                 :        400 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
     869                 :        400 :                    auto mpfr1 = fpMPFR(fmt, bv1);
     870                 :        400 :                    auto mpfr2 = fpMPFR(fmt, bv2);
     871                 :        400 :                    auto sym1 = fpSymFPU(fmt, bv1);
     872                 :        400 :                    auto sym2 = fpSymFPU(fmt, bv2);
     873         [ +  + ]:       1200 :                    for (bool zeroCaseLeft : {false, true})
     874                 :            :                    {
     875         [ -  + ]:       1600 :                      ASSERT_EQ(mpfr1.maxTotal(mpfr2, zeroCaseLeft)->pack(),
     876         [ +  - ]:        800 :                                sym1.maxTotal(sym2, zeroCaseLeft)->pack());
     877         [ -  + ]:       1600 :                      ASSERT_EQ(mpfr1.minTotal(mpfr2, zeroCaseLeft)->pack(),
     878         [ +  - ]:        800 :                                sym1.minTotal(sym2, zeroCaseLeft)->pack());
     879                 :            :                    }
     880 [ +  - ][ +  - ]:        400 :                  });
         [ +  - ][ +  - ]
                 [ +  - ]
     881                 :          1 : }
     882                 :            : 
     883                 :            : /* -------------------------------------------------------------------------- */
     884                 :            : /* Comparisons: ==, <=, <                                                     */
     885                 :            : /* -------------------------------------------------------------------------- */
     886                 :            : 
     887                 :          4 : TEST_F(TestUtilBlackFloatingPoint, comparisons)
     888                 :            : {
     889                 :          0 :   auto fun16 = [this](const BitVector& bvexp, const BitVector& bvsig) {
     890                 :          0 :     bool sign = pickBool();
     891         [ -  - ]:          0 :     BitVector bvsign = sign ? BitVector::mkOne(1) : BitVector::mkZero(1);
     892                 :          0 :     BitVector bv1 = bvsign.concat(bvexp).concat(bvsig);
     893                 :          0 :     BitVector bv2 = BitVector::mkRandom(d_fp16.packedWidth());
     894                 :            : 
     895                 :          0 :     auto mpfr1 = fpMPFR(d_fp16, bv1);
     896                 :          0 :     auto mpfr2 = fpMPFR(d_fp16, bv2);
     897                 :          0 :     auto sym1 = fpSymFPU(d_fp16, bv1);
     898                 :          0 :     auto sym2 = fpSymFPU(d_fp16, bv2);
     899                 :            : 
     900                 :          0 :     ASSERT_EQ(mpfr1 == mpfr2, sym1 == sym2);
     901                 :          0 :     ASSERT_EQ(mpfr1 <= mpfr2, sym1 <= sym2);
     902                 :          0 :     ASSERT_EQ(mpfr1 < mpfr2, sym1 < sym2);
     903                 :            : 
     904                 :            :     // Self-comparison
     905                 :          0 :     ASSERT_EQ(mpfr1 == mpfr1, sym1 == sym1);
     906                 :          0 :     ASSERT_EQ(mpfr1 <= mpfr1, sym1 <= sym1);
     907                 :          0 :     ASSERT_EQ(mpfr1 < mpfr1, sym1 < sym1);
     908 [ -  - ][ -  - ]:          1 :   };
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     909                 :          1 :   testForFloat16(fun16);
     910                 :          1 :   testForFormats(d_test_formats,
     911                 :            :                  N_TESTS,
     912                 :        400 :                  [](const FloatingPointSize& fmt, const BitVector& bv1) {
     913                 :        400 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
     914                 :        400 :                    auto mpfr1 = fpMPFR(fmt, bv1);
     915                 :        400 :                    auto mpfr2 = fpMPFR(fmt, bv2);
     916                 :        400 :                    auto sym1 = fpSymFPU(fmt, bv1);
     917                 :        400 :                    auto sym2 = fpSymFPU(fmt, bv2);
     918 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1 == mpfr2, sym1 == sym2);
     919 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1 <= mpfr2, sym1 <= sym2);
     920 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1 < mpfr2, sym1 < sym2);
     921 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1 == mpfr1, sym1 == sym1);
     922 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1 <= mpfr1, sym1 <= sym1);
     923 [ -  + ][ +  - ]:        400 :                    ASSERT_EQ(mpfr1 < mpfr1, sym1 < sym1);
     924 [ +  - ][ +  - ]:        400 :                  });
         [ +  - ][ +  - ]
                 [ +  - ]
     925                 :          1 : }
     926                 :            : 
     927                 :            : /* -------------------------------------------------------------------------- */
     928                 :            : /* Convert (FP to FP)                                                         */
     929                 :            : /* -------------------------------------------------------------------------- */
     930                 :            : 
     931                 :          4 : TEST_F(TestUtilBlackFloatingPoint, fpConvert)
     932                 :            : {
     933         [ +  + ]:        101 :   for (uint32_t i = 0; i < N_TESTS; ++i)
     934                 :            :   {
     935                 :        100 :     FloatingPointSize srcFmt = pickFormat();
     936                 :        100 :     FloatingPointSize dstFmt = pickFormat();
     937                 :        100 :     BitVector bv = BitVector::mkRandom(srcFmt.packedWidth());
     938                 :        100 :     RoundingMode rm = pickRm();
     939                 :            : 
     940                 :        100 :     auto mpfr = fpMPFR(srcFmt, bv);
     941                 :        100 :     auto sym = fpSymFPU(srcFmt, bv);
     942                 :            : 
     943         [ -  + ]:        200 :     ASSERT_EQ(mpfr.convert(dstFmt, rm)->pack(),
     944         [ +  - ]:        100 :               sym.convert(dstFmt, rm)->pack());
     945 [ +  - ][ +  - ]:        100 :   }
                 [ +  - ]
     946                 :            : }
     947                 :            : 
     948                 :            : /* -------------------------------------------------------------------------- */
     949                 :            : /* Convert to BV (signed / unsigned)                                          */
     950                 :            : /* -------------------------------------------------------------------------- */
     951                 :            : 
     952                 :          4 : TEST_F(TestUtilBlackFloatingPoint, convertToBV)
     953                 :            : {
     954         [ +  + ]:        101 :   for (uint32_t i = 0; i < N_TESTS; ++i)
     955                 :            :   {
     956                 :        100 :     FloatingPointSize fmt = pickFormat();
     957                 :        100 :     BitVector bv = BitVector::mkRandom(fmt.packedWidth());
     958                 :        100 :     RoundingMode rm = pickRm();
     959                 :        100 :     uint32_t width = d_rng.pick<uint32_t>(MIN_SIZE_TO_BV, MAX_SIZE_TO_BV);
     960                 :        100 :     BitVector undef = BitVector::mkRandom(width);
     961                 :            : 
     962                 :        100 :     auto mpfr = fpMPFR(fmt, bv);
     963                 :        100 :     auto sym = fpSymFPU(fmt, bv);
     964                 :            : 
     965                 :            :     // SymFPU to_sbv has an issue for a corner case, see #12734 that may
     966                 :            :     // get triggered in this test, thus it is temporarily disabled.
     967                 :            :     // ASSERT_EQ(mpfr.convertToSBVTotal(width, rm, undef),
     968                 :            :     //           sym.convertToSBVTotal(width, rm, undef));
     969         [ -  + ]:        200 :     ASSERT_EQ(mpfr.convertToUBVTotal(width, rm, undef),
     970         [ +  - ]:        100 :               sym.convertToUBVTotal(width, rm, undef));
     971 [ +  - ][ +  - ]:        100 :   }
         [ +  - ][ +  - ]
     972                 :            : }
     973                 :            : 
     974                 :            : /* -------------------------------------------------------------------------- */
     975                 :            : /* Chained operations                                                         */
     976                 :            : /* -------------------------------------------------------------------------- */
     977                 :            : 
     978                 :          4 : TEST_F(TestUtilBlackFloatingPoint, chainedAddMul)
     979                 :            : {
     980                 :          1 :   testForFormats(d_all_formats,
     981                 :            :                  N_TESTS,
     982                 :       1200 :                  [this](const FloatingPointSize& fmt, const BitVector& bv1) {
     983                 :        400 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
     984                 :        400 :                    BitVector bv3 = BitVector::mkRandom(fmt.packedWidth());
     985                 :            : 
     986                 :        400 :                    auto mpfr1 = fpMPFR(fmt, bv1);
     987                 :        400 :                    auto mpfr2 = fpMPFR(fmt, bv2);
     988                 :        400 :                    auto mpfr3 = fpMPFR(fmt, bv3);
     989                 :        400 :                    auto sym1 = fpSymFPU(fmt, bv1);
     990                 :        400 :                    auto sym2 = fpSymFPU(fmt, bv2);
     991                 :        400 :                    auto sym3 = fpSymFPU(fmt, bv3);
     992                 :            : 
     993                 :        400 :                    RoundingMode rm1 = pickRm();
     994                 :        400 :                    RoundingMode rm2 = pickRm();
     995                 :            : 
     996                 :            :                    // (a + b) * c
     997         [ -  + ]:        800 :                    ASSERT_EQ(mpfr1.add(rm1, mpfr2)->mult(rm2, mpfr3)->pack(),
     998         [ +  - ]:        400 :                              sym1.add(rm1, sym2)->mult(rm2, sym3)->pack());
     999 [ +  - ][ +  - ]:        400 :                  });
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1000                 :          1 : }
    1001                 :            : 
    1002                 :          4 : TEST_F(TestUtilBlackFloatingPoint, chainedAbsAdd)
    1003                 :            : {
    1004                 :          1 :   testForFormats(d_all_formats,
    1005                 :            :                  N_TESTS,
    1006                 :        800 :                  [this](const FloatingPointSize& fmt, const BitVector& bv1) {
    1007                 :        400 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
    1008                 :            : 
    1009                 :        400 :                    auto mpfr1 = fpMPFR(fmt, bv1);
    1010                 :        400 :                    auto mpfr2 = fpMPFR(fmt, bv2);
    1011                 :        400 :                    auto sym1 = fpSymFPU(fmt, bv1);
    1012                 :        400 :                    auto sym2 = fpSymFPU(fmt, bv2);
    1013                 :            : 
    1014                 :        400 :                    RoundingMode rm = pickRm();
    1015                 :            : 
    1016                 :            :                    // abs(a + b)
    1017         [ -  + ]:        800 :                    ASSERT_EQ(mpfr1.add(rm, mpfr2)->absolute()->pack(),
    1018         [ +  - ]:        400 :                              sym1.add(rm, sym2)->absolute()->pack());
    1019                 :            :                    // neg(a + b)
    1020         [ -  + ]:        800 :                    ASSERT_EQ(mpfr1.add(rm, mpfr2)->negate()->pack(),
    1021         [ +  - ]:        400 :                              sym1.add(rm, sym2)->negate()->pack());
    1022 [ +  - ][ +  - ]:        400 :                  });
         [ +  - ][ +  - ]
                 [ +  - ]
    1023                 :          1 : }
    1024                 :            : 
    1025                 :          4 : TEST_F(TestUtilBlackFloatingPoint, chainedSqrtAdd)
    1026                 :            : {
    1027                 :          1 :   testForFormats(d_all_formats,
    1028                 :            :                  N_TESTS,
    1029                 :       1200 :                  [this](const FloatingPointSize& fmt, const BitVector& bv1) {
    1030                 :        400 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
    1031                 :            : 
    1032                 :        400 :                    auto mpfr1 = fpMPFR(fmt, bv1);
    1033                 :        400 :                    auto mpfr2 = fpMPFR(fmt, bv2);
    1034                 :        400 :                    auto sym1 = fpSymFPU(fmt, bv1);
    1035                 :        400 :                    auto sym2 = fpSymFPU(fmt, bv2);
    1036                 :            : 
    1037                 :        400 :                    RoundingMode rm1 = pickRm();
    1038                 :        400 :                    RoundingMode rm2 = pickRm();
    1039                 :            : 
    1040                 :            :                    // sqrt(a + b)
    1041         [ -  + ]:        800 :                    ASSERT_EQ(mpfr1.add(rm2, mpfr2)->sqrt(rm1)->pack(),
    1042         [ +  - ]:        400 :                              sym1.add(rm2, sym2)->sqrt(rm1)->pack());
    1043                 :            :                    // rti(a + b)
    1044         [ -  + ]:        800 :                    ASSERT_EQ(mpfr1.add(rm2, mpfr2)->rti(rm1)->pack(),
    1045         [ +  - ]:        400 :                              sym1.add(rm2, sym2)->rti(rm1)->pack());
    1046 [ +  - ][ +  - ]:        400 :                  });
         [ +  - ][ +  - ]
                 [ +  - ]
    1047                 :          1 : }
    1048                 :            : 
    1049                 :          4 : TEST_F(TestUtilBlackFloatingPoint, chainedRemAdd)
    1050                 :            : {
    1051                 :          1 :   testForFormats(d_all_formats,
    1052                 :            :                  N_TESTS_REM,
    1053                 :        400 :                  [this](const FloatingPointSize& fmt, const BitVector& bv1) {
    1054                 :        200 :                    BitVector bv2 = BitVector::mkRandom(fmt.packedWidth());
    1055                 :        200 :                    BitVector bv3 = BitVector::mkRandom(fmt.packedWidth());
    1056                 :            : 
    1057                 :        200 :                    auto mpfr1 = fpMPFR(fmt, bv1);
    1058                 :        200 :                    auto mpfr2 = fpMPFR(fmt, bv2);
    1059                 :        200 :                    auto mpfr3 = fpMPFR(fmt, bv3);
    1060                 :        200 :                    auto sym1 = fpSymFPU(fmt, bv1);
    1061                 :        200 :                    auto sym2 = fpSymFPU(fmt, bv2);
    1062                 :        200 :                    auto sym3 = fpSymFPU(fmt, bv3);
    1063                 :            : 
    1064                 :        200 :                    RoundingMode rm = pickRm();
    1065                 :            : 
    1066                 :            :                    // (a + b) rem c
    1067         [ -  + ]:        400 :                    ASSERT_EQ(mpfr1.add(rm, mpfr2)->rem(mpfr3)->pack(),
    1068         [ +  - ]:        200 :                              sym1.add(rm, sym2)->rem(sym3)->pack());
    1069                 :            :                    // (a rem b) + c
    1070         [ -  + ]:        400 :                    ASSERT_EQ(mpfr1.rem(mpfr2)->add(rm, mpfr3)->pack(),
    1071         [ +  - ]:        200 :                              sym1.rem(sym2)->add(rm, sym3)->pack());
    1072 [ +  - ][ +  - ]:        200 :                  });
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1073                 :          1 : }
    1074                 :            : #else
    1075                 :            : TEST_F(TestUtilBlackFloatingPoint, crosscheckDisabled)
    1076                 :            : {
    1077                 :            :   GTEST_SKIP() << "MPFR-vs-SymFPU cross-checks require -DUSE_MPFR=ON";
    1078                 :            : }
    1079                 :            : #endif
    1080                 :            : 
    1081                 :            : }  // namespace test
    1082                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14