13 static precision_t mDefaultPrecision;
18 * Constructors & Destructors
23 mpfr_init2(mValue, mDefaultPrecision);
24 mpfr_set_zero(mValue, 1);
27 // Default precision is initially set to 53 bits in mpfr implementation
28 FLOAT_T(const double _double, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
30 mpfr_init2(mValue,_prec);
31 mpfr_set_d(mValue,_double,mpfr_rnd_t(_rnd));
34 // Default precision is initially set to 53 bits in mpfr implementation
35 FLOAT_T(const float _float, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
37 mpfr_init2(mValue,_prec);
38 mpfr_set_flt(mValue, _float, mpfr_rnd_t(_rnd));
41 // Default precision is initially set to 53 bits in mpfr implementation
42 FLOAT_T(const int _int, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
44 mpfr_init2(mValue,_prec);
45 mpfr_set_si(mValue,_int,mpfr_rnd_t(_rnd));
48 // Default precision is initially set to 53 bits in mpfr implementation
49 FLOAT_T(const unsigned _int, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
51 mpfr_init2(mValue,_prec);
52 mpfr_set_ui(mValue,_int,mpfr_rnd_t(_rnd));
55 // Default precision is initially set to 53 bits in mpfr implementation
57 FLOAT_T(const long _long, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
59 mpfr_init2(mValue,_prec);
60 mpfr_set_si(mValue,_long,mpfr_rnd_t(_rnd));
63 // Default precision is initially set to 53 bits in mpfr implementation
64 FLOAT_T(const unsigned long _long, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
66 mpfr_init2(mValue,_prec);
67 mpfr_set_ui(mValue,_long,mpfr_rnd_t(_rnd));
70 FLOAT_T(const mpfr_t& _mpfrNumber)
72 mpfr_init2(mValue,mpfr_get_prec(_mpfrNumber));
73 mpfr_set(mValue, _mpfrNumber, MPFR_RNDN);
76 FLOAT_T(const FLOAT_T<mpfr_t>& _float)
78 mpfr_init2(mValue, mpfr_get_prec(_float.mValue));
79 mpfr_set(mValue, _float.mValue, MPFR_RNDN);
82 FLOAT_T(FLOAT_T<mpfr_t>&& _float)
84 if(this->mValue == _float.value()){
85 mpfr_swap(mValue,_float.mValue);
87 mpfr_init2(mValue, mpfr_get_prec(_float.value()));
88 mpfr_swap(mValue,_float.mValue);
92 FLOAT_T(const std::string& _string)
94 mpfr_init_set_str(mValue, _string.c_str(), 10, MPFR_RNDN);
97 template<typename F, DisableIf< std::is_same<F, mpfr_t> > = dummy>
98 FLOAT_T(const FLOAT_T<F>& _float, const CARL_RND _rnd=CARL_RND::N, precision_t _prec=mDefaultPrecision)
100 mpfr_init2(mValue,_prec);
101 mpfr_set_d(mValue,_float.to_double(),mpfr_rnd_t(_rnd));
109 static inline const FLOAT_T<mpfr_t> const_infinity(){
111 mpfr_init2(tmp, FLOAT_T<mpfr_t>::defaultPrecision());
113 return FLOAT_T<mpfr_t>(tmp);
116 inline const FLOAT_T<mpfr_t> setNan(){
117 mpfr_set_nan(mValue);
121 inline FLOAT_T<mpfr_t> increment() const {
122 FLOAT_T<mpfr_t> tmp(*this);
123 mpfr_nextabove(tmp.mValue);
127 inline FLOAT_T<mpfr_t> decrement() const {
128 FLOAT_T<mpfr_t> tmp(*this);
129 mpfr_nextbelow(tmp.mValue);
133 static inline FLOAT_T<mpfr_t> machine_epsilon(precision_t prec)
135 /* the smallest eps such that 1 + eps != 1 */
136 return machine_epsilon(FLOAT_T<mpfr_t>(1,CARL_RND::N, prec));
139 static inline FLOAT_T<mpfr_t> machine_epsilon(const FLOAT_T<mpfr_t>& x)
141 /* the smallest eps such that x + eps != x */
142 FLOAT_T<mpfr_t> tmp(x);
145 return -tmp.increment() + tmp;
147 return tmp.increment() - tmp;
151 static inline carl::FLOAT_T<mpfr_t> minval(const CARL_RND _rnd=CARL_RND::N, precision_t prec=FLOAT_T<mpfr_t>::defaultPrecision()) {
152 /* min = 1/2 * 2^emin = 2^(emin - 1) */
154 mpfr_init2(tmp,prec);
155 mpfr_set_ui(tmp,1,mpfr_rnd_t(_rnd));
156 mpfr_mul_2ui(tmp,tmp,(unsigned)mpfr_get_emin()-1,mpfr_rnd_t(_rnd));
157 return FLOAT_T<mpfr_t>(tmp);
160 static inline FLOAT_T<mpfr_t> maxval(const CARL_RND _rnd=CARL_RND::N, precision_t prec=FLOAT_T<mpfr_t>::defaultPrecision())
162 /* max = (1 - eps) * 2^emax, eps is machine epsilon */
164 mpfr_init2(tmp,prec);
165 mpfr_set_ui(tmp,1, mpfr_rnd_t(_rnd));
166 mpfr_sub(tmp,tmp,machine_epsilon(prec).value(), mpfr_rnd_t(_rnd));
167 mpfr_mul_2ui(tmp,tmp,(unsigned)mpfr_get_emax(),mpfr_rnd_t(_rnd));
168 return (FLOAT_T<mpfr_t>(tmp));
175 const mpfr_t& value() const
180 static void setDefaultPrecision(precision_t _prec) {
181 mDefaultPrecision = _prec;
184 static precision_t defaultPrecision () {
185 return mDefaultPrecision;
188 precision_t precision() const
190 return mpfr_get_prec(mValue);
193 FLOAT_T<mpfr_t>& setPrecision( const precision_t& _prec, const CARL_RND _rnd=CARL_RND::N )
195 mpfr_prec_round(mValue, convPrec(_prec), mpfr_rnd_t(_rnd));
203 FLOAT_T<mpfr_t>& operator = (const FLOAT_T<mpfr_t>& _rhs)
205 if(this->mValue == _rhs.value())
208 // Note: This is a workaround to get the limb size correct. Instead use free and reallocate.
209 mpfr_set_prec(mValue, mpfr_get_prec(_rhs.mValue));
210 mpfr_set(mValue, _rhs.mValue, MPFR_RNDN);
213 mValue->_mpfr_prec = _rhs.mValue->_mpfr_prec;
214 mValue->_mpfr_sign = _rhs.mValue->_mpfr_sign;
215 mValue->_mpfr_exp = _rhs.mValue->_mpfr_exp;
218 std::size_t limbs = (std::size_t)std::ceil(double(_rhs.mValue->_mpfr_prec)/double(mp_bits_per_limb));
221 mValue->_mpfr_d[limbs-1] = _rhs.mValue->_mpfr_d[limbs-1];
228 FLOAT_T<mpfr_t>& safeSet (const FLOAT_T<mpfr_t>& _rhs, const CARL_RND _rnd=CARL_RND::N)
230 mpfr_set_prec(mValue, mpfr_get_prec(_rhs.mValue));
231 mpfr_set(mValue, _rhs.mValue, mpfr_rnd_t(_rnd));
239 bool operator == ( const FLOAT_T<mpfr_t>& _rhs) const
241 return mpfr_cmp(mValue,_rhs.mValue) == 0;
244 bool operator != ( const FLOAT_T<mpfr_t> & _rhs) const
246 return mpfr_equal_p(mValue, _rhs.mValue) == 0;
249 bool operator > ( const FLOAT_T<mpfr_t> & _rhs) const
251 return mpfr_greater_p(mValue, _rhs.mValue) != 0;
254 bool operator > ( int _rhs) const
256 return mpfr_cmp_si(mValue, _rhs) > 0;
259 bool operator > ( unsigned _rhs) const
261 return mpfr_cmp_ui(mValue, _rhs) > 0;
264 bool operator < ( const FLOAT_T<mpfr_t> & _rhs) const
266 return mpfr_less_p(mValue, _rhs.mValue) != 0;
269 bool operator < ( int _rhs) const
271 return mpfr_cmp_si(mValue, _rhs) < 0;
274 bool operator < ( unsigned _rhs) const
276 return mpfr_cmp_ui(mValue, _rhs) < 0;
279 bool operator <= ( const FLOAT_T<mpfr_t> & _rhs) const
281 return mpfr_lessequal_p(mValue, _rhs.mValue) != 0;
284 bool operator >= ( const FLOAT_T<mpfr_t> & _rhs) const
286 return mpfr_greaterequal_p(mValue, _rhs.mValue) != 0;
290 * arithmetic operations
293 FLOAT_T<mpfr_t>& add_assign( const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N )
295 mpfr_add(mValue, mValue, _op2.mValue, mpfr_rnd_t(_rnd));
299 void add( FLOAT_T<mpfr_t>& _result, const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N ) const
301 mpfr_add(_result.mValue, this->mValue, _op2.mValue, mpfr_rnd_t(_rnd));
304 FLOAT_T<mpfr_t>& sub_assign( const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N )
306 mpfr_sub(mValue, mValue, _op2.mValue, mpfr_rnd_t(_rnd));
310 void sub( FLOAT_T<mpfr_t>& _result, const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N ) const
312 mpfr_sub(_result.mValue, this->mValue, _op2.mValue, mpfr_rnd_t(_rnd));
315 FLOAT_T<mpfr_t>& mul_assign(const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N)
317 mpfr_mul(mValue, mValue, _op2.mValue, mpfr_rnd_t(_rnd));
321 void mul( FLOAT_T<mpfr_t>& _result, const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N) const
323 mpfr_mul(_result.mValue, this->mValue, _op2.mValue, mpfr_rnd_t(_rnd));
326 FLOAT_T<mpfr_t>& div_assign(const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N)
329 mpfr_div(mValue, mValue, _op2.mValue, mpfr_rnd_t(_rnd));
333 void div( FLOAT_T<mpfr_t>& _result, const FLOAT_T<mpfr_t>& _op2, CARL_RND _rnd=CARL_RND::N) const
336 mpfr_div(_result.mValue, this->mValue, _op2.mValue, mpfr_rnd_t(_rnd));
343 FLOAT_T<mpfr_t>& sqrt_assign(CARL_RND _rnd = CARL_RND::N)
346 mpfr_sqrt(mValue, mValue, mpfr_rnd_t(_rnd));
350 void sqrt(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
353 mpfr_sqrt(_result.mValue, mValue, mpfr_rnd_t(_rnd));
356 FLOAT_T<mpfr_t>& cbrt_assign(CARL_RND _rnd = CARL_RND::N)
359 mpfr_cbrt(mValue, mValue, mpfr_rnd_t(_rnd));
363 void cbrt(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
366 mpfr_cbrt(_result.mValue, mValue, mpfr_rnd_t(_rnd));
369 FLOAT_T<mpfr_t>& root_assign(unsigned long int _k, CARL_RND _rnd = CARL_RND::N)
372 mpfr_root(mValue, mValue, _k, mpfr_rnd_t(_rnd));
376 void root(FLOAT_T<mpfr_t>& _result, unsigned long int _k, CARL_RND _rnd = CARL_RND::N) const
379 mpfr_root(_result.mValue, mValue, _k, mpfr_rnd_t(_rnd));
382 FLOAT_T<mpfr_t>& pow_assign(unsigned long int _exp, CARL_RND _rnd = CARL_RND::N)
384 mpfr_pow_ui(mValue, mValue, _exp, mpfr_rnd_t(_rnd));
388 void pow(FLOAT_T<mpfr_t>& _result, unsigned long int _exp, CARL_RND _rnd = CARL_RND::N) const
390 mpfr_pow_ui(_result.mValue, mValue, _exp, mpfr_rnd_t(_rnd));
393 FLOAT_T<mpfr_t>& abs_assign(CARL_RND _rnd = CARL_RND::N)
395 mpfr_abs(mValue, mValue, mpfr_rnd_t(_rnd));
399 void abs(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
401 mpfr_abs(_result.mValue, mValue, mpfr_rnd_t(_rnd));
404 FLOAT_T<mpfr_t>& exp_assign(CARL_RND _rnd = CARL_RND::N)
406 mpfr_exp(mValue, mValue, mpfr_rnd_t(_rnd));
410 void exp(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
412 mpfr_exp(_result.mValue, mValue, mpfr_rnd_t(_rnd));
415 FLOAT_T<mpfr_t>& sin_assign(CARL_RND _rnd = CARL_RND::N)
417 mpfr_sin(mValue, mValue, mpfr_rnd_t(_rnd));
421 void sin(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
423 mpfr_sin(_result.mValue, mValue, mpfr_rnd_t(_rnd));
426 FLOAT_T<mpfr_t>& cos_assign(CARL_RND _rnd = CARL_RND::N)
428 mpfr_cos(mValue, mValue, mpfr_rnd_t(_rnd));
432 void cos(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
434 mpfr_cos(_result.mValue, mValue, mpfr_rnd_t(_rnd));
437 FLOAT_T<mpfr_t>& log_assign(CARL_RND _rnd = CARL_RND::N)
439 mpfr_log(mValue, mValue, mpfr_rnd_t(_rnd));
443 void log(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
445 mpfr_log(_result.mValue, mValue, mpfr_rnd_t(_rnd));
448 FLOAT_T<mpfr_t>& tan_assign(CARL_RND _rnd = CARL_RND::N)
450 mpfr_tan(mValue, mValue, mpfr_rnd_t(_rnd));
454 void tan(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
456 mpfr_tan(_result.mValue, mValue, mpfr_rnd_t(_rnd));
459 FLOAT_T<mpfr_t>& asin_assign(CARL_RND _rnd = CARL_RND::N)
461 mpfr_asin(mValue, mValue, mpfr_rnd_t(_rnd));
465 void asin(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
467 mpfr_asin(_result.mValue, mValue, mpfr_rnd_t(_rnd));
470 FLOAT_T<mpfr_t>& acos_assign(CARL_RND _rnd = CARL_RND::N)
472 mpfr_acos(mValue, mValue, mpfr_rnd_t(_rnd));
476 void acos(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
478 mpfr_acos(_result.mValue, mValue, mpfr_rnd_t(_rnd));
481 FLOAT_T<mpfr_t>& atan_assign(CARL_RND _rnd = CARL_RND::N)
483 mpfr_atan(mValue, mValue, mpfr_rnd_t(_rnd));
487 void atan(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
489 mpfr_atan(_result.mValue, mValue, mpfr_rnd_t(_rnd));
492 FLOAT_T<mpfr_t>& sinh_assign(CARL_RND _rnd = CARL_RND::N)
494 mpfr_sinh(mValue, mValue, mpfr_rnd_t(_rnd));
498 void sinh(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
500 mpfr_sinh(_result.mValue, mValue, mpfr_rnd_t(_rnd));
503 FLOAT_T<mpfr_t>& cosh_assign(CARL_RND _rnd = CARL_RND::N)
505 mpfr_cosh(mValue, mValue, mpfr_rnd_t(_rnd));
509 void cosh(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
511 mpfr_cosh(_result.mValue, mValue, mpfr_rnd_t(_rnd));
514 FLOAT_T<mpfr_t>& tanh_assign(CARL_RND _rnd = CARL_RND::N)
516 mpfr_tanh(mValue, mValue, mpfr_rnd_t(_rnd));
520 void tanh(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
522 mpfr_tanh(_result.mValue, mValue, mpfr_rnd_t(_rnd));
525 FLOAT_T<mpfr_t>& asinh_assign(CARL_RND _rnd = CARL_RND::N)
527 mpfr_asinh(mValue, mValue, mpfr_rnd_t(_rnd));
531 void asinh(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
533 mpfr_asinh(_result.mValue, mValue, mpfr_rnd_t(_rnd));
536 FLOAT_T<mpfr_t>& acosh_assign(CARL_RND _rnd = CARL_RND::N)
538 mpfr_acosh(mValue, mValue, mpfr_rnd_t(_rnd));
542 void acosh(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
544 mpfr_acosh(_result.mValue, mValue, mpfr_rnd_t(_rnd));
547 FLOAT_T<mpfr_t>& atanh_assign(CARL_RND _rnd = CARL_RND::N)
549 mpfr_atanh(mValue, mValue, mpfr_rnd_t(_rnd));
553 void atanh(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
555 mpfr_atanh(_result.mValue, mValue, mpfr_rnd_t(_rnd));
558 void floor(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
560 mpfr_init(_result.mValue);
561 mpfr_set_zero(_result.mValue, 1);
562 mpfr_rint_floor(_result.mValue, mValue, mpfr_rnd_t(_rnd));
563 //_result = mpfr_integer_p(result);
564 //mpfr_clear(result);
567 FLOAT_T& floor_assign(CARL_RND _rnd = CARL_RND::N)
569 mpfr_rint_floor(mValue, mValue, mpfr_rnd_t(_rnd));
573 void ceil(FLOAT_T<mpfr_t>& _result, CARL_RND _rnd = CARL_RND::N) const
575 mpfr_init(_result.mValue);
576 mpfr_set_zero(_result.mValue, 1);
577 mpfr_rint_ceil(_result.mValue, mValue, mpfr_rnd_t(_rnd));
578 //_result = mpfr_integer_p(result);
579 //mpfr_clear(result);
582 FLOAT_T& ceil_assign(CARL_RND _rnd = CARL_RND::N)
584 mpfr_rint_ceil(mValue, mValue, mpfr_rnd_t(_rnd));
589 * conversion operators
592 double to_double(CARL_RND _rnd=CARL_RND::N) const
594 return mpfr_get_d(mValue, mpfr_rnd_t(_rnd));
598 * Explicit typecast operator to integer.
599 * @return Integer representation of this.
601 explicit operator int() const
603 return (int)this->to_double();
607 * Explicit typecast operator to long.
608 * @return Long representation of this.
610 explicit operator long() const
612 return (long)(this->to_double());
616 * Explicit typecast operator to double.
617 * @return Double representation of this.
619 explicit operator double() const
621 return this->to_double();
625 friend std::ostream & operator<< (std::ostream& ostr, const FLOAT_T<mpfr_t> & p) {
626 ostr << p.toString();
632 friend bool operator== (const FLOAT_T<mpfr_t>& _lhs, const int _rhs)
634 return mpfr_cmp_si(_lhs.mValue, _rhs) == 0;
637 friend bool operator== (const int _lhs, const FLOAT_T<mpfr_t>& _rhs)
642 friend bool operator== (const FLOAT_T<mpfr_t>& _lhs, const double _rhs)
644 return mpfr_cmp_d(_lhs.mValue,_rhs) == 0;
647 friend bool operator== (const double _lhs, const FLOAT_T<mpfr_t>& _rhs)
652 friend bool operator== (const FLOAT_T<mpfr_t>& _lhs, const float _rhs)
654 return mpfr_cmp_d(_lhs.mValue, _rhs);
657 friend bool operator== (const float _lhs, const FLOAT_T<mpfr_t>& _rhs)
666 friend FLOAT_T<mpfr_t> operator +(const FLOAT_T<mpfr_t>& _lhs, const FLOAT_T<mpfr_t>& _rhs)
669 mpfr_add(res.mValue, _lhs.mValue, _rhs.mValue, MPFR_RNDN);
673 friend FLOAT_T<mpfr_t> operator +(const mpfr_t& _lhs, const FLOAT_T<mpfr_t>& _rhs)
676 mpfr_add(res.mValue, _lhs, _rhs.mValue, MPFR_RNDN);
680 friend FLOAT_T<mpfr_t> operator +(const FLOAT_T<mpfr_t>& _lhs, const mpfr_t& _rhs)
683 mpfr_add(res.mValue, _lhs.mValue, _rhs, MPFR_RNDN);
687 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
688 friend FLOAT_T<mpfr_t> operator +(const Other& _lhs, const FLOAT_T<mpfr_t>& _rhs)
691 mpfr_add(res.mValue, FLOAT_T<mpfr_t>(_lhs).mValue, _rhs.mValue, MPFR_RNDN);
695 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
696 friend FLOAT_T<mpfr_t> operator +(const FLOAT_T<mpfr_t>& _lhs, const Other& _rhs)
701 friend FLOAT_T<mpfr_t> operator -(const FLOAT_T<mpfr_t>& _lhs, const FLOAT_T<mpfr_t>& _rhs)
704 mpfr_sub(res.mValue, _lhs.mValue, _rhs.mValue, MPFR_RNDN);
708 friend FLOAT_T<mpfr_t> operator -(const mpfr_t& _lhs, const FLOAT_T<mpfr_t>& _rhs)
711 mpfr_sub(res.mValue, _lhs, _rhs.mValue, MPFR_RNDN);
715 friend FLOAT_T<mpfr_t> operator -(const FLOAT_T<mpfr_t>& _lhs, const mpfr_t& _rhs)
718 mpfr_sub(res.mValue, _lhs.mValue, _rhs, MPFR_RNDN);
722 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
723 friend FLOAT_T<mpfr_t> operator -(const Other& _lhs, const FLOAT_T<mpfr_t>& _rhs)
726 mpfr_sub(res.mValue, FLOAT_T<mpfr_t>(_lhs).mValue, _rhs.mValue, MPFR_RNDN);
730 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
731 friend FLOAT_T<mpfr_t> operator -(const FLOAT_T<mpfr_t>& _lhs, const Other& _rhs)
734 mpfr_sub(res.mValue, _lhs.mValue, FLOAT_T<mpfr_t>(_rhs).mValue, MPFR_RNDN);
738 friend FLOAT_T<mpfr_t> operator -(const FLOAT_T<mpfr_t>& _lhs)
741 mpfr_mul_si(res.mValue, _lhs.mValue, -1, MPFR_RNDN);
745 friend FLOAT_T<mpfr_t> operator *(const FLOAT_T<mpfr_t>& _lhs, const FLOAT_T<mpfr_t>& _rhs)
748 mpfr_mul(res.mValue, _lhs.mValue, _rhs.mValue, MPFR_RNDN);
752 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
753 friend FLOAT_T<mpfr_t> operator *(const Other& _lhs, const FLOAT_T<mpfr_t>& _rhs)
756 FLOAT_T<mpfr_t> lhs = FLOAT_T<mpfr_t>(_lhs);
757 mpfr_mul(res.mValue, lhs.mValue, _rhs.mValue, MPFR_RNDN);
761 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
762 friend FLOAT_T<mpfr_t> operator *(const FLOAT_T<mpfr_t>& _lhs, const Other& _rhs)
767 friend FLOAT_T<mpfr_t> operator *(const mpfr_t& _lhs, const FLOAT_T<mpfr_t>& _rhs)
770 mpfr_mul(res.mValue, _lhs, _rhs.mValue, MPFR_RNDN);
774 friend FLOAT_T<mpfr_t> operator *(const FLOAT_T<mpfr_t>& _lhs, const mpfr_t& _rhs)
777 mpfr_mul(res.mValue, _lhs.mValue, _rhs, MPFR_RNDN);
781 friend FLOAT_T<mpfr_t> operator /(const FLOAT_T<mpfr_t>& _lhs, const FLOAT_T<mpfr_t>& _rhs)
783 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
785 mpfr_div(res.mValue, _lhs.mValue, _rhs.mValue, MPFR_RNDN);
789 friend FLOAT_T<mpfr_t> operator /(const mpfr_t& _lhs, const FLOAT_T<mpfr_t>& _rhs)
791 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
793 mpfr_div(res.mValue, _lhs, _rhs.mValue, MPFR_RNDN);
797 friend FLOAT_T<mpfr_t> operator /(const FLOAT_T<mpfr_t>& _lhs, const mpfr_t& _rhs)
799 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
801 mpfr_div(res.mValue, _lhs.mValue, _rhs, MPFR_RNDN);
805 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
806 friend FLOAT_T<mpfr_t> operator /(const Other& _lhs, const FLOAT_T<mpfr_t>& _rhs)
808 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
810 mpfr_div(res.mValue, FLOAT_T<mpfr_t>(_lhs).mValue, _rhs.mValue, MPFR_RNDN);
814 template<typename Other, EnableIf< is_number_type<Other>, Not<is_interval_type<Other>> > = dummy>
815 friend FLOAT_T<mpfr_t> operator /(const FLOAT_T<mpfr_t>& _lhs, const Other& _rhs)
817 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
819 mpfr_div(res.mValue, _lhs.mValue, FLOAT_T<mpfr_t>(_rhs).mValue, MPFR_RNDN);
823 friend FLOAT_T<mpfr_t>& operator++(FLOAT_T<mpfr_t>& _num)
825 mpfr_add_ui(_num.mValue, _num.mValue, 1, MPFR_RNDN);
829 friend FLOAT_T<mpfr_t>& operator--(FLOAT_T<mpfr_t>& _num)
831 mpfr_sub_ui(_num.mValue, _num.mValue, 1, MPFR_RNDN);
835 FLOAT_T<mpfr_t>& operator +=(const FLOAT_T<mpfr_t>& _rhs)
837 mpfr_add(mValue, mValue, _rhs.mValue, MPFR_RNDN);
841 FLOAT_T<mpfr_t>& operator +=(const mpfr_t& _rhs)
843 mpfr_add(mValue, mValue, _rhs, MPFR_RNDN);
847 FLOAT_T<mpfr_t>& operator -=(const FLOAT_T<mpfr_t>& _rhs)
849 mpfr_sub(mValue,mValue, _rhs.mValue, MPFR_RNDN);
853 FLOAT_T<mpfr_t>& operator -=(const mpfr_t& _rhs)
855 mpfr_sub(mValue,mValue, _rhs, MPFR_RNDN);
859 FLOAT_T<mpfr_t> operator-()
862 mpfr_mul_si(res.mValue, this->mValue, -1, MPFR_RNDN);
866 FLOAT_T<mpfr_t>& operator *=(const FLOAT_T<mpfr_t>& _rhs)
868 mpfr_mul(mValue, mValue, _rhs.mValue, MPFR_RNDN);
872 FLOAT_T<mpfr_t>& operator *=(const mpfr_t& _rhs)
874 mpfr_mul(mValue, mValue, _rhs, MPFR_RNDN);
878 FLOAT_T<mpfr_t>& operator /=(const FLOAT_T<mpfr_t>& _rhs)
880 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
881 mpfr_div(mValue, mValue, _rhs.mValue, MPFR_RNDN);
885 FLOAT_T<mpfr_t>& operator /=(const mpfr_t& _rhs)
887 // TODO: mpfr_div results in infty when dividing by zero, although this should not be defined.
888 mpfr_div(mValue, mValue, _rhs, MPFR_RNDN);
893 * Auxiliary Functions
896 std::string toString() const
898 // TODO: Better rounding mode?
901 // str << mpfr_get_d(mValue, MPFR_RNDN);
902 mpfr_sprintf(out, "%.50RDe", mValue);
903 return std::string(out);
906 static void integerDistance(const FLOAT_T<mpfr_t>& a, const FLOAT_T<mpfr_t>& b, mpz_t& dist) {
907 distance(a.value(), b.value(), dist);
910 inline static std::size_t bits2digits(precision_t b) {
911 const double LOG10_2 = 0.30102999566398119;
912 return std::size_t(std::floor( double(b) * LOG10_2 ));
921 mpfr_prec_t convPrec(precision_t _prec) const
927 * @brief Converts a given float to its integer representation
928 * @details This function converts a mpfr float to a corresponding integer representation. This is done as follows:
929 * We can use a transformation similar to the one used for c++ doubles (with modifications). We use the mantissa and extend
930 * it by the exponent (we left-shift the exponent in front of the mantissa) and add the sign. This can be interpreted as an
931 * integer. Note that zero is a special case, which should be handled separately.
933 * @param intRep Parameter where we write the integer to.
934 * @param a input mpfr float.
936 static void to_int(mpz_t& intRep, const mpfr_t a) {
938 //std::cout << "Bits per limb " << mp_bits_per_limb << std::endl;
939 //std::cout << "Number limbs " << std::ceil(double(a->_mpfr_prec)/double(mp_bits_per_limb)) << std::endl;
940 //std::cout << "Precision is " << a->_mpfr_prec << std::endl;
941 //std::cout << "Sign is " << a->_mpfr_sign << std::endl;
942 //std::cout << "Exponent is " << carl::binary(a->_mpfr_exp) << std::endl;
943 //std::cout << "Exponent is " << a->_mpfr_exp << std::endl;
944 //std::cout << "Min Exponent is " << mpfr_get_emin() << std::endl;
945 //std::cout << "Min Exponent is " << carl::binary(mpfr_get_emin()) << std::endl;
946 //std::cout << "Scaled exponent: " << (a->_mpfr_exp + std::abs(mpfr_get_emin())) << std::endl;
947 //std::cout << "Scaled exponent: " << carl::binary((a->_mpfr_exp + std::abs(mpfr_get_emin()))) << std::endl;
949 // mpfr mantissa is stored in limbs (usually 64-bit words) - the number of those depends on the precision.
950 std::size_t limbs = (std::size_t)std::ceil(double(a->_mpfr_prec)/double(mp_bits_per_limb));
952 std::cout << "Mantissa is ";
954 std::cout << carl::binary(h->_mpfr_d[limbs-1]) << " " << std::endl;
957 std::cout << std::endl;
958 limbs = std::ceil(double(h->_mpfr_prec)/double(mp_bits_per_limb));
966 // as mpfr uses whole limbs (64-bit) we can cut away the additional zeroes (offset), if there are any
967 long offset = mp_bits_per_limb - (a->_mpfr_prec % mp_bits_per_limb);
968 //std::cout << "Offset is " << offset << " bits" << std::endl;
969 //std::cout << "Mantissa is ";
972 // assemble the integer representation of the mantissa. The limbs are stored in reversed order, least significant first.
974 mpz_set_ui(tmp, a->_mpfr_d[limbs-1]);
975 //std::cout << "Shift: " << (mp_bits_per_limb*(limbs-1)) << " bits" << std::endl;
976 mpz_mul_2exp(tmp, tmp, ((std::size_t)mp_bits_per_limb*(limbs-1)));
977 mpz_add(mant, mant, tmp);
980 // cut away unnecessary zeroes at the end (divide by 2^offset -> left-shift).
981 mpz_cdiv_q_2exp(mant, mant, offset);
983 //mpz_get_str(outStr, 2,mant);
984 //std::cout << "Mantissa: " << std::string(outStr) << std::endl;
986 // set the exponent (8-bit), as it is in 2s complement, subtract the minimum to shift the exponent and get exponents ordered,
987 // right shift to put it before the mantissa later.
988 mpz_set_ui(tmp, (a->_mpfr_exp + std::abs(mpfr_get_emin())));
989 //std::cout << "Shift by " << (std::ceil(double(h->_mpfr_prec)/double(mp_bits_per_limb))*64+64-offset) << " bits" << std::endl;
990 mpz_mul_2exp(tmp,tmp,a->_mpfr_prec);
992 // assemble the whole representation by addition and finally add sign.
993 mpz_add(mant,mant,tmp);
994 mpz_mul_si(mant,mant,a->_mpfr_sign);
995 mpz_set(intRep, mant);
997 mpz_get_str(outStr, 2,mant);
998 std::cout << std::string(outStr) << std::endl;
999 mpz_get_str(outStr, 10,mant);
1000 std::cout << std::string(outStr) << std::endl;
1009 * @brief Calculates the distance in ULPs between two mpfr floats a and b.
1010 * @details We use an integer representation for calculating the distance. Special cases are whenever we reach or cross
1011 * zero. TODO: Include cases for NaN and INFTY.
1016 * @return [description]
1018 static void distance(const mpfr_t& a, const mpfr_t& b, mpz_t& dist) {
1019 // initialize variables
1025 // the offset is used to cope with the exponent differences
1026 long offset = a->_mpfr_exp - b->_mpfr_exp;
1027 //std::cout << "Offset " << offset << std::endl;
1029 // get integer representations, we use absolute values for simplicity.
1032 mpz_abs(intRepA, intRepA);
1033 mpz_abs(intRepB, intRepB);
1035 // case distinction to cope with zero.
1036 if(mpfr_zero_p(a) != 0) { // a is zero
1037 if(mpfr_zero_p(b) != 0){ // b is also zero
1041 // b is not zero -> we compute the distance from close to zero to b and add 1.
1044 mpfr_init2(zero,mpfr_get_prec(a));
1045 mpz_init(intRepZero);
1047 mpfr_set_ui(zero,0, MPFR_RNDZ);
1048 if(b->_mpfr_sign > 0) {
1049 mpfr_nextabove(zero);
1051 mpfr_nextbelow(zero);
1054 to_int(intRepZero, zero);
1055 mpz_abs(intRepZero, intRepZero);
1056 mpz_sub(dist, intRepB,intRepZero);
1057 mpz_add_ui(dist,dist, 1);
1060 mpz_clear(intRepZero);
1062 } else if(mpfr_zero_p(b) != 0) { // a is not zero, b is zero
1065 mpfr_init2(zero,mpfr_get_prec(a));
1066 mpz_init(intRepZero);
1068 mpfr_set_ui(zero,0, MPFR_RNDZ);
1069 if(a->_mpfr_sign > 0) {
1070 mpfr_nextabove(zero);
1072 mpfr_nextbelow(zero);
1075 to_int(intRepZero, zero);
1076 mpz_abs(intRepZero, intRepZero);
1077 mpz_sub(dist, intRepA,intRepZero);
1078 mpz_add_ui(dist,dist, 1);
1081 mpz_clear(intRepZero);
1082 } else if(a->_mpfr_sign == b->_mpfr_sign) { // both are not zero and at the same side
1083 mpz_sub(dist, intRepA, intRepB);
1085 } else { // both are not zero and one is larger, the other one is less zero, compute both dists to zero and add 2.
1087 mpfr_init2(zeroA,mpfr_get_prec(a));
1089 mpfr_init2(zeroB,mpfr_get_prec(a));
1091 mpfr_set_ui(zeroA,0, MPFR_RNDZ);
1092 mpfr_set_ui(zeroB,0, MPFR_RNDZ);
1094 if(a->_mpfr_sign > 0) {
1095 mpfr_nextabove(zeroA);
1096 mpfr_nextbelow(zeroB);
1098 mpfr_nextbelow(zeroA);
1099 mpfr_nextabove(zeroB);
1102 mpz_init(intRepZeroA);
1104 mpz_init(intRepZeroB);
1108 to_int(intRepZeroA, zeroA);
1109 mpz_abs(intRepZeroA, intRepZeroA);
1110 to_int(intRepZeroB, zeroB);
1111 mpz_abs(intRepZeroB, intRepZeroB);
1113 mpz_sub(dist, intRepA,intRepZeroA);
1114 mpz_sub(d2, intRepB,intRepZeroB);
1115 mpz_add(dist, dist, d2);
1116 mpz_add_ui(dist,dist, 2);
1120 mpz_clear(intRepZeroA);
1121 mpz_clear(intRepZeroB);
1124 //std::cout << "Modify by " << 2*std::abs(offset)*a->_mpfr_prec << std::endl;
1126 // shift by offset (exponent differences).
1127 long shift = 2*std::abs(offset)*unsigned(a->_mpfr_prec);
1128 mpz_sub_ui(dist, dist, shift);
1136 inline bool isInfinity(const FLOAT_T<mpfr_t>& _in) {
1137 return (mpfr_inf_p(_in.value()) != 0);
1141 inline bool isNan(const FLOAT_T<mpfr_t>& _in) {
1142 return (mpfr_nan_p(_in.value()) != 0);
1146 inline bool AlmostEqual2sComplement<FLOAT_T<mpfr_t>>(const FLOAT_T<mpfr_t>& A, const FLOAT_T<mpfr_t>& B, unsigned maxUlps)
1148 //std::cout << "Distance: " << FLOAT_T<mpfr_t>::integerDistance(A,B) << std::endl;
1151 FLOAT_T<mpfr_t>::integerDistance(A,B,distance);
1152 mpz_sub_ui(distance, distance, maxUlps);
1153 bool less = (mpz_sgn(distance) <= 0);
1154 mpz_clear(distance);
1163 struct hash<carl::FLOAT_T<mpfr_t>> {
1164 size_t operator()(const carl::FLOAT_T<mpfr_t>& _in) const {
1166 __mpfr_struct numStruct = *_in.value();
1167 std::size_t limbs = (std::size_t)std::ceil(double(numStruct._mpfr_prec)/double(mp_bits_per_limb));
1170 //std::cout << "start hash" << std::endl;
1171 //std::cout << "seed: " << seed << std::endl;
1172 if(mpfr_number_p(_in.value()) && mpfr_zero_p(_in.value()) == 0){
1174 carl::hash_add(seed,numStruct._mpfr_d[limbs-1]);
1175 //std::cout << "seed: " << seed << std::endl;
1179 //std::cout << "seed: " << seed << std::endl;
1180 if(mpfr_nan_p(_in.value()) == 0){
1181 carl::hash_add(seed, size_t(numStruct._mpfr_sign));
1183 //std::cout << "seed: " << seed << std::endl;
1184 carl::hash_add(seed, size_t(numStruct._mpfr_prec));
1185 //std::cout << "seed: " << seed << std::endl;
1186 carl::hash_add(seed, size_t(numStruct._mpfr_exp));
1187 //std::cout << "seed: " << seed << std::endl;
1188 //std::cout << "end hash" << std::endl;
1194 class numeric_limits<carl::FLOAT_T<mpfr_t>>
1197 static const bool is_specialized = true;
1198 static const bool is_signed = true;
1199 static const bool is_integer = false;
1200 static const bool is_exact = false;
1201 static const int radix = 2;
1203 static const bool has_infinity = true;
1204 static const bool has_quiet_NaN = true;
1205 static const bool has_signaling_NaN = true;
1207 static const bool is_iec559 = true; // = IEEE 754
1208 static const bool is_bounded = true;
1209 static const bool is_modulo = false;
1210 static const bool traps = true;
1211 static const bool tinyness_before = true;
1213 static const float_denorm_style has_denorm = denorm_absent;
1216 inline static carl::FLOAT_T<mpfr_t> (min) (carl::CARL_RND _rnd = carl::CARL_RND::N, carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision()) { return carl::FLOAT_T<mpfr_t>::minval(_rnd, precision); }
1217 inline static carl::FLOAT_T<mpfr_t> (max) (carl::CARL_RND _rnd = carl::CARL_RND::N, carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision()) { return carl::FLOAT_T<mpfr_t>::maxval(_rnd, precision); }
1218 inline static carl::FLOAT_T<mpfr_t> lowest (carl::CARL_RND _rnd = carl::CARL_RND::N, carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision()) { return -carl::FLOAT_T<mpfr_t>::maxval(_rnd, precision); }
1220 // Returns smallest eps such that 1 + eps != 1 (classic machine epsilon)
1221 inline static carl::FLOAT_T<mpfr_t> epsilon(carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision()) { return carl::FLOAT_T<mpfr_t>::machine_epsilon(precision); }
1223 // Returns smallest eps such that x + eps != x (relative machine epsilon)
1224 inline static carl::FLOAT_T<mpfr_t> epsilon(const carl::FLOAT_T<mpfr_t>& x) { return carl::FLOAT_T<mpfr_t>::machine_epsilon(x); }
1226 inline static carl::FLOAT_T<mpfr_t> round_error(carl::CARL_RND _rnd = carl::CARL_RND::N, carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision()) { return carl::FLOAT_T<mpfr_t>(0.5, _rnd, precision); }
1228 inline static const carl::FLOAT_T<mpfr_t> infinity() { return carl::FLOAT_T<mpfr_t>::const_infinity(); }
1230 inline static const carl::FLOAT_T<mpfr_t> quiet_NaN() { return carl::FLOAT_T<mpfr_t>().setNan(); }
1231 inline static const carl::FLOAT_T<mpfr_t> signaling_NaN() { return carl::FLOAT_T<mpfr_t>().setNan(); }
1232 inline static const carl::FLOAT_T<mpfr_t> denorm_min() { return (min)(); }
1234 // Please note, exponent range is not fixed in MPFR
1235 static const int min_exponent = MPFR_EMIN_DEFAULT;
1236 static const int max_exponent = MPFR_EMAX_DEFAULT;
1237 static const int min_exponent10 = (int) (MPFR_EMIN_DEFAULT * 0.3010299956639811);
1238 static const int max_exponent10 = (int) (MPFR_EMAX_DEFAULT * 0.3010299956639811);
1240 // Following members should be constant according to standard, but they can be variable in MPFR
1241 // So we define them as functions here.
1243 // This is preferable way for std::numeric_limits<carl::FLOAT_T<mpfr_t>> specialization.
1244 // But it is incompatible with standard std::numeric_limits and might not work with other libraries, e.g. boost.
1245 // See below for compatible implementation.
1246 inline static float_round_style round_style() { return round_to_nearest; }
1248 inline static std::size_t digits() { return std::size_t(carl::FLOAT_T<mpfr_t>::defaultPrecision()); }
1249 inline static std::size_t digits( const carl::FLOAT_T<mpfr_t>& x ) { return std::size_t(x.precision()); }
1251 inline static std::size_t digits10( carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision() ) { return carl::FLOAT_T<mpfr_t>::bits2digits(precision); }
1252 inline static std::size_t digits10( const carl::FLOAT_T<mpfr_t>& x ) { return carl::FLOAT_T<mpfr_t>::bits2digits(x.precision()); }
1253 inline static std::size_t max_digits10( carl::precision_t precision = carl::FLOAT_T<mpfr_t>::defaultPrecision() ) { return digits10(precision); }