Opened 11 years ago

Closed 11 years ago

#6092 closed Bugs (fixed)

input from non integral durations makes the compiler fail

Reported by: viboes Owned by: viboes
Milestone: Boost 1.49.0 Component: chrono
Version: Boost 1.47.0 Severity: Problem
Keywords: Cc:

Description

The following input

1.0 seconds

makes the compiler fails when trying to extract the duration

duration<double,milli> d;

cin >> d;

../../../boost/math/common_factor_rt.hpp: In function ‘RingType boost::math::detail::gcd_euclidean(RingType, RingType) [with RingType = long double]’:
../../../boost/math/common_factor_rt.hpp:122: instantiated from ‘IntegerType boost::math::detail::gcd_integer(const IntegerType&, const IntegerType&) [with IntegerType = long double]’
../../../boost/math/common_factor_rt.hpp:240: instantiated from ‘T boost::math::detail::gcd_optimal_evaluator_helper_t<T, true, true>::operator()(const T&, const T&) [with T = long double]’
../../../boost/math/common_factor_rt.hpp:290: instantiated from ‘T boost::math::detail::gcd_optimal_evaluator<T>::operator()(const T&, const T&) [with T = long double]’
../../../boost/math/common_factor_rt.hpp:442: instantiated from ‘T boost::math::detail::gcd_optimal(const T&, const T&) [with T = long double]’
../../../boost/math/common_factor_rt.hpp:473: instantiated from ‘typename boost::math::gcd_evaluator<IntegerType>::result_type boost::math::gcd_evaluator<IntegerType>::operator()(const IntegerType&, const IntegerType&) const [with IntegerType = long double]’
../../../boost/math/common_factor_rt.hpp:505: instantiated from ‘IntegerType boost::math::gcd(const IntegerType&, const IntegerType&) [with IntegerType = long double]’
../../../boost/chrono/io/duration_get.hpp:239: instantiated from ‘InputIterator boost::chrono::duration_get<CharT, InputIterator>::get(InputIterator, InputIterator, std::ios_base&, std::_Ios_Iostate&, boost::chrono::duration<Rep2, Period2>&, const CharT*, const CharT*) const [with Rep = double, Period = boost::ratio<1l, 1l>, CharT = char, InputIterator = std::istreambuf_iterator<char, std::char_traits<char> >]’
../../../boost/chrono/io/duration_get.hpp:294: instantiated from ‘InputIterator boost::chrono::duration_get<CharT, InputIterator>::get(InputIterator, InputIterator, std::ios_base&, std::_Ios_Iostate&, boost::chrono::duration<Rep2, Period2>&) const [with Rep = double, Period = boost::ratio<1l, 1l>, CharT = char, InputIterator = std::istreambuf_iterator<char, std::char_traits<char> >]’
../../../boost/chrono/io/duration_io.hpp:593: instantiated from ‘std::basic_istream<_CharT, _Traits>& boost::chrono::operator>>(std::basic_istream<_CharT, _Traits>&, boost::chrono::duration<Rep2, Period2>&) [with CharT = char, Traits = std::char_traits<char>, Rep = double, Period = boost::ratio<1l, 1l>]’
io/duration_input.cpp:15: instantiated from ‘void test_good(const char*, D) [with D = boost::chrono::duration<double, boost::ratio<1l, 1l> >]’
io/duration_input.cpp:52: instantiated from here
../../../boost/math/common_factor_rt.hpp:102: error: invalid operands of types ‘long double’ and ‘long double’ to binary ‘operator%’
../../../boost/math/common_factor_rt.hpp:102: error: in evaluation of ‘operator%=(long double, long double)’
../../../boost/math/common_factor_rt.hpp:106: error: invalid operands of types ‘long double’ and ‘long double’ to binary ‘operator%’
../../../boost/math/common_factor_rt.hpp:106: error: in evaluation of ‘operator%=(long double, long double)’

This is because the common type is a double and gcd doesn't works for it.

// if (is_integral<intermediate_type>::value)
// {
// // Reduce r * num / den
// common_type_t t = math::gcd<common_type_t>(r, den);
// r /= t;
// den /= t;
// if (den != 1)
// {
// // Conversion to Period is integral and not exact
// is.setstate(is.failbit);
// return is;
// }
// }

This code could be replaced by a template to avoid the bad code to be instantiated.

template <typename intermediate_type>
typename enable_if<is_integral<intermediate_type>, bool>::type
reduce(intermediate_type& r, unsigned long long& den, std::ios_base::iostate& err)
{
typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;

// Reduce r * num / den
common_type_t t = math::gcd<common_type_t>(common_type_t(r), common_type_t(den));
r /= t;
den /= t;
if (den != 1)
{
// Conversion to Period is integral and not exact
err |= std::ios_base::failbit;
return false;
}
return true;
}
template <typename intermediate_type>
typename disable_if<is_integral<intermediate_type>, bool>::type
reduce(intermediate_type& , unsigned long long& , std::ios_base::iostate& )
{
return true;
}

Change History (3)

comment:1 by viboes, 11 years ago

Status: newassigned

Fixed in trunk r75237.

comment:2 by viboes, 11 years ago

Milestone: To Be DeterminedBoost 1.49.0

comment:3 by viboes, 11 years ago

Resolution: fixed
Status: assignedclosed

(In [75665]) Chrono: Fix #6092,#6093,#6113

Note: See TracTickets for help on using tickets.