[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Don't initialize constexpr variable with std::ldexp()
From: |
Greg Chicares |
Subject: |
Re: [lmi] Don't initialize constexpr variable with std::ldexp() |
Date: |
Thu, 31 Aug 2017 22:24:52 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 |
On 2017-04-24 16:16, Vadim Zeitlin wrote:
> On Mon, 24 Apr 2017 15:25:48 +0000 Greg Chicares <address@hidden> wrote:
[...]
> GC> However...
> GC>
> GC> static constexpr From limit = std::ldexp(From(1), to_traits::digits);
> GC>
> GC> In a dialect that includes P0533R0 [cited above], 'constexpr' is legal
> here,
> GC> and the question arises whether we should use 'static' as well.
> 'constexpr'
> GC> already requires that the value be computed at compile time (and used
> every
> GC> time the function is called), which is the reason we used 'static' above.
> GC> Thus, there's no reason to use 'static' in addition to 'constexpr' here.
>
> Yes.
>
> GC> But is there any reason not to use 'static' here?
>
> I think there is, and this reason is just that it's unnecessary, i.e.
> removing it doesn't affect the program behaviour in any way, but just makes
> it one word shorter, which is always a worthwhile optimization.
>
> GC> Is that your reasoning for suggesting s/static constexpr/static/g
> throughout
> GC> this header?
>
> I think the above is just a typo but, just to be sure, this is not what
> I'm suggesting: I'm rather suggesting "s/static constexpr/constexpr/g".
Another argument against 'static': with gcc-6.3.0 and '-std=c++17',
lmi compiles with no diagnostics except for this single line in
'bourn_cast.hpp':
static From const limit = std::ldexp(From(1), to_traits::digits);
which gives:
error: 'limit' declared 'static' in 'constexpr' function
Perhaps this is the reason:
https://stackoverflow.com/questions/38619259/literal-string-declared-static-in-constexpr-function
| You can't have static variables in constexpr functions currently.
| There is a proposal to relax that requirement if the variable is
| initialized with a compile time expression.
With this change:
- static From const limit = std::ldexp(From(1), to_traits::digits);
+ constexpr From limit = std::ldexp(From(1), to_traits::digits);
it compiles with both '-std=c++11' and '-std=c++17', and this change
doesn't materially affect speed according to the measurements below,
so I'm going to commit it and change to C++17 mode (even though
gcc-6.3.0's C++17 support is incomplete). Because this change works in
C++11 mode, there seems to be no good reason to make it conditional
on the value of __cplusplus.
Here are my timings (all of which use '-frounding-math' BTW)...
-std=c++11, original code:
static From const limit = std::ldexp(From(1), to_traits::digits);
static_cast<U>(S): 3.392e-004 s mean; 334 us least of 100 runs
bourn_cast<U>(S): 3.371e-004 s mean; 334 us least of 100 runs
bourn_cast<S>(U): 3.352e-004 s mean; 334 us least of 100 runs
static_cast<D>(U): 6.713e-004 s mean; 668 us least of 100 runs
bourn_cast<D>(U): 2.033e-003 s mean; 2005 us least of 100 runs
static_cast<U>(D): 2.473e-003 s mean; 2427 us least of 100 runs
bourn_cast<U>(D): 1.358e-002 s mean; 12934 us least of 74 runs
bourn_cast<S>(D): 6.824e-003 s mean; 6702 us least of 100 runs
static_cast<F>(D): 1.316e-003 s mean; 1287 us least of 100 runs
bourn_cast<F>(D): 3.797e-003 s mean; 3417 us least of 100 runs
bourn_cast<D>(F): 4.680e-003 s mean; 4595 us least of 100 runs
-std=c++11, new code:
constexpr From limit = std::ldexp(From(1), to_traits::digits);
static_cast<U>(S): 3.396e-004 s mean; 334 us least of 100 runs
bourn_cast<U>(S): 3.361e-004 s mean; 334 us least of 100 runs
bourn_cast<S>(U): 3.343e-004 s mean; 334 us least of 100 runs
static_cast<D>(U): 6.710e-004 s mean; 668 us least of 100 runs
bourn_cast<D>(U): 2.014e-003 s mean; 2004 us least of 100 runs
static_cast<U>(D): 2.656e-003 s mean; 2589 us least of 100 runs
bourn_cast<U>(D): 1.349e-002 s mean; 12878 us least of 75 runs
bourn_cast<S>(D): 6.664e-003 s mean; 6284 us least of 100 runs
static_cast<F>(D): 1.263e-003 s mean; 1207 us least of 100 runs
bourn_cast<F>(D): 3.897e-003 s mean; 3204 us least of 100 runs
bourn_cast<D>(F): 4.941e-003 s mean; 4595 us least of 100 runs
-std=c++17, new code:
constexpr From limit = std::ldexp(From(1), to_traits::digits);
static_cast<U>(S): 3.152e-004 s mean; 313 us least of 100 runs
bourn_cast<U>(S): 3.135e-004 s mean; 313 us least of 100 runs
bourn_cast<S>(U): 3.152e-004 s mean; 313 us least of 100 runs
static_cast<D>(U): 6.272e-004 s mean; 626 us least of 100 runs
bourn_cast<D>(U): 1.880e-003 s mean; 1879 us least of 100 runs
static_cast<U>(D): 2.483e-003 s mean; 2427 us least of 100 runs
bourn_cast<U>(D): 1.294e-002 s mean; 12880 us least of 78 runs
bourn_cast<S>(D): 6.287e-003 s mean; 6284 us least of 100 runs
static_cast<F>(D): 1.212e-003 s mean; 1206 us least of 100 runs
bourn_cast<F>(D): 5.204e-003 s mean; 4386 us least of 100 runs
bourn_cast<D>(F): 5.081e-003 s mean; 4595 us least of 100 runs
Only conversions from floating to integral are affected by the code
change--i.e., the third of four "paragraphs" of timings, which all
appear to be equivalent. (The only significant change seems to be in
the bourn_cast<F>(D) conversion on the second-to-last line, which
takes about one-third longer with '-std=c++17', but I don't see that
as a strong reason not to use C++17 mode.)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [lmi] Don't initialize constexpr variable with std::ldexp(),
Greg Chicares <=