I am wondering what is the most portable way of checking whether right shift is arithmetic when operating for on signed types (e.g. whether -2 >> 1
is -1
) at compile-time.
My idea is to check this somehow on compile time and be able to detect this, so I can compile different versions of the function (depending whether the operator >>
is really arithmetic shift or not).
By reading the topic Verifying that C / C++ signed right shift is arithmetic for a particular compiler? I came to the idea to initialize a flag
static const bool is_arithmetic_rs = (((signed int)-1)>>1) == ((signed int)-1));
and to test it at run-time like this:
if (is_arithmetic_rs) {
// some fast algorithm using arithmetic right shifts (using >> operator)
} else {
// the same algorithm without arithmetic right shifts (much slower)
}
However, I would like to avoid this branching if possible every time. For simplicity, let's suppose I want to implement a portable arithmetic right shift; if I had to check this every time a function is called, this would be a huge performance impact, so I would like to do it at compile time, if possible.
If there exist no portable way of doing this check, is there a way to do this by checking on the best-effort basis, like checking with ifdefs for a specific compiler/platform?
The best way to perform such checks is what e.g. GNU autotools do:
Compile a small program on your target platform and test what happens
Set an appropriate #define
in a header file
Include that header file in your source files
Optionally, use appropriately defined macros so that you don't clutter your code with #ifdef
directives for every little thing.
Compile your main project
That way you avoid having to create tables with the supported features and the various quirks of each hardware platform and operating system in the wild - let alone their combinations. If you do not build your code on your target, however, you will have to replace the first step with a pre-supplied table/list of features for your target.
You should probably have a look at widely used build systems such as GNU autotools or CMake, in order to reuse existing macros and platform-specific information and avoid having to create your own and therefore reinvent the wheel.
BTW, any decent compiler these days should optimise-out simple tests with constant expressions, so using a runtime test where necessary - perhaps through a macro - should not hurt performance too much. You should test and profile your code to find out.
The branch could be avoided by using a preprocessing-time test
#if ((-1)>>1) == (-1))
...
#else
...
#endif
Really more of a comment than answer (but apparently I'm not reputable)
A couple of the answers here use pre-processor checks like
#if ((-1)>>1) == (-1))
Personally, I wouldn't trust the pre-processor to tell me what kind of code the compiler generates.
Have you actually verified that your compiler doesn't optimize division into arithmetic shift when it's available?
Otherwise I think you can use templates.
template <bool B>
void do_work();
template <>
void do_work<true>()
{
// Do stuff with H/W.
}
template <>
void do_work<false>()
{
// Do slow stuff with S/W.
}
do_work<(-2 >> 1) == -1>();
Then make it prettier to use with an inline function:
inline real_do_work()
{
do_work<(-2 >> 1) == -1>();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With