Code-Eli  0.3.6
floating_point.hpp
Go to the documentation of this file.
1 /*********************************************************************************
2 * Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * David D. Marshall - initial code and implementation
11 ********************************************************************************/
12 
13 #ifndef eli_util_floating_point_hpp
14 #define eli_util_floating_point_hpp
15 
16 #include <iostream>
17 
18 #include "eli/code_eli.hpp"
19 
20 #include "eli/util/traits.hpp"
21 
22 namespace eli
23 {
24  namespace util
25  {
26  union float_type
27  {
28  typedef uint32_t integer_type;
29  integer_type i;
30  struct
31  {
32  uint64_t mantissa : 23;
33  uint32_t exponent : 8;
34  uint32_t sign : 1;
35  } parts;
36  };
37 
38  struct double_type
39  {
40  typedef uint64_t integer_type;
41  integer_type i;
42  struct
43  {
44  uint64_t mantissa : 52;
45  uint32_t exponent : 11;
46  uint32_t sign : 1;
47  } parts;
48  };
49 
51  {
52 #if defined(_WIN32)
53  typedef uint64_t integer_type;
54  integer_type i;
55  struct
56  {
57  uint64_t mantissa : 52;
58  uint32_t exponent : 11;
59  uint32_t sign : 1;
60  } parts;
61 #else
62  typedef uint64_t integer_type;
63  integer_type i[2];
64  struct
65  {
66  uint64_t mantissa : 63;
67  uint32_t integer_bit : 1;
68  uint32_t exponent : 15;
69  uint32_t sign : 1;
70  } parts;
71 #endif
72  };
73 
74  const float_type * set_floating_point_type(const float * pcf)
75  {
76  return static_cast<const float_type *>(static_cast<const void *>(pcf));
77  }
78 
80  {
81  return static_cast<float_type *>(static_cast<void *>(pf));
82  }
83 
84  const double_type * set_floating_point_type(const double * pcf)
85  {
86  return static_cast<const double_type *>(static_cast<const void *>(pcf));
87  }
88 
90  {
91  return static_cast<double_type *>(static_cast<void *>(pf));
92  }
93 
94  const long_double_type * set_floating_point_type(const long double * pcf)
95  {
96  return static_cast<const long_double_type *>(static_cast<const void *>(pcf));
97  }
98 
100  {
101  return static_cast<long_double_type *>(static_cast<void *>(pf));
102  }
103 
104  std::ostream & operator<<(std::ostream &ostr, const float_type &ft)
105  {
106  float_type::integer_type sign_shift(31);
107  float_type::integer_type mantissa_mask(1); mantissa_mask=(mantissa_mask<<23) - 1;
108  float_type::integer_type exponent_shift(23);
109  float_type::integer_type exponent_mask(0xff);
110 
111  ostr << std::hex << "0x" << (ft.i >> sign_shift)
112  << " 0x" << (ft.i & mantissa_mask)
113  << " 0x" << ((ft.i >> exponent_shift) & exponent_mask)
114  << std::dec;
115 
116  return ostr;
117  }
118 
119  std::ostream & operator<<(std::ostream &ostr, const double_type &ft)
120  {
121  double_type::integer_type sign_shift(63);
122  double_type::integer_type mantissa_mask(1); mantissa_mask=(mantissa_mask<<52) - 1;
123  double_type::integer_type exponent_shift(52);
124  double_type::integer_type exponent_mask(0x7ffb);
125 
126  ostr << std::hex << "0x" << (ft.i >> sign_shift)
127  << " 0x" << (ft.i & mantissa_mask)
128  << " 0x" << ((ft.i >> exponent_shift) & exponent_mask)
129  << std::dec;
130 
131  return ostr;
132  }
133 
134  std::ostream & operator<<(std::ostream &ostr, const long_double_type &ft)
135  {
136 #if defined(_WIN32)
137  double_type::integer_type sign_shift(63);
138  double_type::integer_type mantissa_mask(1); mantissa_mask=(mantissa_mask<<52) - 1;
139  double_type::integer_type exponent_shift(52);
140  double_type::integer_type exponent_mask(0x7ffb);
141 
142  ostr << std::hex << "0x" << (ft.i >> sign_shift)
143  << " 0x" << (ft.i & mantissa_mask)
144  << " 0x" << ((ft.i >> exponent_shift) & exponent_mask)
145  << std::dec;
146 
147  return ostr;
148 #else
149  double_type::integer_type mantissa_mask(1); mantissa_mask=0x7FFFFFFFFFFFFFFF;
150  double_type::integer_type exponent_shift(0);
151  double_type::integer_type exponent_mask(0x7fff);
152 
153  ostr << std::hex << "0x" << ft.parts.sign
154  << " 0x" << ft.parts.integer_bit
155  << " 0x" << (ft.i[0] & mantissa_mask)
156  << " 0x" << ((ft.i[1] >> exponent_shift) & exponent_mask)
157  << std::dec;
158 
159  return ostr;
160 #endif
161  }
162 
163  template<typename data__>
164  data__ increment_ulp(const data__ &/*d*/, const int &/*n_ulp*/)
165  {
166  static_assert(always_false<data__>::value, "Function not specialized for given type");
167  }
168 
169  template<>
170  float increment_ulp<float>(const float &f, const int &n_ulp)
171  {
172 #if defined(__GNUC__) && defined(NDEBUG) && !defined(__clang__) && (__GNUC__==4) && (__GNUC_MINOR__==5)
173  volatile
174 #endif
175  int32_t *pi;
176  float fr(f);
177 
178  pi=static_cast<int32_t *>(static_cast<void *>(&fr));
179  (*pi)+=n_ulp;
180  return fr;
181  }
182 
183  template<>
184  double increment_ulp<double>(const double &f, const int &n_ulp)
185  {
186 #if defined(__GNUC__) && defined(NDEBUG) && !defined(__clang__) && (__GNUC__==4) && (__GNUC_MINOR__==5)
187  volatile
188 #endif
189  int64_t *pi;
190  double fr(f);
191 
192  pi=static_cast<int64_t *>(static_cast<void *>(&fr));
193  (*pi)+=n_ulp;
194  return fr;
195  }
196 
197  template<>
198  long double increment_ulp<long double>(const long double &f, const int &n_ulp)
199  {
200 #if defined(_WIN32)
201  int64_t *pi;
202  double fr(f);
203 
204  pi=static_cast<int64_t *>(static_cast<void *>(&fr));
205  (*pi)+=n_ulp;
206  return fr;
207 #else
208  int32_t orig_integer_bit;
209 #if defined(__GNUC__) && defined(NDEBUG) && !defined(__clang__) && (__GNUC__==4) && (__GNUC_MINOR__==5)
210  volatile
211 #endif
212  int64_t *pi;
213 #if defined(__GNUC__) && defined(NDEBUG) && !defined(__clang__) && (__GNUC__==4) && (__GNUC_MINOR__==5)
214  volatile
215 #endif
216  long_double_type *pft;
217  long double fr(f);
218 
219  pi=static_cast<int64_t *>(static_cast<void *>(&fr));
220  pft=static_cast<long_double_type *>(static_cast<void *>(&fr));
221 
222  orig_integer_bit=pft->parts.integer_bit;
223  pi[0]+=n_ulp;
224 
225  // check if wrapped mantissa and correct
226  if ((pft->parts.integer_bit!=orig_integer_bit) && (orig_integer_bit==1))
227  {
228  pft->parts.integer_bit=1;
229  if (n_ulp>0)
230  {
231  ++(pft->parts.exponent);
232  }
233  else
234  {
235  --(pft->parts.exponent);
236  }
237  }
238  return fr;
239 #endif
240  }
241  }
242 }
243 #endif
float increment_ulp< float >(const float &f, const int &n_ulp)
Definition: floating_point.hpp:170
uint64_t integer_type
Definition: floating_point.hpp:62
Definition: math.hpp:20
const float_type * set_floating_point_type(const float *pcf)
Definition: floating_point.hpp:74
uint32_t sign
Definition: floating_point.hpp:46
Definition: traits.hpp:27
uint64_t integer_type
Definition: floating_point.hpp:40
integer_type i
Definition: floating_point.hpp:29
Definition: floating_point.hpp:50
Definition: floating_point.hpp:38
double increment_ulp< double >(const double &f, const int &n_ulp)
Definition: floating_point.hpp:184
uint64_t mantissa
Definition: floating_point.hpp:66
struct eli::util::float_type::@2 parts
uint64_t mantissa
Definition: floating_point.hpp:32
uint32_t integer_bit
Definition: floating_point.hpp:67
uint32_t integer_type
Definition: floating_point.hpp:28
std::ostream & operator<<(std::ostream &ostr, const float_type &ft)
Definition: floating_point.hpp:104
integer_type i
Definition: floating_point.hpp:41
uint32_t sign
Definition: floating_point.hpp:34
long double increment_ulp< long double >(const long double &f, const int &n_ulp)
Definition: floating_point.hpp:198
uint32_t exponent
Definition: floating_point.hpp:45
data__ increment_ulp(const data__ &, const int &)
Definition: floating_point.hpp:164
struct eli::util::double_type::@3 parts
uint32_t exponent
Definition: floating_point.hpp:68
Definition: floating_point.hpp:26
uint32_t sign
Definition: floating_point.hpp:69
uint64_t mantissa
Definition: floating_point.hpp:44
struct eli::util::long_double_type::@4 parts
uint32_t exponent
Definition: floating_point.hpp:33
integer_type i[2]
Definition: floating_point.hpp:63