public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-1753] libstdc++: More efficient std::chrono::year::leap
@ 2021-06-23 17:29 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2021-06-23 17:29 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:b92d12d3fe3f1aa56d190d960e40c62869a6cfbb

commit r12-1753-gb92d12d3fe3f1aa56d190d960e40c62869a6cfbb
Author: Cassio Neri <cassio.neri@gmail.com>
Date:   Wed Jun 23 15:32:16 2021 +0100

    libstdc++: More efficient std::chrono::year::leap
    
    Simple change to std::chrono::year::is_leap. If a year is multiple of 100,
    then it's divisible by 400 if and only if it's divisible by 16. The latter
    allows for better code generation.
    
    The expression is then either y%16 or y%4 which are both powers of two
    and so it can be rearranged to use simple bitmask operations.
    
    Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
    Co-authored-by: Ulrich Drepper <drepper@redhat.com>
    
    libstdc++-v3/ChangeLog:
    
            * include/std/chrono (chrono::year::is_leap()): Optimize.

Diff:
---
 libstdc++-v3/include/std/chrono | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 4631a727d73..863b6a27bdf 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -1606,13 +1606,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	// [1] https://github.com/cassioneri/calendar
 	// [2] https://accu.org/journals/overload/28/155/overload155.pdf#page=16
 
+	// Furthermore, if y%100 != 0, then y%400==0 is equivalent to y%16==0,
+	// so we can rearrange the expression to (mult_100 ? y % 4 : y % 16)==0
+	// which is equivalent to (y & (mult_100 ? 15 : 3)) == 0.
+	// See https://gcc.gnu.org/pipermail/libstdc++/2021-June/052815.html
+
 	constexpr uint32_t __multiplier   = 42949673;
 	constexpr uint32_t __bound        = 42949669;
 	constexpr uint32_t __max_dividend = 1073741799;
 	constexpr uint32_t __offset       = __max_dividend / 2 / 100 * 100;
 	const bool __is_multiple_of_100
 	  = __multiplier * (_M_y + __offset) < __bound;
-	return (!__is_multiple_of_100 || _M_y % 400 == 0) && _M_y % 4 == 0;
+	return (_M_y & (__is_multiple_of_100 ? 15 : 3)) == 0;
       }
 
       explicit constexpr


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-06-23 17:29 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-23 17:29 [gcc r12-1753] libstdc++: More efficient std::chrono::year::leap Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).