File: safe_double.h

package info (click to toggle)
libtioga-ruby 1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 9,956 kB
  • ctags: 3,257
  • sloc: ansic: 31,801; ruby: 16,346; sh: 172; makefile: 114
file content (104 lines) | stat: -rw-r--r-- 2,772 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**********************************************************************

   safe_double.h: small abstraction for storing double without endianess
   problems
   
   Copyright (C) 2006 Vincent Fourmond

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Library Public License as published
   by the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Library General Public License for more details.
   
   You should have received a copy of the GNU Library General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   
**********************************************************************/

/* This file provides two functions: store_double and get_double, which
   can be used in a 'safe' way to store doubles  and retrive them
   in a hopefully platform-independent form. However, it just 
   stores it without regards to that if ieee754.h isn't found...
*/

#ifndef _DOUBLE_H
#define _DOUBLE_H

#define STORE_LOWER_BYTE(a,p) do {\
*(p++) = (a) & 0xFF; (a) >>= 8; }\
while(0)
#define STORE_UNSIGNED(a,p)   for(i = 0; i < 4; i++) STORE_LOWER_BYTE(a,p);
#define GET_UNSIGNED(a,p) do { a = 0; for(i = 0; i < 4; i++) \
(a) |= *(p++) << (i * 8); } while (0)

#ifdef HAVE_IEEE754_H
#include <ieee754.h>


static inline void store_double(double a, unsigned char * p)
{
  unsigned int tmp;
  int i;
  union ieee754_double d;
  d.d = a;
  /* we store it with lower bytes firts */
  tmp = d.ieee.mantissa1;
  STORE_UNSIGNED(tmp, p);
  tmp = d.ieee.negative << 31 |
    d.ieee.exponent << 20 | 
    d.ieee.mantissa0;
  STORE_UNSIGNED(tmp, p);
}


static inline double get_double(const unsigned char * p)
{
  unsigned int tmp;
  int i;
  union ieee754_double d;
  GET_UNSIGNED(tmp, p);
  d.ieee.mantissa1 = tmp;
  GET_UNSIGNED(tmp, p);
  d.ieee.mantissa0 = tmp & 0xFFFFF;
  d.ieee.exponent = (tmp >> 20) & 0x7FF;
  d.ieee.negative = (tmp >> 31) & 0x1;
  return d.d;
}

#else

union basic_double{
  double d;
  struct {
    unsigned int a:32;
    unsigned int b:32;
  } i;
};

static inline void store_double(double a, unsigned char * p)
{
  union basic_double d;
  int i;
  d.d = a;
  STORE_UNSIGNED(d.i.a, p);
  STORE_UNSIGNED(d.i.b, p);
}

static inline double get_double(const unsigned char * p)
{
  union basic_double d;
  int i;
  GET_UNSIGNED(d.i.a, p);
  GET_UNSIGNED(d.i.b, p);
  return d.d;
}

#endif /* HAVE_IEEE754_H */

#endif /* _DOUBLE_H */