[parsec-users] which program supports solaris/sparc ?

Christian Bienia cbienia at CS.Princeton.EDU
Sun Apr 13 01:53:40 EDT 2008


Hi Kshitij,

My bad, I overlooked that we're also dealing with floats. The routines I sent 
only work for integers, swapping floats is a little more tricky. The code 
breaks because we force the compiler to convert a float to an int when we 
pass it to the byte swap routine. Of course the float is still in 
little-endian format which makes no sense on a big-endian machine, so we just 
mess it up.

In order to byte-swap a float we may furthermore not store it in a float 
variable at any time before the swap. I found a little explanation and some 
sample code here:

	http://www.idevapps.com/forum/archive/index.php/t-896.html

It's probably best to read the float into an unsigned int and do the whole 
conversion in a new routine in order to keep all the endianness details 
separate from the actual program logic. The following should work better:

...

//Invert the byte order of a 32-bit float
float swap_32f(DWORD x) {
 char buffer[ 4 ];
 
 buffer[ 0 ] = ((char *)&x)[ 3 ];
 buffer[ 1 ] = ((char *)&x)[ 2 ];
 buffer[ 2 ] = ((char *)&x)[ 1 ];
 buffer[ 3 ] = ((char *)&x)[ 0 ];
 
 return *( (float *) &buffer );
}

...

  DWORD float_temp;
  file.read((char *)&float_temp, 4);
  file.read((char *)&origNumParticles, 4);
        
  if(!isLittleEndian()) {
    restParticlesPerMeter = swap_32f(float_temp);
    origNumParticles = swap_32(origNumParticles);
  } else {
    restParticlesPerMeter = *( (float *) &float_temp );
  }


I hope that does that job. There might still be an issue if Sparc uses a 
different floating-point format than the numbers in the file are stored in. 
Let's hope that this is not the case because then it'll get unpleasant.

- Chris


On Saturday 12 April 2008 08:40 pm, Kshitij Sudan wrote:
> Hi Christian,
>
> I tried your suggestions but there's a slight problem with the code
> you sent. The problem arises while converting a little-endian, 32-bit
> floating point number read from the binary file on SPARC.
>
> The routines you wrote for swapping 32-bit numbers is somehow messing
> up correct value of float because when the variable
> "restParticlesPerMeter" is read and converted on SPARC it gives the
> following value:
> restParticlesPerMeter= 0.000000
>
> however, when this is read on x86, it gives this value>>
> restParticlesPerMeter= 392.000000
>
> The conversion for 32-bit integers works and the variable
> "numParticles" is correctly read and swapped on the SPARC m/c.
>
> Any pointers for porting floating point numbers?
>
> -Kshitij
>
> This is a scrub program I wrote from your functions and fluidanimate
> code for testing>>
> -----------------------------------------------------------------
> #include<iostream>
> #include<fstream>
> #include<stdio.h>
> #include<assert.h>
>
> typedef uint8_t BYTE;
> typedef uint16_t WORD;
> typedef uint32_t DWORD;
> typedef int32_t LONG;
>
> bool isLittleEndian() {
>   union {
>     WORD word;
>     BYTE byte;
>   }endian_test;
>   endian_test.word = 0x00FF;
>   return (endian_test.byte == 0xFF);
> }
>
> //Invert the byte order of a 16-bit word
> WORD swap_16(WORD x) {
>   union {
>     WORD x_16;
>     BYTE x_8[2];
>   } mem_array;
>   BYTE temp;
>
>   mem_array.x_16 = x;
>   temp = mem_array.x_8[0];
>   mem_array.x_8[0] = mem_array.x_8[1];
>   mem_array.x_8[1] = temp;
>
>   return mem_array.x_16;
> }
>
> //Invert the byte order of a 32-bit word
> DWORD swap_32(DWORD x) {
>   union {
>     DWORD x_32;
>     WORD x_16[2];
>     BYTE x_8[4];
>   } mem_array;
>   BYTE temp;
>
>   mem_array.x_32 = x;
>   //swap outer bytes
>   temp = mem_array.x_8[0];
>   mem_array.x_8[0] = mem_array.x_8[3];
>   mem_array.x_8[3] = temp;
>   //swap inner bytes
>   temp = mem_array.x_8[1];
>   mem_array.x_8[1] = mem_array.x_8[2];
>   mem_array.x_8[2] = temp;
>
>   return mem_array.x_32;
> }
>
> int main(void)
> {
>   float restParticlesPerMeter;
>   int origNumParticles, numParticles;
>
>   std::ifstream file("in_35K.fluid", std::ios::binary);
>   assert(file);
>
>   file.read((char *)&restParticlesPerMeter, 4);
>   file.read((char *)&origNumParticles, 4);
>
>   if(!isLittleEndian()) {
>     printf("flipping bytes for SPARC!\n");
>     restParticlesPerMeter = swap_32(restParticlesPerMeter);
>     origNumParticles = swap_32(origNumParticles);
>   }
>
>   numParticles = origNumParticles;
>   printf("numParticles= %d\n",numParticles);
>   printf("restParticlesPerMeter= %f\n",restParticlesPerMeter);
>   return 0;
> }
>
>
> On Thu, Apr 15, 2004 at 10:51 PM, Christian Bienia
>
> <cbienia at cs.princeton.edu> wrote:
> > Hi Kshitij,
> >
> >  You made a good observation. Fluidanimate loads its input data from a
> >  file which is in binary format. In order to use the program it is
> >  necessary to flip all loaded variables larger than 1 byte. That's not
> >  difficult to do, I've already done that for bodytrack but haven't had
> >  the time to fix the other programs. You can use the routines I wrote for
> >  bodytrack in file FlexIO.cpp to get it to run correctly. Here they are:
> >
> >  //Detect endianness of this machine
> >  bool isLittleEndian() {
> >   union {
> >     WORD word;
> >     BYTE byte;
> >   } endian_test;
> >
> >   endian_test.word = 0x00FF;
> >   return (endian_test.byte == 0xFF);
> >  }
> >
> >  //Invert the byte order of a 16-bit word
> >  WORD swap_16(WORD x) {
> >   union {
> >     WORD x_16;
> >     BYTE x_8[2];
> >   } mem_array;
> >   BYTE temp;
> >
> >   mem_array.x_16 = x;
> >   temp = mem_array.x_8[0];
> >   mem_array.x_8[0] = mem_array.x_8[1];
> >   mem_array.x_8[1] = temp;
> >
> >   return mem_array.x_16;
> >  }
> >
> >  //Invert the byte order of a 32-bit word
> >  DWORD swap_32(DWORD x) {
> >   union {
> >     DWORD x_32;
> >     WORD x_16[2];
> >     BYTE x_8[4];
> >   } mem_array;
> >   BYTE temp;
> >
> >   mem_array.x_32 = x;
> >   //swap outer bytes
> >   temp = mem_array.x_8[0];
> >   mem_array.x_8[0] = mem_array.x_8[3];
> >   mem_array.x_8[3] = temp;
> >   //swap inner bytes
> >   temp = mem_array.x_8[1];
> >   mem_array.x_8[1] = mem_array.x_8[2];
> >   mem_array.x_8[2] = temp;
> >
> >   return mem_array.x_32;
> >  }
> >
> >
> >
> >  You would use them as follows after you've loaded a value into a
> >  variable (example also taken from FlexIO.cpp):
> >
> >
> >  if(!isLittleEndian()) {
> >   bmfh->bfType = swap_16(bmfh->bfType);
> >   bmfh->bfSize = swap_32(bmfh->bfSize);
> >   bmfh->bfReserved1 = swap_16(bmfh->bfReserved1);
> >   bmfh->bfReserved2 = swap_16(bmfh->bfReserved2);
> >   bmfh->bfOffBits = swap_32(bmfh->bfOffBits);
> >  }
> >
> >
> >  Fluidanimate uses the file.read method to load data from file. I counted
> >  11 occurrences. Simply convert it as follows as shown below. The code...
> >
> >  file.read((char *)&restParticlesPerMeter, 4);
> >  file.read((char *)&origNumParticles, 4);
> >
> >  ...would become...
> >
> >  file.read((char *)&restParticlesPerMeter, 4);
> >  file.read((char *)&origNumParticles, 4);
> >  if(!isLittleEndian()) {
> >   restParticlesPerMeter = swap_32(restParticlesPerMeter);
> >   origNumParticles = swap_32(origNumParticles);
> >  }
> >
> >  Do the same where it reads the particles a little farther down and it
> >  should work. If you get something to work please post a patch to this
> >  mailing list.
> >
> >  - Chris
>
> _______________________________________________
> parsec-users mailing list
> parsec-users at lists.cs.princeton.edu
> https://lists.cs.princeton.edu/mailman/listinfo/parsec-users



More information about the parsec-users mailing list