KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
float.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 KM3NeT Collaboration
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : float.c
11  * Created : 11 apr. 2014
12  * Author : Vincent van Beveren
13  */
14 
15 #include "util/float.h"
16 
17 #include <stdbool.h>
18 
19 #include "util/macro.h"
20 #include "util/func.h"
21 
22 #define F32_SIGN BIT(31)
23 #define F32_EXP_SHIFT 23
24 #define F32_EXP_MASK ( MASK(8) << ( F32_EXP_SHIFT ) )
25 #define F32_EXP_BIAS 127
26 #define F32_FRAC_MASK MASK(23)
27 #define F32_FRAC_SIZE 23
28 
29 static const int fltDecToMul[] = {
30  1,
31  10,
32  100,
33  1000,
34  10000,
35  100000,
36  1000000,
37  10000000,
38  100000000
39 };
40 
41 static int countbits(uint32_t val)
42 {
43  int c;
44  for (c = 0; val != 0; val >>= 1, c++) {};
45  return c;
46 }
47 
48 static int32_t _fltToI32(f32_t vin, uint32_t multiplier, bool applySign)
49 {
50  // uint32_t vin = castFloatToU32(vin_);
51 
52  // get exponent shift
53  int shift = ((vin & F32_EXP_MASK) >> F32_EXP_SHIFT) - F32_EXP_BIAS;
54 
55  // get fractional part
56  int32_t vout = vin & F32_FRAC_MASK;
57 
58  // add 1 << 23
59  vout |= 1 << F32_FRAC_SIZE;
60 
61  // indicate 23 lower bits should be shifted off.
62  shift -= F32_FRAC_SIZE;
63 
64  // check if the multiplication stays within 31 bits (excluding sign byte)
65  if (multiplier > 0xFF)
66  {
67  int toomany = countbits(multiplier) - 8;
68  // shift them off right now, we'll loose precision, but its not to be helped
69  vout >>= toomany;
70  // and, since we already shifted this off, we don't need to do those later on
71  shift += toomany;
72  }
73 
74  // now multiply
75  vout *= multiplier;
76 
77  // apply the rest of the exponent
78  if (shift > 0)
79  vout <<= shift;
80  else if (shift < -31)
81  vout = 0;
82  else
83  vout = (int32_t)((uint32_t)vout >> (-shift)); // needs the cast, otherwise it shifts the sign
84 
85  if (applySign && (vin & F32_SIGN)) vout = -vout;
86 
87  return vout;
88 }
89 
90 int32_t fltToI32(f32_t vin, uint32_t multiplier)
91 {
92  return _fltToI32(vin, multiplier, true);
93 }
94 
95 
96 uint32_t fltFrac(f32_t value, int decimals)
97 {
98 
99  return _fltToI32(value, fltDecToMul[decimals], false) % fltDecToMul[decimals];
100 }
101 
102 int32_t fltInt(f32_t value)
103 {
104  return _fltToI32(value, 1, true);
105 }
106 
107 
108 // #define WITH_FLOAT
109 
110 #ifdef WITH_FLOAT
111 
112 float fltFromI16(int16_t val, int fBits)
113 {
114  float r = val * (1.0f/(32768 >> (15 - fBits)));
115  return r;
116 }
117 
118 #endif
119 
120 #ifndef WITH_FLOAT
121 
122 f32_t fltFromI16(int16_t val, int fBits)
123 {
124  bool sign;
125  uint32_t ival;
126  int zeros;
127 
128  if (val == 0) return 0;
129 
130  if (val < 0) { ival = -val; sign = true; }
131  else { ival = val; sign = false; }
132 
133  zeros = clz(ival) - 16;
134 
135  ival = (ival << (zeros + 8)) & 0x007fffff;
136  ival |= (142 - (zeros + fBits)) << 23;
137  if (sign) ival |= F32_SIGN;
138 
139  return ival;
140 }
141 
142 #endif
int32_t fltInt(f32_t value)
Returns the integer part of the floating point value.
Definition: float.c:102
uint32_t fltFrac(f32_t value, int decimals)
Returns the fractional part of the floating point with the specified number of decimals.
Definition: float.c:96
Special library for primitive IEEE 754 floating point handling without dragging all float support alo...
int clz(uint32_t val)
Count the leading zero&#39;s.
Definition: func.c:17
uint32_t f32_t
32 bit representation for float.
Definition: float.h:30
f32_t fltFromI16(int16_t val, int fBits)
Takes an integer value and converts it to a float.
Definition: float.c:122
Various useful functions.
Provides common macros.
int32_t fltToI32(f32_t value, uint32_t multiplier)
This takes a f32_t IEEE 754 single precision floating point, and converts it to a multiplied integer...
Definition: float.c:90