0

I want to decode a GPS navigation message where some parameters are marked such that:

Parameters so indicated shall be two's complement, with the sign bit (+ or -) occupying the MSB

For example, I want to store a parameter af0 which has 22 number of bits, with bit 22 as the MSB. The parameter af0 has been decoded by me and now I need to perform the two's complement operation. I stored af0 using an uint32_t integer type.

There are also other parameters like IDOT which has 14 number of bits and I stored it using an uint16_t.

I'm not sure, but if I understand it correctly if have to check the MSB for 1 or 0. If it is 1 I can simply calculate the two's complement by negation (and casting) of the value, i.e. int32_t af0_i = -(int32_t)af0. If the MSB is 0 I just cast the value according: int32_t af0_i = (int32_t)af0.

Is this correct for uintX_t integer types? I also tried out: https://stackoverflow.com/a/34076866/6518689 but it didn't fixed my problem, the value remains the same.

Max
  • 17
  • 2
  • You are overlooking a tiny detail. Based on the description, the MSB is bit 22. Negating the entire `int` if bit 22 is set ...will not work. Your `int32_t` has 32 bits, not 22. You'll have ten more pesky bits in the way. You need to sign-extend bit 22 to bit 31, then simply check if the number is negative. The End. – Sam Varshavchik Jun 10 '20 at 15:06
  • But... *two's complement* doesn't use *the sign bit*... That's kinda the whole point of it. – Fureeish Jun 10 '20 at 15:06
  • Does this answer your question? [Sign extend a nine-bit number in C](https://stackoverflow.com/questions/5814072/sign-extend-a-nine-bit-number-in-c) It's for C but you can use the same code. I recommend the xor/subtract version, it does not rely on potentially-unreliable "shift into sign" or on "shift negative number right". Or you could pick [this duplicate](https://stackoverflow.com/q/42534749/555045) – harold Jun 10 '20 at 16:52

1 Answers1

0

af0_i = -(int32_t)af0 will not work as expected; it'll flip all the bits, whereas you need to sign-extend the MSB instead and keep the rest unchanged.

Let's assume you extracted the raw 22 bits into a 32-bit variable:

int32_t af0 = ... /* some 22-bit value, top 10 bits are 0 */;

So now bit 21 is the sign bit. But with int32_t the sign bit is bit 31 (technically two's complement isn't guaranteed until C++20).

So we can shift left by 10 bits and immediately back right, which will sign-extend it.

af0 <<= 10; af0 >>= 10;

The code above is guaranteed to sign-extend since C++20, and is implementation-defined before that (on x86 will work as expected, though you can add a static_assert for that).

rustyx
  • 80,671
  • 25
  • 200
  • 267