mirror of
https://github.com/Z3Prover/z3
synced 2025-06-22 13:53:39 +00:00
u256
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
ff717a9db1
commit
e19a7f71aa
3 changed files with 100 additions and 4 deletions
|
@ -7,12 +7,25 @@ u256::u256() {
|
||||||
}
|
}
|
||||||
|
|
||||||
u256::u256(uint64_t n) {
|
u256::u256(uint64_t n) {
|
||||||
|
// TBD use instead: bn_from_bytes_be?
|
||||||
m_num[0] = n;
|
m_num[0] = n;
|
||||||
m_num[1] = m_num[2] = m_num[3] = 0;
|
m_num[1] = m_num[2] = m_num[3] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u256::u256(rational const& n) {
|
||||||
|
uint8_t bytes[32];
|
||||||
|
for (unsigned i = 0; i < 32; ++i)
|
||||||
|
bytes[i] = 0;
|
||||||
|
for (unsigned i = 0; i < 256; ++i)
|
||||||
|
bytes[(i / 7)] |= n.get_bit(i) << (i % 8);
|
||||||
|
auto* v = Hacl_Bignum256_new_bn_from_bytes_be(32, bytes);
|
||||||
|
std::uninitialized_copy(v, v + 4, m_num);
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u256::u256(uint64_t const* v) {
|
u256::u256(uint64_t const* v) {
|
||||||
std::uninitialized_copy(v, v + sizeof(*this), m_num);
|
std::uninitialized_copy(v, v + 4, m_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
u256 u256::operator*(u256 const& other) const {
|
u256 u256::operator*(u256 const& other) const {
|
||||||
|
@ -37,3 +50,52 @@ u256& u256::operator-=(u256 const& other) {
|
||||||
Hacl_Bignum256_sub(const_cast<uint64_t*>(m_num), const_cast<uint64_t*>(other.m_num), m_num);
|
Hacl_Bignum256_sub(const_cast<uint64_t*>(m_num), const_cast<uint64_t*>(other.m_num), m_num);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u256& u256::inv() {
|
||||||
|
uint64_t zero[4];
|
||||||
|
zero[0] = zero[1] = zero[2] = zero[3] = 0;
|
||||||
|
Hacl_Bignum256_sub(zero, const_cast<uint64_t*>(m_num), m_num);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
u256 u256::mul_inverse() const {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write `a mod n` in `res`.
|
||||||
|
|
||||||
|
The argument a is meant to be a 512-bit bignum, i.e. uint64_t[8].
|
||||||
|
The argument n and the outparam res are meant to be 256-bit bignums, i.e. uint64_t[4].
|
||||||
|
|
||||||
|
The function returns false if any of the following preconditions are violated,
|
||||||
|
true otherwise.
|
||||||
|
• 1 < n
|
||||||
|
• n % 2 = 1
|
||||||
|
VERIFY(Hacl_Bignum256_mod(uint64_t *n, uint64_t *a, uint64_t *res));
|
||||||
|
*/
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned u256::trailing_zeros() const {
|
||||||
|
unsigned r = 0;
|
||||||
|
for (unsigned i = 0; i < 3; ++i) {
|
||||||
|
r += ::trailing_zeros(m_num[i]);
|
||||||
|
if (r != (i+1)*64)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return r + ::trailing_zeros(m_num[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
u256 u256::gcd(u256 const& other) const {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& u256::display(std::ostream& out) const {
|
||||||
|
rational n;
|
||||||
|
for (unsigned i = 0; i < 4; ++i)
|
||||||
|
if (m_num[i] != 0)
|
||||||
|
n += rational(m_num[i], rational::ui64()) * rational::power_of_two(i * 64);
|
||||||
|
return out << n;
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,52 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
#include "util/rational.h"
|
||||||
|
|
||||||
class u256 {
|
class u256 {
|
||||||
uint64_t m_num[4];
|
uint64_t m_num[4];
|
||||||
|
u256(uint64_t const* v);
|
||||||
public:
|
public:
|
||||||
u256();
|
u256();
|
||||||
u256(uint64_t n);
|
u256(uint64_t n);
|
||||||
u256(uint64_t const* v);
|
u256(rational const& n);
|
||||||
u256 operator*(u256 const& other) const;
|
u256 operator*(u256 const& other) const;
|
||||||
u256 operator+(u256 const& other) const { u256 r = *this; return r += other; }
|
u256 operator+(u256 const& other) const { u256 r = *this; return r += other; }
|
||||||
u256 operator-(u256 const& other) const { u256 r = *this; return r -= other; }
|
u256 operator-(u256 const& other) const { u256 r = *this; return r -= other; }
|
||||||
|
u256 operator-() const { u256 r = *this; return r.inv(); }
|
||||||
|
|
||||||
|
u256 mul_inverse() const;
|
||||||
|
unsigned trailing_zeros() const;
|
||||||
|
u256 gcd(u256 const& other) const;
|
||||||
|
|
||||||
|
// updates
|
||||||
|
void reset() { m_num[0] = m_num[1] = m_num[2] = m_num[3] = 0; }
|
||||||
u256& operator+=(u256 const& other);
|
u256& operator+=(u256 const& other);
|
||||||
u256& operator*=(u256 const& other);
|
u256& operator*=(u256 const& other);
|
||||||
u256& operator-=(u256 const& other);
|
u256& operator-=(u256 const& other);
|
||||||
|
u256& inv(); /* unary minus */
|
||||||
|
|
||||||
|
// comparisons
|
||||||
|
bool operator==(u256 const& other) const;
|
||||||
|
bool operator!=(u256 const& other) const;
|
||||||
|
bool operator<(u256 const& other) const;
|
||||||
|
bool operator<=(u256 const& other) const;
|
||||||
|
bool operator>(u256 const& other) const;
|
||||||
|
bool operator>=(u256 const& other) const;
|
||||||
|
|
||||||
|
bool operator<(uint64_t other) const;
|
||||||
|
bool operator<=(uint64_t other) const;
|
||||||
|
bool operator>(uint64_t other) const;
|
||||||
|
bool operator>=(uint64_t other) const;
|
||||||
|
|
||||||
|
bool is_zero() const { return m_num[0] == 0 && m_num[1] == 0 && m_num[2] == 0 && m_num[3] == 0; }
|
||||||
|
bool is_one() const { return m_num[0] == 1 && m_num[1] == 0 && m_num[2] == 0 && m_num[3] == 0; }
|
||||||
|
bool is_even() const { return (m_num[0]&1) == 0; }
|
||||||
|
|
||||||
|
std::ostream& display(std::ostream& out) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, u256 const& u) {
|
||||||
|
return u.display(out);
|
||||||
|
}
|
||||||
|
|
|
@ -123,7 +123,6 @@ Numeral mod_interval<Numeral>::closest_value(Numeral const& n) const {
|
||||||
|
|
||||||
// TBD: correctness and completeness for wrap-around semantics needs to be checked/fixed
|
// TBD: correctness and completeness for wrap-around semantics needs to be checked/fixed
|
||||||
|
|
||||||
|
|
||||||
template<typename Numeral>
|
template<typename Numeral>
|
||||||
mod_interval<Numeral>& mod_interval<Numeral>::intersect_uge(Numeral const& l) {
|
mod_interval<Numeral>& mod_interval<Numeral>::intersect_uge(Numeral const& l) {
|
||||||
if (is_empty())
|
if (is_empty())
|
||||||
|
@ -153,7 +152,7 @@ mod_interval<Numeral>& mod_interval<Numeral>::intersect_ugt(Numeral const& l) {
|
||||||
set_empty();
|
set_empty();
|
||||||
else if (lo < hi)
|
else if (lo < hi)
|
||||||
lo = l + 1;
|
lo = l + 1;
|
||||||
else if (hi < lo && hi <= l + 1 && l <= lo - 1)
|
else if (hi < lo && hi <= l + 1 && l < lo)
|
||||||
hi = 0;
|
hi = 0;
|
||||||
else if (hi < lo && lo <= l)
|
else if (hi < lo && lo <= l)
|
||||||
hi = 0, lo = l + 1;
|
hi = 0, lo = l + 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue