mirror of
https://github.com/Z3Prover/z3
synced 2025-04-16 22:05:36 +00:00
171 lines
5.1 KiB
C++
171 lines
5.1 KiB
C++
/*++
|
|
Copyright (c) 2011 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
hwf.h
|
|
|
|
Abstract:
|
|
|
|
Hardware Floating Point Numbers
|
|
|
|
Author:
|
|
|
|
Christoph Wintersteiger (cwinter) 2012-07-30.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#pragma once
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
#include "util/mpz.h"
|
|
#include "util/mpq.h"
|
|
#include "util/mpf.h"
|
|
|
|
class hwf {
|
|
friend class hwf_manager;
|
|
double value;
|
|
uint64_t get_raw() const {
|
|
uint64_t n;
|
|
SASSERT(sizeof(n) == sizeof(value));
|
|
memcpy(&n, &value, sizeof(value));
|
|
return n;
|
|
}
|
|
|
|
public:
|
|
void swap(hwf & other) noexcept { std::swap(value, other.value); }
|
|
};
|
|
|
|
|
|
class hwf_manager {
|
|
unsynch_mpq_manager m_mpq_manager;
|
|
unsynch_mpz_manager & m_mpz_manager; // A mpq_manager is a mpz_manager, reusing it.
|
|
|
|
public:
|
|
typedef hwf numeral;
|
|
hwf_manager();
|
|
~hwf_manager();
|
|
|
|
void reset(hwf & o) { set(o, 0); }
|
|
void set(hwf & o, int value);
|
|
void set(hwf & o, mpf_rounding_mode rm, int n, int d);
|
|
void set(hwf & o, float value);
|
|
void set(hwf & o, double value);
|
|
void set(hwf & o, mpf_rounding_mode rm, mpq const & value);
|
|
void set(hwf & o, mpf_rounding_mode rm, char const * value);
|
|
void set(hwf & o, mpf_rounding_mode rm, mpq const & significand, mpz const & exponent);
|
|
void set(hwf & o, bool sign, uint64_t significand, int exponent);
|
|
void set(hwf & o, hwf const & x);
|
|
|
|
// auxiliary methods to make the interface compatible with mpf
|
|
void reset(hwf & o, unsigned ebits, unsigned sbits) { set(o, 0); }
|
|
void set(hwf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & value) { set(o, rm, value); }
|
|
void set(hwf & o, unsigned ebits, unsigned sbits, int value) { set(o, value); }
|
|
void set(hwf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, int n, int d) { set(o, rm, n, d); }
|
|
void set(hwf & o, unsigned ebits, unsigned sbits, float value) { set(o, value); }
|
|
void set(hwf & o, unsigned ebits, unsigned sbits, double value) { set(o, value); }
|
|
|
|
|
|
void del(hwf & x) {}
|
|
|
|
void abs(hwf & o);
|
|
void abs(hwf const & x, hwf & o);
|
|
|
|
void neg(hwf & o);
|
|
void neg(hwf const & x, hwf & o);
|
|
|
|
bool is_zero(hwf const & x);
|
|
bool is_neg(hwf const & x);
|
|
bool is_pos(hwf const & x);
|
|
|
|
bool is_nzero(hwf const & x);
|
|
bool is_pzero(hwf const & x);
|
|
|
|
bool is_one(hwf const & x);
|
|
|
|
bool eq(hwf const & x, hwf const & y);
|
|
bool lt(hwf const & x, hwf const & y);
|
|
bool lte(hwf const & x, hwf const & y);
|
|
bool le(hwf const & x, hwf const & y) { return lte(x, y); }
|
|
bool gt(hwf const & x, hwf const & y);
|
|
bool gte(hwf const & x, hwf const & y);
|
|
bool ge(hwf const & x, hwf const & y) { return gte(x, y); }
|
|
|
|
void add(mpf_rounding_mode rm, hwf const & x, hwf const & y, hwf & o);
|
|
void sub(mpf_rounding_mode rm, hwf const & x, hwf const & y, hwf & o);
|
|
void mul(mpf_rounding_mode rm, hwf const & x, hwf const & y, hwf & o);
|
|
void div(mpf_rounding_mode rm, hwf const & x, hwf const & y, hwf & o);
|
|
|
|
void fma(mpf_rounding_mode rm, hwf const & x, hwf const & y, hwf const &z, hwf & o);
|
|
|
|
void sqrt(mpf_rounding_mode rm, hwf const & x, hwf & o);
|
|
|
|
void round_to_integral(mpf_rounding_mode rm, hwf const & x, hwf & o);
|
|
|
|
void rem(hwf const & x, hwf const & y, hwf & o);
|
|
|
|
void maximum(hwf const & x, hwf const & y, hwf & o);
|
|
void minimum(hwf const & x, hwf const & y, hwf & o);
|
|
|
|
std::string to_string(hwf const & a);
|
|
std::string to_rational_string(hwf const & a);
|
|
void display_decimal(std::ostream & out, hwf const & a, unsigned k);
|
|
void display_smt2(std::ostream & out, hwf const & a, bool decimal);
|
|
|
|
double to_double(hwf const & x) { return x.value; }
|
|
float to_float(hwf const & x) { return (float) x.value; }
|
|
void to_rational(hwf const & x, unsynch_mpq_manager & qm, mpq & o);
|
|
void to_rational(hwf const & x, scoped_mpq & o) { to_rational(x, o.m(), o); }
|
|
|
|
|
|
bool sgn(hwf const & x) const {
|
|
return (x.get_raw() & 0x8000000000000000ull) != 0;
|
|
}
|
|
|
|
uint64_t sig(hwf const & x) const {
|
|
return x.get_raw() & 0x000FFFFFFFFFFFFFull;
|
|
}
|
|
|
|
int exp(hwf const & x) const {
|
|
return ((x.get_raw() & 0x7FF0000000000000ull) >> 52) - 1023;
|
|
}
|
|
|
|
bool is_nan(hwf const & x);
|
|
bool is_inf(hwf const & x);
|
|
bool is_pinf(hwf const & x);
|
|
bool is_ninf(hwf const & x);
|
|
bool is_normal(hwf const & x);
|
|
bool is_denormal(hwf const & x);
|
|
bool is_regular(hwf const & x);
|
|
bool is_int(hwf const & x);
|
|
|
|
void mk_zero(bool sign, hwf & o);
|
|
void mk_nzero(hwf & o);
|
|
void mk_pzero(hwf & o);
|
|
void mk_nan(hwf & o);
|
|
void mk_inf(bool sign, hwf & o);
|
|
void mk_pinf(hwf & o);
|
|
void mk_ninf(hwf & o);
|
|
|
|
unsigned hash(hwf const & a) { return hash_ull(a.get_raw()); }
|
|
|
|
inline void set_rounding_mode(mpf_rounding_mode rm);
|
|
|
|
/**
|
|
\brief Return the biggest k s.t. 2^k <= a.
|
|
|
|
\remark Return 0 if a is not positive.
|
|
*/
|
|
unsigned prev_power_of_two(hwf const & a);
|
|
|
|
protected:
|
|
#ifdef _WINDOWS
|
|
unsigned x86_state, sse2_state;
|
|
#endif
|
|
};
|
|
|
|
typedef _scoped_numeral<hwf_manager> scoped_hwf;
|
|
typedef _scoped_numeral_vector<hwf_manager> scoped_hwf_vector;
|