[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-07 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

Jonathan Wakely  changed:

   What|Removed |Added

   Target Milestone|--- |13.3

--- Comment #7 from Jonathan Wakely  ---
Fixed on trunk so far.

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-07 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

--- Comment #6 from GCC Commits  ---
The master branch has been updated by Jonathan Wakely :

https://gcc.gnu.org/g:5f9d7a5b6cf64639274e63051caf70fbc8418ea2

commit r14-9376-g5f9d7a5b6cf64639274e63051caf70fbc8418ea2
Author: Jonathan Wakely 
Date:   Thu Mar 7 13:15:41 2024 +

libstdc++: Fix parsing of fractional seconds [PR114244]

When converting a chrono::duration to a result type with an
integer representation we should use chrono::round<_Duration> so that we
don't truncate towards zero. Rounding ensures that e.g. 0.001999s
becomes 2ms not 1ms.

We can also remove some redundant uses of chrono::duration_cast to
convert from seconds to _Duration, because the _Parser class template
requires _Duration type to be able to represent seconds without loss of
precision.

This also fixes a bug where no fractional part would be parsed for
chrono::duration because its period is ratio<1>. We should
also consider treat_as_floating_point when deciding whether to skip
reading a fractional part.

libstdc++-v3/ChangeLog:

PR libstdc++/114244
* include/bits/chrono_io.h (_Parser::operator()): Remove
redundant uses of duration_cast. Use chrono::round to convert
long double value to durations with integer representations.
Check represenation type when deciding whether to skip parsing
fractional seconds.
* testsuite/20_util/duration/114244.cc: New test.
* testsuite/20_util/duration/io.cc: Check that a floating-point
duration with ratio<1> precision can be parsed.

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-06 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

--- Comment #5 from Jonathan Wakely  ---
Yup, that's what I have in my local tree now.

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-06 Thread howard.hinnant at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

--- Comment #4 from Howard Hinnant  ---
Not positive (because I don't know your code that well), but I think:

  __s = round<_Duration>(__fs);

will do it.

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-06 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

--- Comment #3 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #1)
> Yup, the seconds part "00.002" is parsed using std::numpunct (in order to

Oops, std::num_get obviously.

> handle the locale's decimal point) and then converted to milliseconds using
> duration_cast:
> 
> auto& __ng = use_facet>(__loc);
> long double __val;
> ios_base::iostate __err2{};
> __ng.get(__buf, {}, __buf, __err2, __val);
> if (__is_failed(__err2)) [[unlikely]]
>   __err |= __err2;
> else
>   {
> duration __fs(__val);
> __s = duration_cast<_Duration>(__fs);
>   }

As an unrelated optimization, when the locale is "C" we could use
std::from_chars or std::stod instead of std::num_get.

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-06 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

--- Comment #2 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #1)
> and another duration_cast in chrono::from_stream for durations. That one
> could be used with either integral or floating-point reps.

Ah, but we're converting from common_type_t to Duration, so
either it's float-to-float or integer-to-integer, and duration_cast is OK if
we're fine with truncating.

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-06 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

--- Comment #1 from Jonathan Wakely  ---
Yup, the seconds part "00.002" is parsed using std::numpunct (in order to
handle the locale's decimal point) and then converted to milliseconds using
duration_cast:

  auto& __ng = use_facet>(__loc);
  long double __val;
  ios_base::iostate __err2{};
  __ng.get(__buf, {}, __buf, __err2, __val);
  if (__is_failed(__err2)) [[unlikely]]
__err |= __err2;
  else
{
  duration __fs(__val);
  __s = duration_cast<_Duration>(__fs);
}


We also use duration_cast when parsing %c and %X using std::time_get, but
that's an integer conversion there (but the duration_cast should have been
qualified to prevent ADL):

  __h = hours(__tm.tm_hour);
  __min = minutes(__tm.tm_min);
  __s = duration_cast<_Duration>(seconds(__tm.tm_sec));

and another duration_cast in chrono::from_stream for durations. That one could
be used with either integral or floating-point reps.

Do we want to parse "00:00:31" as minutes(1)? I don't think we do, so only the
first case where converting long double to milliseconds should be rounded?

[Bug libstdc++/114244] Need to use round when parsing fractional seconds

2024-03-05 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244

Jonathan Wakely  changed:

   What|Removed |Added

 Ever confirmed|0   |1
 Status|UNCONFIRMED |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |redi at gcc dot gnu.org
   Last reconfirmed||2024-03-05