414 lines
12 KiB
C++
414 lines
12 KiB
C++
// The code is copyrighted 2008 by Carsten Frigaard.
|
|
// All rights placed in public domain under GNU licence V2, 2008
|
|
//
|
|
// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software
|
|
// and its documentation for any purpose and without fee is hereby granted, provided that
|
|
// the above copyright notice appear in all copies and that both that copyright notice
|
|
// and this permission notice appear in supporting documentation.
|
|
|
|
#ifndef __FUNS_H__
|
|
#define __FUNS_H__
|
|
|
|
#define Unimplemented throw_("Function unimplemented")
|
|
#define Dontgethere throw_("Dontgethere")
|
|
|
|
#ifndef NDEBUG
|
|
#define ON_DEBUG(a) a
|
|
#else
|
|
#define ON_DEBUG(a)
|
|
#endif
|
|
|
|
#ifdef USE_FFTW
|
|
extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size);
|
|
#endif
|
|
|
|
// Small template funs
|
|
template<class T,class R> bool isinmap (const map<T,R>& m,const T& t) {return m.size()>=2 && m.begin()->first<=t && t<(--m.end())->first;}
|
|
template<class T> const size_t getsteps(const T& r0,const T& r1,const T& rstep,const bool logarithmic) {size_t N=0; for(T r=r0;r<r1;logarithmic ? r*=rstep/T(1) : r+=rstep) ++N; return N;}
|
|
|
|
inline std::string Version(){return string("VERSION: ") + VERSION + "." + VERSION_REV;}
|
|
|
|
inline std::string Config()
|
|
{
|
|
std::string s;
|
|
#ifdef NDEBUG
|
|
s+="NDEBUG";
|
|
#else
|
|
#ifdef PROFILE
|
|
s+="PROFILE";
|
|
#else
|
|
s+="DEBUG";
|
|
#endif
|
|
#endif
|
|
#ifdef USE_UNITS
|
|
s+= " USE_UNITS";
|
|
#endif
|
|
#ifdef USE_FLOAT_CHECKS
|
|
s+= " USE_FLOAT_CHECKS";
|
|
#endif
|
|
#ifdef USE_FFTW_IC
|
|
s+= " USE_FFTW_IC";
|
|
#endif
|
|
#ifdef USE_FFTW
|
|
s+= " USE_FFTW";
|
|
#endif
|
|
#ifdef USE_MPI
|
|
s+= " USE_MPI";
|
|
#endif
|
|
if (sizeof(void*)==4) s+=" 32BIT";
|
|
else if (sizeof(void*)==8) s+=" 64BIT";
|
|
else s+=" XXBIT";
|
|
|
|
const long one= 1;
|
|
const int big=!(*(reinterpret_cast<const char *>(&one)));
|
|
if (big) s+=" BIGENDIAN";
|
|
else s+=" LITENDIAN";
|
|
|
|
return s;
|
|
}
|
|
|
|
inline string FormatCompilerMsg(const string& file,const int line)
|
|
{
|
|
#ifdef WIN32
|
|
return file + ":" + line + ":";
|
|
#else
|
|
return file + "(" + line + ")";
|
|
#endif
|
|
}
|
|
|
|
#ifdef WIN32
|
|
extern "C"{
|
|
#ifdef _UNICODE
|
|
#pragma message("ERROR: toolsfun cannot handle unicode...giving up compilation");
|
|
ERROR_complier
|
|
#endif
|
|
|
|
#ifdef _AFXDLL
|
|
__declspec(dllimport) void* __stdcall GetCurrentThread();
|
|
__declspec(dllimport) void* __stdcall GetCurrentThreadId();
|
|
__declspec(dllimport) int __stdcall SetThreadPriority(void* hThread,int nPriority);
|
|
#else
|
|
//void* __stdcall GetCurrentThread();
|
|
//void* __stdcall GetCurrentThreadId();
|
|
//int __stdcall SetThreadPriority(void* hThread,int nPriority);
|
|
__declspec(dllimport) void* __stdcall GetCurrentThread();
|
|
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
|
__declspec(dllimport) int __stdcall SetThreadPriority(void* hThread,int nPriority);
|
|
__declspec(dllimport) int __stdcall GetThreadPriority(void* hThread);
|
|
__declspec(dllimport) unsigned int __stdcall WinExec(const char* lpCmdLine,unsigned int uCmdShow);
|
|
#ifndef _WINDOWS_
|
|
__declspec(dllimport) unsigned int __stdcall MessageBox(void* hWnd,const char* lpText,const char* lpCaption,unsigned int Type);
|
|
__declspec(dllimport) unsigned long __stdcall GetCurrentDirectory(unsigned long nBufferLength,char* lpBuffer);
|
|
#endif
|
|
#endif
|
|
}
|
|
#else
|
|
int nice(int inc);
|
|
#endif
|
|
|
|
inline int Message(const string& title,const string& msg,const int type)
|
|
{
|
|
#ifdef WIN32
|
|
// 0 = MB_OK
|
|
// 1 = MB_OKCANCEL
|
|
// 2 = MB_ABORTRETRYIGNORE
|
|
// 3 = MB_YESNOCANCEL
|
|
// 4 = MB_YESNO
|
|
// 5 = MB_RETRYCANCEL
|
|
// 6 = MB_CANCELTRYCONTINUE: if(WINVER >= 0x0500)
|
|
const long hr=MessageBox(NULL,msg.c_str(),title.c_str(),type);
|
|
#else
|
|
Unimplemented;
|
|
#endif
|
|
return 1;
|
|
}
|
|
/*
|
|
string GetCurrentDir()
|
|
{
|
|
#ifdef WIN32
|
|
char buff[16*1024];
|
|
if(GetCurrentDirectory(16*1024,buff)==0) throw_("GetCurrentDirectory() failed");
|
|
return tostring(buff);
|
|
#else
|
|
Unimplemented;
|
|
return "";
|
|
#endif
|
|
}
|
|
*/
|
|
|
|
inline void SetNiceLevel(const int level)
|
|
{
|
|
#ifdef WIN32
|
|
// THREAD_PRIORITY_ABOVE_NORMAL 1 Priority 1 point above the priority class.
|
|
// THREAD_PRIORITY_BELOW_NORMAL -1 Priority 1 point below the priority class.
|
|
// THREAD_PRIORITY_HIGHEST 2 Priority 2 points above the priority class.
|
|
// THREAD_PRIORITY_IDLE -15 Base priority of 1 for IDLE_PRIORITY_CLASS,...
|
|
// THREAD_PRIORITY_LOWEST -2 Priority 2 points below the priority class.
|
|
// THREAD_PRIORITY_NORMAL 0 Normal priority for the priority class.
|
|
// THREAD_PRIORITY_TIME_CRITICAL 15 Base priority of 15 for IDLE_PRIORITY_CLASS,...
|
|
if (level!=0 && level!=1 && level!=-1 && level!=2 && level!=-2 && level!=15 && level!=-15) throw_("wrong Win32 nice level, must be oneof -15,-2,-1,0,1,2,15");
|
|
SetThreadPriority(GetCurrentThread(),-level);
|
|
assert( GetThreadPriority(GetCurrentThread())==-level );
|
|
#else
|
|
const int n=nice(level);
|
|
if (n<0) throw_("Could not set nice level");
|
|
#endif
|
|
}
|
|
|
|
inline size_t GetThreadId()
|
|
{
|
|
#ifdef WIN32
|
|
assert( sizeof(size_t)==sizeof(unsigned long) );
|
|
return GetCurrentThreadId();
|
|
#else
|
|
// may be replaced by return 0; if phtread not found!
|
|
assert( sizeof(size_t)==sizeof(pthread_t) );
|
|
const pthread_t p=pthread_self();
|
|
size_t q=0;
|
|
memcpy(&q,&p,sizeof(q));
|
|
return q;
|
|
#endif
|
|
}
|
|
|
|
#ifdef TOOLSFUN_QUIET_WIN32_SYSTEM
|
|
#ifdef WIN32
|
|
// make a special non-console system call, instead of the standard system()
|
|
// XXX SystemWin, does not wait for process to finish, CreatProc still create window
|
|
|
|
int SystemWin(const string& cmd)
|
|
{
|
|
//ShellExecute, CreateProcess, WinExec or system
|
|
// HINSTANCE hi=ShellExecute(NULL,NULL,cmdx,"","",SW_SHOSNOACTIVATE);
|
|
// if (reinterpret_cast<int>(hi)<32) MessageBox(NULL,(string("ShellExecute <") + cmd + "> failed").c_str(),"Error",0);
|
|
|
|
// const string cmd2="\\\"" + cmd + "\\\""; // fix problem with spaces in executable, not working yet
|
|
unsigned int r=WinExec(cmd.c_str(),4);
|
|
return r<32 ? -1 : 0;
|
|
}
|
|
|
|
bool CreateProc(const string& cmd,const bool throwexception=true,const bool waitforprocesstofinish=true)
|
|
{
|
|
STARTUPINFO s;
|
|
PROCESS_INFORMATION p;
|
|
memset(&s,0,sizeof(s));
|
|
memset(&p,0,sizeof(p));
|
|
s.cb=sizeof(s);
|
|
|
|
// to avoid const cast of char* in CreateProcess
|
|
char cmdx[16*1024];
|
|
strcpy_s(cmdx,16*1024,cmd.c_str());
|
|
|
|
const int r=CreateProcess(0,cmdx,0,0,false,CREATE_DEFAULT_ERROR_MODE,0,0,&s,&p);
|
|
if (r!=0) {if(waitforprocesstofinish) WaitForSingleObject(p.hProcess,INFINITE);}
|
|
else {
|
|
if (throwexception) throw_(string("CreateProcess() failed with return code <") + GetLastError() + ">");
|
|
else return false;
|
|
}
|
|
|
|
// Release handles
|
|
assert(r!=0);
|
|
CloseHandle(p.hProcess);
|
|
CloseHandle(p.hThread);
|
|
return true;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
inline string System(const string& cmd,const bool throwexception=true,const bool captureoutput=false,int* pret=0)
|
|
{
|
|
if (!captureoutput){
|
|
#ifdef TOOLSFUN_QUIET_WIN32_SYSTEM
|
|
const int n=SystemWin(cmd);
|
|
#else
|
|
const int n=system(cmd.c_str());
|
|
#endif
|
|
if (n!=0 && throwexception) throw_(string("system command failed with code=") + n + " cmd=<" + cmd + ">");
|
|
if (pret!=0) *pret=n;
|
|
return "";
|
|
} else {
|
|
static size_t n=0;
|
|
#ifdef WIN32
|
|
const string rm="del ";
|
|
char tmp[1024];
|
|
if (tmpnam_s(tmp,1024)) throw_("error in creating win32 temp name");
|
|
const string file(tmp);
|
|
#else
|
|
const string rm="rm ";
|
|
const string file=tmpnam("tempfile");
|
|
#endif
|
|
ifstream s1(file.c_str());
|
|
if(s1) {
|
|
s1.close();
|
|
System((rm + file).c_str(),true,false);
|
|
}
|
|
System(cmd + " > " + file,throwexception,false,pret);
|
|
|
|
string t;
|
|
char buff[16*1024];
|
|
ifstream s2(file.c_str());
|
|
while(s2) {
|
|
s2.getline(buff,16*1024);
|
|
if (s2) t += buff;
|
|
}
|
|
s2.close();
|
|
System((rm + file).c_str(),true,false);
|
|
return t;
|
|
}
|
|
}
|
|
|
|
string Getlocaltime()
|
|
{
|
|
FUNSTACK;
|
|
time_t rawtime;
|
|
time(&rawtime);
|
|
struct tm timeinfo;
|
|
localtime_s(&timeinfo,&rawtime);
|
|
char buff[1024];
|
|
asctime_s(buff,1014,&timeinfo);
|
|
return string(buff);
|
|
}
|
|
|
|
class timer
|
|
{
|
|
private:
|
|
double m_t,m_cpu_t;
|
|
double* m_addt;
|
|
mutable double m_last_t,m_last_eta;
|
|
|
|
static double gettime()
|
|
{
|
|
#ifdef WIN32
|
|
return 1.0*clock()/CLOCKS_PER_SEC; // use low-res clock
|
|
// FILETIME ft;
|
|
// unsigned __int64 tmpres = 0;
|
|
//
|
|
// GetSystemTimeAsFileTime(&ft);
|
|
//
|
|
// tmpres |= ft.dwHighDateTime;
|
|
// tmpres <<= 32;
|
|
// tmpres |= ft.dwLowDateTime;
|
|
//
|
|
// converting file time to unix epoch
|
|
// tmpres -= DELTA_EPOCH_IN_MICROSECS;
|
|
// tmpres /= 10; // convert into microseconds
|
|
// tv->tv_sec = (long)(tmpres / 1000000UL);
|
|
// tv->tv_usec = (long)(tmpres % 1000000UL);
|
|
#else
|
|
struct timeval tv;
|
|
gettimeofday(&tv,NULL);
|
|
return tv.tv_sec + static_cast<double>(tv.tv_usec)/1000000;
|
|
#endif
|
|
}
|
|
|
|
static double getcputime()
|
|
{
|
|
static const double f=1.0/CLOCKS_PER_SEC;
|
|
return f*clock();
|
|
}
|
|
|
|
template<class T>
|
|
static double Remaining(const double t,const T& n,const T& N)
|
|
{
|
|
if (n>=N || N<=T(0)) throw_("value out of range in timer::Remaining, n>=N or N<=0, n=" + tostring(n) + " N=" + tostring(N));
|
|
const double p=static_cast<double>(n/T(1)+1)/(N/T(1));
|
|
const double p2=p>0 ? t/p : 0;
|
|
return p2>t ? p2-t : 0;
|
|
}
|
|
|
|
public:
|
|
timer() : m_t(gettime()), m_cpu_t(getcputime()), m_addt(0), m_last_t(-1), m_last_eta(-1) {}
|
|
timer(double& t) : m_t(gettime()), m_cpu_t(getcputime()), m_addt(&t), m_last_t(-1), m_last_eta(-1) {}
|
|
~timer() {if (m_addt!=0) (*m_addt) += elapsed();}
|
|
|
|
void reset () {m_t=gettime(); m_cpu_t=getcputime(); m_last_t=-1; m_last_eta=-1;}
|
|
double elapsed() const {return gettime()-m_t;}
|
|
double cputime() const {return getcputime()-m_cpu_t;}
|
|
|
|
static string ToHMS(const double& t)
|
|
{
|
|
assert( t>=0 );
|
|
const unsigned int it=static_cast<unsigned int>(t+.5);
|
|
const unsigned int hours=it/(60*60);
|
|
const unsigned int mins=(it-hours*60*60)/(60);
|
|
const unsigned int secs=(it-hours*60*60-mins*60);
|
|
assert( secs<60 && mins<60);
|
|
return tostring(hours) + ":" + (mins<10 ? "0": "") + tostring(mins) + ":" + (secs<10 ? "0": "") + tostring(secs);
|
|
}
|
|
|
|
template<class T> static inline int Topercent(const T x,const T N,const int decimals=-1)
|
|
{
|
|
assert(x<N && N!=T(0));
|
|
float pf=static_cast<float>(x/T(1))/(N/T(1));
|
|
if (decimals>0) pf=static_cast<int>(pf*decimals)/(1.0*decimals);
|
|
return static_cast<int>(pf*100+.5);
|
|
}
|
|
|
|
template<class T> void ToEta(const T& n,const T& N,ostream& s,const double timeprintsteps=30,const bool verboseprint=false) const
|
|
{
|
|
if (n>=N) return;
|
|
assert( n<N );
|
|
|
|
const double t=gettime()-m_t;
|
|
if (n==T(0)) {
|
|
m_last_t=t;
|
|
return;
|
|
}
|
|
|
|
const double e=(t-m_last_t);
|
|
if (e>timeprintsteps) {
|
|
const double f=timeprintsteps*60;
|
|
const double r=Remaining(t,n,N);
|
|
if (m_last_eta<0 || r<f || (r>f && e>f) /*|| (m_last_eta>0 && r>1.2*m_last_eta) */ ){
|
|
time_t tm;
|
|
time(&tm);
|
|
const string systime=ctime(&tm);
|
|
if (m_last_eta<0) s << "Current system time: " << systime;
|
|
tm += static_cast<time_t>(r);
|
|
const string eta=ctime(&tm);
|
|
const bool extraday=(eta.substr(0,3)!=systime.substr(0,3));
|
|
const string eday=extraday ? " "+eta.substr(0,3)+" " : "";
|
|
s << "Time [h:m:s]=" << ToHMS(t) << ", R=" << ToHMS(r) << ", ETA=" << eday << eta.substr(11,8);
|
|
if(verboseprint) {
|
|
const string t=", n/N=" + tostring(n) + "/" + tostring(N) + "=" + tostring(Topercent(n,N,10)) + " percent,";
|
|
s << t;
|
|
for(size_t i=t.size();i<42;++i) s << " ";
|
|
s << " CPU=" << ToHMS(cputime());
|
|
}
|
|
s << endl;
|
|
|
|
m_last_t=t;
|
|
m_last_eta=r;
|
|
}
|
|
}
|
|
}
|
|
friend ostream& operator<<(ostream& s,const timer x)
|
|
{
|
|
return s << "Time [h:m:s]= " << x.ToHMS(x.elapsed()) << " CPU=" << x.ToHMS(x.cputime());
|
|
}
|
|
};
|
|
|
|
/*
|
|
int SwapEndian(void *data,const size_t size) {
|
|
|
|
short xs;
|
|
long xl;
|
|
|
|
switch (size){
|
|
case 2:
|
|
xs = *(short *)data;
|
|
*(short *)data = ( ((xs & 0x0000ff00) >> 8) | ((xs & 0x000000ff) << 8) );
|
|
break;
|
|
case 4:
|
|
xl = *(long *)data;
|
|
*(long *)data = ( ((xl & 0xff000000) >> 24) | ((xl & 0x00ff0000) >> 8) |
|
|
((xl & 0x0000ff00) << 8) | ((xl & 0x000000ff) << 24) );
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
#endif // __FUNS_H__
|