The details of fixed-point and floating-point formats require an understanding of sign-magnitude, two’s complement, and offset-binary signed number representations.
But looks like sm7_from_offset128 contains a mistake. Excerpt from "Table of conversions from 8-bit offset-128": (Edit: sorry, looks like substack doesn't support code snippet formatting)
This seems to suggest that 1 in offset-128 (0x81) is also represented as 0x81 in sm7. But of course the sign-magnitude representation for 1 is 0x01, as I confirmed using the "Table of 8-bit sign-magnitude values" (Oh, and looks like the u value is also wrong in the excerpt above)
| hex | bin | s | m | value |
|------|----------|---|-----|-------|
| 0x01 | 00000001 | 0 | 1 | 1 |
Looks like the implementation was intended to flip the sign bit to convert to two's-complement, then use the same conversion strategy as sm7_from_int8. But on the second reference to offset128, it was used it directly instead of the bit-flipped value. The corrected version should be
Huge thanks for writing this series!
But looks like sm7_from_offset128 contains a mistake. Excerpt from "Table of conversions from 8-bit offset-128": (Edit: sorry, looks like substack doesn't support code snippet formatting)
| hex | bin | value | u-128 | int8 | sm7 |
|------|----------|-------|---------|------|------|
| 0x81 | 10000001 | 1 | 127-128 | 0x01 | 0x81 |
This seems to suggest that 1 in offset-128 (0x81) is also represented as 0x81 in sm7. But of course the sign-magnitude representation for 1 is 0x01, as I confirmed using the "Table of 8-bit sign-magnitude values" (Oh, and looks like the u value is also wrong in the excerpt above)
| hex | bin | s | m | value |
|------|----------|---|-----|-------|
| 0x01 | 00000001 | 0 | 1 | 1 |
Looks like the implementation was intended to flip the sign bit to convert to two's-complement, then use the same conversion strategy as sm7_from_int8. But on the second reference to offset128, it was used it directly instead of the bit-flipped value. The corrected version should be
uint8_t
sm7_from_offset128( uint8_t offset128 )
{
int8_t s = (int8_t)(offset128^0x80) >> 7;
uint8_t m = ((offset128^0x80) ^ s)-s;
return (s & 0x80)|m;
}
which is just the expansion of
uint8_t
sm7_from_offset128( uint8_t offset128 )
{
return sm7_from_int8(int8_from_offset128(offset128));
}
Plugging that into the table generator, the problematic row is corrected
| hex | bin | value | u-128 | int8 | sm7 |
|------|----------|-------|---------|------|------|
| 0x81 | 10000001 | 1 | 127-128 | 0x01 | 0x01 |