I'm trying to create a function in C in Windows that has as input a double (8Bytes) and returns another double but rearranged, that is, the input is B7 ... B0 and the output is B0 ... B7. My compiler gives me an error when working with int and double data.
I thought about taking the input value and make masks with a high level byte (0xFF) and thus separate the 8Bytes that form the double input value, then concatenate them in the order other than the one they entered and get my double output ordered as I want, but it does not work.
The code is the following:
double ordena_lineal(double lineal)
{
// Recibo B7...B0 y devuelvo B0...B7
uint8_t B0,B1,B2,B3,B4,B5,B6,B7;
double lineal_final;
B0 = lineal&&0xFF;
B1 = (lineal>>8)&&0xFF;
B2 = (lineal>>8*2)&&0xFF;
B3 = (lineal>>8*3)&&0xFF;
B4 = (lineal>>8*4)&&0xFF;
B5 = (lineal>>8*5)&&0xFF;
B6 = (lineal>>8*6)&&0xFF;
B7 = (lineal>>8*7)&&0xFF;
lineal_final = (B7 | (B6 << 8) | (B5 << 8*2) | (B4 << 8*3) | (B3 << 8*4) | (B2 << 8*5) | (B1 << 8*6) | (B0 << 8*7))
return lineal_final;
}
Bitwise operators are illegal to be used on floating point types. Also, when you assign the shifted bytes back to lineal_final, you're assigning the value of that expression, not its representation.
You need to use a union to do what you intend.
union double_bytes {
double d;
uint8_t b[sizeof(double)];
};
double ordena_lineal(double lineal)
{
union double_bytes src, dst;
src.d = lineal;
for (int i = 0; i < sizeof(double); i++) {
dst.b[sizeof(double) - 1 - i] = src.b[i];
}
return dst.d;
}
This allows you to access the object representation of a double and perform aliasing in a standard compliant manner.
Related
I'm reading/writing a binary file in little-endian format from big-endian using C and bswap_{16,32,64} macros from byteswap.h for byte-swapping.
All values are read and written correctly, except a bit-field of 40 bits.
The bswap_40 macro doesn't exist and I don't know how do it or if a better solution is possible.
Here is a small code showing this problem:
#include <stdio.h>
#include <inttypes.h>
#include <byteswap.h>
#define bswap_40(x) bswap_64(x)
struct tIndex {
uint64_t val_64;
uint64_t val_40:40;
} s1 = { 5294967296, 5294967296 };
int main(void)
{
// write swapped values
struct tIndex s2 = { bswap_64(s1.val_64), bswap_40(s1.val_40) };
FILE *fp = fopen("index.bin", "w");
fwrite(&s2, sizeof(s2), 1, fp);
fclose(fp);
// read swapped values
struct tIndex s3;
fp = fopen("index.bin", "r");
fread(&s3, sizeof(s3), 1, fp);
fclose(fp);
s3.val_64 = bswap_64(s3.val_64);
s3.val_40 = bswap_40(s3.val_40);
printf("val_64: %" PRIu64 " -> %s\n", s3.val_64, (s1.val_64 == s3.val_64 ? "OK" : "Error"));
printf("val_40: %" PRIu64 " -> %s\n", s3.val_40, (s1.val_40 == s3.val_40 ? "OK" : "Error"));
return 0;
}
That code is compiled with:
gcc -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
swap_40.c -o swap_40
How can I define bswap_40 macro for read and write these values of 40 bits doing byte-swap?
By defining bswap_40 to be the same as bswap_64, you're swapping 8 bytes instead of 5. So if you start with this:
00 00 00 01 02 03 04 05
You end up with this:
05 04 03 02 01 00 00 00
Instead of this:
00 00 00 05 04 03 02 01
The simplest way to handle this is to take the result of bswap_64 and right shift it by 24:
#define bswap_40(x) (bswap_64(x) >> 24)
EDIT
I got better performance writing this macro (comparing with my initial code, this produced less assembly instructions):
#define bswap40(s) \
((((s)&0xFF) << 32) | (((s)&0xFF00) << 16) | (((s)&0xFF0000)) | \
(((s)&0xFF000000) >> 16) | (((s)&0xFF00000000) >> 32))
use:
s3.val_40 = bswap40(s3.val_40);
... but it might be an optimizer issue. I thinks they should be optimized to the same thing.
Original Post
I love dbush's answer better... I was about to write this:
static inline void bswap40(void* s) {
uint8_t* bytes = s;
bytes[0] ^= bytes[3];
bytes[1] ^= bytes[2];
bytes[3] ^= bytes[0];
bytes[2] ^= bytes[1];
bytes[0] ^= bytes[3];
bytes[1] ^= bytes[2];
}
It's a destructive inline function for switching the bytes...
I'm reading/writing a binary file in little-endian format from big-endian using C and bswap_{16,32,64} macros from byteswap.h for byte-swapping.
Suggest a different way of approaching this problem: Far more often, code needs to read a file in a known endian format and then convert to the code's endian. This may involve a byte swap, it may not the trick is to write code that works under all conditions.
unsigned char file_data[5];
// file data is in big endidan
fread(file_data, sizeof file_data, 1, fp);
uint64_t y = 0;
for (i=0; i<sizeof file_data; i++) {
y <<= 8;
y |= file_data[i];
}
printf("val_64: %" PRIu64 "\n", y);
uint64_t val_40:40; is not portable. Bit ranges on types other that int, signed int, unsigned are not portable and have implementation specified behavior.
BTW: Open the file in binary mode:
// FILE *fp = fopen("index.bin", "w");
FILE *fp = fopen("index.bin", "wb");
Say I have 8 32-bit registers:
A 0-31 E 0-31
B 0-31 F 0-31
C 0-31 G 0-31
D 0-31 H 0-31
And I want their bits rearranged like:
A' := A0 E0 A8 E8 A16 E16 A24 E24 B0 F0 B8 F8 B16 F16 B24 F24 C0 G0 ...etc. H24
B' := A1 E1 A9 E9 A17 E17 A25 E25 B1 F1 B9 F9 B17 F17 B25 F25 C1 G1 ...etc. H25
C' := A2 E2 A10 E10 A18 E18 A26 E26 B2 ... etc.
D' := ... etc.
E' := ... etc.
F' := ... etc.
G' := ... etc.
H' := ... etc.
What would be the most efficient way to compute this shuffling in either C or ARM assembly? (So no intel with SSE, no 64-bit registers, not enough registers to contain both input and output.) The calculator at http://programming.sirrida.de/calcperm.php is really nice, but it doesn't easily extend to multiple words. I believe it can be done more efficiently than the naive way of selecting one bit at the time.
If you make components A0 _ _ _ _ _ _ _ A8 _ _ _ _ _ _ _ A16 etc (just trivial masking).
And similar for the other registers, you can easily make this:
A0 E0 B0 F0 C0 G0 D0 H0 A8 E8 ..
Which you can turn into the right order with two bit_permute_step's, as given by calcperm:
x = bit_permute_step(x, 0x00cc00cc, 6); // Bit index swap 1,3
x = bit_permute_step(x, 0x0000f0f0, 12); // Bit index swap 2,4
Similar story for the other registers, just offset a bit.
Essentially moving 4 bits at once, with a bit of fixup which only happens 8 times.
; 1) Copy the top most 8 bits of H into the lowest bits of the output registers:
lsr H ; H.31 -> carry
rol H' ; carry -> H'.0
lsr H ; H.30 -> carry
rol G' ; carry -> G'.0
lsr H
rol F'
...
lsr H ; H.24 -> carry
rol A' ; carry to A'.0
; 2) go on with top 8 bits of D
lsr D ; D.31 -> carry
rol H' ; H'.0 -> H'.1 and carry -> H'.0
lsr D
rol G'
...
lsr D
rol A'
Continue until all bits are in place. The last step is
lsr A ; A.0 -> carry
rol A' ; A'.0 -> A'.1 -> A'.2 ... and carry -> A'.0
the fastest version I came up with:
// merges 32 bit a (low) and b (hi) into single 64 bit
#define m(a, b) (((uint64_t) (a)) | (((uint64_t) (b)) << 32))
// gets bit at position opos and moves it to position npos
#define s(a, opos, npos) (((opos) >= (npos)) ? (((a) & ( ((uint64_t)1) << (opos))) >> ((opos) - (npos))) : (((a) & (((uint64_t)1) << (opos))) << ((npos) - (opos))))
// gets 8 different bits from 64 bit number and puts them together into 1 byte, starting from idx
#define b(a, idx) (s(a, 0, idx) | s(a, 32, (idx - 1)) | s(a, 8, (idx - 2)) | s(a, 40, (idx - 3)) | s(a, 16, (idx - 4)) | s(a, 48, (idx - 5)) | s(a, 24, (idx - 6)) | s(a, 56, (idx - 7)))
// takes 8 32 bit registers in in, outputs in out
void shuffle(const uint32_t* in, uint32_t* out) {
uint64_t t[4] = { m(in[0], in[4]), m(in[1], in[5]), m(in[2], in[6]), m(in[3], in[7]) };
for (int i = 0; i < 8; i++, t[0] >>= 1, t[1] >>= 1, t[2] >>= 1, t[3] >>= 1)
out[i] = b(t[0], 31) | b(t[1], 23) | b(t[2], 15) | b(t[3], 7);
}
the only "optimization" in comparison to straight forward approach is to merge two 32 bit registers into single 64 bit, so we can reduce number of shifts in loop
On x86 with SSE: punpcklbw (_mm_unpacklo_epi8 can interleave bytes of the source regs.
Use vector shifts then pmovmskb to grab the high bit of each byte, giving you results like
A0 E0 A8 E8 A16 E16 A24 E24
Then combine these byte results to get the 8 dest registers. This kind of sucks, because it requires a shift/pmovmskb for each of result byte. There are 8 * 4 result bytes, so that's a lot of code.
I'm a bit late to the party but I'll post an answer anyway.
Firstly, notice that the bytes in the output words each use only even/odd bits of a pair of input words. combining the odd bits of A with the even bits of B gives all the bits necessary for the first byte of A,C,E,G. Code for the resulting permutation can be found via the calculator linked above and simplifies to two bit swapping operations per word. The resulting bytes can be written back to memory in their correct locations and read back if necessary.
Permuting the bytes within a word costs about as much as writing out the bytes to memory but is also possible.
Cost is 17 bit operations per word. A little less on ARM where rotations are free. Vectorisation is easy with byte shuffling replacing the last step.
The following vanilla C code should do it:
#include <stdio.h>
#include <stdint.h>
int32_t inline bit_permute_step(int32_t x, int32_t m, int shift) {
int32_t t;
t = ((x >> shift) ^ x) & m;
x = (x ^ t) ^ (t << shift);
return x;
}
void permute(int32_t input[8], int32_t output[8]){
int8_t *outputc=(int8_t*)output;
for(int i=0;i<4;i++){
int32_t A=input[3-i];
int32_t E=input[3-i+4];
//swap the even bits of A/B/C/D with the odd bits of E/F/G/H
int32_t t=(A^(E>>1))&0x55555555;
A^=t;E^=t<<1;
A = bit_permute_step(A, 0x00cc00cc, 6); // Bit index swap 1,3
E = bit_permute_step(E, 0x00cc00cc, 6); // Bit index swap 1,3
A = bit_permute_step(A, 0x0000f0f0, 12); // Bit index swap 2,4
E = bit_permute_step(E, 0x0000f0f0, 12); // Bit index swap 2,4
outputc[i+0 ]=A>>24;
outputc[i+4 ]=E>>24;
outputc[i+8 ]=A>>16;
outputc[i+12]=E>>16;
outputc[i+16]=A>>8;
outputc[i+20]=E>>8;
outputc[i+24]=A;
outputc[i+28]=E;
}
}
void printBits(unsigned int num){
for(int bit=31;bit>=0; bit--){
printf("%i", (num>>bit)&1);
if(bit && !(bit&7)){printf(" ");}
}printf("\n");
}
int32_t main(){
volatile int32_t input[8]=
{0xf<<0,0xf<<8,0xf<<16,0xf<<24,0xf<<4,0xf<<12,0xf<<20,0xf<<28};
int32_t output[8]={-1,-1,-1,-1,-1,-1,-1,-1};
printf("input\n");
permute((int32_t*)input,output);
for(int i=0;i<8;i++){
printf(" %c:",'A'+i);
printBits(input[i]);
}
printf("output\n");
for(int i=0;i<8;i++){
printf(" %c:",'A'+i);
printBits(output[i]);
}
}
I'm writing a Pebble Time Watch app using Pebble SDK 3.0 on the basalt platform that requires text to be displayed upsidedown.
The logic is:-
Write to screen
Capture screen buffer
Flip screen buffer (using flipHV routine, see below)
Release buffer.
After a fair amount of experimentation I've got it working after a fashion but the (black) text has what seems to be random vertical white lines through it (see image below) which I suspect is something to do with shifting bits.
The subroutine I'm using is:-
void flipHV(GBitmap *bitMap) {
GRect fbb = gbitmap_get_bounds(bitMap);
int Width = 72; // fbb.size.w;
int Height = 84; // fbb.size.h;
uint32_t *pBase = (uint32_t *)gbitmap_get_data(bitMap);
uint32_t *pTopRemainingPixel = pBase;
uint32_t *pBottomRemainingPixel = pBase + (Height * Width);
while (pTopRemainingPixel < pBottomRemainingPixel) {
uint32_t TopPixel = *pTopRemainingPixel;
uint32_t BottomPixel = *pBottomRemainingPixel;
TopPixel = (TopPixel << 16) | (TopPixel >> 16);
*pBottomRemainingPixel = TopPixel;
BottomPixel = (BottomPixel << 16) | (BottomPixel >> 16);
*pTopRemainingPixel = BottomPixel;
pTopRemainingPixel++;
pBottomRemainingPixel--;
}
}
and its purpose is to work though the screen buffer taking the first pixel and swapping with the last one, the second one and swapping it with the second last one etc etc.
Because each 32 bit 'byte' holds 2 pixels I also need to rotate it through 16 bits.
I suspect that that is where the problem lies.
Can someone have a look at my code and see if they can see what is going wrong and put me right. I should say that I'm both a C and Pebble SDK newbie so please explain everything as if to a child!
Your assignments like
TopPixel = (TopPixel << 16) | (TopPixel >> 16)
swap pixels pair-wise
+--+--+ +--+--+
|ab|cd| => |cd|ab|
+--+--+ +--+--+
What you want instead is a full swap:
+--+--+ +--+--+
|ab|cd| => |dc|ba|
+--+--+ +--+--+
That can be done with even more bit-fiddling, e.g
TopPixel = ((TopPixel << 24) | // move d from 0..7 to 24..31
((TopPixel << 8) & 0x00ff0000) | // move c from 8..15 to 16..23
((TopPixel >> 8) & 0x0000ff00) | // move b from 16..23 to 8..15
((TopPixel >> 24) | // move a from 24..31 to 0..7
or - way more readable(!) - by using GColor8 instead of uint32_t and a loop on a per-pixel-basis:
// only loop to half of the distance to avoid swapping twice
for (int16_t y = 0; y <= max_y / 2; y++) {
for (int16_t x = 0; x <= max_x / 2; x++) {
GColor8 *value_1 = gbitmap_get_bytes_per_row(bmp) * y + x;
GColor8 *value_2 = gbitmap_get_bytes_per_row(bmp) * (max_y - y) + (max_x - x);
// swapping the two pixel values, could be simplified with a SWAP(a,b) macro
GColor8 tmp = *value_1;
*value_1 = *value_2;
*value_2 = tmp;
}
}
Disclaimer: I haven't compiled this code. It might also be necessary to cast the gbitmap_get_byes_per_row()... expressions to GColor8*. And the whole pointer arithmetic can be tuned if you see that this is a performance bottle-neck.
It turns out that I needed to replace all of the uint32_t with uint8_t and do away with the shifting.
I have a binary file, and I want to read a double from it.
In hex representation, I have these 8 bytes in a file (and then some more after that):
40 28 25 c8 9b 77 27 c9 40 28 98 8a 8b 80 2b d5 40 ...
This should correspond to a double value of around 10 (based on what that entry means).
I have used
#include<stdio.h>
#include<assert.h>
int main(int argc, char ** argv) {
FILE * f = fopen(argv[1], "rb");
assert(f != NULL);
double a;
fread(&a, sizeof(a), 1, f);
printf("value: %f\n", a);
}
However, that prints
value: -261668255698743527401808385063734961309220864.000000
So clearly, the bytes are not converted into a double correctly. What is going on?
Using ftell, I could confirm that 8 bytes are being read.
Just like integer types, floating point types are subject to platform endianness. When I run this program on a little-endian machine:
#include <stdio.h>
#include <stdint.h>
uint64_t byteswap64(uint64_t input)
{
uint64_t output = (uint64_t) input;
output = (output & 0x00000000FFFFFFFF) << 32 | (output & 0xFFFFFFFF00000000) >> 32;
output = (output & 0x0000FFFF0000FFFF) << 16 | (output & 0xFFFF0000FFFF0000) >> 16;
output = (output & 0x00FF00FF00FF00FF) << 8 | (output & 0xFF00FF00FF00FF00) >> 8;
return output;
}
int main()
{
uint64_t bytes = 0x402825c89b7727c9;
double a = *(double*)&bytes;
printf("%f\n", a);
bytes = byteswap64(bytes);
a = *(double*)&bytes;
printf("%f\n", a);
return 0;
}
Then the output is
12.073796
-261668255698743530000000000000000000000000000.000000
This shows that your data is stored in the file in little endian format, but your platform is big endian. So, you need to perform a byte swap after reading the value. The code above shows how to do that.
Endianness is convention. Reader and writer should agree on what endianness to use and stick to it.
You should read your number as int64, convert endianness and then cast to double.
I'm wondering if there is any possibility of replacing arguments in directive #define by the values of the arguments, they actually have in program. Here's the code:
typedef struct {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} BIT_FIELD;
#define _PORTD (*( volatile BIT_FIELD*)&PORTD)
#define kupa(s) _PORTD.b##s
void SentByteTo74HC595 (uint8_t val){
for(int i = 7 ; i >=0 ; i--) {
DS = kupa(i);
SHCPpulse() ;
}
The problem is that kupa makes _PORTD.bi insted of _PORTD.b0, PORTD.b1 etc. I was trying diffrent ways with # or ## but I'm not sure if it's even possbile to achieve what i want to achieve.
Because preprocessor (the thing that expands macros) is run even before the compiler. What you want is to access names of struct's fields in runtime, which is impossible, because names of fields are not preserved. C is not a dynamic language and do not have reflections.
You can, however, write your for iteration as a separate define and call it 8 times. Not the best solution, though - in your case I'd use bit shifts instead of bit fields. It's easier to support, use and read.
Pre-processor directives are processed and applied prior to processing (i.e. compilation). kupa is a pre-processor macro, so the compiler never sees it. So no, you can't do it like this.
What you're trying to do is not portable, how the bits are stored is compiler dependent.
You may be better using bit manipulation such as defining enums which specify a given bit
enum {
b0 = 0x001,
b1 = 0x002,
b3 = 0x004,
...
};
You may still need to perform (e.g.) endian conversions on values depending on how you are exchanging them.
typedef struct {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} BIT_FIELD;
union u_ToSend {
uint8_t ui8val;
BIT_FIELD BFval;
} ;
void SentByteTo74HC595 (uint8_t val){
union u_ToSend tmp;
tmp.ui8val = val;
for (int i = 7; i >=0; i--){
DS = tmp.BFval.b7 ;
tmp.ui8val <<= 1 ;
SHCPpulse() ;
}
Is there any other way to write it, so that program consume less RAM and Flash memory ?