mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-02-01 20:52:09 +00:00
Fix assignment operations to be safe after a move.
Added test cases to catch bug case. Refs #8667. [SVN r84687]
This commit is contained in:
@@ -1015,8 +1015,9 @@ struct gmp_int
|
||||
explicit gmp_int(const gmp_rational& o);
|
||||
gmp_int& operator = (const gmp_int& o)
|
||||
{
|
||||
if(o.m_data[0]._mp_d)
|
||||
mpz_set(m_data, o.m_data);
|
||||
if(m_data[0]._mp_d == 0)
|
||||
mpz_init(this->m_data);
|
||||
mpz_set(m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
@@ -1728,8 +1729,9 @@ struct gmp_rational
|
||||
}
|
||||
gmp_rational& operator = (const gmp_rational& o)
|
||||
{
|
||||
if(o.m_data[0]._mp_num._mp_d)
|
||||
mpq_set(m_data, o.m_data);
|
||||
if(m_data[0]._mp_den._mp_d == 0)
|
||||
mpq_init(m_data);
|
||||
mpq_set(m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
@@ -702,21 +702,29 @@ struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationTy
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpfr_t val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpf_t val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set_f(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpz_t val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set_z(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpq_t val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set_q(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
@@ -724,22 +732,30 @@ struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationTy
|
||||
template <unsigned D, mpfr_allocation_type AT>
|
||||
mpfr_float_backend& operator=(const mpfr_float_backend<D, AT>& val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
template <unsigned D>
|
||||
mpfr_float_backend& operator=(const gmp_float<D>& val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const gmp_int& val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const gmp_rational& val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
|
||||
mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
@@ -803,7 +819,10 @@ struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0
|
||||
|
||||
mpfr_float_backend& operator=(const mpfr_float_backend& o)
|
||||
{
|
||||
mpfr_set_prec(this->m_data, mpfr_get_prec(o.data()));
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, mpfr_get_prec(o.data()));
|
||||
else
|
||||
mpfr_set_prec(this->m_data, mpfr_get_prec(o.data()));
|
||||
mpfr_set(this->m_data, o.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
@@ -822,47 +841,67 @@ struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpfr_t val)
|
||||
{
|
||||
mpfr_set_prec(this->m_data, mpfr_get_prec(val));
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, mpfr_get_prec(val));
|
||||
else
|
||||
mpfr_set_prec(this->m_data, mpfr_get_prec(val));
|
||||
mpfr_set(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpf_t val)
|
||||
{
|
||||
mpfr_set_prec(this->m_data, mpf_get_prec(val));
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, mpf_get_prec(val));
|
||||
else
|
||||
mpfr_set_prec(this->m_data, mpf_get_prec(val));
|
||||
mpfr_set_f(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpz_t val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
|
||||
mpfr_set_z(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const mpq_t val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
|
||||
mpfr_set_q(this->m_data, val, GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
template <unsigned D>
|
||||
mpfr_float_backend& operator=(const mpfr_float_backend<D>& val)
|
||||
{
|
||||
mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, mpfr_get_prec(val.data()));
|
||||
else
|
||||
mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
|
||||
mpfr_set(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
template <unsigned D>
|
||||
mpfr_float_backend& operator=(const gmp_float<D>& val)
|
||||
{
|
||||
mpfr_set_prec(this->m_data, mpf_get_prec(val.data()));
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, mpf_get_prec(val.data()));
|
||||
else
|
||||
mpfr_set_prec(this->m_data, mpf_get_prec(val.data()));
|
||||
mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const gmp_int& val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
|
||||
mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
mpfr_float_backend& operator=(const gmp_rational& val)
|
||||
{
|
||||
if(this->m_data[0]._mpfr_d == 0)
|
||||
mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
|
||||
mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,36 @@ void test_std_lib()
|
||||
BOOST_TEST(b == 2);
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
void test_move_and_assign(T x, A val)
|
||||
{
|
||||
// move away from x, then assign val to x.
|
||||
T z(x);
|
||||
T y(std::move(x));
|
||||
x.assign(val);
|
||||
BOOST_CHECK_EQUAL(x, T(val));
|
||||
BOOST_CHECK_EQUAL(z, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_move_and_assign()
|
||||
{
|
||||
T x(23);
|
||||
test_move_and_assign(x, static_cast<short>(2));
|
||||
test_move_and_assign(x, static_cast<int>(2));
|
||||
test_move_and_assign(x, static_cast<long>(2));
|
||||
test_move_and_assign(x, static_cast<long long>(2));
|
||||
test_move_and_assign(x, static_cast<unsigned short>(2));
|
||||
test_move_and_assign(x, static_cast<unsigned int>(2));
|
||||
test_move_and_assign(x, static_cast<unsigned long>(2));
|
||||
test_move_and_assign(x, static_cast<unsigned long long>(2));
|
||||
test_move_and_assign(x, static_cast<float>(2));
|
||||
test_move_and_assign(x, static_cast<double>(2));
|
||||
test_move_and_assign(x, static_cast<long double>(2));
|
||||
test_move_and_assign(x, x);
|
||||
test_move_and_assign(x, "23");
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -131,6 +161,9 @@ int main()
|
||||
d = std::move(e);
|
||||
e = d;
|
||||
BOOST_TEST(e == d);
|
||||
|
||||
test_move_and_assign<mpfr_float>();
|
||||
test_move_and_assign<mpfr_float_50>();
|
||||
}
|
||||
#endif
|
||||
#ifdef TEST_GMP
|
||||
@@ -170,6 +203,9 @@ int main()
|
||||
d = std::move(e);
|
||||
e = d;
|
||||
BOOST_TEST(e == d);
|
||||
|
||||
test_move_and_assign<mpf_float>();
|
||||
test_move_and_assign<mpf_float_50>();
|
||||
}
|
||||
{
|
||||
test_std_lib<mpz_int>();
|
||||
@@ -194,6 +230,8 @@ int main()
|
||||
d = std::move(e);
|
||||
e = d;
|
||||
BOOST_TEST(e == d);
|
||||
|
||||
test_move_and_assign<mpz_int>();
|
||||
}
|
||||
{
|
||||
test_std_lib<mpq_rational>();
|
||||
@@ -217,6 +255,8 @@ int main()
|
||||
d = std::move(e);
|
||||
e = d;
|
||||
BOOST_TEST(e == d);
|
||||
|
||||
test_move_and_assign<mpq_rational>();
|
||||
}
|
||||
#endif
|
||||
#ifdef TEST_TOMMATH
|
||||
@@ -245,6 +285,8 @@ int main()
|
||||
d = std::move(e);
|
||||
e = d;
|
||||
BOOST_TEST(e == d);
|
||||
|
||||
test_move_and_assign<tom_int>();
|
||||
}
|
||||
#endif
|
||||
#ifdef TEST_CPP_INT
|
||||
@@ -273,6 +315,9 @@ int main()
|
||||
d = std::move(e);
|
||||
e = d;
|
||||
BOOST_TEST(e == d);
|
||||
|
||||
test_move_and_assign<cpp_int>();
|
||||
test_move_and_assign<int512_t>();
|
||||
}
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
|
||||
Reference in New Issue
Block a user