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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
|
// --------------------------------------------------------------------------
// OpenMS -- Open-Source Mass Spectrometry
// --------------------------------------------------------------------------
// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
// ETH Zurich, and Freie Universitaet Berlin 2002-2013.
//
// This software is released under a three-clause BSD license:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of any author or any participating institution
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
// For a full list of authors, refer to the file AUTHORS.
// --------------------------------------------------------------------------
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// --------------------------------------------------------------------------
// $Maintainer: Oliver Kohlbacher $
// $Authors: Marc Sturm, Clemens Groepl $
// --------------------------------------------------------------------------
#ifndef OPENMS_CONCEPT_TYPES_H
#define OPENMS_CONCEPT_TYPES_H
#include <OpenMS/config.h>
#include <limits>
#include <cstddef> // for size_t
#include <ctime>
#include <cmath>
#include <string>
#include <iostream>
#include <iomanip>
// If possible use the ISO C99-compliant header stdint.h
// to define the portable integer types.
#ifdef OPENMS_HAS_STDINT_H
#include <stdint.h>
#endif
namespace OpenMS
{
/**
@brief Signed integer type (32bit)
@ingroup Concept
*/
typedef OPENMS_INT32_TYPE Int32;
/**
@brief Signed integer type (64bit)
@ingroup Concept
*/
typedef OPENMS_INT64_TYPE Int64;
/**
@brief Unsigned integer type (64bit)
@ingroup Concept
*/
typedef OPENMS_UINT64_TYPE UInt64;
/**
@brief Time type
Use this type to represent a point in time (as a synonym for time_t).
@ingroup Concept
*/
typedef time_t Time;
/**
@brief Unsigned integer type
@ingroup Concept
*/
//typedef size_t UInt;
typedef unsigned int UInt;
/**
@brief Signed integer type
@ingroup Concept
*/
//typedef OPENMS_SIZE_T_SIGNED Int;
typedef int Int;
/**
@brief Real type
Use this type to represent standard floating point numbers.
@ingroup Concept
*/
typedef float Real;
/**
@brief Double-precision real type
Use this type to represent double precision floating point numbers.
@ingroup Concept
*/
typedef double DoubleReal;
/**
@brief Byte type
Use this type to represent byte data (8 bit length). A Byte is always unsigned.
@ingroup Concept
*/
typedef OPENMS_BYTE_TYPE Byte;
/**
@brief A unique object ID (as unsigned 64bit type).
@see PersistentObject
@ingroup Concept
*/
typedef OPENMS_UINT64_TYPE UID;
/**
@brief Size type e.g. used as variable which can hold result of size()
@ingroup Concept
*/
typedef size_t Size;
/**
@brief Signed Size type e.g. used as pointer difference
@ingroup Concept
*/
typedef ptrdiff_t SignedSize;
enum ASCII
{
ASCII__BACKSPACE = '\b',
ASCII__BELL = '\a',
ASCII__CARRIAGE_RETURN = '\r',
ASCII__HORIZONTAL_TAB = '\t',
ASCII__NEWLINE = '\n',
ASCII__RETURN = ASCII__NEWLINE,
ASCII__SPACE = ' ',
ASCII__TAB = ASCII__HORIZONTAL_TAB,
ASCII__VERTICAL_TAB = '\v',
ASCII__COLON = ':',
ASCII__COMMA = ',',
ASCII__EXCLAMATION_MARK = '!',
ASCII__POINT = '.',
ASCII__QUESTION_MARK = '?',
ASCII__SEMICOLON = ';'
};
/**
@name Numbers of digits used for writing floating point numbers (a.k.a. precision).
These functions are provided to unify the handling of this issue throughout
%OpenMS. (So please don't use ad-hoc numbers ;-) )
If you want to avoid side effects you can use precisionWrapper() to write a
floating point number with appropriate precision; in this case the original
state of the stream is automatically restored afterwards. See
precisionWrapper() for details.
In practice, the number of decimal digits that the type can represent
without loss of precision are 6 digits for single precision
and 15 digits for double precision.
We have \f$2^{24}/10^{6}=16.777216\f$ and \f$2^{53}/10^{15}=9.007199254740992\f$,
so rounding will remove the remaining difference.
Example:
@code
#define NUMBER 12345.67890123456789012345678901
std::cout << NUMBER << '\n'; // default precision, writes: 12345.7
DoubleReal d = NUMBER;
std::cout.precision(writtenDigits<DoubleReal>()); // explicit template instantiation
std::cout << writtenDigits<DoubleReal>() << ": " << d << '\n'; // writes: 15: 12345.6789012346
Real r = NUMBER;
std::cout.precision(writtenDigits(r)); // type deduced from argument
std::cout << writtenDigits(r) << ": " << r << '\n'; // writes: 6: 12345.7
long double l = NUMBER;
std::cout.precision(writtenDigits(1L)); // argument is not used, but L suffix indicates a long double
std::cout << writtenDigits(1L) << ": " << l << '\n'; // writes: 18: 12345.6789012345671
DoubleReal x = 88.99;
std::cout.precision(15);
std::cout << "15: " << x << '\n'; // writes: 15: 88.99
std::cout.precision(16);
std::cout << "16: " << x << '\n'; // writes: 16: 88.98999999999999
@endcode
*/
//@{
/**@brief Number of digits commonly used for writing a floating point type
(a.k.a. precision). Specializations are defined for float, double, long
double.
*/
template <typename FloatingPointType>
inline Int writtenDigits(const FloatingPointType & /* unused */ = FloatingPointType());
/// Number of digits commonly used for writing a @c float (a.k.a. precision).
template <>
inline Int writtenDigits<float>(const float &)
{
return std::numeric_limits<float>::digits10;
}
/// Number of digits commonly used for writing a @c double (a.k.a. precision).
template <>
inline Int writtenDigits<double>(const double &)
{
return std::numeric_limits<double>::digits10;
}
/// We do not want to bother people who unintentionally provide an int argument to this.
template <>
inline Int writtenDigits<int>(const int &)
{
return std::numeric_limits<int>::digits10;
}
/// We do not want to bother people who unintentionally provide an unsigned int argument to this.
template <>
inline Int writtenDigits<unsigned int>(const unsigned int &)
{
return std::numeric_limits<unsigned int>::digits10;
}
/// We do not want to bother people who unintentionally provide a long int argument to this.
template <>
inline Int writtenDigits<long int>(const long int &)
{
return std::numeric_limits<int>::digits10;
}
/// We do not want to bother people who unintentionally provide an unsigned long int argument to this.
template <>
inline Int writtenDigits<unsigned long int>(const unsigned long int &)
{
return std::numeric_limits<unsigned int>::digits10;
}
class DataValue;
/// DataValue will be printed like double.
template <>
inline Int writtenDigits<DataValue>(const DataValue &)
{
return std::numeric_limits<double>::digits10;
}
/*
META-COMMENT: DO NOT INTRODUCE ANY LINEBREAKS BELOW IN
"<code>std::numeric_limits<long double>::digits10 == 18</code>".
The doxygen parser (version 1.5.5) will get confused! (Clemens)
*/
/**@brief Number of digits commonly used for writing a @c long @c double (a.k.a. precision). ...
Note: On Microsoft platforms, the I/O sytem seems to treat @c long @c double
just like @c double. We observed that
<code>std::numeric_limits<long double>::digits10 == 18</code>
with GCC 3.4 on MinGW, but this promise is
<i>not</i> kept by the Microsoft I/O sytem libraries. Therefore we use the
value of @c digits10 for @c double also for @c long @c double. See
http://msdn.microsoft.com/ + search: "long double".
*/
template <>
inline Int writtenDigits<long double>(const long double &)
{
#ifndef OPENMS_WINDOWSPLATFORM
return std::numeric_limits<long double>::digits10;
#else
return std::numeric_limits<double>::digits10;
#endif
}
/// The general template definition will force a compile-time error if FloatingPointType is in fact not a floating point type. Only the template specializations for float, double, long double shall be used.
template <typename FloatingPointType>
inline Int writtenDigits(const FloatingPointType & /* unused */)
{
// Self-explanatory compile time error!
return FloatingPointType::Sorry_but_writtenDigits_is_designed_to_work_for_floating_point_types_only;
}
// Note: I once tried to move PrecisionWrapper to namespace Internal, but oops! operator << won't be found (through ADL?) anymore.
/// Wrapper class to implement output with appropriate precision. See precisionWrapper().
template <typename FloatingPointType>
struct PrecisionWrapper
{
/// Constructor. Note: Normally you will prefer to use the "make"-function precisionWrapper(), which see.
PrecisionWrapper(const FloatingPointType rhs) :
ref_(rhs) {}
PrecisionWrapper(const PrecisionWrapper & rhs) :
ref_(rhs.ref_) {}
FloatingPointType const ref_;
private:
PrecisionWrapper(); // intentionally not implemented
};
/**@brief Wrapper function that sets the appropriate precision for output
temporarily. The original precision is restored afterwards so that no side
effects remain. This is a "make"-function that deduces the typename
FloatingPointType from its argument and returns a
PrecisionWrapper<FloatingPointType>.
Example:
@code
std::cout
<< 0.1234567890123456789f << ' ' << 0.1234567890123456789 << ' ' << 0.1234567890123456789l << '\n'
<< precisionWrapper(0.1234567890123456789f) << '\n' // float
<< 0.1234567890123456789f << ' ' << 0.1234567890123456789 << ' ' << 0.1234567890123456789l << '\n'
<< precisionWrapper(0.1234567890123456789) << '\n' // double
<< 0.1234567890123456789f << ' ' << 0.1234567890123456789 << ' ' << 0.1234567890123456789l << '\n'
<< precisionWrapper(0.1234567890123456789l) << '\n' // long double
<< 0.1234567890123456789f << ' ' << 0.1234567890123456789 << ' ' << 0.1234567890123456789l << '\n';
@endcode
Result:
@code
0.123457 0.123457 0.123457
0.123457
0.123457 0.123457 0.123457
0.123456789012346
0.123457 0.123457 0.123457
0.123456789012345679
0.123457 0.123457 0.123457
@endcode
Note: Unfortunately we cannot return a const& - this will change when rvalue
references become part of the new C++ standard. In the meantime, we need a
copy constructor for PrecisionWrapper.
*/
template <typename FloatingPointType>
inline const PrecisionWrapper<FloatingPointType> precisionWrapper(const FloatingPointType rhs)
{
return PrecisionWrapper<FloatingPointType>(rhs);
}
/// Output operator for a PrecisionWrapper. Specializations are defined for float, double, long double.
template <typename FloatingPointType>
inline std::ostream & operator<<(std::ostream & os, const PrecisionWrapper<FloatingPointType> & rhs)
{
// Same test as used by isnan(), spelled out here to avoid issues during overload resolution.
if (rhs.ref_ != rhs.ref_)
{
// That's what Linux GCC uses, and gnuplot understands.
// Windows would print stuff like 1.#QNAN which makes testing hard.
return os << "nan";
}
else
{
const std::streamsize prec_save = os.precision();
return os << std::setprecision(writtenDigits(FloatingPointType()))
<< rhs.ref_ << std::setprecision(prec_save);
}
}
//@}
/**
@brief Returns the @c Type as as std::string.
Have you ever spent a long time trying to find out what a @c typedef
actually "points" to? Then this can help.
typeAsString is implemented as a function template. There are two ways to us this:
@code
SomeType instance;
string what_type_1 = typeAsString(instance);
string what_type_2 = typeAsString< SomeType >();
@endcode
The %typeAsString< SomeType >() version seems to go a bit deeper.
Sometimes the results
depend on how the %typeAsString() is instantiated in the first place.
The argument given to the function is never used, it only serves to infer the type.
You can even supply function pointers, etc.
Example (Tutorial_typeAsString.C):
@dontinclude Tutorial_typeAsString.C
@until end of Tutorial_typeAsString.C
On a 64 bit platform running GCC 4.3.1, this produced the following output:
@code
int
unsigned int
double
float
int
long unsigned int
OpenMS::Peak1D
OpenMS::Peak1D
OpenMS::DPosition<1u>
double
float
double ()(int, int*)
WOW<const char* const*** const&, 5>
Oink<double, 55, 666u, WOW>
float ()(float&)
double (WOW<char, 8>::*)(const double&)
@endcode
*/
template <typename Type>
std::string typeAsString(const Type & /* unused */ = Type())
{
#ifndef OPENMS_COMPILER_GXX
return "[ Sorry, OpenMS::typeAsString() relies upon GNU extension __PRETTY_FUNCTION__ ]";
#else
std::string pretty(__PRETTY_FUNCTION__);
static char const context_left[] = "with Type =";
static char const context_right[] = "]";
size_t left = pretty.find(context_left);
left += sizeof(context_left);
size_t right = pretty.rfind(context_right);
if (right <= left)
return pretty; // oops!
return pretty.substr(left, right - left);
#endif
}
namespace Internal
{
/** Used to set the locale to "C", to avoid
problems on machines with incompatible
locale settings (this overwrites the
locale setting of the environment!)
*/
extern OPENMS_DLLAPI const char * OpenMS_locale;
}
} // namespace OpenMS
#endif // OPENMS_CONCEPT_TYPES_H
|