lmi
[Top][All Lists]
Advanced

[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.)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]