pxmlw6n2f/Gazebo_Distributed_MPI/gazebo/math/Helpers.hh

321 lines
8.2 KiB
C++

/*
* Copyright (C) 2012 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef _GAZEBO_MATH_FUNCTIONS_HH_
#define _GAZEBO_MATH_FUNCTIONS_HH_
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/round.hpp>
#include <algorithm>
#include <cmath>
#include <limits>
#include <string>
#include <iostream>
#include <vector>
/// \brief Double maximum value
#define GZ_DBL_MAX std::numeric_limits<double>::max()
/// \brief Double min value
#define GZ_DBL_MIN std::numeric_limits<double>::min()
/// \brief Double positive infinite value
#define GZ_DBL_INF std::numeric_limits<double>::infinity()
/// \brief Float maximum value
#define GZ_FLT_MAX std::numeric_limits<float>::max()
/// \brief Float minimum value
#define GZ_FLT_MIN std::numeric_limits<float>::min()
/// \brief 32bit unsigned integer maximum value
#define GZ_UINT32_MAX std::numeric_limits<uint32_t>::max()
/// \brief 32bit unsigned integer minimum value
#define GZ_UINT32_MIN std::numeric_limits<uint32_t>::min()
/// \brief 32bit integer maximum value
#define GZ_INT32_MAX std::numeric_limits<int32_t>::max()
/// \brief 32bit integer minimum value
#define GZ_INT32_MIN std::numeric_limits<int32_t>::min()
namespace gazebo
{
namespace math
{
/// \addtogroup gazebo_math
/// \brief A set of classes that encapsulate math related properties and
/// functions.
/// \{
/// \brief Returns the representation of a quiet not a number (NAN)
static const double NAN_D = std::numeric_limits<double>::quiet_NaN();
/// \brief Returns the representation of a quiet not a number (NAN)
static const int NAN_I = std::numeric_limits<int>::quiet_NaN();
/// \brief Simple clamping function
/// \param[in] _v value
/// \param[in] _min minimum
/// \param[in] _max maximum
template<typename T>
inline T clamp(T _v, T _min, T _max)
{
return std::max(std::min(_v, _max), _min);
}
/// \brief check if a float is NaN
/// \param[in] _v the value
/// \return true if _v is not a number, false otherwise
inline bool isnan(float _v)
{
return (boost::math::isnan)(_v);
}
/// \brief check if a double is NaN
/// \param[in] _v the value
/// \return true if _v is not a number, false otherwise
inline bool isnan(double _v)
{
return (boost::math::isnan)(_v);
}
/// \brief Fix a nan value.
/// \param[in] _v Value to correct.
/// \return 0 if _v is NaN, _v otherwise.
inline float fixnan(float _v)
{
return isnan(_v) || std::isinf(_v) ? 0.0f : _v;
}
/// \brief Fix a nan value.
/// \param[in] _v Value to correct.
/// \return 0 if _v is NaN, _v otherwise.
inline double fixnan(double _v)
{
return isnan(_v) || std::isinf(_v) ? 0.0 : _v;
}
/// \brief get mean of vector of values
/// \param[in] _values the vector of values
/// \return the mean
template<typename T>
inline T mean(const std::vector<T> &_values)
{
T sum = 0;
for (unsigned int i = 0; i < _values.size(); ++i)
sum += _values[i];
return sum / _values.size();
}
/// \brief get variance of vector of values
/// \param[in] _values the vector of values
/// \return the squared deviation
template<typename T>
inline T variance(const std::vector<T> &_values)
{
T avg = mean<T>(_values);
T sum = 0;
for (unsigned int i = 0; i < _values.size(); ++i)
sum += (_values[i] - avg) * (_values[i] - avg);
return sum / _values.size();
}
/// \brief get the maximum value of vector of values
/// \param[in] _values the vector of values
/// \return maximum
template<typename T>
inline T max(const std::vector<T> &_values)
{
T max = std::numeric_limits<T>::min();
for (unsigned int i = 0; i < _values.size(); ++i)
if (_values[i] > max)
max = _values[i];
return max;
}
/// \brief get the minimum value of vector of values
/// \param[in] _values the vector of values
/// \return minimum
template<typename T>
inline T min(const std::vector<T> &_values)
{
T min = std::numeric_limits<T>::max();
for (unsigned int i = 0; i < _values.size(); ++i)
if (_values[i] < min)
min = _values[i];
return min;
}
/// \brief check if two values are equal, within a tolerance
/// \param[in] _a the first value
/// \param[in] _b the second value
/// \param[in] _epsilon the tolerance
template<typename T>
inline bool equal(const T &_a, const T &_b,
const T &_epsilon = 1e-6)
{
return std::fabs(_a - _b) <= _epsilon;
}
/// \brief get value at a specified precision
/// \param[in] _a the number
/// \param[in] _precision the precision
/// \return the value for the specified precision
template<typename T>
inline T precision(const T &_a, const unsigned int &_precision)
{
if (!std::isinf(_a))
{
return boost::math::round(
_a * pow(10, _precision)) / pow(10, _precision);
}
else
{
return _a;
}
}
/// \brief is this a power of 2?
/// \param[in] _x the number
/// \return true if _x is a power of 2, false otherwise
inline bool isPowerOfTwo(unsigned int _x)
{
return ((_x != 0) && ((_x & (~_x + 1)) == _x));
}
/// \brief Get the smallest power of two that is greater or equal to a given
/// value
/// \param[in] _x the number
/// \return the same value if _x is already a power of two. Otherwise,
/// it returns the smallest power of two that is greater than _x
inline unsigned int roundUpPowerOfTwo(unsigned int _x)
{
if (_x == 0)
return 1;
if (isPowerOfTwo(_x))
return _x;
while (_x & (_x - 1))
_x = _x & (_x - 1);
_x = _x << 1;
return _x;
}
/// \brief parse string into an integer
/// \param[in] _input the string
/// \return an integer, 0 or 0 and a message in the error stream
inline int parseInt(const std::string& _input)
{
const char *p = _input.c_str();
if (!*p || *p == '?')
return NAN_I;
int s = 1;
while (*p == ' ')
p++;
if (*p == '-')
{
s = -1;
p++;
}
double acc = 0;
while (*p >= '0' && *p <= '9')
acc = acc * 10 + *p++ - '0';
if (*p)
{
std::cerr << "Invalid int numeric format[" << _input << "]\n";
return 0.0;
}
return s * acc;
}
/// \brief parse string into float
/// \param _input the string
/// \return a floating point number (can be NaN) or 0 with a message in the
/// error stream
inline double parseFloat(const std::string& _input)
{
const char *p = _input.c_str();
if (!*p || *p == '?')
return NAN_D;
int s = 1;
while (*p == ' ')
p++;
if (*p == '-')
{
s = -1;
p++;
}
double acc = 0;
while (*p >= '0' && *p <= '9')
acc = acc * 10 + *p++ - '0';
if (*p == '.')
{
double k = 0.1;
p++;
while (*p >= '0' && *p <= '9')
{
acc += (*p++ - '0') * k;
k *= 0.1;
}
}
if (*p == 'e')
{
int es = 1;
int f = 0;
p++;
if (*p == '-')
{
es = -1;
p++;
}
else if (*p == '+')
{
es = 1;
p++;
}
while (*p >= '0' && *p <= '9')
f = f * 10 + *p++ - '0';
acc *= pow(10, f*es);
}
if (*p)
{
std::cerr << "Invalid double numeric format[" << _input << "]\n";
return 0.0;
}
return s * acc;
}
/// \}
}
}
#endif