Allolib  1.0
C++ Components For Interactive Multimedia
al_Conversion.hpp
1 #ifndef INCLUDE_AL_CONVERSION_HPP
2 #define INCLUDE_AL_CONVERSION_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  This is a grab bag of routines for converting between built-in types
40 
41  File author(s):
42  Lance Putnam, 2010, putnam.lance@gmail.com
43 */
44 
45 #include <limits.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <cstdint>
49 #include <iostream>
50 #include <sstream> /* string conversion */
51 
52 namespace al {
53 
54 #ifndef UINT32_C
55 #define UINT32_C(v) v##UL
56 #endif
57 
58 #ifndef UINT64_C
59 #define UINT64_C(v) v##ULL
60 #endif
61 
62 #define CONST_(N, vf, vd) \
63  template <class T> \
64  struct N; \
65  template <> \
66  struct N<float> { \
67  operator uint32_t() const { return UINT32_C(vf); } \
68  }; \
69  template <> \
70  struct N<double> { \
71  operator uint64_t() const { return UINT64_C(vd); } \
72  };
73 
74 CONST_(MaskExpo, 0x7F800000,
75  0x7FF0000000000000) // IEEE-754 floating-point exponent bit mask
76 CONST_(MaskFrac, 0x007FFFFF,
77  0x000FFFFFFFFFFFFF) // IEEE-754 floating-point fraction bit mask
78 CONST_(MaskSign, 0x80000000,
79  0x8000000000000000) // IEEE-754 floating-point sign bit mask
80 CONST_(Expo1, 0x3F800000,
81  0x3FF0000000000000) // IEEE-754 floating-point [1-2) exponent interval
82 #undef CONST_
83 
85 template <class T>
86 struct Twiddle;
87 
88 template <>
89 struct Twiddle<float> {
90  Twiddle(const float& v) : f(v) {}
91  Twiddle(const uint32_t& v) : u(v) {}
92  Twiddle(const int32_t& v) : i(v) {}
93  union {
94  int32_t i;
95  uint32_t u;
96  float f;
97  };
98 };
99 
100 template <>
101 struct Twiddle<double> {
102  Twiddle(const double& v) : f(v) {}
103  Twiddle(const uint64_t& v) : u(v) {}
104  Twiddle(const int64_t& v) : i(v) {}
105  union {
106  int64_t i;
107  uint64_t u;
108  double f;
109  };
110 };
111 
113 char base10To36(int dec10);
114 
116 int base36To10(char ascii36);
117 
119 
123 uint32_t bitsToUInt(const char* strBin);
124 
126 float blockSubnormal(float v);
127 
129 double blockSubnormal(double v);
130 
132 
135 template <class T>
136 T clone(const T& obj) {
137  return T(obj);
138 }
139 
141 int endian();
142 
144 
148 uint32_t floatExponent(float v);
149 
151 float floatMantissa(float v);
152 
154 
157 float fraction(uint32_t bits, uint32_t phase);
158 
160 float intToUnit(int16_t v);
161 
163 
166 inline float punUF(uint32_t v) {
167  Twiddle<float> u(v);
168  return u.f;
169 }
170 
172 
175 inline uint32_t punFU(float v) {
176  Twiddle<float> u(v);
177  return u.u;
178 }
179 
181 inline int32_t punFI(float v) {
182  Twiddle<float> u(v);
183  return u.i;
184 }
185 
187 inline uint64_t punFU(double v) {
188  Twiddle<double> u(v);
189  return u.u;
190 }
191 
193 inline int64_t punFI(double v) {
194  Twiddle<double> u(v);
195  return u.i;
196 }
197 
199 inline double punUF(uint64_t v) {
200  Twiddle<double> u(v);
201  return u.f;
202 }
203 
205 inline double punIF(int64_t v) {
206  Twiddle<double> u(v);
207  return u.f;
208 }
209 
211 template <typename T>
212 void swapBytes(T& word);
213 
215 template <typename T>
216 void swapBytes(T* data, unsigned count);
217 
219 template <class T>
220 std::string toString(const char* fmt, const T& v);
221 
223 template <class T>
224 std::string toString(const T& v);
225 
227 template <class T>
228 std::string toString(const T* v, int num, int stride = 1);
229 
231 template <class T>
232 T uintToUnit(uint32_t v);
233 
235 template <class T>
236 T uintToUnitS(uint32_t v);
237 
239 int16_t unitToInt16(float v);
240 
242 
245 uint32_t unitToUInt(float u);
246 
248 
252 uint32_t unitToUInt2(float u);
253 
255 uint8_t unitToUInt8(float u);
256 
257 // Implementation
258 //------------------------------------------------------------------------------
259 
260 inline char base10To36(int v) {
261  static const char* c = "0123456789abcdefghijklmnopqrstuvwxyz";
262  if (v >= 0 && v <= 35) return c[v];
263  return '0';
264 }
265 
266 inline int base36To10(char v) {
267  v = tolower(v);
268  if (v >= '0' && v <= '9') return v - '0';
269  if (v >= 'a' && v <= 'z') return v - 'a' + 10;
270  return 0; // non-alphanumeric
271 }
272 
273 inline uint32_t bitsToUInt(const char* string) {
274  uint32_t v = 0;
275  size_t n = strlen(string);
276  for (size_t i = 0; i < n; ++i)
277  if (string[i] == '1') v |= 1 << (n - 1 - i);
278  return v;
279 }
280 
281 // alternate version...
282 // inline uint32_t bitsToUInt(const char * bits){
283 // uint32_t i=0, r=0;
284 // for(; bits[i] && i<32; ++i) r |= ((bits[i]=='1'?1:0) << (31-i));
285 // return r>>(32-i);
286 //}
287 
289 inline float blockSubnormal(float v) {
290  const uint32_t i = punFU(v);
291  const uint32_t frac = i & MaskFrac<float>();
292  const uint32_t expo = i & MaskExpo<float>();
293  if (expo == 0 && frac != 0) v = 0.f;
294  return v;
295 }
296 
298 inline double blockSubnormal(double v) {
299  const uint64_t i = punFU(v);
300  const uint64_t frac = i & MaskFrac<double>();
301  const uint64_t expo = i & MaskExpo<double>();
302  if (expo == 0 && frac != 0) v = 0.;
303  return v;
304 }
305 
306 inline int endian() {
307  static int x = 1;
308  return *(char*)&x;
309 }
310 
311 inline uint32_t floatExponent(float v) { return punFU(v) >> 23 & 0xff; }
312 
313 inline float floatMantissa(float v) {
314  uint32_t frac = punFU(v);
315  frac = (frac & MaskFrac<float>()) | Expo1<float>();
316  return punUF(frac) - 1.f;
317 }
318 
319 inline float fraction(uint32_t bits, uint32_t phase) {
320  phase = phase << bits >> 9 | Expo1<float>();
321  return punUF(phase) - 1.f;
322 }
323 
324 inline float intToUnit(int16_t v) {
325  uint32_t vu = (((uint32_t)v) + 0x808000)
326  << 7; // set fraction in float [2, 4)
327  return punUF(vu) - 3.f;
328 }
329 
330 // This is used by swapBytes
331 template <int NumBytes>
332 void swapBytesN(void* word);
333 
334 template <>
335 inline void swapBytesN<1>(void* word) {}
336 
337 template <>
338 inline void swapBytesN<2>(void* word) {
339  uint16_t& v = *(uint16_t*)word;
340  v = (v >> 8) | (v << 8);
341 }
342 
343 template <>
344 inline void swapBytesN<3>(void* word) {
345  uint8_t* v = (uint8_t*)word;
346  v[0] ^= v[2];
347  v[2] ^= v[0];
348  v[0] ^= v[2];
349 }
350 
351 template <>
352 inline void swapBytesN<4>(void* word) {
353  uint32_t& v = *(uint32_t*)word;
354  v = ((v >> 24)) | ((v >> 8) & 0x0000ff00UL) | ((v << 8) & 0x00ff0000UL) |
355  ((v << 24));
356 }
357 
358 template <>
359 inline void swapBytesN<8>(void* word) {
360  uint64_t& v = *(uint64_t*)word;
361  v = ((v >> 56)) | ((v >> 40) & 0x000000000000ff00ULL) |
362  ((v >> 24) & 0x0000000000ff0000ULL) | ((v >> 8) & 0x00000000ff000000ULL) |
363  ((v << 8) & 0x000000ff00000000ULL) | ((v << 24) & 0x0000ff0000000000ULL) |
364  ((v << 40) & 0x00ff000000000000ULL) | ((v << 56));
365 }
366 
367 template <typename T>
368 inline void swapBytes(T& v) {
369  swapBytesN<sizeof(v)>(&v);
370 }
371 
372 template <class T>
373 inline void swapBytes(T* data, unsigned count) {
374  for (unsigned i = 0; i < count; ++i) swapBytes(data[i]);
375 }
376 
377 template <class T>
378 std::string toString(const char* fmt, const T& v) {
379  char buf[32];
380  snprintf(buf, sizeof(buf), fmt, v);
381  return std::string(buf);
382 }
383 
384 template <class T>
385 std::string toString(const T* v, int n, int s) {
386  std::string r;
387  for (int i = 0; i < n; ++i) {
388  r += toString(v[i * s]);
389  if (i < (n - 1)) r += ", ";
390  }
391  return r;
392 }
393 
394 template <class T>
395 std::string toString(const T& v) {
396  using namespace std;
397  stringstream ss(stringstream::in | stringstream::out);
398  ss << v;
399  string r;
400  ss >> r;
401  return r;
402 }
403 
404 template <>
405 inline float uintToUnit<float>(uint32_t v) {
406  v = v >> 9 | Expo1<float>(); // float in [1, 2)
407  return punUF(v) - 1.f;
408 }
409 
410 template <>
411 inline float uintToUnitS<float>(uint32_t v) {
412  v = v >> 9 | 0x40000000; // float in [2, 4)
413  return punUF(v) - 3.f;
414 }
415 
416 inline int16_t unitToInt16(float v) {
417  float r = v + 3.f; // put in [2,4)
418  return int16_t((al::punFU(r) >> 7) + (1 << 15));
419 }
420 
421 inline uint32_t unitToUInt(float v) {
422  ++v; // go into [1,2] range, FP fraction is now result
423  return punFU(v) << 9;
424 }
425 
426 // TODO: make 64-bit ready
427 inline uint32_t unitToUInt2(float v) {
428  uint32_t normalU = punFU(v);
429  uint32_t rbs = 126UL - (normalU >> 23UL);
430  // printf("%x %lu\n", (normalU | 0x800000) << 8, rbs);
431  // printf("%x\n", 0x80000000UL >> rbs);
432  return (((normalU | 0x800000UL) << 8UL) & (~ULONG_MAX | 0xffffffffUL)) >> rbs;
433 
434  // uint32_t normalU = punFU(v);
435  // uint32_t rbs = 118UL - ((normalU >> 23UL) & (~ULONG_MAX | 0x7fffffUL));
438  // return ((normalU & (~ULONG_MAX | 0xffffffUL)) | 0x800000UL) >> rbs;
441 
442  // Her00
443  // float y = v + 1.f;
444  // return ((unsigned long&)v) & 0x7FFFFF; // last 23 bits
445 }
446 
447 inline uint8_t unitToUInt8(float u) {
448  ++u;
449  return (punFU(u) >> 15) & MaskFrac<float>();
450 }
451 
452 } // namespace al
453 
454 #endif
Definition: al_App.hpp:23
uint32_t floatExponent(float v)
Returns biased decimal value of 32-bit float exponent field.
uint32_t punFU(float v)
Type-pun 32-bit float to 32-bit unsigned int.
int base36To10(char ascii36)
Convert ascii base-36 character to decimal integer.
int16_t unitToInt16(float v)
Convert float in [-1, 1) to 16-bit signed int in [0, 2^16)
uint32_t bitsToUInt(const char *strBin)
Convert a string of 1s and 0s to an integer.
float floatMantissa(float v)
Returns mantissa field as float between [0, 1).
float punUF(uint32_t v)
Type-pun 32-bit unsigned int to 32-bit float.
int endian()
Returns 1 if little endian, 0 if big endian.
T clone(const T &obj)
Returns temporary copy-constructed object.
float blockSubnormal(float v)
Returns zero if argument is subnormal, otherwise returns argument.
float fraction(uint32_t bits, uint32_t phase)
Converts linear integer phase to fraction.
char base10To36(int dec10)
Convert decimal integer to ascii base-36 character.
uint32_t unitToUInt(float u)
Convert float in [0, 1) to 32-bit unsigned int in [0, 2^32)
T uintToUnitS(uint32_t v)
Convert 32-bit unsigned integer to unit float in [-1, 1)
uint32_t unitToUInt2(float u)
Convert float in [0, 1) to 32-bit unsigned int in [0, 2^32)
void swapBytes(T &word)
Swap the bytes of a word in-place.
T uintToUnit(uint32_t v)
Convert 32-bit unsigned integer to unit float in [0, 1)
float intToUnit(int16_t v)
Convert 16-bit signed integer to floating point in [-1, 1)
int32_t punFI(float v)
Type-pun 32-bit float to 32-bit signed int.
uint8_t unitToUInt8(float u)
Convert float in [0, 1) to 8-bit unsigned int in [0, 256)
std::string toString(const char *fmt, const T &v)
Convert argument to a string using snprintf.
double punIF(int64_t v)
Type-pun 64-bit signed int to 64-bit float.
Union for twiddling bits of floats.