LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - sampler.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 69 73 94.5 %
Date: 2026-02-09 12:26:33 Functions: 2 3 66.7 %
Branches: 27 29 93.1 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andres Noetzli, Aina Niemetz
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * Sampler class that generates random values of different sorts
      14                 :            :  *
      15                 :            :  * The Sampler class can be used to generate random values of different sorts
      16                 :            :  * with biased and unbiased distributions.
      17                 :            :  */
      18                 :            : 
      19                 :            : #include "util/sampler.h"
      20                 :            : 
      21                 :            : #include <sstream>
      22                 :            : 
      23                 :            : #include "base/check.h"
      24                 :            : #include "util/bitvector.h"
      25                 :            : #include "util/random.h"
      26                 :            : 
      27                 :            : namespace cvc5::internal {
      28                 :            : 
      29                 :     272690 : BitVector Sampler::pickBvUniform(unsigned sz)
      30                 :            : {
      31                 :     272690 :   Random& rnd = Random::getRandom();
      32                 :            : 
      33                 :     272690 :   std::stringstream ss;
      34         [ +  + ]:    5431340 :   for (unsigned i = 0; i < sz; i++)
      35                 :            :   {
      36         [ +  + ]:    5158650 :     ss << (rnd.pickWithProb(0.5) ? "1" : "0");
      37                 :            :   }
      38                 :            : 
      39                 :     818070 :   return BitVector(ss.str(), 2);
      40                 :            : }
      41                 :            : 
      42                 :          0 : FloatingPoint Sampler::pickFpUniform(unsigned e, unsigned s)
      43                 :            : {
      44                 :          0 :   return FloatingPoint(e, s, pickBvUniform(e + s));
      45                 :            : }
      46                 :            : 
      47                 :      19994 : FloatingPoint Sampler::pickFpBiased(unsigned e, unsigned s)
      48                 :            : {
      49                 :            :   // The biased generation of random FP values is inspired by
      50                 :            :   // PyMPF [0].
      51                 :            :   //
      52                 :            :   // [0] https://github.com/florianschanda/PyMPF
      53                 :            : 
      54                 :      19994 :   Random& rnd = Random::getRandom();
      55                 :            : 
      56                 :      39988 :   BitVector zero(1);
      57                 :      39988 :   BitVector one(1, static_cast<unsigned int>(1));
      58                 :            : 
      59                 :      39988 :   BitVector sign(1);
      60                 :      39988 :   BitVector exp(e);
      61                 :      39988 :   BitVector sig(s - 1);
      62                 :            : 
      63         [ +  + ]:      19994 :   if (rnd.pickWithProb(probSpecial))
      64                 :            :   {
      65                 :            :     // Generate special values
      66                 :            : 
      67                 :       4032 :     uint64_t type = rnd.pick(0, 12);
      68 [ +  + ][ +  + ]:       4032 :     switch (type)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  - ]
      69                 :            :     {
      70                 :            :       // NaN
      71                 :            :       // sign = 1, exp = 11...11, sig = 11...11
      72                 :        330 :       case 0:
      73                 :        330 :         sign = one;
      74                 :        330 :         exp = BitVector::mkOnes(e);
      75                 :        330 :         sig = BitVector::mkOnes(s - 1);
      76                 :        330 :         break;
      77                 :            : 
      78                 :            :       // +/- inf
      79                 :            :       // sign = x, exp = 11...11, sig = 00...00
      80                 :        282 :       case 1: sign = one; CVC5_FALLTHROUGH;
      81                 :        600 :       case 2: exp = BitVector::mkOnes(e); break;
      82                 :            : 
      83                 :            :       // +/- zero
      84                 :            :       // sign = x, exp = 00...00, sig = 00...00
      85                 :        344 :       case 3: sign = one; CVC5_FALLTHROUGH;
      86                 :        652 :       case 4: break;
      87                 :            : 
      88                 :            :       // +/- max subnormal
      89                 :            :       // sign = x, exp = 00...00, sig = 11...11
      90                 :        338 :       case 5: sign = one; CVC5_FALLTHROUGH;
      91                 :        596 :       case 6: sig = BitVector::mkOnes(s - 1); break;
      92                 :            : 
      93                 :            :       // +/- min subnormal
      94                 :            :       // sign = x, exp = 00...00, sig = 00...01
      95                 :        308 :       case 7: sign = one; CVC5_FALLTHROUGH;
      96                 :        670 :       case 8: sig = BitVector(s - 1, static_cast<unsigned int>(1)); break;
      97                 :            : 
      98                 :            :       // +/- max normal
      99                 :            :       // sign = x, exp = 11...10, sig = 11...11
     100                 :        304 :       case 9: sign = one; CVC5_FALLTHROUGH;
     101                 :        650 :       case 10:
     102                 :        650 :         exp = BitVector::mkOnes(e) - BitVector(e, static_cast<unsigned int>(1));
     103                 :        650 :         sig = BitVector::mkOnes(s - 1);
     104                 :        650 :         break;
     105                 :            : 
     106                 :            :       // +/- min normal
     107                 :            :       // sign = x, exp = 00...01, sig = 00...00
     108                 :        240 :       case 11: sign = one; CVC5_FALLTHROUGH;
     109                 :        534 :       case 12: exp = BitVector(e, static_cast<unsigned int>(1)); break;
     110                 :            : 
     111                 :          0 :       default: Unreachable();
     112                 :            :     }
     113                 :            :   }
     114                 :            :   else
     115                 :            :   {
     116                 :            :     // Generate normal and subnormal values
     117                 :            : 
     118                 :            :     // 50% chance of positive/negative sign
     119         [ +  + ]:      15962 :     if (rnd.pickWithProb(0.5))
     120                 :            :     {
     121                 :       7958 :       sign = one;
     122                 :            :     }
     123                 :            : 
     124                 :      15962 :     uint64_t pattern = rnd.pick(0, 5);
     125 [ +  + ][ +  + ]:      15962 :     switch (pattern)
            [ +  + ][ - ]
     126                 :            :     {
     127                 :       2784 :       case 0:
     128                 :            :         // sign = x, exp = xx...x0, sig = 11...11
     129                 :       2784 :         exp = pickBvUniform(e - 1).concat(zero);
     130                 :       2784 :         sig = BitVector::mkOnes(s - 1);
     131                 :       2784 :         break;
     132                 :            : 
     133                 :       2662 :       case 1:
     134                 :            :         // sign = x, exp = xx...x0, sig = 00...00
     135                 :       2662 :         exp = pickBvUniform(e - 1).concat(zero);
     136                 :       2662 :         break;
     137                 :            : 
     138                 :       2644 :       case 2:
     139                 :            :         // sign = x, exp = 0x...x1, sig = 11...11
     140                 :       2644 :         exp = zero.concat(pickBvUniform(e - 2).concat(one));
     141                 :       2644 :         sig = BitVector::mkOnes(s - 1);
     142                 :       2644 :         break;
     143                 :            : 
     144                 :       2552 :       case 3:
     145                 :            :         // sign = x, exp = xx...x0, sig = xx...xx
     146                 :       2552 :         exp = pickBvUniform(e - 1).concat(zero);
     147                 :       2552 :         sig = pickBvUniform(s - 1);
     148                 :       2552 :         break;
     149                 :            : 
     150                 :       2598 :       case 4:
     151                 :            :         // sign = x, exp = 0x...x1, sig = xx...xx
     152                 :       2598 :         exp = zero.concat(pickBvUniform(e - 2).concat(one));
     153                 :       2598 :         sig = pickBvUniform(s - 1);
     154                 :       2598 :         break;
     155                 :            : 
     156                 :       2722 :       case 5:
     157                 :            :       {
     158                 :            :         // sign = x, exp = xx...xx0xx...xx, sig = xx...xx
     159                 :       2722 :         uint64_t lsbSize = rnd.pick(1, e - 2);
     160                 :       2722 :         uint64_t msbSize = e - lsbSize - 1;
     161                 :       5444 :         BitVector lsb = pickBvUniform(lsbSize);
     162                 :       5444 :         BitVector msb = pickBvUniform(msbSize);
     163                 :       2722 :         exp = msb.concat(zero.concat(lsb));
     164                 :       2722 :         sig = pickBvUniform(s - 1);
     165                 :       2722 :         break;
     166                 :            :       }
     167                 :            : 
     168                 :          0 :       default: Unreachable();
     169                 :            :     }
     170                 :            :   }
     171                 :            : 
     172                 :      39988 :   BitVector bv = sign.concat(exp.concat(sig));
     173                 :      39988 :   return FloatingPoint(e, s, bv);
     174                 :            : }
     175                 :            : 
     176                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14