-rw-r--r-- 5343 cryptattacktester-20231020/bigfloat_mpfi.cpp raw
#include <cassert> #include <map> #include <mpfr.h> #include "bigfloat_mpfi.h" using namespace std; void bigfloat::set_default_precision(bigint p) { mpfr_set_default_prec(p); } bigint bigfloat::get_default_precision(void) { return mpfr_get_default_prec(); } ostream &operator<<(ostream &o,const bigfloat &a) { char *s = 0; assert(mpfr_asprintf(&s,"[%.9RDg,%.9RUg]",&a.x->left,&a.x->right) >= 0); o << s; mpfr_free_str(s); return o; } bigfloat bigfloat_guarantee_nonnegative(const bigfloat &a) { bigfloat result; mpfr_t left,right; mpfr_init(left); mpfr_init(right); mpfi_get_left(left,a.x); mpfi_get_right(right,a.x); if (mpfr_sgn(left) < 0) mpfr_set_zero(left,1); // XXX: can produce empty interval mpfi_interv_fr(result.x,left,right); mpfr_clear(right); mpfr_clear(left); return result; } bool bigfloat::definitely_zero() { return mpfi_is_zero(x); } bool bigfloat::definitely_positive() { return mpfi_is_strictly_pos(x); } bool bigfloat::definitely_less(const bigfloat &b) { // mpfi documentation says mpfi_cmp returns 1 for invalid operands return mpfi_cmp(x,b.x) < 0; } bool bigfloat::maybe_between(double f,double g) { return mpfi_cmp_d(x,f) >= 0 && mpfi_cmp_d(x,g) <= 0; } // returns 1 if all of the following occur: // * interval is a bounded interval [left,right] // * left > 0 // * 2^reasonable(right-left) < left; i.e. right/left < 1+1/2^reasonable bool bigfloat::definitely_positive_and_reasonably_precise(long reasonable) { if (!mpfi_bounded_p(x)) return 0; if (!mpfi_is_strictly_pos(x)) return 0; mpfr_t left,gap; mpfr_init(left); mpfr_init(gap); mpfi_get_left(left,x); mpfi_get_right(gap,x); mpfr_sub(gap,gap,left,GMP_RNDU); mpfr_mul_2ui(gap,gap,reasonable,GMP_RNDU); bool result = mpfr_cmp(gap,left) < 0; mpfr_clear(gap); mpfr_clear(left); return result; } // returns total ordering on (left,right), suitable for sorting // beware that NaN follows its own rules bool operator<(const bigfloat &a,const bigfloat &b) { mpfr_t aleft,aright,bleft,bright; mpfr_init(aleft); mpfr_init(aright); mpfr_init(bleft); mpfr_init(bright); mpfi_get_left(aleft,a.x); mpfi_get_right(aright,a.x); mpfi_get_left(bleft,b.x); mpfi_get_right(bright,b.x); bool result = mpfr_less_p(aleft,bleft) || (mpfr_equal_p(aleft,bleft) && mpfr_less_p(aright,bright)); mpfr_clear(bright); mpfr_clear(bleft); mpfr_clear(aright); mpfr_clear(aleft); return result; } // returns total ordering on (left,right), suitable for sorting // beware that NaN follows its own rules bool operator>(const bigfloat &a,const bigfloat &b) { mpfr_t aleft,aright,bleft,bright; mpfr_init(aleft); mpfr_init(aright); mpfr_init(bleft); mpfr_init(bright); mpfi_get_left(aleft,a.x); mpfi_get_right(aright,a.x); mpfi_get_left(bleft,b.x); mpfi_get_right(bright,b.x); bool result = mpfr_greater_p(aleft,bleft) || (mpfr_equal_p(aleft,bleft) && mpfr_greater_p(aright,bright)); mpfr_clear(bright); mpfr_clear(bleft); mpfr_clear(aright); mpfr_clear(aleft); return result; } bigfloat operator+(const bigfloat &a,const bigfloat &b) { bigfloat result; mpfi_add(result.x,a.x,b.x); return result; } bigfloat& operator+=(bigfloat &a,const bigfloat &b) { mpfi_add(a.x,a.x,b.x); return a; } bigfloat operator-(const bigfloat &a,const bigfloat &b) { bigfloat result; mpfi_sub(result.x,a.x,b.x); return result; } bigfloat operator-(const bigfloat &a) { bigfloat result; mpfi_neg(result.x,a.x); return result; } bigfloat operator*(const bigfloat &a,const bigfloat &b) { bigfloat result; mpfi_mul(result.x,a.x,b.x); return result; } bigfloat& operator*=(bigfloat &a,const bigfloat &b) { mpfi_mul(a.x,a.x,b.x); return a; } bigfloat operator/(const bigfloat &a,const bigfloat &b) { bigfloat result; mpfi_div(result.x,a.x,b.x); return result; } bigfloat log(const bigfloat &a) { bigfloat result; mpfi_log(result.x,a.x); return result; } bigfloat log2(const bigfloat &a) { bigfloat result; mpfi_log2(result.x,a.x); return result; } bigfloat log1p(const bigfloat &a) { bigfloat result; mpfi_log1p(result.x,a.x); return result; } bigfloat exp(const bigfloat &a) { bigfloat result; mpfi_exp(result.x,a.x); return result; } bigfloat expm1(const bigfloat &a) { bigfloat result; mpfi_expm1(result.x,a.x); return result; } bigfloat exp2(const bigfloat &a) { bigfloat result; mpfi_exp2(result.x,a.x); return result; } bigfloat pow(const bigfloat &a,const bigfloat &b) { return exp(b*log(a)); } bigint floor_as_bigint(const bigfloat &a) { assert(mpfi_bounded_p(a.x)); // XXX mpz_t zleft; mpfr_t left; mpz_init(zleft); mpfr_init(left); mpfi_get_left(left,a.x); mpfr_get_z(zleft,left,GMP_RNDD); bigint result(zleft); mpfr_clear(left); mpz_clear(zleft); return result; } bigint ceil_as_bigint(const bigfloat &a) { assert(mpfi_bounded_p(a.x)); // XXX mpz_t zright; mpfr_t right; mpz_init(zright); mpfr_init(right); mpfi_get_right(right,a.x); mpfr_get_z(zright,right,GMP_RNDU); bigint result(zright); mpfr_clear(right); mpz_clear(zright); return result; } bigfloat binomial_bigfloat(const bigfloat &n,const bigint &k) { if (k < 0) return 0; if (k == 0) return 1; bigfloat n1 = n-1; bigint k1 = k-1; bigfloat result = binomial_bigfloat(n1,k1)*n/bigfloat(k); return result; }