#ifndef UTILITY_H #define UTILITY_H #include #include #include #undef near #include #include #include #include #include #include #include #include #include "ATC_Error.h" namespace ATC_Utility { /** constants */ static const double Pi_ = 4.0*atan(1.0); static const double Big_ = 1.e20; const static double parsetol_ = 1.0e-8; //const static double parsetol_ = 1.0e-10; const static double parsebig_ = 1.0e10; /** scalar triple product */ inline double det3(double * v1, double * v2, double * v3) { return -v1[2]*v2[1]*v3[0] + v1[1]*v2[2]*v3[0] + v1[2]*v2[0]*v3[1] -v1[0]*v2[2]*v3[1] - v1[1]*v2[0]*v3[2] + v1[0]*v2[1]*v3[2]; } inline void plane_coords(int i, int & i1, int & i2) { if (i==0) { i1 = 1; i2 = 2; } else if (i==1) { i1 = 2; i2 = 0; } else if (i==2) { i1 = 0; i2 = 1; } } /** 2d cross product */ inline double cross2(double * v1, double * v2) { return v1[0]*v2[1] - v1[1]*v2[0]; } /** 3d cross product */ inline void cross3(double * v1, double * v2, double * v) { v[0] = v1[1]*v2[2] - v1[2]*v2[1]; v[1] = v1[2]*v2[0] - v1[0]*v2[3]; v[2] = v1[0]*v2[1] - v1[1]*v2[0]; } inline double norm3(double * v) {return sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); } inline int sgn(double x) { return (int) ((x>0) - (x<0)); } // template int sgn(T val) { return (T(0) < val) - (val < T(0)); } inline int rnd(double x) { return (int) (x+sgn(x)*0.5); } /** Compares doubles acceptably */ inline bool dbl_geq(double dblL, double dblR, int tolMult=2) { return ( (dblL > dblR) || ((dblL <= (dblR + \ std::numeric_limits::epsilon() * \ tolMult * std::max(abs(dblL), abs(dblR)))) && (dblR <= (dblL + \ std::numeric_limits::epsilon() * \ tolMult * std::max(abs(dblL), abs(dblR)))))); } inline double tolerance(double x, double tol = parsetol_) { return std::max(tol,tol*fabs(x)); } inline double nudge_up(double x) { return x+tolerance(x); } inline double nudge_down(double x) { return x-tolerance(x); } inline double parse_min(const char * arg) { if (std::strcmp(arg,"INF") == 0) return -parsebig_; else if (std::strcmp(arg,"-INF") == 0) return -parsebig_; else return (atof(arg)); } inline double parse_max(const char * arg) { if (std::strcmp(arg,"INF") == 0) return parsebig_; else return (atof(arg)); } inline double parse_minmax(const char * arg) { if (std::strcmp(arg,"-INF") == 0) return -parsebig_; else if (std::strcmp(arg,"INF") == 0) return parsebig_; else return atof(arg); } inline void split_values(double & min, double & max) { min = nudge_down(min); max = nudge_up(max); } /** Returns true if the value v is between min & max */ template inline bool in_range(const T &v, const T &min, const T &max) { return v >= min && v <= max; } /** Returns true if the value v is between min & max within tolerance TOL */ template inline bool in_range(const T &v, const T &min, const T &max, const T &tol) { return in_range(v, min-tol, max+tol); } /** Returns the value with the larger absolute value */ template inline T max_abs(const T &a, const T &b) { return (a*a > b*b) ? a : b; } /** Returns the value with the smaller absolute value */ template inline T min_abs(const T &a, const T &b) { return (a*a < b*b) ? a : b; } /** A simple Matlab like timing function */ inline double tictoc() { double t_new = clock() / (double) CLOCKS_PER_SEC; static double t = t_new; double dt = t_new - t; t = t_new; return dt; } /** A simple timer */ inline double timer() { double t_new = clock() / (double) CLOCKS_PER_SEC; static double t = t_new; // done once at first time the function is evoked double dt = t_new - t; return dt; } /** Binary search between low & high for value (assumes array is sorted) */ template inline int search_sorted(const T* A, T value, int low, int high) { int mid; while (low < high) { mid = (low + high) >> 1; // set mid to mean of high and low, ">>" is a bit shift which divides by 2, rounding down if (A[mid] > value) high = mid; // mid was too high, reduce high else if (A[mid] < value) low = mid+1; // mid was too low, increase low else return mid; } return -1; // value not found in array, return -1 } /** Flat search between low & high for value (assumes array is NOT sorted) */ template inline int search_unsorted(const T* A, T value, int low, int high) { for (int i=low; i inline void swap(T &a, T &b) { T temp = a; a = b; b = temp; } //=================================================================== /** A collection of string convesion/manipulation routines */ //=================================================================== /** converts anything that has iostream::<< defined to a string */ template inline std::string to_string(const T &v, int precision=0) { std::ostringstream out; if (precision) { out << std::setprecision(precision); out << std::setw(precision+3); out << std::showpoint; } out << v; out << std::noshowpoint; return out.str(); } /** formatted double to a string */ inline std::string to_string(int precision, const double v) { char b[50]; sprintf(b, "%*.*f",4+precision,precision, v); std::string s(b); return s; } /** conversion to string */ inline std::string true_false(const double &v) { if (v) return "TRUE"; else return "FALSE"; } /** test conversion to double */ inline bool is_numeric(const std::string &s) { double v; std::istringstream in(s); in >> v; // in.good() == true indicates, that not the whole string was converted. return !(in.fail() || in.good()); } /** convert a string to anything that has iostream::>> defined, second arg is to disambibuate type */ template inline T str2T(const std::string &s, T v) { std::istringstream in(s); if (!(in >> v)) throw ATC::ATC_Error("str2T invalid string conversion"); return v; } /** convert a string to a double */ inline double str2dbl(const std::string &s) { return str2T(s, double(0.0)); } /** tests if conversion to double is possible */ inline bool is_dbl(const std::string &s) { char *endptr; strtod(s.c_str(), &endptr); if(endptr != NULL && *endptr == '\0') return true; return false; } inline bool is_number(const std::string& s) { std::string::const_iterator it = s.begin(); while (it != s.end() && std::isdigit(*it)) ++it; return !s.empty() && it == s.end(); } /** convert a string to an int */ inline int str2int(const std::string &s) { return str2T(s, int(4)); } //* replaces all characters in a set of characters with a character //* @param str input string //* @param *s pointer to array of characters that will be replaced //* @param r character to replace characters in s[] with static void replace_all_of(std::string &str, const char *s, const char r) { size_t found; found = str.find_first_of(s); while (found != std::string::npos) { str[found] = r; found = str.find_first_of(s, found+1); } } /** converts the string to lowercase */ inline std::string& to_lower(std::string &s) { std::transform(s.begin(),s.end(),s.begin(),static_cast(tolower)); return s; } /** converts the string to uppercase */ inline std::string& to_upper(std::string &s) { std::transform(s.begin(),s.end(),s.begin(),static_cast(toupper)); return s; } /** removes any whitespace from the beginning or end of string */ static std::string& trim(std::string &s) { if (s.empty()) return s; size_t found = s.find_last_not_of(" \t\n"); if (found < s.size()-1) s.erase(found+1); found = s.find_first_not_of(" \t\n"); if (found != std::string::npos) s = s.substr(found); return s; } /** splits delimited string into a vector of strings */ static void split(const std::string &s, std::vector &ss, char del=' ') { ss.clear(); size_t begin=0, end=0; while (end != std::string::npos) { begin = s.find_first_not_of(del, end); // find beginning of fragment end = s.find_first_of(del,begin); if (begin != std::string::npos) // safe if end is npos-1 ss.push_back(s.substr(begin,end-begin)); } } static std::string cap(std::string & s) { s[0] = toupper(s[0]); return s; } /* turns Aa_Bb_Cc into aa_bb_cc */ static std::string to_cap(const std::string &s) { std::vector words; std::string delimiter = "_"; split(s,words,(delimiter.c_str())[0]); std::string name = ""; for (unsigned int i = 0; i < words.size(); i++) { name = name + cap(words[i]); } return name; } //* scans a string for a list of commands delimited by ', \t' with # comments //* @param line The input line to be parsed //* @cs A vector of strings parsed from the input line static void command_strings(std::string line, std::vector &cs) { if (line.find('#') != std::string::npos) line.erase(line.find("#")); replace_all_of(line, "\t,", ' '); to_lower(trim(line)); split(line, cs); } //* reads a single line from a file and splits it into a vector of strings //* returns the number of strings in the vector inline int command_line(std::fstream &fid, std::vector &cs) { std::string line; getline(fid, line); command_strings(line, cs); return cs.size(); } } #endif