Quantcast
Channel: GameDev.net
Viewing all articles
Browse latest Browse all 17825

Well-defined shifts

$
0
0
This is basically a repost of http://www.gamedev.ru/flame/forum/?id=228402 . As many programmers know, there is quite a lot of undefined behavior in C++ shifts. So let's make our own ones! Since the task is relatively small, it seems worth doing WELL, to save everyone using it a bit of time. Motivation: 0. Well-defined semantics rulez. 1. For many cases (e. g. shifts by a constant) the result should be exactly the same as built-in shifts, with no performance penalty. 2. For many other cases performance does not matter. 3. If old code (with built-in shifts) worked, then, presumably the shift amount was always in the allowed range, and the branch in the new code would have essentially 100% prediction. 4. For the cases, where shifts are variable, and performance matters so much, that even predicted branches make difference (e. g. coding/decoding) - well there built-in shifts still remain. Hopefully, it is <5% of code. My present attempt: // This software is in the public domain. Where that dedication is not // recognized, you are granted a perpetual, irrevocable license to copy // and modify this file as you see fit. template<typename L,typename R> L shl(L value,R amount) { if(amount>=R(sizeof(L))*8) return L(0); if(amount<R(0)) { if(amount<=-R(sizeof(L))*8) { if(value<L(0)) return L(-1); return L(0); } return value>>(-amount); } return value<<amount; } template<typename L,typename R> L shr(L value,R amount) { if(amount>=R(sizeof(L))*8) { if(value<L(0)) return L(-1); return L(0); } if(amount<R(0)) { if(amount<=-R(sizeof(L))*8) return L(0); return value<<(-amount); } return value>>amount; } I subject it to scrutiny of the community. Basically, pretty please, check that all corner cases actually work. Quite a bit of trickery went into the writing this code, to satisfy the rules of C++. As you can imagine, there are A LOT of corner cases, and I am not confident everithing works correctly. Some useful links: http://www.gamedev.ru/flame/forum/?id=228402 - original post (in Russian) http://en.cppreference.com/w/cpp/language/operator_arithmetic - for language-lawering http://en.cppreference.com/w/cpp/language/implicit_cast#Integral_promotion - likewise http://rextester.com - for testing snippets http://gcc.godbolt.org - for testing assembly output P. S. Does anyone see a nice way to do it in C? Templates are C11, macros evaluate arguments multiple times, and lots of functions are ugly. I'm asking because it seems like a good candidate for inclusion into stb_* (right along with stb_divide.h), and maybe if we ask really nicely, Sean Barrett can do just that.

Viewing all articles
Browse latest Browse all 17825

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>