xoreos  0.0.5
util.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/util.h"
26 #include "src/common/debugman.h"
27 
28 #include <cassert>
29 #include <cstdarg>
30 #include <cstdio>
31 #include <cstdlib>
32 
33 void warning(const char *s, ...) {
34  char buf[STRINGBUFLEN];
35  va_list va;
36 
37  va_start(va, s);
38  vsnprintf(buf, STRINGBUFLEN, s, va);
39  va_end(va);
40 
41 #ifndef DISABLE_TEXT_CONSOLE
42  std::fputs("WARNING: ", stderr);
43  std::fputs(buf, stderr);
44  std::fputs("!\n", stderr);
45 #endif
46 
47  DebugMan.logString("WARNING: ");
48  DebugMan.logString(buf);
49  DebugMan.logString("!\n");
50 }
51 
52 void status(const char *s, ...) {
53  char buf[STRINGBUFLEN];
54  va_list va;
55 
56  va_start(va, s);
57  vsnprintf(buf, STRINGBUFLEN, s, va);
58  va_end(va);
59 
60 #ifndef DISABLE_TEXT_CONSOLE
61  std::fputs(buf, stderr);
62  std::fputs("\n", stderr);
63 #endif
64 
65  DebugMan.logString(buf);
66  DebugMan.logString("\n");
67 }
68 
69 void info(const char *s, ...) {
70  char buf[STRINGBUFLEN];
71  va_list va;
72 
73  va_start(va, s);
74  vsnprintf(buf, STRINGBUFLEN, s, va);
75  va_end(va);
76 
77 #ifndef DISABLE_TEXT_CONSOLE
78  std::fputs(buf, stdout);
79  std::fputs("\n", stdout);
80 #endif
81 
82  DebugMan.logString(buf);
83  DebugMan.logString("\n");
84 }
85 
86 void NORETURN_PRE error(const char *s, ...) {
87  char buf[STRINGBUFLEN];
88  va_list va;
89 
90  va_start(va, s);
91  vsnprintf(buf, STRINGBUFLEN, s, va);
92  va_end(va);
93 
94 #ifndef DISABLE_TEXT_CONSOLE
95  std::fputs("ERROR: ", stderr);
96  std::fputs(buf, stderr);
97  std::fputs("!\n", stderr);
98 #endif
99 
100  DebugMan.logString("ERROR: ");
101  DebugMan.logString(buf);
102  DebugMan.logString("!\n");
103 
104  std::exit(1);
105 }
106 
107 
108  // We just directly convert here because most systems have float in IEEE 754-1985
109  // format anyway. However, should we find another system that has this differently,
110  // we might have to do something more here...
113  float dFloat;
114 };
115 
117 
118  floatConvert conv;
119 
120  conv.dInt = data;
121 
122  return conv.dFloat;
123 }
124 
125 uint32 convertIEEEFloat(float value) {
126  floatConvert conv;
127 
128  conv.dFloat = value;
129 
130  return conv.dInt;
131 }
132 
133 
134  // We just directly convert here because most systems have double in IEEE 754-1985
135  // format anyway. However, should we find another system that has this differently,
136  // we might have to do something more here...
137 
140  double dDouble;
141 };
142 
143 double convertIEEEDouble(uint64 data) {
144  doubleConvert conv;
145 
146  conv.dInt = data;
147 
148  return conv.dDouble;
149 }
150 
151 uint64 convertIEEEDouble(double value) {
152  doubleConvert conv;
153 
154  conv.dDouble = value;
155 
156  return conv.dInt;
157 }
158 
159 double readNintendoFixedPoint(uint32 value, bool sign, uint8 iBits, uint8 fBits) {
160  /* The Nintendo DS uses fixed point values of various formats. This method can
161  * convert them all into a usual floating point double. */
162 
163  assert((iBits + fBits + (sign ? 1 : 0)) <= 32);
164 
165  // Masks for the integer, fractional and sign parts
166  const uint32 fMask = (UINT64_C(1) << fBits) - 1;
167  const uint32 iMask = ((UINT64_C(1) << (iBits + fBits)) - 1) - fMask;
168  const uint32 sMask = UINT64_C(1) << (iBits + fBits);
169 
170  // Step of a fractional unit
171  const uint32 fDiv = (1 << fBits);
172 
173  // The fractional and integer parts themselves
174  int32 fPart = value & fMask;
175  int32 iPart = (value & iMask) >> fBits;
176 
177  // If this is a negative value, negate the integer part (which is a two's complement)
178  if (sign && ((value & sMask) != 0))
179  iPart = -((int32) ((~iPart & (iMask >> fBits)) + 1));
180 
181  return (double)iPart + ((double) fPart) / ((double) fDiv);
182 }
183 
184 /* .--- Convert IEEE float16 to IEEE float32, based on code by James Tursa ---.
185  *
186  * This function extends a 16-bit (half-precision) IEEE 754 floating-point
187  * number into a 32-bit (full-precision) IEEE 754 float-point number.
188  *
189  * The special cases of -Inf, Inf and NaN are handled correctly.
190  * Denormalized float16 numbers are adjusted to normalized float32 numbers.
191  *
192  * This code is heavily based on the halfp2singles() function found in
193  * ieeehalfprecision.c by James Tursa, released under the terms of the
194  * 2-Clause BSD license as part of the "IEEE 754r Half Precision floating
195  * point converter" MATLAB package.
196  * (<https://www.mathworks.com/matlabcentral/fileexchange/23173-ieee-754r-half-precision-floating-point-converter>)
197  */
198 float readIEEEFloat16(uint16 value) {
199  // Check for 0.0 / -0.0
200  if ((value & 0x7FFF) == 0)
201  return convertIEEEFloat(((uint32) value) << 16);
202 
203  uint16 vS = value & 0x8000; // float16 sign
204  uint16 vE = value & 0x7C00; // float16 exponent
205  uint16 vM = value & 0x03FF; // float16 mantissa
206 
207  const uint32 fS = ((uint32) vS) << 16; // float32 sign
208 
209  // Check for (-)Inf and NaN
210  if (vE == 0x7C00) {
211  // All exponent bits are set and the mantissa is 0: Inf / -Inf
212  if (vM == 0)
213  return convertIEEEFloat(0x7F800000 | fS);
214 
215  // All exponent bits are set and the mantissa is != 0: NaN
216  return convertIEEEFloat(0xFFC00000);
217  }
218 
219  // Not zero, infinity or NaN: this is a regular number
220 
221  // Unbias the float16 exponent, and bias the float32 exponent accordingly
222  int32 fER = ((int32) (vE >> 10)) - 15 + 127;
223 
224  // Is this float normalized? If so, we can directly extend it
225  if (vE != 0) {
226  const uint32 fE = ((uint32) fER) << 23; // float32 exponent, rebiased
227  const uint32 fM = ((uint32) vM ) << 13; // float32 mantissa
228 
229  // Combine sign, exponent and mantissa
230  return convertIEEEFloat(fS | fE | fM);
231  }
232 
233  // Denormalized float, we need to normalize it first
234 
235  // Shift the mantissa until it overflows, to find out the exponent adjustment
236  int aE = -1;
237  do {
238  aE++;
239  vM <<= 1;
240  } while ((vM & 0x0400) == 0);
241 
242  // Adjust the exponent, and clip the shifted mantissa to valid range again
243  fER -= aE;
244  vM &= 0x03FF;
245 
246  const uint32 fE = ((uint32) fER) << 23; // float32 exponent, rebiased and normalized
247  const uint32 fM = ((uint32) vM ) << 13; // float32 mantissa, normalized
248 
249  // Combine sign, exponent and mantissa
250  return convertIEEEFloat(fS | fE | fM);
251 }
252 // '--- Convert IEEE float16 to IEEE float32, based on code by James Tursa ---'
uint64_t uint64
Definition: types.h:206
uint8_t uint8
Definition: types.h:200
uint32 dInt
Definition: util.cpp:112
double convertIEEEDouble(uint64 data)
Convert a uint64 holding the bit pattern of a 64-bit IEEE 754 double precision floating point value i...
Definition: util.cpp:143
The debug manager, managing debug channels.
double dDouble
Definition: util.cpp:140
uint16_t uint16
Definition: types.h:202
Utility templates and functions.
#define UINT64_C(c)
Definition: types.h:220
void info(const char *s,...)
Definition: util.cpp:69
double readNintendoFixedPoint(uint32 value, bool sign, uint8 iBits, uint8 fBits)
Read a fixed-point value, in a format used by the Nintendo DS.
Definition: util.cpp:159
void warning(const char *s,...)
Definition: util.cpp:33
#define DebugMan
Shortcut for accessing the debug manager.
Definition: debugman.h:195
#define STRINGBUFLEN
Definition: system.h:415
float convertIEEEFloat(uint32 data)
Convert a uint32 holding the bit pattern of a 32-bit IEEE 754 single precision floating point value i...
Definition: util.cpp:116
uint32_t uint32
Definition: types.h:204
void status(const char *s,...)
Definition: util.cpp:52
float dFloat
Definition: util.cpp:113
float readIEEEFloat16(uint16 value)
Read a half-precision 16-bit IEEE float, converting it into a 32-bit iEEE float.
Definition: util.cpp:198
#define NORETURN_PRE
Definition: noreturn.h:35
void NORETURN_PRE error(const char *s,...)
Definition: util.cpp:86
uint64 dInt
Definition: util.cpp:139
int32_t int32
Definition: types.h:203