// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// Licence: GNU General Public License version 2
// $Id: common.h 317 2007-07-15 00:39:46Z wojdyr $
/*
* various headers and definitions. Included by all files.
*/
#ifndef FITYK__COMMON__H__
#define FITYK__COMMON__H__
#if HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef VERSION
# define VERSION "unknown"
#endif
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <map>
#include <math.h>
#include <assert.h>
#include "fityk.h" //ExecuteError
using fityk::ExecuteError;
using fityk::ExitRequestedException;
//-------------------------- N U M E R I C --------------------------------
/// favourite floating point type
#ifdef FP_IS_LDOUBLE
typedef long double fp;
#else
typedef double fp;
#endif
/// epsilon is used for comparision of real numbers
/// defined in settings.cpp; it can be changed in Settings
extern fp epsilon;
inline bool is_eq(fp a, fp b) { return fabs(a-b) <= epsilon; }
inline bool is_neq(fp a, fp b) { return fabs(a-b) > epsilon; }
inline bool is_lt(fp a, fp b) { return a < b - epsilon; }
inline bool is_gt(fp a, fp b) { return a > b + epsilon; }
inline bool is_le(fp a, fp b) { return a <= b + epsilon; }
inline bool is_ge(fp a, fp b) { return a >= b - epsilon; }
inline bool is_zero(fp a) { return fabs(a) <= epsilon; }
inline bool is_finite(fp a)
#if HAVE_FINITE
{ return finite(a); }
#else
{ return a == a; }
#endif
#ifndef M_PI
# define M_PI 3.1415926535897932384626433832795029 // pi
#endif
#ifndef M_LN2
# define M_LN2 0.6931471805599453094172321214581766 // log_e 2
#endif
#ifndef M_SQRT2
# define M_SQRT2 1.4142135623730950488016887242096981 // sqrt(2)
#endif
/** idea of exp_() is taken from gnuplot:
* some machines have trouble with exp(-x) for large x
* if MINEXP is defined at compile time, use exp_(x) instead,
* which returns 0 for exp_(x) with x < MINEXP
*/
#ifdef MINEXP
inline fp exp_(fp x) { return (x < (MINEXP)) ? 0.0 : exp(x); }
#else
# define exp_(x) exp(x)
#endif
/// Round real to integer.
inline int iround(fp d) { return static_cast<int>(floor(d+0.5)); }
#ifndef __GNUC__
//TODO implement erf and erfc
inline float erfc(float f) { return 0.5f; }
inline float erf(float f) { return 0.5f; }
inline float trunc(float f) { return (float) (int) f; }
#endif // !__GNUC__
//--------------------------- S T R I N G --------------------------------
/// S() converts to string
template <typename T>
inline std::string S(T k) {
return static_cast<std::ostringstream&>(std::ostringstream() << k).str();
}
inline std::string S(bool b) { return b ? "true" : "false"; }
inline std::string S(char const *k) { return std::string(k); }
inline std::string S(char *k) { return std::string(k); }
inline std::string S(char const k) { return std::string(1, k); }
inline std::string S(std::string const &k) { return k; }
inline std::string S() { return std::string(); }
// double -> string, with given precision
inline std::string S(double k, int /*prec*/) {
return static_cast<std::ostringstream&>(std::ostringstream()
/* << std::setprecision(prec) */<< k).str();
}
/// True if the string contains only a real number
bool is_double (std::string const& s);
/// True if the string contains only an integer number
bool is_int (std::string const& s);
/// replace all occurences of old in string s with new_
void replace_all(std::string &s, std::string const &old,
std::string const &new_);
void replace_words(std::string &t, std::string const &old_word,
std::string const &new_word);
/// splits string into tokens, separated by one-character delimitors
template<typename T>
std::vector<std::string> split_string(std::string const &s, T delim) {
std::vector<std::string> v;
std::string::size_type start_pos = 0, pos=0;
while (pos != std::string::npos) {
pos = s.find_first_of(delim, start_pos);
v.push_back(std::string(s, start_pos, pos-start_pos));
start_pos = pos+1;
}
return v;
}
/// similar to Python string.strip() method
inline std::string strip_string(std::string const &s) {
char const *blank = " \r\n\t";
std::string::size_type first = s.find_first_not_of(blank);
if (first == std::string::npos)
return std::string();
return std::string(s, first, s.find_last_not_of(blank)-first+1);
}
/// similar to Python string.startswith() method
inline bool startswith(std::string const& s, std::string const& p) {
return p.size() <= s.size() && std::string(s, 0, p.size()) == p;
}
std::string::size_type find_matching_bracket(std::string const& formula,
std::string::size_type left_pos);
template<typename T, typename T2>
bool contains_element(std::basic_string<T> const& str, T2 const& t)
{
return (str.find(t) != std::basic_string<T>::npos);
}
//--------------------------- V E C T O R --------------------------------
/// Makes 1-element vector
template <typename T>
inline std::vector<T> vector1 (T a) { return std::vector<T>(1, a); }
/// Makes 2-element vector
template <typename T>
inline std::vector<T> vector2 (T a, T b)
{ std::vector<T> v = std::vector<T>(2, a); v[1] = b; return v;}
/// Make 3-element vector
template <typename T>
inline std::vector<T> vector3 (T a, T b, T c)
{ std::vector<T> v = std::vector<T>(3, a); v[1] = b; v[2] = c; return v;}
/// Make 4-element vector
template <typename T>
inline std::vector<T> vector4 (T a, T b, T c, T d) {
std::vector<T> v = std::vector<T>(4, a); v[1] = b; v[2] = c; v[3] = d;
return v;
}
/// Make (u-l)-element vector, filled by numbers: l, l+1, ..., u-1.
std::vector<int> range_vector(int l, int u);
/// Expression like "i<v.size()", where i is int and v is a std::vector gives:
/// "warning: comparison between signed and unsigned integer expressions"
/// implicit cast IMHO makes code less clear than "i<size(v)":
template <typename T>
inline int size(std::vector<T> const& v) { return static_cast<int>(v.size()); }
/// Return 0 <= n < a.size()
template <typename T>
inline bool is_index (int idx, std::vector<T> const& v)
{
return idx >= 0 && idx < static_cast<int>(v.size());
}
template <typename T>
inline std::string join_vector(std::vector<T> const& v, std::string const& sep)
{
if (v.empty())
return "";
std::string s = S(v[0]);
for (typename std::vector<T>::const_iterator i = v.begin() + 1;
i != v.end(); i++)
s += sep + S(*i);
return s;
}
template <typename T1, typename T2>
inline std::vector<std::string> concat_pairs(std::vector<T1> const& v1,
std::vector<T2> const& v2,
std::string const& sep="")
{
std::vector<std::string> result(std::min(v1.size(), v2.size()));
for (size_t i = 0; i < result.size(); ++i)
result.push_back(S(v1[i]) + sep + S(v2[i]));
return result;
}
template <typename T>
inline std::vector<std::string> concat_pairs(std::string const& s1,
std::vector<T> const& v2)
{
std::vector<std::string> result(v2.size());
for (size_t i = 0; i != v2.size(); ++i)
result[i] = s1 + S(v2[i]);
return result;
}
template <typename T>
inline std::vector<std::string> concat_pairs(std::vector<T> const& v1,
std::string const& s2)
{
std::vector<std::string> result(v1.size());
for (size_t i = 0; i != v1.size(); ++i)
result[i] = S(v1[i]) + s2;
return result;
}
/// for vector<T*> - delete object and erase pointer
template<typename T>
void purge_element(std::vector<T*> &vec, int n)
{
assert(n >= 0 && n < size(vec));
delete vec[n];
vec.erase(vec.begin() + n);
}
/// delete all objects handled by pointers and clear vector
template<typename T>
void purge_all_elements(std::vector<T*> &vec)
{
for (typename std::vector<T*>::iterator i=vec.begin(); i!=vec.end(); ++i)
delete *i;
vec.clear();
}
/// check if vector (first arg) contains given element (second arg)
template<typename T, typename T2>
bool contains_element(std::vector<T> const& vec, T2 const& t)
{
return (find(vec.begin(), vec.end(), t) != vec.end());
}
/// return first index of value, or -1 if not found
template<typename T, typename T2>
int index_of_element(std::vector<T> const& vec, T2 const& t)
{
typename std::vector<T>::const_iterator p = find(vec.begin(), vec.end(), t);
if (p != vec.end())
return p - vec.begin();
else
return -1;
}
//--------------------------- M A P --------------------------------
template<typename T1, typename T2>
std::vector<T2> get_map_keys(std::map<T1,T2> const& m)
{
std::vector<T2> result;
for (typename std::map<T1,T2>::const_iterator i=m.begin(); i!=m.end(); ++i)
result.push_back(i->first);
return result;
}
template<typename T1, typename T2>
std::vector<T2> get_map_values(std::map<T1,T2> const& m)
{
std::vector<T2> result;
for (typename std::map<T1,T2>::const_iterator i=m.begin(); i!=m.end(); ++i)
result.push_back(i->second);
return result;
}
//---------------- filename utils -------------------------------------
#if defined(_WIN32) || defined(WIN32) || defined(__NT__) || defined(__WIN32__) || defined(__OS2__)
#define PATH_COMPONENT_SEP '\\'
#elif defined(__MAC__) || defined(__APPLE__) || defined(macintosh)
//Mac OS <= 9
#define PATH_COMPONENT_SEP ':'
#else
#define PATH_COMPONENT_SEP '/'
#endif
inline std::string get_directory(std::string const& filename)
{
std::string::size_type i = filename.rfind(PATH_COMPONENT_SEP);
return i==std::string::npos ? std::string() : std::string(filename, 0, i+1);
}
//-------------------- M I S C E L A N O U S ------------------------------
extern const char* fityk_version_line; /// it is used to put version to script
/// flag that is set to interrupt fitting (it is checked after each iteration)
extern volatile bool user_interrupt;
extern const std::string help_filename;
/// Get current date and time as formatted string
std::string time_now ();
enum OutputStyle { os_normal, os_warn, os_quot, os_input };
#endif
syntax highlighted by Code2HTML, v. 0.9.1