3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 00:26:38 +00:00

Add rational::next_power_of_two

This commit is contained in:
Jakob Rath 2023-08-16 09:48:32 +02:00
parent 0bfebe3de1
commit 11b582cce7
6 changed files with 69 additions and 0 deletions

View file

@ -466,6 +466,28 @@ static void tst12() {
std::cout << i << ": " << r.get_bit(i) << "\n";
}
static void tst13() {
std::cout << "test13\n";
rational const step = rational(1) / rational(3);
for (rational r; r < 5000; r += step) {
{
unsigned k = r.prev_power_of_two();
if (r >= 1) {
VERIFY(rational::power_of_two(k) <= r);
VERIFY(r < rational::power_of_two(k + 1));
}
else {
VERIFY_EQ(k, 0);
}
}
{
unsigned k = r.next_power_of_two();
VERIFY(r <= rational::power_of_two(k));
VERIFY(k == 0 || rational::power_of_two(k - 1) < r);
}
}
}
void tst_rational() {
TRACE("rational", tout << "starting rational test...\n";);
@ -492,4 +514,5 @@ void tst_rational() {
tst10(true);
tst10(false);
tst12();
tst13();
}

View file

@ -316,6 +316,12 @@ unsigned mpq_manager<SYNCH>::prev_power_of_two(mpq const & a) {
return prev_power_of_two(_tmp);
}
template<bool SYNCH>
unsigned mpq_manager<SYNCH>::next_power_of_two(mpq const & a) {
_scoped_numeral<mpz_manager<SYNCH> > _tmp(*this);
ceil(a, _tmp);
return next_power_of_two(_tmp);
}
template<bool SYNCH>
template<bool SUB>

View file

@ -848,6 +848,14 @@ public:
unsigned prev_power_of_two(mpz const & a) { return mpz_manager<SYNCH>::prev_power_of_two(a); }
unsigned prev_power_of_two(mpq const & a);
/**
\brief Return the smallest k s.t. a <= 2^k.
\remark Return 0 if a is not positive.
*/
unsigned next_power_of_two(mpz const & a) { return mpz_manager<SYNCH>::next_power_of_two(a); }
unsigned next_power_of_two(mpq const & a);
bool is_int_perfect_square(mpq const & a, mpq & r) {
SASSERT(is_int(a));
reset_denominator(r);

View file

@ -2288,6 +2288,19 @@ unsigned mpz_manager<SYNCH>::bitsize(mpz const & a) {
return mlog2(a) + 1;
}
template<bool SYNCH>
unsigned mpz_manager<SYNCH>::next_power_of_two(mpz const & a) {
if (is_nonpos(a))
return 0;
if (is_one(a))
return 0;
unsigned shift;
if (is_power_of_two(a, shift))
return shift;
else
return log2(a) + 1;
}
template<bool SYNCH>
bool mpz_manager<SYNCH>::is_perfect_square(mpz const & a, mpz & root) {
if (is_neg(a))

View file

@ -692,6 +692,13 @@ public:
\remark Return 0 if a is not positive.
*/
unsigned prev_power_of_two(mpz const & a) { return log2(a); }
/**
\brief Return the smallest k s.t. a <= 2^k.
\remark Return 0 if a is not positive.
*/
unsigned next_power_of_two(mpz const & a);
/**
\brief Return true if a^{1/n} is an integer, and store the result in a.

View file

@ -489,6 +489,18 @@ public:
return get_num_digits(rational(10));
}
/**
* \brief Return the biggest k s.t. 2^k <= a.
* \remark Return 0 if a is not positive.
*/
unsigned prev_power_of_two() const { return m().prev_power_of_two(m_val); }
/**
* \brief Return the smallest k s.t. a <= 2^k.
* \remark Return 0 if a is not positive.
*/
unsigned next_power_of_two() const { return m().next_power_of_two(m_val); }
bool get_bit(unsigned index) const {
return m().get_bit(m_val, index);
}