Bit compression ( two 8 bits in 13 bits register) - compression

I have two 8 bits data (For ex: A and B). But i have only 13 bits register. How can i save two 8 bits data ( A and B ) in 13 bits register by applying some algorithm ( C = A func B) so that i can reconstruct A and B from that saved C data..?

It is not possible to "compress" 16 bits in a 13 bits register and "decompress" them back to the original 16 bits. When you have 2^13 = 8192 possible values for your register C then you can have only 2^13 = 8192 possible combinations for the original registers A and B. You have only mappings for 8192 combinations, but are missing the remaining 57344 combinations (65536 - 8192 = 57344). This is somehow related to the pigeonhole principle.

Related

Understanding bitwise operations - shifting and AND

uint8_t payload[] = { 0, 0 };
pin5 = analogRead(A0);
payload[0] = pin5 >> 8 & 0xff;
payload[1] = pin5 & 0xff;
This is code from the XBee library published by andrewrapp on GitHub. I was wondering how the bitwise operation worked.
so suppose pin 5 gets an analog value of 256 which as I am using a particle photon board comes in a 12bit format text as 000100000000. so does payload[0] get the last eight bits ie 00000000, or does it get value after shifting ie, 00000001? Also then what becomes the value in payload[1]?
I want to add a 4-bit code of my on using a bitmask to the first four bits in the array followed by the data bits. Can I & payload[1] with a 0X1 to payload[1] for this?
The code in your example reverser the content of pin5's two bytes into payload array: the most significant byte is placed into payload[0] and the least significant byte is placed into payload[1].
If, for example, pin5 is 0x0A63, then payload would contain 0x63, 0x0A.
If pin5 has a 12-bit value, you can use its four most significant bits to store a four-bit value of your own. To make sure the upper bits are zeroed out, use 0x0F mask instead of 0xFF:
payload[0] = pin5 >> 8 & 0x0f;
// ^
Now you can move your data into the upper four bits with | operator:
payload[0] |= myFourBits << 4;
So you want to understand what the stated operations do. Let's have a look if we can clarify this, by examining the pin5 variable and subdividing it into 2 parts:
pin5 000100000000
MMMMLLLLLLLL
M = 4 Most significant bits, L = 8 Least significant bits
payload[0] takes the result of some operations on pin5:
pin5 000100000000
>> 8 000000000001 Shifts all bits 8 positions to the right
00000000MMMM and fills the left part with zeroes
so you have the originally leading 4 bits right-aligned now, on which an additional operation is performed:
000000000001
& 0xFF 000011111111 Anding with FF
000000000001
Right-shifting a 12-bits variable by 8 positions leaves 4 significant positions; the leading 8 bits will always be 0. 0xFF is binary 11111111, i.e., represents 8 set bits. So what is done here is Anding the 4 least significant bits with 8 least significant bits in order to make sure, that the 4 most significant bits get erased.
00000000xxxx Potentially set bits (you have 0001)
000011111111 & 0xFF
00000000xxxx Result
0000xxxx Storing in 8-bits variable
payload[0] = 00000001 in your case
In this case, the Anding operation is not useful and a complete waste of time, because Anding any variable with 0xFF does never change its 8 least significant bits in any way, and since the 4 most significant bits are never set anyway, there simply is no point in this operation.
(Technically, because the source is a 12-bits variable (presumably it is a 16 bits variable though, with only 12 significant (relevant) binary digits), 0x0F would have sufficed for the Anding mask. Can you see why? But even this would simply be a wasted CPU cycle.)
payload[1] also takes the result of an operation on pin5:
pin5 MMMMLLLLLLLL potentially set bits
& 0xFF 000011111111 mask to keep LLLLLLLL only
0000LLLLLLLL result (you have 00000000)
xxxxxxxx Storing in 8-bits variable
payload[1] = 00000000 in your case
In this case, Anding with 11111111 makes perfect sense, because it discards MMMM, which in your case is 0001.
So, all in all, your value
pin5 000100000000
MMMMLLLLLLLL
is split such, that payload[0] contains MMMM (0001 = decimal 1), and payload[1] contains LLLLLLLL (00000000 = decimal 0).
If the input was
pin5 101110010001
MMMMLLLLLLLL
instead, you would find in payload[0]: 1011 (decimal 8+2+1 = 11), and in payload[1]: 10010001 (decimal 128+16+1 = 145).
You would interpret this result as decimal 11 * 256 + 145 = 2961, the same result you obtain when converting the original 101110010001 from binary into decimal, for instance using calc.exe in Programmer mode (Alt+3), if you are using Windows.
Likewise, your original data is being interpreted as 1 * 256 + 0 = 256, as expected.

Divide 8-bit integers by 4 (or shift) using SSE

How can I divide 16 8-bit integers by 4 (or shift them 2 to the right) using SSE intrinsics?
Unfortunately there are no SSE shift instructions for 8 bit elements. If the elements are 8 bit unsigned then you can use a 16 bit shift and mask out the unwanted high bits, e.g.
v = _mm_srli_epi16(v, 2);
v = _mm_and_si128(v, _mm_set1_epi8(0x3f));
For 8 bit signed elements it's a little fiddlier, but still possible, although it might just be easier to unpack to 16 bits, do the shifts, then pack back to 8 bits.

Keep every n-th bits and collapse them in the least significant bits

I have a 32 bits integer that I treat as a bitfield. I'm interested in the value of the bits with an index of the form 3n where n range from 0 to 6 (every third bit between 0 and 18) I'm not interested in the bits with index in the form 3n+1 or 3n+2.
I can easily use the bitwise AND operator to keep the bits i'm interested in and set all the others bits to zero.
I would also need to "pack" the bits I'm interested in in the 7 least significant bits positions. So the bit at position 0 stay at 0, but the bit at position 3 is moved to position 1, the bit at position 6 moves to position 2 and so on.
I would like to do this in an efficient way, ideally without using a loop. Is there a combinations of operations I could apply to an integer to achieve this?
Since we're only talking about integer arithmetics here, I don't think the programming language I plan to use is of importance. But if you need to know :
I'm gonna use JavaScript.
If the order of the bits is not important, they can be packed into bits 0-6 like this:
function packbits(a)
{
// mask out the bits we're not interested in:
var b = a & 299593; // 1001001001001001001 in binary
// pack into the lower 7 bits:
return (b | (b >> 8) | (b >> 13)) & 127;
}
If the initial bit ordering is like this:
bit 31 bit 0
xxxxxxxxxxxxxGxxFxxExxDxxCxxBxxA
Then the packed ordering is like this:
bit 7 bit 0
0CGEBFDA

(C++) Integer on a specific number of bits (MIDI File)

The midi norm for music allows to code delta time duration as integer values (representing ticks).
For example I have a delta time of 960.
The binary value of 960 is 1111000000.
The thing is that the midi norm doesn't code the number on 16 bits.
It codes it on 14 bits and then, adds 10 at the 2 first bits to create another 16 bits value, 1 meaning that there is a following byte, and 0 meaning that it is the last byte.
My question is : how can I easily calculate 960 as a binary value coded on 14 bits?
Cheers
In the bytes that make up a delta time, the most significant bit specifies whether another byte with more bits is following.
This means that a 14-bit value like 00001111000000 is split into two parts, 0000111 and 1000000, and encoded as follows:
1 0000111 0 1000000
^ ^ ^ lower 7 bits
| | \
| \ last byte
\ upper 7 bits
more bytes follow
In C, a 14-bit value could be encoded like this:
int value = 960;
write_byte(0x80 | ((value >> 7) & 0x7f));
write_byte(0x00 | ((value >> 0) & 0x7f));
(Also see the function var_value() in arecordmidi.c.)
You can specify any number of bits as length inside a struct like so:
struct customInt {
unsigned int n:14; // 14-bit long unsigned integer type
};
Or you can make your own functions that take care of these kind of specific calculations/values.
If you are using unsigned integers, just do the calculations normally.
Start with
value = 960 ;
To convert the final output to 14 bits, do
value &= 0x3FFF ;
To add binary 10 to the front do
value |= 0x8000 ;

Calculating polynomial division result as well as remainder (CRC)

I'm trying to write a table-based CRC routine for receiving Mode S uplink interrogator messages. On the downlink side, the CRC is just the 24-bit CRC based on polynomial P=0x1FFF409. So far, so good -- I wrote a table-based implementation that follows the usual byte-at-a-time convention, and it's working fine.
On the uplink side, though, things get weird. The protocol specification says that calculating the target uplink address is by finding:
U' = x^24 * U / G(x)
...where U is the received message and G(x) is the encoding polynomial 0x1FFF409, resulting in:
U' = x^24 * m(x) + A(x) + r(x) / G(x)
...where m(x) is the original message, A(x) is the address, and r(x) is the remainder. I want the low-order quotient A(x); e.g., the result of the GF(2) polynomial division operation instead of the remainder. The remainder is effectively discarded. The target address is encoded with the transmitted checksum such that the receiving aircraft can validate the checksum by comparing it with its address.
This is great and all, and I have a bitwise implementation which follows from the above. Please ignore the weird shifting of the polynomial and checksum, this has been cribbed from this Pascal implementation (on page 15) which assumes 32-bit registers and makes optimizations based on that assumption. In reality the message and checksum come as a single, 56-bit transmission.
#This is the reference bit-shifting implementation. It is slow.
def uplink_bitshift_crc():
p = 0xfffa0480 #polynomial (0x1FFF409 shifted left 7 bits)
a = 0x00000000 #rx'ed uplink data (32 bits)
adr = 0xcc5ee900 #rx'ed checksum (24 bits, shifted left 8 bits)
ad = 0 #will hold division result low-order bits
for j in range(56):
#if MSBit is 1, xor w/poly
if a & 0x80000000:
a = a ^ p
#shift off the top bit of A (we're done with it),
#and shift in the top bit of adr
a = ((a << 1) & 0xFFFFFFFF) + ((adr >> 31) & 1)
#shift off the top bit of adr
adr = (adr << 1) & 0xFFFFFFFF
if j > 30:
#shift ad left 1 bit and shift in the msbit of a
#this extracts the LS 24bits of the division operation
#and ignores the remainder at the end
ad = ad + ((a >> 31) & 1)
ad = ((ad << 1) & 0xFFFFFFFF)
#correct the ad
ad = ad >> 2
return ad
The above is of course slower than molasses in software and I'd really like to be able to construct a lookup table that would allow similar byte-at-a-time calculation of the received address, or massage the remainder (which is quickly calculated) into a quotient.
TL;DR:
Given a message, the encoding polynomial, and the remainder (calculated by the normal CRC method), is there a faster way to obtain the quotient of the polynomial division operation than by using shift registers to do polynomial division "longhand"?
You might take a look at the PyCRC library, I guess this may answer your questions.
Too late for the OP, but I'm posting this for others that might see this question. You can generate two tables to operate a byte at a time. The first 256 by 8 bit table is indexed by the current leading 8 bits of the dividend (message), and the 8 bit values are the quotients. The second 256 by 32 bit table is indexed by the 8 bit quotient and the 32 bit values are the 32 bit product of the 8 bit quotient times the 25 bit polynomial (since this is a carryless multiply, the product is 32 bits, (x^7 * x^24 = x^31)), which you xor to the upper 32 bits of the dividend, which will zero out the upper 8 bits of the dividend. Then loop back for the next 8 bits of the dividend.
A modern X86 cpu has the carryless multiply instruction, PCLMULQDQ that operates on 128 bit xmm registers, performing a 64 bit by 64 bit multiply to produce a 128 bit product (since it's a carryless multiply bit 127 is always 0, so it's really a 127 bit product). A multiply of the 56 bit message by the 41 bit constant 2^64/G(x) will produce a 96 bit product, of which the upper 32 bits will be the quotient (lower 64 bits are not used).