-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;
}