right shifting negative integers is tecnically undefined, this means that
the implementation used for encoding integers:
(n<<1)^(n>>(digits-1))
is tecnically undefined according to:
> The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits
> are zero-filled. If E1 has an unsigned type, the value of the result is E1
> × 2 E2, reduced modulo one more than the maximum value representable in the
> result type. Otherwise, if E1 has a signed type and non-negative value, and
> E1 × 2 E2 is representable in the corresponding unsigned type of the result
> type, then that value, converted to the result type, is the resulting
> value; otherwise, the behavior is undefined.
and the implementation for decoding:
(n>>1)^(-(n&1))
depends on the 2s complement as well and is probably tecnically undefined
(but I cant find a quote from the standard).
This is why I propose the following solution:
template<typename S,class U = typename std::make_unsigned<S>::type>>
U constexpr zigzag_encode(const S &n){
return (U(n)<<1)^(n<0?~U(0):U(0));
}
template<typename U,class S = typename std::make_signed<U>::type>>
S constexpr zigzag_decode(const U &n){
return (n&1)?-1-S(n>>1):(n>>1);
}
This does not look as cool, but modern compilers (llvm and gcc were tested)
will compile to bascially the same instructions, gcc will introduce 1
additional instruction for decode.
--
You received this message because you are subscribed to the Google Groups
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.