#ifndef __UTIL_H #define __UTIL_H /** @file * @brief ユーティリティ * * ユーティリティメソッドを収録したファイル */ #if defined(_MSC_VER) && _MSC_VER >= 1400 #define _USE_MATH_DEFINES #endif #ifdef __cplusplus #include #else #include #endif #ifndef PI #define PI 3.1415926535897932384626433832795 #endif #ifndef M_PI #define M_PI PI #endif #ifndef M_PI_2 #define M_PI_2 (M_PI / 2) #endif #define __RAND_MT__ ///< メルセンヌツイスタ用スイッチ #ifdef __cplusplus #include "util/iostream_format.h" #include #include #if ENABLE_IOSTREAM #include /** * 度、分、秒フォーマットで出力する * 例 135.24.30.3456(135度24分30秒3456) * * @param degree 度 * @return (string) 文字列 */ std::string pretty_deg(double degree){ char buffer[128]; std::sprintf(buffer, "%d.", (int)degree); //度 (degree -= (int)degree) *= 60; std::sprintf(buffer, "%s%d.", buffer, (int)degree); //分 (degree -= (int)degree) *= 60; std::sprintf(buffer, "%s%f", buffer, degree); //秒 return std::string(buffer); } #endif /** * 絶対値を求める関数。 * 汎用的なため、比較演算子<と単項オペレータ-が定義されていれば利用可能です。 * * @param T 型 * @param v 値 * @return T 絶対値 */ template inline T _abs(T v){return v < 0 ? -v : v;} /** * 絶対値を求める関数。 * int専用を特殊化によって実現。 * * 内部的にはabs関数を利用。 * * @param v 値 * @return (int) 絶対値 */ template<> inline int _abs(int v){return std::abs(v);} /** * 絶対値を求める関数。 * double専用を特殊化によって実現。 * 内部的にはfabs関数を利用。 * * @param v 値 * @return (double) 絶対値 */ template<> inline double _abs(double v){ #if !defined(__TI_COMPILER_VERSION__) return std::abs(v); #else #ifdef _TMS320C6700 return _fabs(v); #else return fabs(v); #endif #endif } /** * 絶対値を求める関数。 * float専用を特殊化によって実現。 * * 内部的にはfabsf関数を利用。 * * @param v 値 * @return (float) 絶対値 */ template<> inline float _abs(float v){ #if !defined(__TI_COMPILER_VERSION__) return std::abs(v); #else #ifdef _TMS320C6700 return _fabsf(v); #else return fabsf(v); #endif #endif } template inline T &_min(const T &x, const T &y){ return ((x) < (y) ? (x) : (y)); } template inline T &_max(const T &x, const T &y){ return ((x) > (y) ? (x) : (y)); } #if defined(__GNUC__) #include namespace std { template inline int finite(const T &x){return ::finite(x);} }; #elif defined(_MSC_VER) #include namespace std { template inline int isnan(const T &x){return _isnan(x);} template inline int finite(const T &x){return _finite(x);} }; #endif /* _MSC_VER */ extern "C" { #else // __cplusplus #include #include #include #ifndef min_macro #define min_macro(x, y) ((x) < (y) ? (x) : (y)) ///< minマクロ #endif #ifndef max_macro #define max_macro(x, y) ((x) > (y) ? (x) : (y)) ///< maxマクロ #endif #endif // __cplusplus /** * 度からラジアンに変換 * * @param degree 度 * @return (double) ラジアン */ double deg2rad(const double °ree){return degree * PI / 180;} /** * ラジアンから度に変換 * * @param radians ラジアン * @return (double) 度 */ double rad2deg(const double &radians){return radians * 180 / PI;} static bool init_flag = false; ///< 乱数初期化フラグ #ifdef __RAND_MT__ //メルセンヌ・ツイスタ用 #include "util/mt19937ar.h" /** * 乱数生成器の初期化 * * @param seed 種 */ void rand_init(unsigned long seed){ init_genrand(seed); init_flag = true; } /** * int型で乱数を生成 * * @return 乱数 * @see genrand_int31() * @see mt19937ar.h */ int randMT(){ if(!init_flag){ init_genrand((unsigned long)std::time(NULL)); init_flag = true; } return (int)genrand_int31(); } /** * double型で乱数を生成 * * @return 乱数 * @see genrand_real1() * @see mt19937ar.h */ double drandMT(){ if(!init_flag){ init_genrand((unsigned long)std::time(NULL)); init_flag = true; } return genrand_real1(); } #ifdef __cplusplus #ifdef __GNUC__ namespace std { inline int randMT(){return ::randMT();} inline double drandMT(){return ::drandMT();} }; #endif #endif #define rand() randMT() ///< rand()をrandMT()で上書き #define drand() drandMT() ///< drand()をdrandMT()で上書き #else //通常のC言語の標準rand()、性能悪し /** * 乱数生成器の初期化 * * @param seed 種 */ void rand_init(unsigned long seed){ srand(seed); init_flag = true; } /** * int型で乱数を生成 * 内部的にはrand()を呼び出しているだけです。 * * @return 乱数 */ int randC(){ if(!init_flag){ srand((unsigned int)time(NULL)); init_flag = true; } return rand(); } /** * double型で乱数を生成 * 内部的にはdrand()を呼び出しているだけです。 * * @return 乱数 */ double drandC(){ if(!init_flag){ srand((unsigned int)time(NULL)); init_flag = true; } return (double)rand() / RAND_MAX; } #define rand() randC() ///< rand()をrandC()で上書き #define drand() drandC() ///< drand()をdrandC()で上書き #endif /** * 正規化ノイズを発生させます。 * Box-Muller法を採用しています。 * * @param mu 平均 * @param sigma 偏差 * @return ノイズ * @see * Wikipedia『乱数列』の正規乱数の項を参照のこと */ double rand_regularized(double mu, double sigma){ static double v_1, v_2, s; static bool flag = false; if(flag = !flag){ do{ v_1 = drand() * 2 - 1; v_2 = drand() * 2 - 1; }while((s = v_1 * v_1 + v_2 * v_2) >= 1.0 || s == 0); return sigma * v_1 * sqrt(-2 * log(s) / s) + mu; }else{ return sigma * v_2 * sqrt(-2 * log(s) / s) + mu; } } #define TO_STRING( s ) #s #define CONCATENATE( x, y ) x ## y #ifdef __cplusplus } #endif // __cplusplus #endif /* __UTIL_H */