4

I have a 32 bit number (uint32) that contains four numbers in the following manner:

  • Var1 is in bits 32:31
  • Var2 is in bits 30:22
  • Var3 is in bits 21:13
  • Var4 is in bits 12:1

The following code works but I'd like to make it faster

Var1=bitshift(fourbytes,-30);
Var2_temp=bitshift(fourbytes,-21);
Var2=bitand(Var2_temp,511);
Var3_temp=bitshift(fourbytes,-12);
Var3=bitand(Var2_temp,511);
Var4=bitand(fourbytes,2^12-1));

Example:

fourbytes = 2149007896;

Results in

Var1=2;
Var2=0;
Var3=372
Var4=536

I've tried something like

Var1=bin2dec(num2str(bitget(fourbytes,32:-1:31)));

but that is incredibly slow as is bi2de

bi2de(bitget(onebyte(1),32:-1:31),'left-msb');

Is my only alternative to write this part in C, or is there a better way I'm missing ?

Tom Mozdzen
  • 338
  • 4
  • 16
  • 1
    Juat a suggestion: I'm guessing this can be achieved fairly efficiently using C through mex. – Dev-iL Sep 06 '21 at 06:55
  • 1
    @Dev-iL I shall put that on my list of things to investigate. – Tom Mozdzen Sep 06 '21 at 15:03
  • 1
    Are you always going to be working on a scalar (1-long) array of these 32-bit values, or will you want to do "vectorized" extraction from a multi-element array of them? That could make a significant difference in how you want to do this. – Andrew Janke Sep 18 '21 at 15:54
  • @AndrewJanke the data is stored as a binary file (10s of GBs) with one 32 bit set of numbers after another. I read 2^30 of the 32 bit numbers at a time, extract info from the data and put it into a histogram and repeat, stuffing the histogram until the entire file is read. I'm reading it in with these commands: fileID = fopen(filename,'r','l'); databytes=fread(fileID,2^30,'*ubit32'); Any speedup suggestions are definitely welcome. – Tom Mozdzen Sep 18 '21 at 23:56

1 Answers1

5

This can be done with

  • division followed by floor to get rid of the unwanted rightmost bits, and then
  • mod to get rid of the unwanted leftmost bits.

I haven't timed it, but it's probably faster than your current approach.

fourbytes = 2149007896;
var1 = floor(fourbytes/2^30);
var2 = mod(floor(fourbytes/2^21), 2^9);
var3 = mod(floor(fourbytes/2^12), 2^9);
var4 = mod(fourbytes, 2^12);
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • It’s course-intuitive that this would be faster, but I guess it’s possible because you don’t have the double-to-int conversion. – Cris Luengo Sep 05 '21 at 15:55
  • 2
    Nice! I measured a 10x speed up. I process several GB of these 4 byte data chunks. And that section was the choke point. Thank you! – Tom Mozdzen Sep 05 '21 at 18:33
  • At the moment, I need to be careful about datatypes. For instance: I'm using uint32 for fourbytes=1652559757. Var1 = "2" with the floor function but "1" with bit shifting. I need to work on typecasting to make sure it doesn't get rounded up before the floor operation. I'll need to typecast somewhere. Stay tuned. – Tom Mozdzen Sep 05 '21 at 20:08
  • If iIuse fourbytes=double(original_number), then all is fine! – Tom Mozdzen Sep 05 '21 at 20:19