mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 10:25:18 +00:00
175 lines
5.4 KiB
C++
175 lines
5.4 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:
|
|
|
|
--*/
|
|
#ifndef _HWF_H_
|
|
#define _HWF_H_
|
|
|
|
#include<string>
|
|
#include"mpz.h"
|
|
#include"mpq.h"
|
|
#include"mpf.h" // we use the same rounding modes as mpf's
|
|
|
|
class hwf {
|
|
friend class hwf_manager;
|
|
double value;
|
|
hwf & operator=(hwf const & other) { UNREACHABLE(); return *this; }
|
|
|
|
public:
|
|
hwf() {}
|
|
hwf(hwf const & other) { this->value = other.value; }
|
|
~hwf() {}
|
|
void swap(hwf & other) { double t = value; value = other.value; other.value = t; }
|
|
};
|
|
|
|
|
|
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 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);
|
|
|
|
// structural eq
|
|
bool eq_core(hwf const & x, hwf const & y);
|
|
|
|
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 fused_mul_add(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 {
|
|
uint64 raw = *reinterpret_cast<uint64 const *>(&x.value);
|
|
return (raw & 0x8000000000000000ull) != 0;
|
|
}
|
|
|
|
const uint64 sig(hwf const & x) const {
|
|
return *reinterpret_cast<uint64 const *>(&x.value) & 0x000FFFFFFFFFFFFFull;
|
|
}
|
|
|
|
const int exp(hwf const & x) const {
|
|
return ((*reinterpret_cast<uint64 const *>(&x.value) & 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(*reinterpret_cast<const unsigned long long*>(&a.value)); }
|
|
|
|
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;
|
|
|
|
#endif
|