#include "eparser.h"
#include "ecrypto.h"

#include "sci/estats.h"
#include "sci/estattest.h"
#include "sci/eleastsquare.h"
#include "sci/ecorr.h"

#include "evarcommon.h"
#include "evarclass.h"

#include "esocket.h"

#include "evarclassconverter.h"
#include "estrarray.h"

#include "estr.h"
#include "efile.h"
#include "edir.h"
#include "etable.h"
#include "ecsv.h"
#include "emysql.h"
#include "etimer.h"
#include "ehtml.h"
#include "ehdf5.h"

#include "evarclassconstructor.h"
#include "evarclasscout.h"
#include "eparser.h"
#include "eudl.h"
#include "eheap.h"
//#include "efilesys.h"

#include "ematrix.h"
#include "vector2.h"
#include "vector3.h"
#include "ethread.h"


#include "eregexp.h"

#include "efunc.h"

#include "ernd.h"
#include "eparserinterpreter.h"
#include "emodule.h"

#include "esystem.h"

#include "edistcomp.h"
#include "eterm.h"

#if !defined(_WIN32)
  #include <unistd.h>
#endif

#include <math.h>
#include "evar.h"

#include "ebasichashmap.h"
#include "estrhashof.h"

void varinclude(const estr& file)
{
  epinterpretfile(file);
}

estrarray varexec(const estr& cmd)
{
  estr line;
  efile f(popen(cmd));
  estrarray arr;
  while (f.readln(line))
    arr.add(line);
  return(arr); 
}

void varunset(evar& var)
{
  var.clear();
}

void varprint_json(const evar& var)
{
  estr data;
  var.json_serial(data);
  cout << data << endl;
}

void varprint(const evar& var)
{
  cout << var << endl;
}
void vartype(const evar& var)
{
  cout << var.getClass() << endl;
}
void varaddress(const evar& var)
{
  if (var.var)
    cout << &var << " :: " << var.var << " ("<<var.var->pcount<<")"<<endl;
  else
    cout << &var << " :: " << var.var << endl;
}

void varshow(const evar& var)
{
/*
  if (var.getTypeid()==typeid(efunc)){
    efunc &f(var.get<efunc>());
    cout << getClassName(f.fReturn) << "(";
    for (int i=0; i<f.fArgs.size(); ++i)
      cout << (i>0?" ":"") << getClassName(f.fArgs[i]);
    cout << ")" << endl;
  }
*/
  if (var.getTypeid()==typeid(efunc)){
    efunc &f(var.get<efunc>());
    cout << "Function:"<< endl;
    cout << "  " << (f.fReturn?getClassName(f.fReturn):"void") << " function(";
    for (int j=0; j<f.fArgs.size(); ++j){
      if (j>0) cout << ",";
      cout << getClassName(f.fArgs.at(j));
    }
    cout << ")" << endl;
    return;
  }
  if (getClasses().exists(var.getClass())){
    eclassBase& c(getClasses().values(var.getClass()));
    cout << "Properties:" << endl;
    for (int i=0; i<c.properties.size(); ++i)
      cout << "  " << getClassName(c.properties.at(i).fValue) << " " << etermSetColor(tcGreen) << c.properties.keys(i) << etermUnsetColor() << endl;
    for (int i=0; i<c.parents.size(); ++i){
      eclassBase& cp(*c.parents.values(i));
      cout << "  - inherited: " << etermSetColor(tcRed) << getClassName(&cp.getTypeid()) << etermUnsetColor() << endl;
      for (int j=0; j<cp.properties.size(); ++j)
        cout << "    " << getClassName(cp.properties.at(j).fValue) << " " << etermSetColor(tcGreen) << cp.properties.keys(j) << etermUnsetColor() << endl;
    }
    cout << "Methods:" << endl;
    for (int i=0; i<c.methods.size(); ++i){
      for (int k=0; k<c.methods.values(i).size(); ++k){
        eclassMethodBase &method(*c.methods.values(i).at(k));
        cout << "  " << (method.fReturn?getClassName(method.fReturn):"void") << " " << etermSetColor(tcCyan) << c.methods.keys(i) << etermUnsetColor() << "(";
        for (int j=0; j<method.fArgs.size(); ++j){
          if (j>0) cout << ",";
          cout << getClassName(method.fArgs.at(j));
        }
        cout << ")" << endl;
      }
    }
    for (int i=0; i<c.parents.size(); ++i){
      eclassBase& cp(*c.parents.values(i));
      cout << "  - inherited: " << etermSetColor(tcRed) << getClassName(&cp.getTypeid()) << etermUnsetColor() << endl;
      for (int l=0; l<cp.methods.size(); ++l){
        for (int k=0; k<cp.methods.values(l).size(); ++k){
          eclassMethodBase &method(*cp.methods.values(l).at(k));
          cout << "    " << (method.fReturn?getClassName(method.fReturn):"void") << " " << etermSetColor(tcCyan) << cp.methods.keys(l) << etermUnsetColor() << "(";
          for (int j=0; j<method.fArgs.size(); ++j){
            if (j>0) cout << ",";
            cout << getClassName(method.fArgs.at(j));
          }
          cout << ")" << endl;
        }
      }
    }
  }
}

#ifdef _WIN32
void sleep(int msecs) {
  Sleep(msecs);
}
#endif

edoublearray vec2arr(const evector& v){
  edoublearray res;
  res.reserve(v.length());
  for (long i=0; i<v.size(); ++i)
    res.add(v[i]);
  return(res);
}


bool doneRegister=false;

template void heapsort<evararray>(evararray&);
template eintarray iheapsort<evararray>(evararray&);
template void heapsort<edoublearray>(edoublearray&);
template eintarray iheapsort<edoublearray>(edoublearray&);
//template void heapsort<ebasearray>(ebasearray&);
//template eintarray iheapsort<ebasearray>(ebasearray&);

typedef ebasicstrhashof<estr> ebasicstrhash;

template class ebasichashmap<estr,estr,&hash_lookup3_estr>;
template class ebasicstrhashof<estr>;

void epregisterFunctions()
{
  if (doneRegister) return;
  doneRegister=true;

#ifdef EUTILS_HAVE_REGEX
  epregisterClass(eregexp);
  epregisterClassConstructor(eregexp,(const estr&));
  epregisterClassConverterCast(eregexp,estr);
  epregisterClassMethod(eregexp,compile);
  epregisterClassMethod2D(eregexp,match,int,(const estr&,int,int) const,evararray(0x00));
  epregisterClassMethod2D(eregexp,match,int,(const estr&,int,int&,int&,int) const,evararray(0x00));
//  epregisterClassProperty(eregexp,b);
//  epregisterClassProperty(eregexp,e);
  epregisterFunc2(grep,estr,(estr&,const eregexp&,int));
  epregisterFunc(grepint);
#endif

  epregister2(getSystem(),"sys");
  epregisterClassMethod(esystem,process);
  epregisterClassMethod(esystem,run);
  epregisterClassMethod(esystem,setFrontProcess);
  epregisterClassMethod(esystem,getMemLimit);
  epregisterClassMethod(esystem,getTotalRam);
  epregisterClassMethod(esystem,getFreeRam);
  epregisterClassMethod(esystem,getBufferRam);
  epregisterClassMethod(esystem,getPID);
  epregisterClassMethod(esystem,getHostname);
  epregisterClassMethod(esystem,getExecutablePath);
  epregisterClassMethod(esystem,getLocalAddresses);

//  epregisterFunc3(iheapsort<ebasearray>,"iheapsort");
//  epregisterFunc3((void (*)(ebasearray&))&heapsort<ebasearray>,"heapsort");
  epregisterFunc3(iheapsort<edoublearray>,"iheapsort");
  epregisterFunc3((void (*)(edoublearray&))&heapsort<edoublearray>,"heapsort");
  epregisterFunc3(iheapsort<evararray>,"iheapsort");
  epregisterFunc3((void (*)(evararray&))&heapsort<evararray>,"heapsort");
//  epregisterFunc2(heapsort,void,(evararray&));

  epregisterClass(eudpsocket);
//  epregisterClassMethodD(eudpsocket,listen,"0.0.0.0");
  epregisterClassMethodD(eudpsocket,listen,evararray("0.0.0.0"));
  epregisterClassMethod(eudpsocket,setReuseAddress);
  epregisterClassMethod(eudpsocket,close);
  epregisterClassMethod(eudpsocket,shutdown);
  epregisterClassMethod(eudpsocket,recvfrom);
  epregisterClassMethod(eudpsocket,sendto);
  epregisterClassProperty(eudpsocket,onReceive);

  epregisterClass(esocket);
  epregisterClassMethod(esocket,listen);
  epregisterClassMethod(esocket,connect);
  epregisterClassMethod(esocket,close);
  epregisterClassMethod(esocket,shutdown);
  epregisterClassMethod2(esocket,recv,int,(estr&,int));
  epregisterClassMethod2(esocket,send,int,(const estr&));
  epregisterClassProperty(esocket,onReceive);

  epregisterClass(earray<esocket>);
  epregisterClassInheritance(earray<esocket>,ebasearray);
  epregisterClassPolymorphic(earray<esocket>,ebasearray);



/*
  epregisterClass(eserver<esocket>);
  epregisterClassConstructor(eserver<esocket>,());
  epregisterClassMethodD(eserver<esocket>,listen,"0.0.0.0");
  epregisterClassMethod2(eserver<esocket>,accept,esocket*,());
  epregisterClassProperty(eserver<esocket>,onIncoming);
  epregisterClassProperty(eserver<esocket>,sockets);
*/

  epregisterClassMethod2(ebasearrayof,addvar,void,(evar&,evar&));
  epregisterClassMethod2(ebasearrayof,getvar,evar,(int));
  epregisterClassMethod2(ebasearrayof,getvarkey,evar,(int));
  epregisterClassMethod2A(ebasearrayof,addvar,"add",void,(evar&,evar&));
  epregisterClassMethod2A(ebasearrayof,getvarByKey,"[]",evar,(const evar&));
  epregisterClassMethod2A(ebasearrayof,getvar,"[]",evar,(int));
  epregisterClassMethod2A(ebasearrayof,getvar,"values",evar,(int));
  epregisterClassMethod2A(ebasearrayof,getvarkey,"keys",evar,(int));
  epregisterClassMethod2AD(ebasearrayof,findvarkey,"findkey",long,(const evar&,long),evararray(0));
  epregisterClassMethod2(ebasearrayof,size,int,());

  epregisterClassMethod2(ebasearray,addvar,void,(evar&));
  epregisterClassMethod2(ebasearray,getvar,evar,(size_t));
  epregisterClassMethod2(ebasearray,erase,void,(size_t));
  epregisterClassMethod2(ebasearray,size,size_t,());
  epregisterClassMethod2A(ebasearray,addvar,"add",void,(evar&));
  epregisterClassMethod2A(ebasearray,operator[],"[]",evar,(size_t));

  epregisterFunc(getCatInds);

  epregisterClass(evararrayof<eintarray>);
  epregisterClassInheritance(evararrayof<eintarray>,ebasearrayof);

  epregister2(getClasses(),"classes");
  epregisterClassProperty(eclassBase,properties);
  epregisterClassProperty(eclassBase,methods);
  epregisterClassProperty(eclassBase,parents);

  epregisterClass(ebasicstrhash);
  epregisterClassMethod2(ebasicstrhash,add,estr&,(const estr&,const estr&));
  epregisterClassMethod2(ebasicstrhash,get,ebasicstrhash::iter,(const estr&));
  epregisterClassMethod4(ebasicstrhash,operator[],estr&,(const estr&),"[]");
  epregisterClassMethod4(ebasicstrhash,operator[],const estr&,(const estr&) const,"[]");
  epregisterClassMethod(ebasicstrhash,size);
  epregisterClassMethod(ebasicstrhash,begin);
  epregisterClassMethod(ebasicstrhash,end);
  epregisterClass(ebasicstrhash::iter);
  epregisterClassMethod(ebasicstrhash::iter,key);
  epregisterClassMethod(ebasicstrhash::iter,value);
  epregisterClassMethod4(ebasicstrhash::iter,operator=,ebasicstrhash&,(const ebasicstrhash&),"=");
  epregisterClassMethod4(ebasicstrhash::iter,operator==,bool,(const ebasicstrhash::iter&),"==");
  epregisterClassMethod4(ebasicstrhash::iter,operator++,ebasicstrhash::iter&,(),"++");
  epregisterClassMethod4(ebasicstrhash::iter,operator*,estr&,() const,"*");
 
  epregisterClassInheritance(estrhash,ebasearray);
  epregisterClassInheritance(estrhash,ebasearrayof);
  epregisterClassMethod2(estrhash,add,estr&,(const estr&));
  epregisterClassMethod2(estrhash,add,estr&,(const estr&,const estr&));
  epregisterClassMethod(estrhash,load);
  epregisterClassMethod(estrhash,save);
  epregisterClassMethod(estrhash,join);
  epregisterClassMethod(estrhash,exists);
  epregisterClassMethod2(estrhash,keys,estr&,(size_t));
  epregisterClassMethod2(estrhash,values,estr&,(size_t));
  epregisterClassMethod4(estrhash,operator[],estr&,(size_t),"[]");
  epregisterClassMethod4(estrhash,operator[],estr&,(const estr&),"[]");

  epregisterClassConstructor(estrarray,(const estr&));
  epregisterClassInheritance(estrarray,ebasearray);
  epregisterClassInheritance(estrarray,ebasearrayof);
  epregisterClassMethod2(estrarray,add,estr&,(const estr&));
  epregisterClassMethod2(estrarray,add,estr&,(const estr&,const estr&));
  epregisterClassMethod(estrarray,load);
  epregisterClassMethod(estrarray,save);
  epregisterClassMethod(estrarray,join);
  epregisterClassMethodD(estrarray,find,evararray(0,evarRef(estrarray::equal)));
  epregisterClassMethodD(estrarray,ifind,evararray(0));
  epregisterClassMethodD(estrarray,refind,evararray(0));
  epregisterClassMethodD(estrarray,findkey,evararray(0,evarRef(estrarray::equal)));
//  epregisterClassMethodD(estrarray,findkey,evararray(0));
  epregisterClassMethodD(estrarray,ifindkey,evararray(0));
  epregisterClassMethodD(estrarray,refindkey,evararray(0));
  epregisterClassMethod(estrarray,grep);
  epregisterClassMethod(estrarray,egrep);
  epregisterClassMethod(estrarray,egrepo);
  epregisterClassMethod(estrarray,ifindall);
  epregisterClassMethod(estrarray,ifindallkey);
  epregisterClassMethod(estrarray,refindall);
  epregisterClassMethod(estrarray,refindallkey);


  epregisterClassMethod2(estrarray,keys,const estr&,(size_t) const);
  epregisterClassMethod2(estrarray,values,estr&,(size_t));
  epregisterClassMethod4(estrarray,at,estr&,(size_t),"[]");
  epregisterClassMethod4(estrarray,operator[],estr&,(const estr&),"[]");

  epregisterClassMethod4(estrarray,operator[],estrarray,(const eintarray&) const,"[]");

  epregisterClassMethod4(estrarray,operator-=,estrarray&,(const estrarray&),"-=");
  epregisterClassMethod4(estrarray,operator-,estrarray,(const estrarray&),"-");
  epregisterClassMethod3<estrarray>((estr& (estrarray::*)(const estr&)) &estrarray::add,"+=");

//  epregisterClassInheritance(earray<estr>,ebasearray);
//  epregisterClassConverterCast(earray<estr>,evararray);

  epregisterClass(etimer);
  epregisterClassMethod(etimer,lap);
  epregisterClassMethod(etimer,check);
  epregisterClassMethod(etimer,reset);

  epregisterClassMethod2(evararray,add,evar&,(const evar&));
  epregisterClassMethod4(evararray,at,evar&,(size_t),"[]");
  epregisterClassMethod4(evararray,operator[],evararray,(const eintarray&) const,"[]");
  epregisterClassMethod4(evararray,operator[],evararray,(const elongarray&) const,"[]");
  epregisterClassMethod4(evararray,operator+,evararray,(const evararray&) const,"+");
  epregisterClassMethod4(evararray,operator+=,evararray&,(const evararray&),"+=");

  epregisterClass(eufile);
//  epregisterClassCout(efile);
//  epregisterClassConstructor(efile,(const estr&));
//  epregisterClassConstructor(efile,(const estr&,const estr&));
//  epregisterClassSerializeMethod(efile);
//  epregisterClassMethod2(efile,open,bool,() const);
  epregisterClassMethod2(eufile,open,bool,(const estr&,const estr&));
  epregisterClassMethod2(eufile,open,bool,(const estr&,const estr&,const estr&));
  epregisterClassMethod2(eufile,read,int,(estr&,long int) const);
  epregisterClassMethod2(eufile,read,int,(estr&) const);
//  epregisterClassMethod2(efile,read,bool,(evar&) const);
  epregisterClassMethod2D(eufile,readarr,bool,(estrarray&,const estr&) const,evararray("\t"));
  epregisterClassMethod2D(eufile,readarr,bool,(estr&,estrarray&,const estr&) const,evararray("\t"));
  epregisterClassMethod(eufile,readln);
  epregisterClassMethod(eufile,eof);
  epregisterClassMethod2(eufile,write,int,(const estr&) const);
/*
  epregisterClassMethod(efile,size);
  epregisterClassMethod(efile,exists);
  epregisterClassMethod(efile,basename);
  epregisterClassMethod(efile,close);
*/

  epregisterClass(efile);
  epregisterClassCout(efile);
  epregisterClassConstructor(efile,(const estr&));
  epregisterClassConstructor(efile,(const estr&,const estr&));
  epregisterClassSerializeMethod(efile);
  epregisterClassMethod2(efile,open,bool,() const);
  epregisterClassMethod2(efile,open,bool,(const estr&,const estr&));
  epregisterClassMethod(efile,fileno);
  epregisterClassMethod2(efile,read,int,(estr&,long int) const);
  epregisterClassMethod2(efile,read,int,(estr&) const);
//  epregisterClassMethod2(efile,read,bool,(evar&) const);
  epregisterClassMethod2D(efile,readarr,bool,(estrarray&,const estr&) const,evararray("\t"));
  epregisterClassMethod2D(efile,readarr,bool,(estr&,estrarray&,const estr&) const,evararray("\t"));
  epregisterClassMethod2(efile,readvar,evar,() const);
  epregisterClassMethod(efile,writevar);
  epregisterClassMethod(efile,readln);
  epregisterClassMethod(efile,eof);
  epregisterClassMethod(efile,data);
  epregisterClassMethod(efile,grep);
  epregisterClassMethod(efile,egrep);
  epregisterClassMethod(efile,egrepo);
  epregisterClassMethod2(efile,write,int,(const estr&) const);
  epregisterClassMethod2(efile,writevar,int,(const evar&) const);
  epregisterClassProperty(efile,name);
  epregisterClassMethod(efile,size);
  epregisterClassMethod(efile,exists);
  epregisterClassMethod(efile,basename);
  epregisterClassMethod(efile,close);

  epregisterClass(edir);
  epregisterClassCout(edir);
  epregisterClassConstructor(edir,(const estr&));
  epregisterClassSerializeMethod(edir);
  epregisterClassProperty(edir,dirs);
  epregisterClassProperty(edir,files);

  epregisterClass(estrarrayof<efile>);
  epregisterClassInheritance(estrarrayof<efile>,ebasearrayof);
  epregisterClassMethod(estrarrayof<efile>,size);
  epregisterClassMethod4(estrarrayof<efile>,operator[],efile&,(const estr&),"[]");
  epregisterClassMethod4(estrarrayof<efile>,at,efile&,(size_t),"[]");

  epregisterClass(estrarrayof<edir>);
  epregisterClassInheritance(estrarrayof<edir>,ebasearrayof);
  epregisterClassMethod(estrarrayof<edir>,size);
  epregisterClassMethod2(estrarrayof<edir>,keys,estr&,(size_t));
  epregisterClassMethod2(estrarrayof<edir>,values,edir&,(size_t));
  epregisterClassMethod4(estrarrayof<edir>,operator[],edir&,(const estr&),"[]");
  epregisterClassMethod4(estrarrayof<edir>,at,edir&,(size_t),"[]");


//  epregisterFunc(hca);
  epregisterFuncD(ls,evararray("."));
  epregisterFuncD(cd,evararray("~"));
  epregisterFunc(pwd);
  epregisterFunc2(env,estrarray,());
  
  epregisterFunc(etableTSV);
  epregisterClassMethod4(etable,operator[],evararray&,(size_t),"[]");
  epregisterClassMethod4(etable,operator[],evararray&,(const estr&),"[]");
  epregisterClassMethod(etable,row);
  epregisterClassMethod(etable,filter);
  epregisterClassMethod(etable,addfield);
  epregisterClassMethod(etable,append);
  epregisterClassMethod2(etable,add,void,(const estrarray&));
  epregisterClassMethod2(etable,add,void,(const evarhash&));
  epregisterClassMethod2(etable,add,void,(const estr&,const evar&));
  epregisterClassMethod(etable,size);
  epregisterClassMethod(etable,clear);
  epregisterClassMethod(etable,load);
  epregisterClassMethod(etable,save);
  epregisterClassMethod(etable,getBlockTable);
  epregisterClassProperty(etable,cols);
  epregisterClassProperty(etable,blocks);
  epregisterClassMethod4(erow,operator[],evar&,(size_t),"[]");
  epregisterClassMethod4(erow,operator[],evar&,(const estr&),"[]");
  epregisterClassMethod(erow,size);
  epregisterClassInheritance(estrhashof<evararray>,ebasearrayof);
  epregisterClassMethod2(estrhashof<evararray>,keys,earray<estr>&,());
  epregisterClassMethod4(earray<estr>,operator[],earray<estr>,(const eintarray&) const,"[]");

  epregisterClass(estrarrayof<etable>);
  epregisterClassInheritance(estrarrayof<etable>,ebasearrayof);
  epregisterClassSerializeMethod(estrarrayof<etable>);
  epregisterClassMethod(estrarrayof<etable>,size);
  epregisterClassMethod4(estrarrayof<etable>,operator[],etable&,(size_t),"[]");
  epregisterClassMethod4(estrarrayof<etable>,operator[],etable&,(const estr&),"[]");


  epregisterFunc(tablesLoad);
  epregisterFunc(etableLoadCSV2);
  epregisterFuncD(etableSave,evararray(evarhash()));
  epregisterFuncD(etableLoad,evararray(evarhash()));
  epregisterFuncD(etableLoadCols,evararray(evarhash()));
  epregisterFunc(etableLoadCSV);

  epregisterClassSerializeMethod(evector2);
  epregisterClassConstructor(evector2,(float,float));
  epregisterClassProperty(evector2,x);
  epregisterClassProperty(evector2,y);
  epregisterClassMethod(evector2,len);
  epregisterClassMethod(evector2,unit);
  epregisterClassMethod(evector2,perp);
  epregisterClassMethod3<evector2>(&evector2::operator+,"+");
  epregisterClassMethod4(evector2,operator-,evector2,(const evector2&) const,"-");
  epregisterClassMethod3<evector2>(&evector2::operator+=,"+=");
  epregisterClassMethod3<evector2>(&evector2::operator-=,"-=");
  epregisterClassMethod4(evector2,operator*,float,(const evector2&) const,"*");
  epregisterClassMethod4(evector2,operator*,evector2,(float) const,"*");
  epregisterClassMethod3<evector2>(&evector2::operator/,"/");

  epregisterClassMethod(ematrix,load);
  epregisterClassMethod(ematrix,save);
  epregisterClassMethod2(ematrix,create,void,(int,int));
  epregisterClassMethod2(ematrix,create,void,(const ematrix&));
  epregisterClassMethod(ematrix,mulrow);
  epregisterClassMethod(ematrix,addmulrow);
  epregisterClassMethod(ematrix,swap);
  epregisterClassMethod4(ematrix,operator(),double&,(int,int),"()");
  epregisterClassMethod2(ematrix,row,evector,(int) const);
  epregisterClassMethod2(ematrix,col,evector,(int) const);
  epregisterClassMethod4(ematrix,operator*,evector,(const evector&) const,"*");
  epregisterClassMethod4(ematrix,operator*,ematrix,(const ematrix&) const,"*");
  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,const ematrix&))summat,"+");
  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,const ematrix&))submat,"-");
//  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,const ematrix&))mulmat,"*");
//  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,const ematrix&))divmat,"/");
  epregisterFunc3((ematrix (*)(const ematrix&,const ematrix&))mulmat,"imul");
  epregisterFunc3((ematrix (*)(const ematrix&,const ematrix&))divmat,"idiv");
  epregisterFunc3(tanmat,"tan");
  epregisterFunc3(logmat,"log");
  epregisterFunc3(normmat,"norm");
  epregisterFunc3(maxmat,"max");
  epregisterFunc3(minmat,"min");
  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,double))summat,"+");
  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,double))submat,"-");
  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,double))mulmat,"*");
  epregisterFuncMethod2<ematrix>((ematrix (*)(const ematrix&,double))divmat,"/");
  epregisterFunc3(invmat,"inv");

  epregisterClassMethod2(ematrix,copytranspose,void,(const ematrix&));
  epregisterClassProperty(ematrix,w);
  epregisterClassProperty(ematrix,h);

  epregisterClassConstructorFunc(edoublearray,vec2arr);

  epregisterClassMethod(evector,create);
  epregisterClassMethod4(evector,operator(),double&,(int),"()");
  epregisterClassMethod4(evector,operator[],double&,(int),"[]");
  epregisterClassMethod4(evector,operator*,evector,(const ematrix&) const,"*");
  epregisterClassMethod(evector,length);
  epregisterClassProperty(evector,w);

  epregisterClassConstructor(emysql,());
  epregisterClassMethodD(emysql,connect,evararray("localhost","root","","",3306));
  epregisterClassMethod(emysql,query);

  epregisterClassMethod(emresult,size);
  epregisterClassMethod(emresult,clear);
  epregisterClassMethod(emresult,load);
  epregisterClassMethod(emresult,save);

  epregisterClassMethod(ernd,uniform);
#ifdef EUTILS_HAVE_LIBGSL
  epregisterClassMethod(ernd,gamma);
  epregisterClassMethod(ernd,gaussian);
  epregisterClassMethod(ernd,exponential);
  epregisterClassMethod(ernd,geometric);
  epregisterClassMethod(ernd,dirichlet);

  epregisterFunc(dprime);
#endif


  epregisterFunc(udl_load);

  epregisterFunc(eigenvalues);
  epregisterFunc(svd);
  epregisterFunc(pcoa);
  epregisterFunc(rref);
  epregisterFunc(nullspace);
  epregisterFunc(nullspacer);

  epregisterFunc2(round,float,(float));
  epregisterFunc2(round,double,(double));
  epregisterFunc2(trunc,float,(float));
  epregisterFunc2(trunc,double,(double));
  epregisterFunc2(floor,float,(float));
  epregisterFunc2(floor,double,(double));
  epregisterFunc2(fabs,double,(double));
  epregisterFunc2(fabs,float,(float));
  epregisterFunc2(sin,double,(double));
  epregisterFunc2(cos,double,(double));
  epregisterFunc2(tan,double,(double));
  epregisterFunc2(asin,double,(double));
  epregisterFunc2(acos,double,(double));
  epregisterFunc2(atan,double,(double));
  epregisterFunc2(atan2,double,(double,double));
  epregisterFunc2(sqrt,double,(double));
  epregisterFunc2(pow,double,(double,double));
  epregisterFunc2(log,double,(double));
  epregisterFunc2(log2,double,(double));
  epregisterFunc2(log10,double,(double));
  epregisterFunc2(exp,double,(double));
  epregisterFunc(sleep);
  epregisterFunc2(popen,efile,(const estr&));
  epregisterFunc2(system,int,(const estr&));

  epregisterClass(ekolmogorovsmirnov);
  epregisterClassProperty(ekolmogorovsmirnov,supd);
  epregisterClassProperty(ekolmogorovsmirnov,pval);
  epregisterClassMethod(ekolmogorovsmirnov,test);

#ifdef EUTILS_HAVE_LIBGSL
  epregisterFunc(ecdfChi2);
  epregisterFunc(epdfChi2);
  epregisterFunc(ecdfGaussian);
  epregisterFunc(epdfGaussian);
  epregisterFunc(etest_chi2);
  epregisterFunc(emultifit_linear);
  epregisterFunc2(pearson_corr,double,(edoublearray&,edoublearray&,double&));
  epregisterFunc2(spearman_corr,double,(edoublearray&,edoublearray&,double&));
  epregisterFunc2(pearson_corr,double,(edoublearray&,edoublearray&));
  epregisterFunc2(spearman_corr,double,(edoublearray&,edoublearray&));

  epregisterClass(estatsMMedian);
  epregisterClassProperty(estatsMMedian,med);
  epregisterClassProperty(estatsMMedian,p1);
  epregisterClassProperty(estatsMMedian,p25);
  epregisterClassProperty(estatsMMedian,p75);
  epregisterClassProperty(estatsMMedian,p99);
  epregisterClassMethod(estatsMMedian,calc);
  epregisterClassMethod(estatsMMedian,clear);

#endif

  epregisterFunc(getPercentileValue);

  epregisterClass(estats);
  epregisterClassProperty(estats,values);
  epregisterClassProperty(estats,weights);
  epregisterClassProperty(estats,median);
  epregisterClassProperty(estats,p1);
  epregisterClassProperty(estats,p25);
  epregisterClassProperty(estats,p75);
  epregisterClassProperty(estats,p99);
  epregisterClassMethod2(estats,calc,void,());
  epregisterClassMethod2(estats,calcWeighted,void,());
  epregisterClassMethod2(estats,calc,void,(edoublearray&));
  epregisterClassMethod2(estats,add,void,(double));
  epregisterClassMethod2(estats,add,void,(const edoublearray&));
//  epregisterClassMethod(estats,clear);


  epregisterFunc(etest_fisher2x2);
  epregisterFunc(etest_fisher2x2_log);


  epregisterFunc3(epinterpret,"eval");
  epregisterFunc2(epruninterpret,void,());

  epregisterFunc3(varexec,"exec");
  epregisterFunc3(varunset,"unset");
  epregisterFunc3(varprint,"print");
  epregisterFunc3(varprint_json,"print_json");
  epregisterFunc3(vartype,"type");
  epregisterFunc3(varaddress,"addr");
  epregisterFunc3(varshow,"show");
  epregisterFunc3(varinclude,"include");
  
  epregisterFunc2(hex,estr,(long));
  epregisterFunc2(hex,estr,(unsigned long));
  epregisterFunc2(hex,estr,(int));
  epregisterFunc2(hex,estr,(unsigned int));
  epregisterFunc2(hex,estr,(short));
  epregisterFunc2(hex,estr,(unsigned short));
  epregisterFunc2(hex,estr,(unsigned char));
  epregisterFunc2(hex,estr,(const estr&));

  epregisterFunc2(json_serial,void,(const evar&,estr&));
  epregisterFunc2(serial,void,(const evar&,estr&));
  epregisterFunc2(unserial,evar,(const estr&));

  epregisterClassInheritance(estrhashof<emodule>,ebasearrayof);
  epregisterClassInheritance(estrarrayof<efunc>,ebasearrayof);
  epregister2(getModules(),"modules");
  epregisterClassProperty(emodules,modules);
  epregisterClassMethod(emodules,load);
  epregisterClassMethod(emodules,unload);
  epregisterClassMethod(emodules,reload);
  epregisterClassProperty(emodule,name);
  epregisterClassProperty(emodule,funcs);

  epregister(rnd);

  epregister2(getSystem(),"sys");
  epregisterClassMethodI(esystem,getTotalRam,"return total amount of RAM in system");
  epregisterClassMethodI(esystem,getFreeRam,"return free amount RAM in system");
  epregisterClassMethodI(esystem,getBufferRam,"return amount of RAM used by buffers");
  epregisterClassMethodI(esystem,getMemLimit,"return maximum memory limit set for process");

  epregister2(getDistComp(),"distcomp");
  epregisterClassMethodDI(edistcomp,startProcClient,evararray(estr()),"connect to host");

  epregisterClassMethod(edcnode,call);
  epregisterClassMethod(edcnode,interpret);
  epregisterClassProperty(edcnode,isBusy);
  epregisterClassProperty(edcnode,result);

//  epregisterClass(edistcomp);
  epregisterClassProperty(edistcomp,clients);
  epregisterClassInheritance(estrhashof<edcnode>,ebasearrayof);
  epregisterClassProperty(edistcomp,groups);
  epregisterClassInheritance(estrhashof<etaskQueue>,ebasearrayof);
  epregisterClassProperty(edistcomp,hosts);
  epregisterClassInheritance(estrhashof<edcnode*>,ebasearrayof);

  epregisterClassMethodA(edistcomp,getClient,"[]");
  epregisterClassMethod(edistcomp,getClient);
  epregisterClassMethod(edistcomp,nodeCount);
  epregisterClassProperty(edistcomp,showResult);

  epregisterClass(etaskQueue);
  epregisterClassMethod(etaskQueue,setThreads);
  epregisterClassMethod(etaskQueue,add);

  epregisterClassMethod(etaskBase,wait);
  epregisterClassMethod(etaskBase,waitResult);
  epregisterClassMethod(etaskBase,getResult);
  epregisterClassMethod(etaskBase,queuedCount);
  epregisterClassMethod(etaskBase,isDone);

  epregisterClassCout(etask);
  epregisterClassConstructor(etask,(const efunc&,const evararray&));
  epregisterClassInheritance(etask,etaskBase);

  epregisterClassCout(etaskArray);
  epregisterClassConstructor(etaskArray,(const efunc&,const evararray&,int count));
  epregisterClassInheritance(etaskArray,etaskBase);

  epregisterClassCout(etaskApply);
  epregisterClassConstructor(etaskApply,(const efunc&,const evararray&,evararray&));
  epregisterClassInheritance(etaskApply,etaskBase);

  epregisterFunc(urlencode);
  epregisterFunc(urldecode);

  epregisterClassInheritance(ebasicarray<ehtmltag*>,ebasearray);
  epregisterClassInheritance(earray<ehtmltag>,ebasearray);
  epregisterClassInheritance(estrarrayof<ehtmltag*>,ebasearrayof);

  epregisterClass(ehtml);
  epregisterClassMethod(ehtml,clear);
  epregisterClassMethod(ehtml,parse);
  epregisterClassMethod(ehtml,load);
  epregisterClassMethod(ehtml,save);
  epregisterClassMethod(ehtml,make);
  epregisterClassProperty(ehtml,head);
  epregisterClassProperty(ehtml,body);
  epregisterClassProperty(ehtml,links);
  epregisterClassProperty(ehtml,forms);
  epregisterClassProperty(ehtml,images);
  epregisterClassProperty(ehtml,scripts);
  epregisterClassProperty(ehtml,tags);
  epregisterClass(ehtmltag);
  epregisterClassMethod(ehtmltag,addText);
  epregisterClassMethod(ehtmltag,addTag);
  epregisterClassMethod(ehtmltag,parse);
  epregisterClassMethod(ehtmltag,make);
  epregisterClassProperty(ehtmltag,parts);
  epregisterClassProperty(ehtmltag,text);
  epregisterClassProperty(ehtmltag,single);
  epregisterClassProperty(ehtmltag,type);
  epregisterClassProperty(ehtmltag,args);

  epregisterClass(emutex);
  epregisterClassMethod(emutex,trylock);
  epregisterClassMethod(emutex,lock);
  epregisterClassMethod(emutex,unlock);
  epregisterClass(econdsig);
  epregisterClassMethod(econdsig,wait);
  epregisterClassMethod(econdsig,broadcast);
  epregisterClassMethod(econdsig,signal);
  epregisterClass(ethreads);
  epregisterClassMethod(ethreads,run);
  epregisterClassMethod(ethreads,wait);
  epregisterClassMethod(ethreads,stop);
  epregisterClassMethod(ethreads,setThreads);


#ifdef EUTILS_HAVE_MD5_H
  epregisterFunc(sha1);
#endif
  epregisterFunc(base64encode);

  epregisterFunc(exit);
  epregisterFunc(showless);

#ifdef EUTILS_HAVE_HDF5
  epregisterClass(ehdf5);
  epregisterClassMethod(ehdf5,open);
  epregisterClassMethod(ehdf5,create);
  epregisterClassMethod(ehdf5,close);
  epregisterClassMethod(ehdf5,openGroup);
  epregisterClassMethod(ehdf5,readDataset);
  epregisterClassMethod(ehdf5,writeDataset);
//  epregisterClass(ehdf5Group);
  epregisterClassMethod(ehdf5Group,ls);
  epregisterClassMethod(ehdf5Group,close);
//  epregisterClass(ehdf5Object);
  epregisterClassProperty(ehdf5Object,name);

  epregisterClassInheritance(earray<ehdf5Object>,ebasearray);
#endif

/*
  epregisterClass(etaskman);
  epregisterClassMethod(etaskman,addTask);
  epregisterClassMethod(etaskman,createThread);

  epregisterClassProperty(etask,result);
*/
}


