Pages: [1]   Go Down
Author Topic: 4 byte float (double) to 8 byte  (Read 771 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Is there a way to convert 4 byte double (UNO) to 8 byte double? My soft accepts only 8 byte double. Seems to be very simple but I I am very much beginner. And there is not much in Google about it. Thank you.
Logged

Idaho, US
Offline Offline
God Member
*****
Karma: 19
Posts: 859
Special User
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there a way to convert 4 byte double (UNO) to 8 byte double? My soft accepts only 8 byte double.
What software is that and what protocol are you using to communicate the double to it?
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 50
Posts: 1767
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Is there a way to convert 4 byte double (UNO) to 8 byte double? My soft accepts only 8 byte double. Seems to be very simple but I I am very much beginner. And there is not much in Google about it. Thank you.
There are ways to do the conversion, but since the GCC compiler used by the AVR chips in most Arduinos, has decided that 'double' should be equivalent to 'float', you will have to do the conversion manually.  If you do a search for IEEE 754, it should give you the basic format for single precision and double precision.

Alternatively, if you are shipping the bits to a host computer, add an extra step to read the value as 'float' and then do a conversion to 'double', and it will do the conversion in a few instructions, and you won't have to learn the details of IEEE floating point.  Note, if you are shipping raw bits across a wire, note that depending on what your host computer is, you will have possibly swap the bytes if the host is big endian.
« Last Edit: September 07, 2013, 01:52:38 am by MichaelMeissner » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, thanks.
I am using hodini. Here is a link on what I am looking for: http://www.sidefx.com/docs/houdini12.0/nodes/chop/pipein. I got everything except 4 byte double to 8 byte double. What is the way for manual conversation? thanks a lot.
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You want to send samples to Hodini, but Hodini accepts only double as sample data.

The avr gcc compiler has no double support for the 8-bit microcontrollers.
You have a really tough problem.
http://arduino.cc/en/Reference/Double

You need to do some magical bits and byte shuffling, like this:
http://stackoverflow.com/questions/5614222/parse-double-precision-ieee-floating-point-on-a-c-compiler-with-no-double-precis
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hodini wants 8 bytes for a double, if it wants it in binary format you have to make a struct resembling the double specification consisting of

sign, mantissa, exponent

extract these 3 values from the  arduino flat and assign them to the fields according to specs (not trivial but doable)
Then send the 8 bytes you just filled.

Two helper functions I wrote some ago, so you can started
Code: (experimental)
// HELPER FUNCTIONS

// check IEEE754 bit layout to understand code below.
// note the exponent is a power of 2
byte getExponentByte(float number)
{
    uint8_t e = (*(((byte*) &number)+3) & 0x7F) << 1;
    if (*(((byte*) &number)+2) & 0x80) e++;
    return e;
}

uint8_t getSign(float number)
{
  return (*(((byte*) &number)+3) & 0x80);
}
« Last Edit: September 07, 2013, 10:28:24 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


did some prototyping and this is almost working

Code: (experimental)
//
//    FILE: float2double.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: experimental expands a float in a IEEE 754 double to be posted to PC.
//
// http://en.wikipedia.org/wiki/Double_precision
// http://en.wikipedia.org/wiki/Single-precision_floating-point_format
//
// Released to the public domain
//

struct DBL
{
unsigned long f:29; // filler
unsigned long m:23;
unsigned int e:11;
unsigned int s:1;
}
dbl;

union FLTCONV
{
  struct
  {
unsigned long m:23;
unsigned int e:8;
unsigned int s:1;
  }
  p;
  float f;
}
flt;

union DBLCONV
{
  struct DBL p;
  byte b[8];
}
da;



void setup()
{
  Serial.begin(115200);
  Serial.println(sizeof(dbl));

  Serial.println();
  for (float f = -50.0; f < 50.0; f += 10.0)
  {
    dumpFLOAT(f);
    float2DA(f);
    dumpDA();
    Serial.println();
  }

  dumpFLOAT(0.15625);
  dumpFLOAT(PI);
  float2DA(PI);
  dumpDA();

  Serial.println("done");

}

void loop()
{
}

///////////////////////////////////////////////////////////////////////////////////


void dumpFLOAT(float number)
{
  flt.f = number;
  Serial.print(flt.p.s, HEX);
  Serial.print("\t");
  Serial.print(flt.p.e, HEX);
  Serial.print("\t");
  Serial.println(flt.p.m, HEX);
}

void dumpDBL(struct DBL dbl)
{
  Serial.print(dbl.s, HEX);
  Serial.print("\t");
  Serial.print(dbl.e, HEX);
  Serial.print("\t");
  Serial.println(dbl.m, HEX);
}

void dumpDA()
{
  Serial.print(da.p.s, HEX);
  Serial.print("\t");
  Serial.print(da.p.e, HEX);
  Serial.print("\t");
  Serial.println(da.p.m, HEX);

  for (int i=0; i<8; i++)
  {
    Serial.print(da.b[7-i], HEX);
    Serial.print('\t');
  }
  Serial.println();
}

void float2DA(float number)
{
  flt.f = number;
  da.p.s = flt.p.s;
  da.p.e = flt.p.e-127 +1023;  // exponent differ
  da.p.m = flt.p.m;
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

output of the lines above that convert PI to a double
Code:
 dumpFLOAT(PI);
  float2DA(PI);
  dumpDA();

0   80   490FDB      // sign, exponent, mantisse  float
0   400   490FDB      // sign, exponent, mantisse  double
40   9   21   FB   60   0   0   0         << byte array == dump of the double

Then I did  a quick check in Python t check the byte array
Code:
>> from struct import *
>> unpack('d', '\x00\x00\x00\x60\xFB\x21\x09\x40')       <<< note that the order is inverse  here

output :  (3.1415927410125732,)
Yes!, that looks like PI smiley

Arduino printing PI = 3.14159274101257324218
Python printing PI =  3.14159265359  (7 digits right)

the above code proofs Arduino can convert a 32bit IEEE754 float to an array of bytes representing a 64 bit IEEE754 double.
The way back can also be done in a similar way, main point of attention is the overflow for the exponent.
if exponent is too big mapping to INFinity seems logical

and yes the code still needs a to be cleaned up into proper functions without global vars
void float2DoublePacked(float number; byte* ar; int byteOrder);
float DoublePacked2float(byte ar*; int byteOrder);
maybe part of a IEEE754 conversion class?

« Last Edit: September 07, 2013, 11:36:42 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 50
Posts: 1767
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Note, this code will only work on a little endian system (like the Arduino) sending data to another little endian system (like a PC).  If you have either system that is big endian, then this code will not work.

If you were doing the conversion from double precision down to single precision, you would have to worry about setting the float to infinity if the exponent is too large, doing an appropriate rounding mode, and creating denomalized numbers if the value can be represented as a denormalized number.  However, since you only need to worry about converting from single precision to double, you don't have to worry about it.

Your code does not handle Infinities, NaN's (not a number), nor does it handle denormalized numbers (numbers that cannot be represented in 32-bit floating point directly, but can represent some bits, if you convert these to double precision, you should normalize the bits you have, and fill the remaining bits with 0).

Whether these corner cases will be important in you application, I don't know.  If you don't decide to handle them, you should at least put a comment in the text saying you aren't handling the corner cases, for the next person who uses your code.
« Last Edit: September 07, 2013, 12:16:03 pm by MichaelMeissner » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very true!
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Impressive work robtillaart.
Perhaps you can make a playground page for it. Even if it is completely finished yet.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you guys!!! Everything is working. I feel as I invented a wheel and it is tuning around. I still do not fully understand how it works even though I got a concept.
Mr. robtillaart - you are the best!!! If I were in Netherlands I'd buy you 10^99... liters of beer. I am so happy but now is time to go inside Houdini where I am much more comfortable...
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Impressive work robtillaart.
Perhaps you can make a playground page for it. Even if it is completely finished yet.
Working on unpacking "incoming double" too and collect some IEEE snippets from the trenches of my hard disk smiley-wink
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


see - http://forum.arduino.cc/index.php?topic=186860 - for a draft IEEE754tools lib + ref to playground article
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: