Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
Hi,

I have come across an old header called sane.h. From (Standard Apple
Numeric Environment [SANE]) with different data types, the data type I´m after is called 'extended' and is a 80 bit floating point value. My compiler don´t know what I´m talking about.

So what would be an equivalent to the 'extended' data type in C on a intel mac?
 

Guiyon

macrumors 6502a
Mar 19, 2008
771
4
Cambridge, MA
Hi,

I have come across an old header called sane.h. From (Standard Apple
Numeric Environment [SANE]) with different data types, the data type I´m after is called 'extended' and is a 80 bit floating point value. My compiler don´t know what I´m talking about.

So what would be an equivalent to the 'extended' data type in C on a intel mac?

I would assume you're probably looking for the 'long double' type.
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
Hey, thanks for that. Forget about the thread.

Is there a way to get the memory content of a long double into a char array using C? It´s a 128bit value.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Code:
#include <stdio.h>

int main(int argc, char *argv[]) {
  long double myLd = 97832.932L;
  unsigned char *charList = (unsigned char *)&myLd;
  int len = sizeof(myLd);
  int pos = 0;
  int intVal = 0;

  for(pos = 0; pos < len; pos++) {
    intVal=(int)charList[pos];  
    printf("Byte %d of myLd as digits: %d\n",pos,intVal);
  }

  return 0;
}

I wouldn't recommend this, but it works. Printing as chars is probably a bad idea, as characters above 127 are extended ascii. On my platform long double was only 96 bits (only the first 80 are used for storage, the last 16 are just for alignment), so don't assume 128, use sizeof.

-Lee
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
I wouldn't recommend this, but it works. Printing as chars is probably a bad idea, as characters above 127 are extended ascii. On my platform long double was only 96 bits (only the first 80 are used for storage, the last 16 are just for alignment), so don't assume 128, use sizeof.

-Lee

Thanks! I tried to use the code to write the string to disk but then the values came out differently in hexdump, any idea what the issue might be? sizeof gave 16 btw. I need to somehow restrict the size to 10 bytes, perhaps there are some other solution than using an array.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
So i just ran a test, and it looks like the long double on the version of OS X I am using is 16 bytes, but 6 are being used for padding, to get 16-byte alignment (my guess, 12 bytes would give 4-byte alignment). What that means is the "business" is only the first 10 bytes, which is what you were looking for.

Now i think you should describe what you actually want to do. if you need to store long doubles to disk, and this doesn't need to be used on multiple platforms, you should just write them out in their native format. There's no need to use a character array, and try to write that out in ascii. If you need the values to be readable on other platforms, you'll probably want to go with JSON, XML, etc. for your data storage.

What are you trying to achieve? There may be a easier, cleaner, faster, better, etc. way to do it.

-Lee
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
I´m trying to create a file header. This particulary field is 10 byte in length and a float. The data type is reffered to as extended belonging to sane.h, this data type doesn´t seem to exist, or have been replaced by the long double. Which shouldn´t matter if the space was of no concern. I could use a smaller data type and pad it manually to get ten bytes but then it is represented differently.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
So there's some fixed-width field file format you are trying to reproduce? If so, i would try to set up a struct with the format. For some things like this, you might need to used a char list to get the right number of bytes, then memcpy in the leading N bytes from another type (like the first 10 bytes of these long doubles). You can then write out the struct to the file using binary I/O, read back into the struct, etc. I would say you should just write a routine that takes the "full" data elements, formats the struct, writes the struct to disk, then an alternate routine that will read the struct back up, and copy from the various types back to usable, in-memory items.

Also, are you sure that the byte-order the file needs to be in matches the endianness of your platform?

-Lee
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
So there's some fixed-width field file format you are trying to reproduce? If so, i would try to set up a struct with the format. For some things like this, you might need to used a char list to get the right number of bytes, then memcpy in the leading N bytes from another type (like the first 10 bytes of these long doubles). You can then write out the struct to the file using binary I/O, read back into the struct, etc. I would say you should just write a routine that takes the "full" data elements, formats the struct, writes the struct to disk, then an alternate routine that will read the struct back up, and copy from the various types back to usable, in-memory items.

Also, are you sure that the byte-order the file needs to be in matches the endianness of your platform?

-Lee

I´m trying to make a converter and what I have so far works, but with restricted conditions for the input file. At the moment I´m using an int to hold the value and pad the rest of the bits to reach 10 bytes in length. There is also the part of the exponent and signed bit which is just written into the struct for now. nedless to say, If I fed a file with a different value into this section the exponent and signed bit would make no sense at all and the file would be corupt.

BTW this is not a problem that needs a solution, I´m doing this entirely to learn to program.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
I´m trying to make a converter and what I have so far works, but with restricted conditions for the input file. At the moment I´m using an int to hold the value and pad the rest of the bits to reach 10 bytes in length. There is also the part of the exponent and signed bit which is just written into the struct for now. nedless to say, If I fed a file with a different value into this section the exponent and signed bit would make no sense at all and the file would be corupt.

I can't say that I understood this clearly, but long double is what you want. The first 80 bits of your long double will be the value you need.

-Lee
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
I can't say that I understood this clearly, but long double is what you want. The first 80 bits of your long double will be the value you need.

-Lee

Ok sorry, I´m reading in a file, converts its format to another format. The long double seems to store it´s content in the middle bytes BTW. This is what a long double with the value 44100 looks like after it´s been written to disk.

Code:
00 00 00 00 00 00 44 ac  0e 40 00 00 00 00 00 00

44ac is the value and 0e40 is the exponent and signed bit I suppose.
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
Lee, couldn´t the code you posted be used to achive this though? I have a hard time to get casting and pointers right still, I always manage to make some syntactic errors.

Thanks for your help, appreciated.
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
Memcpy did the trick, got a warning first but I forgot to include string.h.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Ok sorry, I´m reading in a file, converts its format to another format. The long double seems to store it´s content in the middle bytes BTW. This is what a long double with the value 44100 looks like after it´s been written to disk.

Code:
00 00 00 00 00 00 44 ac  0e 40 00 00 00 00 00 00

44ac is the value and 0e40 is the exponent and signed bit I suppose.

Just so you're clear (are you working with AIF? Is this the sampling rate?), it's not the "middle" bytes that are storing things, you just have a very, very small significand relative to the size allowed. First things first, we have to reverse the byte order because of the endianness of x86. While we're at it, we'll ignore the padding of the last 6 bytes. This yields:
Code:
40 0E AC 44 00 00 00 00 00 00
in binary:
Code:
01000000 00001110 10101100 01000100 00000000 00000000 00000000 00000000 00000000 00000000

The format is:
bit 79 is the sign bit. In this case, this is 0.

bits 64-78 are the exponent, offset by 16383. This is:
100000000001110
or
16398-16383=15

bits 0-63 are the significand, in this case:
1.0101100010001

So we raise -1 to the sign bit, giving us 1. We then shift the decimal of the significand by the value of the exponent, yielding:
1010110001000100.0
Multiply times 1 for the sign, and convert to decimal, and we get:
44100.0

It seems easiest to just keep the constants for "standard" sampling rates as literals in your code. I'm sure you COULD have an arbitrary rate, but generally things stick to ~6 rates that you could easily just encode once, then always just have constant unsigned char arrays with those values.

-Lee
 

subsonix

macrumors 68040
Original poster
Feb 2, 2008
3,551
79
Just so you're clear (are you working with AIF? Is this the sampling rate?), it's not the "middle" bytes that are storing things, you just have a very, very small significand relative to the size allowed. First things first, we have to reverse the byte order because of the endianness of x86. While we're at it, we'll ignore the padding of the last 6 bytes.

As I said, the program already works, I have taken care of endianess, it´s very obvious if you dont. What I meant with the middle bytes was its not stored from the lowest address as with the extended data type in sane.h, the data have six bytes with zero in them on each side, so in that sence it is the midle.

I have made a function that reads the sample rate field of the file I wan´t to convert in to a long double. I then copy the first ten bytes into a char array, copy the end to a short, perform endian conversion andcopy to the begining.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.