[SCM] Packaging for mathgl branch, experimental, updated. debian/2.1.2+svn722-1-3-g679e0bf

Dimitrios Eftaxiopoulos eftaxi12 at otenet.gr
Sat May 4 06:36:31 UTC 2013


The following commit has been merged in the experimental branch:
commit c59c5061299462e395132baebc6f8e96a0c82d12
Author: Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>
Date:   Fri May 3 11:32:00 2013 +0300

    Imported Upstream version 2.1.3

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 583f290..3364973 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@ endif(NOT CMAKE_BUILD_TYPE)
 
 set(CMAKE_VERBOSE_MAKEFILE ON)
 set(MathGL_VERSION_MAJOR 2)
-set(MathGL_VERSION_MINOR 1.2)
+set(MathGL_VERSION_MINOR 1.3)
 
 
 MACRO(MGL_DEPENDENT_OPTION option doc default depends1 force1 depends2 force2)
@@ -87,6 +87,19 @@ MGL_DEPENDENT_OPTION(enable-octave-install "Octave interface will install for al
 
 include_directories( ${MathGL_SOURCE_DIR}/include ${MathGL_BINARY_DIR}/include)
 set(MGL_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/include/mgl2")
+set(MGL_CGI_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl" CACHE STRING "Set CGI install directory")
+
+if(NOT WIN32)
+#	set(MGL_CGI_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl")
+	set(MGL_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl")
+	set(MGL_DOC_PATH "${CMAKE_INSTALL_PREFIX}/share/doc/mathgl")
+	set(MGL_MAN_PATH "${CMAKE_INSTALL_PREFIX}/share/man")
+	set(MGL_INFO_PATH "${CMAKE_INSTALL_PREFIX}/share/info")
+	set(MGL_FONT_PATH "${MGL_DATA_PATH}/fonts")
+	install(DIRECTORY fonts/ DESTINATION ${MGL_FONT_PATH}
+			PATTERN ".svn" EXCLUDE
+			PATTERN "*.vfm")
+endif(NOT WIN32)
 
 include(CheckFunctionExists)
 include(CMakePushCheckState)
@@ -395,17 +408,6 @@ if(WIN32)
 	add_definitions(-DWIN32)
 endif(WIN32)
 
-if(NOT WIN32)
-set(MGL_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl")
-set(MGL_DOC_PATH "${CMAKE_INSTALL_PREFIX}/share/doc/mathgl")
-set(MGL_MAN_PATH "${CMAKE_INSTALL_PREFIX}/share/man")
-set(MGL_INFO_PATH "${CMAKE_INSTALL_PREFIX}/share/info")
-set(MGL_FONT_PATH "${MGL_DATA_PATH}/fonts")
-install(DIRECTORY fonts/ DESTINATION ${MGL_FONT_PATH}
-		PATTERN ".svn" EXCLUDE
-		PATTERN "*.vfm")
-endif(NOT WIN32)
-
 add_subdirectory( src )
 add_subdirectory( widgets )
 add_subdirectory( include )
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 3e9aeb3..2f14644 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,16 +1,18 @@
-2.1.3 Released ?? April 2013
+2.1.3 Released 2 May 2013
 
-* Improve SinFFT, CosFFT and so on, to be multi-threaded
+* Functions SinFFT, CosFFT, Hankel and so on, become multi-threaded
 * Use DFT instead of FFT if GSL support is disabled (much slow!).
+* Add Join() function for joining mglData arrays
+* Add Roots() function for root finding of nonlinear equation using provided guess(es)
+* Add mglExprC for parsing formula with complex numbers
 * Correctly read #QNAN values in data files
 * Speed up Dots() drawing
+* Add flag to disable tick labels at axis origin (see SetOriginTick())
 * Add MGL commands 'origintick', 'tickshift'
-* JSON now use zlib if filename end at 'z' (like "test.jsonz")
+* WriteJSON now use zlib if filename end at 'z' (like "test.jsonz")
 * Make separate libmgl-mpi
-* Add mglExprC for parsing formula with complex numbers
-* Add SetAutoRanges()
-* Add flag to disable tick labels at axis origin (see SetOriginTick())
-* Add JSON sample usage via QtWebKit
+* Add SetAutoRanges() function (duplicate corresponding options)
+* Add JSON sample usage via QtWebKit (thanks to DATADVANCE)
 * Bugfixes and memory leaks
 
 2.1.2 Released 28 January 2013
diff --git a/clean-svn b/clean-svn
deleted file mode 100755
index f0ba47a..0000000
--- a/clean-svn
+++ /dev/null
@@ -1,3 +0,0 @@
-find . -name '.svn' -print0 | xargs -0 rm -rf
-find . -name '*~' -print0 | xargs -0 rm -f
-rm ./clean-svn
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 304c6c9..e48d41f 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -24,7 +24,7 @@ endif(MGL_HAVE_WX)
 
 if(MGL_HAVE_QT)
 	include(${QT_USE_FILE})
-	qt_wrap_cpp(mgl_qt_example MGL_MOC_EX_FILES ../include/mgl2/qt.h)
+#	qt_wrap_cpp(mgl_qt_example MGL_MOC_EX_FILES ../include/mgl2/qt.h)
 	add_executable(mgl_qt_example wnd_samples.cpp qt_example.cpp ${MGL_MOC_EX_FILES})
 	target_link_libraries(mgl_qt_example mgl-qt)
 endif(MGL_HAVE_QT)
diff --git a/include/mgl2/data.h b/include/mgl2/data.h
index c483e8f..7ff2725 100644
--- a/include/mgl2/data.h
+++ b/include/mgl2/data.h
@@ -143,6 +143,9 @@ public:
 	/// Remove rows with duplicate values in column id
 	inline void Clean(long id)
 	{	mgl_data_clean(this,id);	}
+	/// Join with another data array
+	inline void Join(const mglDataA &d)
+	{	mgl_data_join(this,&d);	}
 	
 	/// Modify the data by specified formula
 	inline void Modify(const char *eq,long dim=0)
@@ -254,7 +257,10 @@ public:
 	{	return mglData(true,mgl_data_evaluate(this,&idat,&jdat,0,norm));	}
 	inline mglData Evaluate(const mglData &idat, const mglData &jdat, const mglData &kdat, bool norm=true) const
 	{	return mglData(true,mgl_data_evaluate(this,&idat,&jdat,&kdat,norm));	}
-
+	/// Find roots for set of nonlinear equations defined by textual formula
+	inline mglData Roots(const char *func, char var='x') const
+	{	return mglData(true,mgl_data_roots(func, this, var));	}
+	
 	/// Cumulative summation the data in given direction or directions
 	inline void CumSum(const char *dir)	{	mgl_data_cumsum(this,dir);	}
 	/// Integrate (cumulative summation) the data in given direction or directions
diff --git a/include/mgl2/data_cf.h b/include/mgl2/data_cf.h
index a1bf01c..e827af3 100644
--- a/include/mgl2/data_cf.h
+++ b/include/mgl2/data_cf.h
@@ -253,6 +253,9 @@ void MGL_EXPORT mgl_data_insert_(uintptr_t *dat, const char *dir, int *at, int *
 /// Delete data rows/columns/slices
 void MGL_EXPORT mgl_data_delete(HMDT dat, char dir, long at, long num);
 void MGL_EXPORT mgl_data_delete_(uintptr_t *dat, const char *dir, int *at, int *num, int);
+/// Joind another data array
+void MGL_EXPORT mgl_data_join(HMDT dat, HCDT d);
+void MGL_EXPORT mgl_data_join_(uintptr_t *dat, uintptr_t *d);
 
 /// Smooth the data on specified direction or directions
 void MGL_EXPORT mgl_data_smooth(HMDT d, const char *dirs, mreal delta);
@@ -434,6 +437,15 @@ uintptr_t MGL_EXPORT mgl_triangulation_3d_(uintptr_t *x, uintptr_t *y, uintptr_t
 HMDT MGL_EXPORT mgl_triangulation_2d(HCDT x, HCDT y);
 uintptr_t MGL_EXPORT mgl_triangulation_2d_(uintptr_t *x, uintptr_t *y);
 
+/// Find root for nonlinear equation
+mreal MGL_EXPORT mgl_find_root(mreal (*func)(mreal val, void *par), mreal ini, void *par);
+/// Find root for nonlinear equation defined by textual formula
+mreal MGL_EXPORT mgl_find_root_txt(const char *func, mreal ini, char var);
+mreal MGL_EXPORT mgl_find_root_txt_(const char *func, mreal *ini, const char *var,int,int);
+/// Find roots for nonlinear equation defined by textual formula
+HMDT MGL_EXPORT mgl_data_roots(const char *func, HCDT ini, char var);
+uintptr_t MGL_EXPORT mgl_data_roots_(const char *func, uintptr_t *ini, const char *var,int,int);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mgl2/datac.h b/include/mgl2/datac.h
index d222509..5661e55 100644
--- a/include/mgl2/datac.h
+++ b/include/mgl2/datac.h
@@ -138,6 +138,9 @@ public:
 	/// Delete data
 	inline void Delete(char dir, long at=0, long num=1)
 	{	mgl_datac_delete(this,dir,at,num);	}
+	/// Join with another data array
+	inline void Join(const mglDataA &d)
+	{	mgl_datac_join(this,&d);	}
 
 	/// Modify the data by specified formula
 	inline void Modify(const char *eq,long dim=0)
diff --git a/include/mgl2/datac_cf.h b/include/mgl2/datac_cf.h
index 8404d76..a6925d8 100644
--- a/include/mgl2/datac_cf.h
+++ b/include/mgl2/datac_cf.h
@@ -154,6 +154,9 @@ void MGL_EXPORT mgl_datac_insert_(uintptr_t *dat, const char *dir, int *at, int
 /// Delete data rows/columns/slices
 void MGL_EXPORT mgl_datac_delete(HADT dat, char dir, long at, long num);
 void MGL_EXPORT mgl_datac_delete_(uintptr_t *dat, const char *dir, int *at, int *num, int);
+/// Joind another data array
+void MGL_EXPORT mgl_datac_join(HADT dat, HCDT d);
+void MGL_EXPORT mgl_datac_join_(uintptr_t *dat, uintptr_t *d);
 
 /// Smooth the data on specified direction or directions
 void MGL_EXPORT mgl_datac_smooth(HADT d, const char *dirs, mreal delta);
diff --git a/src/base.cpp b/src/base.cpp
index fab76bb..af5f2d7 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -52,7 +52,7 @@ void MGL_EXPORT mgl_create_cpp_font(HMGL gr, const wchar_t *how)
 	{
 		ch = f->Internal(s[i]);
 		int m1 = f->GetNl(0,ch), m2 = f->GetNt(0,ch);
-		printf("\t{0x%x,%d,%d,%lu,%d,%lu},\n",s[i],f->GetWidth(0,ch),m1,m,m2,m+2*m1);
+		printf("\t{0x%x,%d,%d,%lu,%d,%lu},\n",unsigned(s[i]),f->GetWidth(0,ch),m1,m,m2,m+2*m1);
 		m += 2*m1+6*m2;
 	}
 	if(m!=l+n)	printf("#error \"%lu !=%lu + %lu\"",m,l,n);
diff --git a/src/base_cf.cpp b/src/base_cf.cpp
index 227cab2..221134a 100644
--- a/src/base_cf.cpp
+++ b/src/base_cf.cpp
@@ -26,8 +26,8 @@
 //-----------------------------------------------------------------------------
 void MGL_EXPORT mgl_set_quality(HMGL gr, int qual)	{	gr->SetQuality(qual);	}
 void MGL_EXPORT mgl_set_quality_(uintptr_t *gr, int *qual)	{	_GR_->SetQuality(*qual);	}
-int MGL_EXPORT mgl_get_quality(HMGL gr, int qual)	{	return gr->GetQuality();	}
-int MGL_EXPORT mgl_get_quality_(uintptr_t *gr, int *qual)	{	return _GR_->GetQuality();	}
+int MGL_EXPORT mgl_get_quality(HMGL gr)	{	return gr->GetQuality();	}
+int MGL_EXPORT mgl_get_quality_(uintptr_t *gr)	{	return _GR_->GetQuality();	}
 int MGL_EXPORT mgl_is_frames(HMGL gr)
 {	return gr->get(MGL_VECT_FRAME) && !(gr->GetQuality()&4);	}
 //-----------------------------------------------------------------------------
diff --git a/src/complex.cpp b/src/complex.cpp
index f68cf15..e7e6ec8 100644
--- a/src/complex.cpp
+++ b/src/complex.cpp
@@ -750,3 +750,46 @@ MGL_EXPORT dual *mgl_datac_value(HADT dat, long i,long j,long k)
 {	register long ii=i*dat->nx*(j+dat->ny*k);
 	return	ii>=0 && ii<dat->GetNN() ? dat->a+ii : 0;	}
 //-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_join(HADT d, HCDT v)
+{
+	register long nx=d->nx, ny=d->ny, nz=d->nz;
+	const mglDataC *mv = dynamic_cast<const mglDataC *>(v);
+	long vx=v->GetNx(), vy=v->GetNy(), vz=v->GetNz();
+	register long i,k=nx*ny*nz;
+
+	if(nx==vx && ny==vy && (nz>1 || vz>1))
+	{
+		dual *b = new dual[nx*ny*(nz+vz)];
+		memcpy(b,d->a,nx*ny*nz*sizeof(dual));
+		if(mv)	memcpy(b+nx*ny*nz,mv->a,nx*ny*vz*sizeof(dual));
+		else 	for(i=0;i<nx*ny*vz;i++)	b[k+i] = v->vthr(i);
+		if(!d->link)	delete []d->a;	d->nz += vz;
+		d->a = b;	d->link=false;	d->NewId();
+	}
+	else if(nx==vx && (ny>1 || vy>1))
+	{
+		ny *= nz;	vy *= vz;
+		dual *b = new dual[nx*(ny+vy)];
+		memcpy(b,d->a,nx*ny*sizeof(dual));
+		if(mv)	memcpy(b+nx*ny,mv->a,nx*vy*sizeof(dual));
+		else 	for(i=0;i<nx*vy;i++)	b[k+i] = v->vthr(i);
+		if(!d->link)	delete []d->a;
+		d->nz = 1;	d->ny = ny+vy;
+		d->a = b;	d->link=false;	d->NewId();
+	}
+	else
+	{
+		nx *= ny*nz;	vx *= vy*vz;
+		dual *b = new dual[nx+vx];
+		memcpy(b,d->a,nx*sizeof(dual));
+		if(mv)	memcpy(b+nx,mv->a,vx*sizeof(dual));
+		else 	for(i=0;i<vx;i++)	b[k+i] = v->vthr(i);
+		if(!d->link)	delete []d->a;
+		d->nz = d->ny = 1;	d->nx = nx+vx;
+		d->a = b;	d->link=false;	d->NewId();
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_join_(uintptr_t *d, uintptr_t *val)
+{	mgl_datac_join(_DC_,_DA_(val));	}
+//-----------------------------------------------------------------------------
diff --git a/src/complex_io.cpp b/src/complex_io.cpp
index 09732c3..a9461d9 100644
--- a/src/complex_io.cpp
+++ b/src/complex_io.cpp
@@ -577,7 +577,7 @@ void MGL_EXPORT mgl_datac_modify_vw(HADT d, const char *eq,HCDT vdat,HCDT wdat)
 	if(wdat && wdat->GetNN()!=nn)	return;
 	mglFormulaC f(eq);
 	if(v && w)	mglStartThreadC(mgl_cmodify,0,nn,d->a,v->a,w->a,par,&f);
-	else if(vdat && wdat)	(mgl_cmodify_gen,nn,d->a,vdat,wdat,par,&f);
+	else if(vdat && wdat)	mglStartThreadV(mgl_cmodify_gen,nn,d->a,vdat,wdat,par,&f);
 	else if(v)	mglStartThreadC(mgl_cmodify,0,nn,d->a,v->a,0,par,&f);
 	else if(vdat)	mglStartThreadV(mgl_cmodify_gen,nn,d->a,vdat,0,par,&f);
 	else	mglStartThreadC(mgl_cmodify,0,nn,d->a,0,0,par,&f);
diff --git a/src/data.cpp b/src/data.cpp
index 84693df..6269f93 100644
--- a/src/data.cpp
+++ b/src/data.cpp
@@ -1960,3 +1960,46 @@ long MGL_EXPORT mgl_data_get_nx_(uintptr_t *d)	{	return _DA_(d)->GetNx();	}
 long MGL_EXPORT mgl_data_get_ny_(uintptr_t *d)	{	return _DA_(d)->GetNy();	}
 long MGL_EXPORT mgl_data_get_nz_(uintptr_t *d)	{	return _DA_(d)->GetNz();	}
 //-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_join(HMDT d, HCDT v)
+{
+	register long nx=d->nx, ny=d->ny, nz=d->nz;
+	const mglData *mv = dynamic_cast<const mglData *>(v);
+	long vx=v->GetNx(), vy=v->GetNy(), vz=v->GetNz();
+	register long i,k=nx*ny*nz;
+
+	if(nx==vx && ny==vy && (nz>1 || vz>1))
+	{
+		mreal *b = new mreal[nx*ny*(nz+vz)];
+		memcpy(b,d->a,nx*ny*nz*sizeof(mreal));
+		if(mv)	memcpy(b+nx*ny*nz,mv->a,nx*ny*vz*sizeof(mreal));
+		else 	for(i=0;i<nx*ny*vz;i++)	b[k+i] = v->vthr(i);
+		if(!d->link)	delete []d->a;	d->nz += vz;
+		d->a = b;	d->link=false;	d->NewId();
+	}
+	else if(nx==vx && (ny>1 || vy>1))
+	{
+		ny *= nz;	vy *= vz;
+		mreal *b = new mreal[nx*(ny+vy)];
+		memcpy(b,d->a,nx*ny*sizeof(mreal));
+		if(mv)	memcpy(b+nx*ny,mv->a,nx*vy*sizeof(mreal));
+		else 	for(i=0;i<nx*vy;i++)	b[k+i] = v->vthr(i);
+		if(!d->link)	delete []d->a;
+		d->nz = 1;	d->ny = ny+vy;
+		d->a = b;	d->link=false;	d->NewId();
+	}
+	else
+	{
+		nx *= ny*nz;	vx *= vy*vz;
+		mreal *b = new mreal[nx+vx];
+		memcpy(b,d->a,nx*sizeof(mreal));
+		if(mv)	memcpy(b+nx,mv->a,vx*sizeof(mreal));
+		else 	for(i=0;i<vx;i++)	b[k+i] = v->vthr(i);
+		if(!d->link)	delete []d->a;
+		d->nz = d->ny = 1;	d->nx = nx+vx;
+		d->a = b;	d->link=false;	d->NewId();
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_join_(uintptr_t *d, uintptr_t *val)
+{	mgl_data_join(_DT_,_DA_(val));	}
+//-----------------------------------------------------------------------------
diff --git a/src/data_new.cpp b/src/data_new.cpp
index 3dcc0e0..439338c 100644
--- a/src/data_new.cpp
+++ b/src/data_new.cpp
@@ -854,3 +854,60 @@ void MGL_EXPORT mgl_data_sort(HMDT dat, long idx, long idy)
 void MGL_EXPORT mgl_data_sort_(uintptr_t *d, int *idx, int *idy)
 {	mgl_data_sort(_DT_,*idx,*idy);	}
 //-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_find_root(mreal (*func)(mreal x, void *par), mreal x0, void *par)
+{
+	mreal x1=x0+1e-2*(x0?x0:1), f0=func(x0,par), f1=func(x1,par), x, f;
+	if(fabs(f0)<1e-7)	return x0;
+	if(fabs(f1)<1e-7)	return x1;
+	if(f0==f1)	return NAN;
+	for(long i=0;i<20;i++)
+	{
+		x = x1-f1*(x1-x0)/(f1-f0);	f = func(x,par);
+		if(fabs(f)<1e-7)	return x;
+/*		if(fabs(f-f1)>0.5*fmin(fabs(f),fabs(f1)))	// TODO switch to bisection if slow
+		{
+			x = (x1+x0)/2;	f = func(x,par);
+			if(fabs(f)<1e-7)	return x;
+		}*/
+		x0=x1;	f0=f1;	x1=x;	f1=f;	// new points
+	}
+	return NAN;	// no roots found
+}
+//-----------------------------------------------------------------------------
+struct MGL_NO_EXPORT mglFuncV	{	mglFormula *eq;	char var;	};
+mreal MGL_NO_EXPORT mgl_funcv(double v, void *par)
+{
+	mglFuncV *f = (mglFuncV *)par;
+	mreal var[MGL_VS];	memset(var,0,('z'-'a')*sizeof(mreal));
+	var[f->var-'a'] = v;
+	return f->eq->Calc(var);
+}
+HMDT MGL_EXPORT mgl_data_roots(const char *func, HCDT ini, char var)
+{
+	if(!ini)	return (new mglData);
+	mglData *res = new mglData(ini);
+
+	mglFormula eq(func);
+	mglFuncV f;	f.eq = &eq;	f.var = var;
+	register long i, n = res->nx*res->ny*res->nz;
+	for(i=0;i<n;i++)
+		res->a[i] = mgl_find_root(mgl_funcv,res->a[i],&f);
+	return res;
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_find_root_txt(const char *func, mreal ini, char var)
+{
+	mglFormula eq(func);
+	mglFuncV f;	f.eq = &eq;	f.var = var;
+	return mgl_find_root(mgl_funcv,ini,&f);
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_data_roots_(const char *func, uintptr_t *ini, const char *var,int l,int)
+{	char *s=new char[l+1];	memcpy(s,func,l);	s[l]=0;
+	uintptr_t r = uintptr_t(mgl_data_roots(s,_DA_(ini),*var));
+	delete []s;	return r;	}
+mreal MGL_EXPORT mgl_find_root_txt_(const char *func, mreal *ini, const char *var,int l,int)
+{	char *s=new char[l+1];	memcpy(s,func,l);	s[l]=0;
+	mreal r = mgl_find_root_txt(s,*ini,*var);
+	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
diff --git a/src/exec.cpp b/src/exec.cpp
index c185d27..9361514 100644
--- a/src/exec.cpp
+++ b/src/exec.cpp
@@ -1799,6 +1799,13 @@ int MGL_NO_EXPORT mgls_extend(mglGraph *, long , mglArg *a, const char *k, const
 	else res = 1;	return res;
 }
 //-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_join(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	a[0].d->Join(*(a[1].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
 int MGL_NO_EXPORT mgls_datas(mglGraph *gr, long , mglArg *a, const char *k, const char *)
 {
 	int res=0;
@@ -2285,6 +2292,16 @@ int MGL_NO_EXPORT mgls_combine(mglGraph *, long , mglArg *a, const char *k, cons
 	else res = 1;	return res;
 }
 //-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_roots(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"dsds"))	*(a[0].d) = a[2].d->Roots(a[1].s.c_str(), a[3].s[0]);
+	else if(!strcmp(k,"dsns"))	a[0].d->a[0] = mgl_find_root_txt(a[1].s.c_str(), a[2].v, a[3].s[0]);
+	else if(!strcmp(k,"dsd"))	*(a[0].d) = a[2].d->Roots(a[1].s.c_str(), 'x');
+	else if(!strcmp(k,"dsn"))	a[0].d->a[0] = mgl_find_root_txt(a[1].s.c_str(), a[2].v, 'x');
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
 int MGL_NO_EXPORT mgls_pde(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
 {
 	int res=0;
@@ -2604,6 +2621,7 @@ mglCommand mgls_base_cmd[] = {
 	{"insert","Insert slice of data","insert Dat 'dir' [pos=0 num=1]", mgls_insert ,3},
 	{"integrate","Integrate data","integrate Dat 'dir'", mgls_integrate ,16},
 	{"jacobian","Get Jacobian","jacobian Res Xdat Ydat [Zdat]", mgls_jacobian ,4},
+	{"join","Join data arrays","join Dat Add", mgls_join ,3},
 	{"label","Draw label at arbitrary position","label Ydat 'txt' ['fmt'='']|Xdat Ydat 'txt' ['fmt'='']|Xdat Ydat Zdat 'txt' ['fmt'='']", mgls_label ,7},
 	{"legend","Draw legend","legend [pos 'fmt']|x y ['fmt']", mgls_legend ,15},
 	{"legendmarks","Set number of marks in the legend","legendmarks val", mgls_legendmarks ,15},
@@ -2656,6 +2674,7 @@ mglCommand mgls_base_cmd[] = {
 	{"return","Return from function","return", 0, 6},
 	{"rhomb","Draw rhombus","rhomb x1 y1 x2 y2 r ['fmt']|x1 y1 z1 x2 y2 z2 r ['fmt']", mgls_rhomb ,13},
 	{"roll","Roll data along direction","roll Dat 'dir' num", mgls_roll ,16},
+	{"roots", "Find roots using data as initial values", "roots Res 'func' Ini ['var']|Res 'func' ini ['var']", mgls_roots ,4},
 	{"rotate","Rotate plot","rotate tetz tetx [tety] | tet x y z", mgls_rotate ,5},
 	{"rotatetext","Set to auto rotate text or not","rotatetext val", mgls_rotatetext ,15},
 	{"save","Save data to file","save Dat 'file'", mgls_save ,3},
diff --git a/src/fft.cpp b/src/fft.cpp
index 33fd541..80fe46b 100644
--- a/src/fft.cpp
+++ b/src/fft.cpp
@@ -464,7 +464,7 @@ MGL_NO_EXPORT void* mgl_cosx(void *par)
 {
 	mglThreadT *t=(mglThreadT *)par;
 	register long i,j,k,nx=t->p[0],nn=nx-1;
-	double *b = t->b+2*nx*t->id, f=sqrt(2./nx);
+	double *b = t->b+2*nx*t->id, f=sqrt(2./nn);
 	mreal *a = (mreal*)t->a;
 	for(i=t->id;i<t->n;i+=mglNumThr)
 	{
@@ -492,7 +492,7 @@ MGL_NO_EXPORT void* mgl_cosy(void *par)
 {
 	mglThreadT *t=(mglThreadT *)par;
 	register long ii,i,j,k,nx=t->p[0],ny=t->p[1],nz=t->p[2],nn=ny-1;
-	double *b = t->b+2*ny*t->id, f=sqrt(2./ny);
+	double *b = t->b+2*ny*t->id, f=sqrt(2./nn);
 	mreal *a = (mreal*)t->a;
 	for(ii=t->id;ii<t->n;ii+=mglNumThr)
 	{
@@ -520,7 +520,7 @@ MGL_NO_EXPORT void* mgl_cosz(void *par)
 {
 	mglThreadT *t=(mglThreadT *)par;
 	register long i,j,nx=t->p[0],ny=t->p[1],nz=t->p[2],k=nx*ny,nn=nz-1;
-	double *b = t->b+2*nz*t->id, f=sqrt(2./nz);
+	double *b = t->b+2*nz*t->id, f=sqrt(2./nn);
 	mreal *a = (mreal*)t->a;
 	for(i=t->id;i<t->n;i+=mglNumThr)
 	{
@@ -659,113 +659,184 @@ uintptr_t MGL_EXPORT mgl_transform_(uintptr_t *re, uintptr_t *im, const char *tr
 void MGL_EXPORT mgl_data_envelop_(uintptr_t *d, const char *dir, int)
 {	mgl_data_envelop(_DT_,*dir);	}
 //-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+MGL_NO_EXPORT void* mgl_chnkx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	register long i,j,nx=t->p[0];
+	double *b = t->b+3*nx*t->id;
+	dual *a = (dual*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+
+	double mm = gsl_sf_bessel_zero_J0(nx+1);
+	for(i=t->id;i<t->n;i+=mglNumThr)
+	{
+		for(j=0;j<nx;j++)	b[j] = real(a[j+nx*i]);
+		gsl_dht_apply(dht,b,b+nx);
+		for(j=0;j<nx;j++)	b[j] = imag(a[j+nx*i]);
+		gsl_dht_apply(dht,b,b+2*nx);
+		for(j=0;j<nx;j++)	a[j+nx*i] = dual(b[j+nx],b[j+2*nx])*mm;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_chnky(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	register long ii,i,j,k,nx=t->p[0],ny=t->p[1];
+	double *b = t->b+3*ny*t->id;
+	dual *a = (dual*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	
+	double mm = gsl_sf_bessel_zero_J0(ny+1);
+	for(ii=t->id;ii<t->n;ii+=mglNumThr)
+	{
+		i = ii%nx;	k = ii/nx;
+		for(j=0;j<ny;j++)	b[j] = real(a[i+nx*(j+ny*k)]);
+		gsl_dht_apply(dht,b,b+ny);
+		for(j=0;j<ny;j++)	b[j] = imag(a[i+nx*(j+ny*k)]);
+		gsl_dht_apply(dht,b,b+2*ny);
+		for(j=0;j<ny;j++)	a[i+nx*(j+ny*k)] = dual(b[j+ny],b[j+2*ny])*mm;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_chnkz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	register long i,j,k=t->p[0]*t->p[1],nz=t->p[2];
+	double *b = t->b+3*nz*t->id;
+	dual *a = (dual*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	
+	double mm = gsl_sf_bessel_zero_J0(nz+1);
+	for(i=t->id;i<t->n;i+=mglNumThr)
+	{
+		for(j=0;j<nz;j++)	b[j] = real(a[i+j*k]);
+		gsl_dht_apply(dht,b,b+nz);
+		for(j=0;j<nz;j++)	b[j] = imag(a[i+j*k]);
+		gsl_dht_apply(dht,b,b+2*nz);
+		for(j=0;j<nz;j++)	a[i+j*k] = dual(b[j+nz],b[j+2*nz])*mm;
+	}
+	return 0;
+}
 void MGL_EXPORT mgl_datac_hankel(HADT d, const char *dir)
 {
-#if MGL_HAVE_GSL
 	if(!dir || *dir==0)	return;
-	double *ai=0, *af=0, *ag=0;
-	mreal mm;
+	if(mglNumThr<1)	mgl_set_num_thr(0);	// manually set number of threads
 	gsl_dht *dht=0;
-	register long i,j,k;
+	double *b=0;
 	long nx=d->nx, ny=d->ny, nz=d->nz;
-	dual *a=d->a;
+	long par[3]={nx,ny,nz};
 	if(strchr(dir,'x') && nx>1)
 	{
-		ai = new double[nx];	af = new double[nx];	ag = new double[nx];
 		dht = gsl_dht_new(nx,0,1);
-		mm = gsl_sf_bessel_zero_J0(nx+1);
-		for(i=0;i<ny*nz;i++)
-		{
-			for(j=0;j<nx;j++)	ai[j] = real(a[j+nx*i]);
-			gsl_dht_apply(dht,ai,af);
-			for(j=0;j<nx;j++)	ai[j] = imag(a[j+nx*i]);
-			gsl_dht_apply(dht,ai,ag);
-			for(j=0;j<nx;j++)	a[j+nx*i] = dual(af[j],ag[j])*mm;
-		}
+		b = new double[3*nx*mglNumThr];
+		mglStartThreadT(mgl_chnkx,ny*nz,d->a,b,dht,0,par);
 	}
 	if(strchr(dir,'y') && ny>1)
 	{
-		ai = new double[ny];	af = new double[ny];	ag = new double[ny];
 		dht = gsl_dht_new(ny,0,1);
-		mm = gsl_sf_bessel_zero_J0(ny+1);
-		for(i=0;i<nx;i++)	for(k=0;k<nz;k++)
-		{
-			for(j=0;j<ny;j++)	ai[j] = real(a[i+nx*(j+ny*k)]);
-			gsl_dht_apply(dht,ai,af);
-			for(j=0;j<ny;j++)	ai[j] = imag(a[i+nx*(j+ny*k)]);
-			gsl_dht_apply(dht,ai,ag);
-			for(j=0;j<ny;j++)	a[i+nx*(j+ny*k)] = dual(af[j],ag[j])*mm;
-		}
+		b = new double[3*ny*mglNumThr];
+		mglStartThreadT(mgl_chnky,nx*nz,d->a,b,dht,0,par);
 	}
 	if(strchr(dir,'z') && nz>1)
 	{
-		ai = new double[nz];	af = new double[nz];	ag = new double[nz];
 		dht = gsl_dht_new(nz,0,1);
-		mm = gsl_sf_bessel_zero_J0(nz+1);
-		k = nx*ny;	for(i=0;i<k;i++)
-		{
-			for(j=0;j<nz;j++)	ai[j] = real(a[i+j*k]);
-			gsl_dht_apply(dht,ai,af);
-			for(j=0;j<nz;j++)	ai[j] = imag(a[i+j*k]);
-			gsl_dht_apply(dht,ai,ag);
-			for(j=0;j<nz;j++)	a[i+j*k] = dual(af[j],ag[j])*mm;
-		}
+		b = new double[3*nz*mglNumThr];
+		mglStartThreadT(mgl_chnkz,nx*ny,d->a,b,dht,0,par);
 	}
-	if(ai)	{	delete []ai;	delete []af;	gsl_dht_free(dht);	}
-#endif
+	if(b)	{	delete []b;	gsl_dht_free(dht);	}
 }
+#else
+void MGL_EXPORT mgl_datac_hankel(HADT , const char *){}
+#endif
 void MGL_EXPORT mgl_datac_hankel_(uintptr_t *d, const char *dir,int l)
 {	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
 	mgl_datac_hankel(_DC_,s);	delete []s;	}
 //-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+MGL_NO_EXPORT void* mgl_hnkx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	register long i,j,nx=t->p[0];
+	double *b = t->b+2*nx*t->id;
+	mreal *a = (mreal*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	
+	double mm = gsl_sf_bessel_zero_J0(nx+1);
+	for(i=t->id;i<t->n;i+=mglNumThr)
+	{
+		for(j=0;j<nx;j++)	b[j] = a[j+nx*i];
+		gsl_dht_apply(dht,b,b+nx);
+		for(j=0;j<nx;j++)	a[j+nx*i] = b[j+nx]*mm;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_hnky(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	register long ii,i,j,k,nx=t->p[0],ny=t->p[1];
+	double *b = t->b+2*ny*t->id;
+	mreal *a = (mreal*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	
+	double mm = gsl_sf_bessel_zero_J0(ny+1);
+	for(ii=t->id;ii<t->n;ii+=mglNumThr)
+	{
+		i = ii%nx;	k = ii/nx;
+		for(j=0;j<ny;j++)	b[j] = a[i+nx*(j+ny*k)];
+		gsl_dht_apply(dht,b,b+ny);
+		for(j=0;j<ny;j++)a[i+nx*(j+ny*k)] = b[j+ny]*mm;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_hnkz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	register long i,j,k=t->p[0]*t->p[1],nz=t->p[2];
+	double *b = t->b+2*nz*t->id;
+	mreal *a = (mreal*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	
+	double mm = gsl_sf_bessel_zero_J0(nz+1);
+	for(i=t->id;i<t->n;i+=mglNumThr)
+	{
+		for(j=0;j<nz;j++)	b[j] = a[i+j*k];
+		gsl_dht_apply(dht,b,b+nz);
+		for(j=0;j<nz;j++)	a[i+j*k] = b[j+nz]*mm;
+	}
+	return 0;
+}
 void MGL_EXPORT mgl_data_hankel(HMDT d, const char *dir)
 {
-#if MGL_HAVE_GSL
 	if(!dir || *dir==0)	return;
-	double *ai=0, *af=0, mm;
+	if(mglNumThr<1)	mgl_set_num_thr(0);	// manually set number of threads
 	gsl_dht *dht=0;
-	register long i,j,k;
+	double *b=0;
 	long nx=d->nx, ny=d->ny, nz=d->nz;
-	mreal *a=d->a;
+	long par[3]={nx,ny,nz};
 	if(strchr(dir,'x') && nx>1)
 	{
-		ai = new double[nx];	af = new double[nx];
 		dht = gsl_dht_new(nx,0,1);
-		mm = gsl_sf_bessel_zero_J0(nx+1);
-		for(i=0;i<ny*nz;i++)
-		{
-			for(j=0;j<nx;j++)	ai[j] = a[j+nx*i];
-			gsl_dht_apply(dht,ai,af);
-			for(j=0;j<nx;j++)	a[j+nx*i] = af[j]*mm;
-		}
+		b = new double[2*nx*mglNumThr];
+		mglStartThreadT(mgl_hnkx,ny*nz,d->a,b,dht,0,par);
 	}
 	if(strchr(dir,'y') && ny>1)
 	{
-		ai = new double[ny];	af = new double[ny];
 		dht = gsl_dht_new(ny,0,1);
-		mm = gsl_sf_bessel_zero_J0(ny+1);
-		for(i=0;i<nx;i++)	for(k=0;k<nz;k++)
-		{
-			for(j=0;j<ny;j++)	ai[j] = a[i+nx*(j+ny*k)];
-			gsl_dht_apply(dht,ai,af);
-			for(j=0;j<ny;j++)	a[i+nx*(j+ny*k)] = af[j]*mm;
-		}
+		b = new double[2*ny*mglNumThr];
+		mglStartThreadT(mgl_hnky,nx*nz,d->a,b,dht,0,par);
 	}
 	if(strchr(dir,'z') && nz>1)
 	{
-		ai = new double[nz];	af = new double[nz];
 		dht = gsl_dht_new(nz,0,1);
-		mm = gsl_sf_bessel_zero_J0(nz+1);
-		k = nx*ny;	for(i=0;i<k;i++)
-		{
-			for(j=0;j<nz;j++)	ai[j] = a[i+j*k];
-			gsl_dht_apply(dht,ai,af);
-			for(j=0;j<nz;j++)	a[i+j*k] = af[j]*mm;
-		}
+		b = new double[2*nz*mglNumThr];
+		mglStartThreadT(mgl_hnkz,nx*ny,d->a,b,dht,0,par);
 	}
-	if(ai)	{	delete []ai;	delete []af;	gsl_dht_free(dht);	}
-#endif
+	if(b)	{	delete []b;	gsl_dht_free(dht);	}
 }
+#else
+void MGL_EXPORT mgl_data_hankel(HMDT , const char *){}
+#endif
 void MGL_EXPORT mgl_data_hankel_(uintptr_t *d, const char *dir,int l)
 {	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
 	mgl_data_hankel(_DT_,s);	delete []s;	}
diff --git a/src/other.cpp b/src/other.cpp
index ed2d512..230f548 100644
--- a/src/other.cpp
+++ b/src/other.cpp
@@ -75,8 +75,8 @@ void MGL_EXPORT mgl_dens_y(HMGL gr, HCDT a, const char *sch, double sv, const ch
 		if(k>m-2)	{	k=m-2;	d=1;	}
 		if(k<0)		{	k=0;	d=0;	}
 		const mglData *ma=dynamic_cast<const mglData *>(a);
-		if(ma)	for(j=0;j<l;j++)	for(i=0;i<m;i++)
-			aa.a[i+m*j] = ma->a[k+n*(i+m*j)]*(1-d) + d*ma->a[k+n+n*(i+m*j)];
+		if(ma)	for(j=0;j<l;j++)	for(i=0;i<n;i++)
+			aa.a[i+n*j] = ma->a[i+n*(k+m*j)]*(1-d) + d*ma->a[i+n+n*(k+m*j)];
 		else	for(j=0;j<l;j++)	for(i=0;i<n;i++)
 			aa.a[i+n*j] = a->v(i,k,j)*(1-d) + d*a->v(i,k+1,j);
 		a = &aa;
@@ -107,8 +107,8 @@ void MGL_EXPORT mgl_dens_z(HMGL gr, HCDT a, const char *sch, double sv, const ch
 		if(k>l-2)	{	k=l-2;	d=1;	}
 		if(k<0)		{	k=0;	d=0;	}
 		const mglData *ma=dynamic_cast<const mglData *>(a);
-		if(ma)	for(j=0;j<l;j++)	for(i=0;i<m;i++)
-			aa.a[i+m*j] = ma->a[k+n*(i+m*j)]*(1-d) + d*ma->a[k+n*m+n*(i+m*j)];
+		if(ma)	for(j=0;j<m;j++)	for(i=0;i<n;i++)
+			aa.a[i+n*j] = ma->a[i+n*(j+m*k)]*(1-d) + d*ma->a[i+n*m+n*(j+m*k)];
 		else	for(j=0;j<m;j++)	for(i=0;i<n;i++)
 			aa.a[i+n*j] = a->v(i,j,k)*(1-d) + d*a->v(i,j,k+1);
 		a = &aa;
@@ -204,8 +204,8 @@ void MGL_EXPORT mgl_cont_y_val(HMGL gr, HCDT v, HCDT a, const char *sch, double
 		if(k>m-2)	{	k=m-2;	d=1;	}
 		if(k<0)		{	k=0;	d=0;	}
 		const mglData *ma=dynamic_cast<const mglData *>(a);
-		if(ma)	for(j=0;j<l;j++)	for(i=0;i<m;i++)
-			aa.a[i+m*j] = ma->a[k+n*(i+m*j)]*(1-d) + d*ma->a[k+n+n*(i+m*j)];
+		if(ma)	for(j=0;j<l;j++)	for(i=0;i<n;i++)
+			aa.a[i+n*j] = ma->a[i+n*(k+m*j)]*(1-d) + d*ma->a[i+n+n*(k+m*j)];
 		else	for(j=0;j<l;j++)	for(i=0;i<n;i++)
 			aa.a[i+n*j] = a->v(i,k,j)*(1-d) + d*a->v(i,k+1,j);
 		a = &aa;
@@ -246,8 +246,8 @@ void MGL_EXPORT mgl_cont_z_val(HMGL gr, HCDT v, HCDT a, const char *sch, double
 		if(k>l-2)	{	k=l-2;	d=1;	}
 		if(k<0)		{	k=0;	d=0;	}
 		const mglData *ma=dynamic_cast<const mglData *>(a);
-		if(ma)	for(j=0;j<l;j++)	for(i=0;i<m;i++)
-			aa.a[i+m*j] = ma->a[k+n*(i+m*j)]*(1-d) + d*ma->a[k+n*m+n*(i+m*j)];
+		if(ma)	for(j=0;j<m;j++)	for(i=0;i<n;i++)
+			aa.a[i+n*j] = ma->a[i+n*(j+m*k)]*(1-d) + d*ma->a[i+n*m+n*(j+m*k)];
 		else	for(j=0;j<m;j++)	for(i=0;i<n;i++)
 			aa.a[i+n*j] = a->v(i,j,k)*(1-d) + d*a->v(i,j,k+1);
 		a = &aa;
@@ -385,8 +385,8 @@ void MGL_EXPORT mgl_contf_y_val(HMGL gr, HCDT v, HCDT a, const char *sch, double
 		if(k>m-2)	{	k=m-2;	d=1;	}
 		if(k<0)		{	k=0;	d=0;	}
 		const mglData *ma=dynamic_cast<const mglData *>(a);
-		if(ma)	for(j=0;j<l;j++)	for(i=0;i<m;i++)
-			aa.a[i+m*j] = ma->a[k+n*(i+m*j)]*(1-d) + d*ma->a[k+n+n*(i+m*j)];
+		if(ma)	for(j=0;j<l;j++)	for(i=0;i<n;i++)
+			aa.a[i+n*j] = ma->a[i+n*(k+m*j)]*(1-d) + d*ma->a[i+n+n*(k+m*j)];
 		else	for(j=0;j<l;j++)	for(i=0;i<n;i++)
 			aa.a[i+n*j] = a->v(i,k,j)*(1-d) + d*a->v(i,k+1,j);
 		a = &aa;
@@ -424,8 +424,8 @@ void MGL_EXPORT mgl_contf_z_val(HMGL gr, HCDT v, HCDT a, const char *sch, double
 		if(k>l-2)	{	k=l-2;	d=1;	}
 		if(k<0)		{	k=0;	d=0;	}
 		const mglData *ma=dynamic_cast<const mglData *>(a);
-		if(ma)	for(j=0;j<l;j++)	for(i=0;i<m;i++)
-			aa.a[i+m*j] = ma->a[k+n*(i+m*j)]*(1-d) + d*ma->a[k+n*m+n*(i+m*j)];
+		if(ma)	for(j=0;j<m;j++)	for(i=0;i<n;i++)
+			aa.a[i+n*j] = ma->a[i+n*(j+m*k)]*(1-d) + d*ma->a[i+n*m+n*(j+m*k)];
 		else	for(j=0;j<m;j++)	for(i=0;i<n;i++)
 			aa.a[i+n*j] = a->v(i,j,k)*(1-d) + d*a->v(i,j,k+1);
 		a = &aa;
diff --git a/texinfo/CMakeLists.txt b/texinfo/CMakeLists.txt
index e695069..d316608 100644
--- a/texinfo/CMakeLists.txt
+++ b/texinfo/CMakeLists.txt
@@ -22,7 +22,7 @@ if(MGL_HAVE_DOC)
 	file(MAKE_DIRECTORY ${MGL_OUT}/json)
 	file(MAKE_DIRECTORY ${MGL_OUT}/pdf)
 	file(COPY ${MGL_TEX}/qt.png ${MGL_TEX}/fltk.png ${MGL_TEX}/classes.png ${MGL_TEX}/emblem_sm.png ${MGL_TEX}/datadvance.png DESTINATION ${MGL_OUT})
-	file(COPY ${MGL_TEX}/toc_ru.html ${MGL_TEX}/toc_fr.html ${MGL_TEX}/toc_en.html ${MGL_TEX}/title.html ${MGL_TEX}/index.html ${MGL_TEX}/json.html ${MGL_TEX}/mathgl.js DESTINATION ${MGL_OUT})
+	file(COPY ${MGL_TEX}/toc_ru.html ${MGL_TEX}/toc_fr.html ${MGL_TEX}/toc_en.html ${MGL_TEX}/title.html ${MGL_TEX}/index.html ${MGL_TEX}/json.html ${MGL_TEX}/mathgl.js ${MGL_TEX}/gunzip.min.js ${MGL_TEX}/inflate.min.js DESTINATION ${MGL_OUT})
 
 	set(UDAV_IMG udav_arg.png udav_calc.png udav_cmd.png udav_data.png 
 		udav_gen_set.png udav_help.png udav_light.png udav_main.png udav_opt.png
@@ -168,7 +168,7 @@ endif(MGL_HAVE_PDF)
 	install(DIRECTORY ${MGL_OUT}/mathgl_en DESTINATION ${MGL_DOC_PATH})
 	install(DIRECTORY ${MGL_OUT}/png DESTINATION ${MGL_DOC_PATH})
 	install(DIRECTORY ${MGL_OUT}/udav DESTINATION ${MGL_DOC_PATH})
-	install(FILES ${MGL_TEX}/mglconv.1 ${MGL_TEX}/mglview.1 ${MGL_TEX}/udav.1 DESTINATION ${MGL_MAN_PATH}/man1)
+	install(FILES ${MGL_TEX}/mglconv.1 ${MGL_TEX}/mglview.1 ${MGL_TEX}/udav.1 ${MGL_TEX}/mgl.cgi.1 DESTINATION ${MGL_MAN_PATH}/man1)
 	install(FILES ${MGL_TEX}/mgl.5 DESTINATION ${MGL_MAN_PATH}/man5)
 # TODO: try to install all mathgl*.info* in future!!!
 	install(FILES ${MGL_OUT}/mathgl_en.info ${MGL_OUT}/mathgl_en.info-1 ${MGL_OUT}/mathgl_en.info-2 DESTINATION ${MGL_INFO_PATH})
diff --git a/texinfo/core_en.texi b/texinfo/core_en.texi
index 348a960..a772779 100644
--- a/texinfo/core_en.texi
+++ b/texinfo/core_en.texi
@@ -864,9 +864,9 @@ Puts further plotting in a rectangle of @var{dx}*@var{dy} cells starting from @v
 @end deftypefn
 
 @anchor{inplot}
- at deftypefn {MGL command} {} inplot @code{x1 x2 y1 y2 [rel=off]}
+ at deftypefn {MGL command} {} inplot @code{x1 x2 y1 y2 [rel=on]}
 @ifclear UDAV
- at deftypefnx {Method on @code{mglGraph}} @code{void} InPlot (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{bool} rel=@code{false})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} InPlot (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{bool} rel=@code{true})
 @deftypefnx {C function} @code{void} mgl_inplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
 @deftypefnx {C function} @code{void} mgl_relplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
 @end ifclear
diff --git a/texinfo/core_ru.texi b/texinfo/core_ru.texi
index 132a06c..ce35e23 100644
--- a/texinfo/core_ru.texi
+++ b/texinfo/core_ru.texi
@@ -824,9 +824,9 @@ Ternary -- специальный тип графика для 3 зависим
 @end deftypefn
 
 @anchor{inplot}
- at deftypefn {Команда MGL} {} inplot @code{x1 x2 y1 y2 [rel=off]}
+ at deftypefn {Команда MGL} {} inplot @code{x1 x2 y1 y2 [rel=on]}
 @ifclear UDAV
- at deftypefnx {Метод класса @code{mglGraph}} @code{void} InPlot (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{bool} rel=@code{false})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} InPlot (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{bool} rel=@code{true})
 @deftypefnx {Функция С} @code{void} mgl_inplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
 @deftypefnx {Функция С} @code{void} mgl_relplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
 @end ifclear
diff --git a/texinfo/data_en.texi b/texinfo/data_en.texi
index 9acbb25..00ac5a3 100644
--- a/texinfo/data_en.texi
+++ b/texinfo/data_en.texi
@@ -6,7 +6,7 @@ This chapter describe commands for allocation, resizing, loading and saving, mod
 @end ifset
 
 @ifclear UDAV
-This chapter describe classes @code{mglData} and @code{mglDataC} for working with data arrays of real and complex numbers. Both classes are derived from abstract class @code{mglDataA}, and can be used as arguments of any plotting functions (see @ref{MathGL core}). These classes are defined in @code{#include <mgl2/data.h>} and @code{#include <mgl2/datac.h>} correspondengly. The classes have mostly the same set of functions for easy and safe allocation, resizing, loading, saving, modifying of data arrays. Also it can numerically differentiate and integrate data, interpolate, fill data by formula and so on. Classes support data with dimensions up to 3 (like function of 3 variables -- x,y,z). The internal representation of numbers is mreal (or dual=std::complex<mreal> for @code{mglDataC}), which can be configured as float or double by selecting option @code{--enable-double} at the MathGL configuring (see @ref{Installation}). Float type have smaller size in memory and usually it has enough precision in plotting purposes. However, double type provide high accuracy what can be important for time-axis, for example. Data arrays are denoted by Small Caps (like @sc{dat}) if it can be (re-)created by MGL commands.
+This chapter describe classes @code{mglData} and @code{mglDataC} for working with data arrays of real and complex numbers. Both classes are derived from abstract class @code{mglDataA}, and can be used as arguments of any plotting functions (see @ref{MathGL core}). These classes are defined in @code{#include <mgl2/data.h>} and @code{#include <mgl2/datac.h>} correspondingly. The classes have mostly the same set of functions for easy and safe allocation, resizing, loading, saving, modifying of data arrays. Also it can numerically differentiate and integrate data, interpolate, fill data by formula and so on. Classes support data with dimensions up to 3 (like function of 3 variables -- x,y,z). The internal representation of numbers is mreal (or dual=std::complex<mreal> for @code{mglDataC}), which can be configured as float or double by selecting option @code{--enable-double} at the MathGL configuring (see @ref{Installation}). Float type have smaller size in memory and usually it has enough precision in plotting purposes. However, double type provide high accuracy what can be important for time-axis, for example. Data arrays are denoted by Small Caps (like @sc{dat}) if it can be (re-)created by MGL commands.
 @end ifclear
 
 @menu
@@ -175,7 +175,9 @@ Deletes the instance of class mglData.
 @cindex Crop
 @cindex Insert
 @cindex Delete
-
+ at cindex Sort
+ at cindex Clean
+ at cindex Join
 
 @deftypefn {MGL command} {} new @sc{dat} [@code{nx=1 ny=1 nz=1}]
 @ifclear UDAV
@@ -294,6 +296,17 @@ Sort data rows (or slices in 3D case) by values of specified column @var{idx} (o
 Delete rows which values are equal to next row for given column @var{idx}.
 @end deftypefn
 
+ at anchor{join}
+ at deftypefn {MGL command} {} join dat vdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {C function} @code{void} mgl_data_join (@code{HMDT} dat, @code{HCDT} vdat)
+ at deftypefnx {C function} @code{void} mgl_datac_join (@code{HADT} dat, @code{HCDT} vdat)
+ at end ifclear
+Join data cells from @var{vdat} to @var{dat}. At this, function increase @var{dat} sizes according following: z-size for 3D data arrays arrays with equal x-,y-sizes; or y-size for 2D data arrays with equal x-sizes; or x-size otherwise.
+ at end deftypefn
+
 
 @c ------------------------------------------------------------------
 @external{}
@@ -641,6 +654,7 @@ Saves data matrix (or @code{ns}-th slice for 3d data) to bitmap file (now suppor
 @cindex Sum
 @cindex Min
 @cindex Max
+ at cindex Roots
 
 @anchor{subdata}
 @deftypefn {MGL command} {} subdata @sc{res} dat @code{xx [yy=: zz=:]}
@@ -809,6 +823,17 @@ Gets array of arguments of the data.
 @end deftypefn
 @end ifclear
 
+ at anchor{roots}
+ at deftypefn {MGL command} {} roots @sc{res} 'func' ini ['var'='x']
+ at deftypefnx {MGL command} {} roots @sc{res} 'func' @code{ini} ['var'='x']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Roots (@code{const char *}func, @code{char} var) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_roots (@code{const char *}func, @code{HCDT} ini, @code{char} var)
+ at deftypefnx {C function} @code{mreal} mgl_find_root_txt (@code{const char *}func, @code{mreal} ini, @code{char} var)
+ at end ifclear
+Find roots of equation 'func'=0 for variable @var{var} with initial guess @var{ini}. Secant method is used for root finding.
+ at end deftypefn
+
 @c ------------------------------------------------------------------
 @external{}
 @node Data changing, Interpolation, Make another data, Data processing
@@ -829,7 +854,7 @@ Gets array of arguments of the data.
 @cindex Norm
 @cindex NormSl
 
-These functions change the data in some direction like differentiations, integrations and so on. The direction in which the change will applied is specified by the string parameter, which may contain @samp{x}, @samp{y} or @samp{z} characters for 1-st, 2-nd and 3-d dimension correspondengly.
+These functions change the data in some direction like differentiations, integrations and so on. The direction in which the change will applied is specified by the string parameter, which may contain @samp{x}, @samp{y} or @samp{z} characters for 1-st, 2-nd and 3-d dimension correspondingly.
 
 @anchor{cumsum}
 @deftypefn {MGL command} {} cumsum dat 'dir'
@@ -890,7 +915,7 @@ Double-differentiates (like Laplace operator) the data in given direction.
 @deftypefnx {Method on @code{mglData}} @code{void} SinFFT (@code{const char *}dir)
 @deftypefnx {C function} @code{void} mgl_data_sinfft (@code{HMDT} dat, @code{const char *}dir)
 @end ifclear
-Do Sine transform of the data in given direction or directions. The Sine transform is @math{\sum a_j \sin(k j)}.
+Do Sine transform of the data in given direction or directions. The Sine transform is @math{\sum a_j \sin(k j)} (see @uref{http://en.wikipedia.org/wiki/Discrete_sine_transform#DST-I}).
 @end deftypefn
 
 @anchor{cosfft}
@@ -899,13 +924,13 @@ Do Sine transform of the data in given direction or directions. The Sine transfo
 @deftypefnx {Method on @code{mglData}} @code{void} CosFFT (@code{const char *}dir)
 @deftypefnx {C function} @code{void} mgl_data_cosfft (@code{HMDT} dat, @code{const char *}dir)
 @end ifclear
-Do Cosine transform of the data in given direction or directions. The Cosine transform is @math{\sum a_j \cos(k j)}.
+Do Cosine transform of the data in given direction or directions. The Cosine transform is @math{\sum a_j \cos(k j)} (see @uref{http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-I}).
 @end deftypefn
 
 @ifclear UDAV
 @deftypefn {Method on @code{mglDataC}} @code{void} FFT (@code{const char *}dir)
 @deftypefnx {C function} @code{void} mgl_datac_fft (@code{HADT} dat, @code{const char *}dir)
-Do Fourier transform of the data in given direction or directions. If @var{dir} contain @samp{i} then inverse Fourier is used. The Fourier transform is @math{\sum a_j \exp(i k j)}.
+Do Fourier transform of the data in given direction or directions. If @var{dir} contain @samp{i} then inverse Fourier is used. The Fourier transform is @math{\sum a_j \exp(i k j)} (see @uref{http://en.wikipedia.org/wiki/Discrete_Fourier_transform}).
 @end deftypefn
 @end ifclear
 
@@ -917,7 +942,7 @@ Do Fourier transform of the data in given direction or directions. If @var{dir}
 @deftypefnx {C function} @code{void} mgl_data_hankel (@code{HMDT} dat, @code{const char *}dir)
 @deftypefnx {C function} @code{void} mgl_datac_hankel (@code{HADT} dat, @code{const char *}dir)
 @end ifclear
-Do Hankel transform of the data in given direction or directions. The Hankel transform is @math{\sum a_j J_0(k j)}.
+Do Hankel transform of the data in given direction or directions. The Hankel transform is @math{\sum a_j J_0(k j)} (see @uref{http://en.wikipedia.org/wiki/Hankel_transform}).
 @end deftypefn
 
 @anchor{swap}
@@ -1434,25 +1459,36 @@ You can use arbitrary formulas of existed data arrays or constants as any argume
 @end ifset
 
 @ifclear UDAV
-MathGL have a special class @code{mglExpr} for evaluating of formula specified by the string. This class is defined in @code{#include <mgl2/mgl.h>}. It is the fast variant of formula evaluation. At creation it will be recognized and compiled to tree-like internal code. At evaluation stage only fast calculations are performed. There is no difference between lower or upper case in formulas. If argument value lie outside the range of function definition then function returns NaN. @xref{Textual formulas}.
+ at cindex mglExpr
+ at cindex mglExprC
+
+MathGL have a special classes @code{mglExpr} and @code{mglExprC} for evaluating of formula specified by the string for real and complex numbers correspondingly. These classes are defined in @code{#include <mgl2/mgl.h>}. It is the fast variant of formula evaluation. At creation it will be recognized and compiled to tree-like internal code. At evaluation stage only fast calculations are performed. There is no difference between lower or upper case in formulas. If argument value lie outside the range of function definition then function returns NaN. @xref{Textual formulas}.
 
 @deftypefn {Constructor on @code{mglExpr}} @code{} mglExpr (@code{const char *}expr)
+ at deftypefnx {Constructor on @code{mglExprC}} @code{} mglExprC (@code{const char *}expr)
 @deftypefnx {C function} @code{HMEX} mgl_create_expr (@code{const char *}expr)
+ at deftypefnx {C function} @code{HAEX} mgl_create_cexpr (@code{const char *}expr)
 Parses the formula @var{expr} and creates formula-tree. Constructor recursively parses the formula and creates a tree-like structure containing functions and operators for fast further evaluating by @code{Calc()} or @code{CalcD()} functions.
 @end deftypefn
 
 @deftypefn {Destructor on @code{mglExpr}} @code{} ~mglExpr ()
- at deftypefnx {C function} @code{HMEX} mgl_delete_expr (@code{HMEX} ex)
+ at deftypefnx {Destructor on @code{mglExprC}} @code{} ~mglExprC ()
+ at deftypefnx {C function} @code{void} mgl_delete_expr (@code{HMEX} ex)
+ at deftypefnx {C function} @code{void} mgl_delete_cexpr (@code{HAEX} ex)
 Deletes the instance of class  mglExpr.
 @end deftypefn
 
 @deftypefn {Method on @code{mglExpr}} @code{mreal} Eval (@code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Method on @code{mglExprC}} @code{dual} Eval (@code{dual} x, @code{dual} y, @code{dual} z)
 @deftypefnx {C function} @code{mreal} mgl_expr_eval (@code{HMEX} ex, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {C function} @code{dual} mgl_cexpr_eval (@code{HAEX} ex, @code{dual} x, @code{dual} y, @code{dual} z)
 Evaluates the formula for @code{'x','r'}=@var{x}, @code{'y','n'}=@var{y}, @code{'z','t'}=@var{z}, @code{'a','u'}=@var{u}.
 @end deftypefn
 
 @deftypefn {Method on @code{mglExpr}} @code{mreal} Eval (@code{mreal} var[26])
+ at deftypefnx {Method on @code{mglExprC}} @code{dual} Eval (@code{dual} var[26])
 @deftypefnx {C function} @code{mreal} mgl_expr_eval_v (@code{HMEX} ex, @code{mreal *}var)
+ at deftypefnx {C function} @code{dual} mgl_expr_eval_v (@code{HAEX} ex, @code{dual *}var)
 Evaluates the formula for variables in array @var{var}[0,...,'z'-'a'].
 @end deftypefn
 
diff --git a/texinfo/data_ru.texi b/texinfo/data_ru.texi
index 9b3f904..852c87b 100644
--- a/texinfo/data_ru.texi
+++ b/texinfo/data_ru.texi
@@ -172,6 +172,9 @@ There are many functions, which can create data for output (see @ref{Data fillin
 @cindex Crop
 @cindex Insert
 @cindex Delete
+ at cindex Sort
+ at cindex Clean
+ at cindex Join
 
 
 @deftypefn {Команда MGL} {} new @sc{dat} [@code{nx=1 ny=1 nz=1}]
@@ -292,6 +295,17 @@ a_ij^new = a_i^old where j=0... at var{n1}. Соответственно, для @v
 @end deftypefn
 
 
+ at anchor{join}
+ at deftypefn {Команда MGL} {} join dat vdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {Функция С} @code{void} mgl_data_join (@code{HMDT} dat, @code{HCDT} vdat)
+ at deftypefnx {Функция С} @code{void} mgl_datac_join (@code{HADT} dat, @code{HCDT} vdat)
+ at end ifclear
+Объединяет данные из массива @var{vdat} с данными массива @var{dat}. При этом, функция увеличивает размер массива @var{dat}: в z-направлении для 3D массивов с одинаковыми размерами по x и y; в y-направлении для 2D массивов с одинаковыми размерами по x; в x-направлении в остальных случаях.
+ at end deftypefn
+
 @c ------------------------------------------------------------------
 @external{}
 @node Data filling, File I/O, Data resizing, Data processing
@@ -637,6 +651,7 @@ a_ij^new = a_i^old where j=0... at var{n1}. Соответственно, для @v
 @cindex Sum
 @cindex Min
 @cindex Max
+ at cindex Roots
 
 @anchor{subdata}
 @deftypefn {Команда MGL} {} subdata @sc{res} dat @code{xx [yy=: zz=:]}
@@ -805,6 +820,17 @@ res_k = \sum_ij how(x_i,y_j,z_k) a_ij/ \sum_ij a_ij
 @end deftypefn
 @end ifclear
 
+ at anchor{roots}
+ at deftypefn {Команда MGL} {} roots @sc{res} 'func' ini ['var'='x']
+ at deftypefnx {Команда MGL} {} roots @sc{res} 'func' @code{ini} ['var'='x']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Roots (@code{const char *}func, @code{char} var) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_roots (@code{const char *}func, @code{HCDT} ini, @code{char} var)
+ at deftypefnx {Функция С} @code{mreal} mgl_find_root_txt (@code{const char *}func, @code{mreal} ini, @code{char} var)
+ at end ifclear
+Возвращает массив корней уравнения 'func'=0 для переменной @var{var} с начальными положениями @var{ini}.
+ at end deftypefn
+
 @c ------------------------------------------------------------------
 @external{}
 @node Data changing, Interpolation, Make another data, Data processing
@@ -825,7 +851,7 @@ res_k = \sum_ij how(x_i,y_j,z_k) a_ij/ \sum_ij a_ij
 @cindex Norm
 @cindex NormSl
 
-These functions change the data in some direction like differentiations, integrations and so on. The direction in which the change will applied is specified by the string parameter, which may contain @samp{x}, @samp{y} or @samp{z} characters for 1-st, 2-nd and 3-d dimension correspondengly.
+These functions change the data in some direction like differentiations, integrations and so on. The direction in which the change will applied is specified by the string parameter, which may contain @samp{x}, @samp{y} or @samp{z} characters for 1-st, 2-nd and 3-d dimension correspondingly.
 
 @anchor{cumsum}
 @deftypefn {Команда MGL} {} cumsum dat 'dir'
@@ -886,7 +912,7 @@ These functions change the data in some direction like differentiations, integra
 @deftypefnx {Метод класса @code{mglData}} @code{void} SinFFT (@code{const char *}dir)
 @deftypefnx {Функция С} @code{void} mgl_data_sinfft (@code{HMDT} dat, @code{const char *}dir)
 @end ifclear
-Выполняет синус преобразование в выбранном направлении(ях). Синус преобразование есть @math{\sum a_j \sin(k j)}.
+Выполняет синус преобразование в выбранном направлении(ях). Синус преобразование есть @math{\sum a_j \sin(k j)} (см. @uref{http://en.wikipedia.org/wiki/Discrete_sine_transform#DST-I}).
 @end deftypefn
 
 @anchor{cosfft}
@@ -895,13 +921,13 @@ These functions change the data in some direction like differentiations, integra
 @deftypefnx {Метод класса @code{mglData}} @code{void} CosFFT (@code{const char *}dir)
 @deftypefnx {Функция С} @code{void} mgl_data_cosfft (@code{HMDT} dat, @code{const char *}dir)
 @end ifclear
-Выполняет косинус преобразование в выбранном направлении(ях). Синус преобразование есть @math{\sum a_j \cos(k j)}.
+Выполняет косинус преобразование в выбранном направлении(ях). Синус преобразование есть @math{\sum a_j \cos(k j)} (см. @uref{http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-I}).
 @end deftypefn
 
 @ifclear UDAV
 @deftypefn {Метод класса @code{mglDataC}} @code{void} FFT (@code{const char *}dir)
 @deftypefnx {Функция С} @code{void} mgl_datac_fft (@code{HADT} dat, @code{const char *}dir)
-Выполняет фурье преобразование в выбранном направлении(ях). Если строка @var{dir} содержит @samp{i}, то используется обратное преобразование фурье. Фурье преобразование есть @math{\sum a_j \exp(i k j)}.
+Выполняет фурье преобразование в выбранном направлении(ях). Если строка @var{dir} содержит @samp{i}, то используется обратное преобразование фурье. Фурье преобразование есть @math{\sum a_j \exp(i k j)} (см. @uref{http://en.wikipedia.org/wiki/Discrete_Fourier_transform}).
 @end deftypefn
 @end ifclear
 
@@ -913,7 +939,7 @@ These functions change the data in some direction like differentiations, integra
 @deftypefnx {Функция С} @code{void} mgl_data_hankel (@code{HMDT} dat, @code{const char *}dir)
 @deftypefnx {Функция С} @code{void} mgl_datac_hankel (@code{HADT} dat, @code{const char *}dir)
 @end ifclear
-Выполняет преобразование Ханкеля в выбранном направлении(ях). Преобразование Ханкеля есть @math{\sum a_j J_0(k j)}.
+Выполняет преобразование Ханкеля в выбранном направлении(ях). Преобразование Ханкеля есть @math{\sum a_j J_0(k j)} (см. @uref{http://en.wikipedia.org/wiki/Hankel_transform}).
 @end deftypefn
 
 @anchor{swap}
@@ -1431,25 +1457,33 @@ These functions change the data in some direction like differentiations, integra
 @end ifset
 
 @ifclear UDAV
-В MathGL есть специальный класс @code{mglExpr} для вычисления формул заданных строкой. Класс определён в @code{#include <mgl2/mgl.h>}. При создании класса происходит разбор формулы в древовидную структуру. А при вычислении только выполняется достаточно быстрый обход по дереву. В данный момент нет различия между верхним и нижним регистром. Если аргумент какой-либо функции лежит вне её области определения, то возвращается NaN. @xref{Textual formulas}.
+В MathGL есть специальные классы @code{mglExpr} и @code{mglExprC} для вычисления формул заданных строкой для действительных и комплексных чисел соответственно. Классы определены в @code{#include <mgl2/mgl.h>}. При создании класса происходит разбор формулы в древовидную структуру. А при вычислении только выполняется достаточно быстрый обход по дереву. В данный момент нет различия между верхним и нижним регистром. Если аргумент какой-либо функции лежит вне её области определения, то возвращается NaN. @xref{Textual formulas}.
 
 @deftypefn {Конструктор класса @code{mglExpr}} @code{} mglExpr (@code{const char *}expr)
+ at deftypefnx {Конструктор класса @code{mglExprC}} @code{} mglExprC (@code{const char *}expr)
 @deftypefnx {Функция С} @code{HMEX} mgl_create_expr (@code{const char *}expr)
+ at deftypefnx {Функция С} @code{HAEX} mgl_create_cexpr (@code{const char *}expr)
 Разбирает формулу @var{expr} и создает древовидную структуру, содержащую последовательность вызова функций и операторов для последующего быстрого вычисления формулы с помощью функций @code{Calc()} и/или @code{CalcD()}.
 @end deftypefn
 
 @deftypefn {Destructor on @code{mglExpr}} @code{} ~mglExpr ()
- at deftypefnx {Функция С} @code{HMEX} mgl_delete_expr (@code{HMEX} ex)
+ at deftypefnx {Destructor on @code{mglExprC}} @code{} ~mglExprC ()
+ at deftypefnx {Функция С} @code{void} mgl_delete_expr (@code{HMEX} ex)
+ at deftypefnx {Функция С} @code{void} mgl_delete_cexpr (@code{HAEX} ex)
 Удаляет объект типа @code{mglExpr}.
 @end deftypefn
 
 @deftypefn {Метод класса @code{mglExpr}} @code{mreal} Eval (@code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Метод класса @code{mglExprC}} @code{dual} Eval (@code{dual} x, @code{dual} y, @code{dual} z)
 @deftypefnx {Функция С} @code{mreal} mgl_expr_eval (@code{HMEX} ex, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Функция С} @code{dual} mgl_cexpr_eval (@code{HAEX} ex, @code{dual} x, @code{dual} y, @code{dual} z)
 Вычисляет значение формулы для @code{'x','r'}=@var{x}, @code{'y','n'}=@var{y}, @code{'z','t'}=@var{z}, @code{'a','u'}=@var{u}.
 @end deftypefn
 
 @deftypefn {Метод класса @code{mglExpr}} @code{mreal} Eval (@code{mreal} var[26])
+ at deftypefnx {Метод класса @code{mglExprC}} @code{dual} Eval (@code{dual} var[26])
 @deftypefnx {Функция С} @code{mreal} mgl_expr_eval_v (@code{HMEX} ex, @code{mreal *}var)
+ at deftypefnx {Функция С} @code{dual} mgl_cexpr_eval_v (@code{HMEX} ex, @code{dual *}var)
 Вычисляет значение формулы для переменных в массиве @var{var}[0,...,'z'-'a'].
 @end deftypefn
 
diff --git a/texinfo/deflate.min.js b/texinfo/deflate.min.js
new file mode 100644
index 0000000..a6e4153
--- /dev/null
+++ b/texinfo/deflate.min.js
@@ -0,0 +1,32 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */
+(function() {'use strict';var j=void 0,z=!0,da=this;function ea(a,c){var b=a.split("."),g=da;!(b[0]in g)&&g.execScript&&g.execScript("var "+b[0]);for(var d;b.length&&(d=b.shift());)!b.length&&c!==j?g[d]=c:g=g[d]?g[d]:g[d]={}};var F="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;function G(a,c){this.index="number"===typeof c?c:0;this.e=0;this.buffer=a instanceof(F?Uint8Array:Array)?a:new (F?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&fa(this)}function fa(a){var c=a.buffer,b,g=c.length,d=new (F?Uint8Array:Array)(g<<1);if(F)d.set(c);else for(b=0;b<g;++b)d[b]=c[b];return a.buffer=d}
+G.prototype.b=function(a,c,b){var g=this.buffer,d=this.index,e=this.e,f=g[d],l;b&&1<c&&(a=8<c?(O[a&255]<<24|O[a>>>8&255]<<16|O[a>>>16&255]<<8|O[a>>>24&255])>>32-c:O[a]>>8-c);if(8>c+e)f=f<<c|a,e+=c;else for(l=0;l<c;++l)f=f<<1|a>>c-l-1&1,8===++e&&(e=0,g[d++]=O[f],f=0,d===g.length&&(g=fa(this)));g[d]=f;this.buffer=g;this.e=e;this.index=d};G.prototype.finish=function(){var a=this.buffer,c=this.index,b;0<this.e&&(a[c]<<=8-this.e,a[c]=O[a[c]],c++);F?b=a.subarray(0,c):(a.length=c,b=a);return b};
+var ga=new (F?Uint8Array:Array)(256),P;for(P=0;256>P;++P){for(var R=P,S=R,ha=7,R=R>>>1;R;R>>>=1)S<<=1,S|=R&1,--ha;ga[P]=(S<<ha&255)>>>0}var O=ga;var ia=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
+2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
+2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
+2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
+3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
+936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];F&&new Uint32Array(ia);function ja(a){this.buffer=new (F?Uint16Array:Array)(2*a);this.length=0}ja.prototype.getParent=function(a){return 2*((a-2)/4|0)};ja.prototype.push=function(a,c){var b,g,d=this.buffer,e;b=this.length;d[this.length++]=c;for(d[this.length++]=a;0<b;)if(g=this.getParent(b),d[b]>d[g])e=d[b],d[b]=d[g],d[g]=e,e=d[b+1],d[b+1]=d[g+1],d[g+1]=e,b=g;else break;return this.length};
+ja.prototype.pop=function(){var a,c,b=this.buffer,g,d,e;c=b[0];a=b[1];this.length-=2;b[0]=b[this.length];b[1]=b[this.length+1];for(e=0;;){d=2*e+2;if(d>=this.length)break;d+2<this.length&&b[d+2]>b[d]&&(d+=2);if(b[d]>b[e])g=b[e],b[e]=b[d],b[d]=g,g=b[e+1],b[e+1]=b[d+1],b[d+1]=g;else break;e=d}return{index:a,value:c,length:this.length}};function ma(a){var c=a.length,b=0,g=Number.POSITIVE_INFINITY,d,e,f,l,s,k,r,m,h;for(m=0;m<c;++m)a[m]>b&&(b=a[m]),a[m]<g&&(g=a[m]);d=1<<b;e=new (F?Uint32Array:Array)(d);f=1;l=0;for(s=2;f<=b;){for(m=0;m<c;++m)if(a[m]===f){k=0;r=l;for(h=0;h<f;++h)k=k<<1|r&1,r>>=1;for(h=k;h<d;h+=s)e[h]=f<<16|m;++l}++f;l<<=1;s<<=1}};function na(a,c){this.d=oa;this.i=0;this.input=a;this.c=0;c&&(c.lazy&&(this.i=c.lazy),"number"===typeof c.compressionType&&(this.d=c.compressionType),c.outputBuffer&&(this.a=F&&c.outputBuffer instanceof Array?new Uint8Array(c.outputBuffer):c.outputBuffer),"number"===typeof c.outputIndex&&(this.c=c.outputIndex));this.a||(this.a=new (F?Uint8Array:Array)(32768))}var oa=2,pa={NONE:0,h:1,g:oa,n:3},T=[],V;
+for(V=0;288>V;V++)switch(z){case 143>=V:T.push([V+48,8]);break;case 255>=V:T.push([V-144+400,9]);break;case 279>=V:T.push([V-256+0,7]);break;case 287>=V:T.push([V-280+192,8]);break;default:throw"invalid literal: "+V;}
+na.prototype.f=function(){var a,c,b,g,d=this.input;switch(this.d){case 0:b=0;for(g=d.length;b<g;){c=F?d.subarray(b,b+65535):d.slice(b,b+65535);b+=c.length;var e=c,f=b===g,l=j,s=j,k=j,r=j,m=j,h=this.a,n=this.c;if(F){for(h=new Uint8Array(this.a.buffer);h.length<=n+e.length+5;)h=new Uint8Array(h.length<<1);h.set(this.a)}l=f?1:0;h[n++]=l|0;s=e.length;k=~s+65536&65535;h[n++]=s&255;h[n++]=s>>>8&255;h[n++]=k&255;h[n++]=k>>>8&255;if(F)h.set(e,n),n+=e.length,h=h.subarray(0,n);else{r=0;for(m=e.length;r<m;++r)h[n++]=
+e[r];h.length=n}this.c=n;this.a=h}break;case 1:var w=new G(new Uint8Array(this.a.buffer),this.c);w.b(1,1,z);w.b(1,2,z);var q=ra(this,d),u,I,y;u=0;for(I=q.length;u<I;u++)if(y=q[u],G.prototype.b.apply(w,T[y]),256<y)w.b(q[++u],q[++u],z),w.b(q[++u],5),w.b(q[++u],q[++u],z);else if(256===y)break;this.a=w.finish();this.c=this.a.length;break;case oa:var x=new G(new Uint8Array(this.a),this.c),A,i,p,C,B,$=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Q,Ga,aa,Ha,ka,qa=Array(19),Ia,U,la,D,Ja;A=oa;x.b(1,1,
+z);x.b(A,2,z);i=ra(this,d);Q=sa(this.m,15);Ga=ua(Q);aa=sa(this.l,7);Ha=ua(aa);for(p=286;257<p&&0===Q[p-1];p--);for(C=30;1<C&&0===aa[C-1];C--);var Ka=p,La=C,K=new (F?Uint32Array:Array)(Ka+La),t,L,v,ba,J=new (F?Uint32Array:Array)(316),H,E,M=new (F?Uint8Array:Array)(19);for(t=L=0;t<Ka;t++)K[L++]=Q[t];for(t=0;t<La;t++)K[L++]=aa[t];if(!F){t=0;for(ba=M.length;t<ba;++t)M[t]=0}t=H=0;for(ba=K.length;t<ba;t+=L){for(L=1;t+L<ba&&K[t+L]===K[t];++L);v=L;if(0===K[t])if(3>v)for(;0<v--;)J[H++]=0,M[0]++;else for(;0<
+v;)E=138>v?v:138,E>v-3&&E<v&&(E=v-3),10>=E?(J[H++]=17,J[H++]=E-3,M[17]++):(J[H++]=18,J[H++]=E-11,M[18]++),v-=E;else if(J[H++]=K[t],M[K[t]]++,v--,3>v)for(;0<v--;)J[H++]=K[t],M[K[t]]++;else for(;0<v;)E=6>v?v:6,E>v-3&&E<v&&(E=v-3),J[H++]=16,J[H++]=E-3,M[16]++,v-=E}a=F?J.subarray(0,H):J.slice(0,H);ka=sa(M,7);for(D=0;19>D;D++)qa[D]=ka[$[D]];for(B=19;4<B&&0===qa[B-1];B--);Ia=ua(ka);x.b(p-257,5,z);x.b(C-1,5,z);x.b(B-4,4,z);for(D=0;D<B;D++)x.b(qa[D],3,z);D=0;for(Ja=a.length;D<Ja;D++)if(U=a[D],x.b(Ia[U],ka[U],
+z),16<=U){D++;switch(U){case 16:la=2;break;case 17:la=3;break;case 18:la=7;break;default:throw"invalid code: "+U;}x.b(a[D],la,z)}var Ma=[Ga,Q],Na=[Ha,aa],N,Oa,ca,ta,Pa,Qa,Ra,Sa;Pa=Ma[0];Qa=Ma[1];Ra=Na[0];Sa=Na[1];N=0;for(Oa=i.length;N<Oa;++N)if(ca=i[N],x.b(Pa[ca],Qa[ca],z),256<ca)x.b(i[++N],i[++N],z),ta=i[++N],x.b(Ra[ta],Sa[ta],z),x.b(i[++N],i[++N],z);else if(256===ca)break;this.a=x.finish();this.c=this.a.length;break;default:throw"invalid compression type";}return this.a};
+function va(a,c){this.length=a;this.k=c}
+function wa(){var a=xa;switch(z){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,a-
+31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:throw"invalid length: "+a;}}var ya=[],xa,za;
+for(xa=3;258>=xa;xa++)za=wa(),ya[xa]=za[2]<<24|za[1]<<16|za[0];var Aa=F?new Uint32Array(ya):ya;
+function ra(a,c){function b(a,c){var b=a.k,d=[],e=0,g;g=Aa[a.length];d[e++]=g&65535;d[e++]=g>>16&255;d[e++]=g>>24;var f;switch(z){case 1===b:f=[0,b-1,0];break;case 2===b:f=[1,b-2,0];break;case 3===b:f=[2,b-3,0];break;case 4===b:f=[3,b-4,0];break;case 6>=b:f=[4,b-5,1];break;case 8>=b:f=[5,b-7,1];break;case 12>=b:f=[6,b-9,2];break;case 16>=b:f=[7,b-13,2];break;case 24>=b:f=[8,b-17,3];break;case 32>=b:f=[9,b-25,3];break;case 48>=b:f=[10,b-33,4];break;case 64>=b:f=[11,b-49,4];break;case 96>=b:f=[12,b-
+65,5];break;case 128>=b:f=[13,b-97,5];break;case 192>=b:f=[14,b-129,6];break;case 256>=b:f=[15,b-193,6];break;case 384>=b:f=[16,b-257,7];break;case 512>=b:f=[17,b-385,7];break;case 768>=b:f=[18,b-513,8];break;case 1024>=b:f=[19,b-769,8];break;case 1536>=b:f=[20,b-1025,9];break;case 2048>=b:f=[21,b-1537,9];break;case 3072>=b:f=[22,b-2049,10];break;case 4096>=b:f=[23,b-3073,10];break;case 6144>=b:f=[24,b-4097,11];break;case 8192>=b:f=[25,b-6145,11];break;case 12288>=b:f=[26,b-8193,12];break;case 16384>=
+b:f=[27,b-12289,12];break;case 24576>=b:f=[28,b-16385,13];break;case 32768>=b:f=[29,b-24577,13];break;default:throw"invalid distance";}g=f;d[e++]=g[0];d[e++]=g[1];d[e++]=g[2];var i,k;i=0;for(k=d.length;i<k;++i)h[n++]=d[i];q[d[0]]++;u[d[3]]++;w=a.length+c-1;m=null}var g,d,e,f,l,s={},k,r,m,h=F?new Uint16Array(2*c.length):[],n=0,w=0,q=new (F?Uint32Array:Array)(286),u=new (F?Uint32Array:Array)(30),I=a.i,y;if(!F){for(e=0;285>=e;)q[e++]=0;for(e=0;29>=e;)u[e++]=0}q[256]=1;g=0;for(d=c.length;g<d;++g){e=l=
+0;for(f=3;e<f&&g+e!==d;++e)l=l<<8|c[g+e];s[l]===j&&(s[l]=[]);k=s[l];if(!(0<w--)){for(;0<k.length&&32768<g-k[0];)k.shift();if(g+3>=d){m&&b(m,-1);e=0;for(f=d-g;e<f;++e)y=c[g+e],h[n++]=y,++q[y];break}if(0<k.length){var x=j,A=j,i=0,p=j,C=j,B=j,$=j,Q=c.length,C=0,$=k.length;a:for(;C<$;C++){x=k[$-C-1];p=3;if(3<i){for(B=i;3<B;B--)if(c[x+B-1]!==c[g+B-1])continue a;p=i}for(;258>p&&g+p<Q&&c[x+p]===c[g+p];)++p;p>i&&(A=x,i=p);if(258===p)break}r=new va(i,g-A);m?m.length<r.length?(y=c[g-1],h[n++]=y,++q[y],b(r,
+0)):b(m,-1):r.length<I?m=r:b(r,0)}else m?b(m,-1):(y=c[g],h[n++]=y,++q[y])}k.push(g)}h[n++]=256;q[256]++;a.m=q;a.l=u;return F?h.subarray(0,n):h}
+function sa(a,c){function b(a){var c=u[a][I[a]];c===m?(b(a+1),b(a+1)):--w[c];++I[a]}var g=a.length,d=new ja(572),e=new (F?Uint8Array:Array)(g),f,l,s,k,r;if(!F)for(k=0;k<g;k++)e[k]=0;for(k=0;k<g;++k)0<a[k]&&d.push(k,a[k]);f=Array(d.length/2);l=new (F?Uint32Array:Array)(d.length/2);if(1===f.length)return e[d.pop().index]=1,e;k=0;for(r=d.length/2;k<r;++k)f[k]=d.pop(),l[k]=f[k].value;var m=l.length,h=new (F?Uint16Array:Array)(c),n=new (F?Uint8Array:Array)(c),w=new (F?Uint8Array:Array)(m),q=Array(c),u=
+Array(c),I=Array(c),y=(1<<c)-m,x=1<<c-1,A,i,p,C,B;h[c-1]=m;for(i=0;i<c;++i)y<x?n[i]=0:(n[i]=1,y-=x),y<<=1,h[c-2-i]=(h[c-1-i]/2|0)+m;h[0]=n[0];q[0]=Array(h[0]);u[0]=Array(h[0]);for(i=1;i<c;++i)h[i]>2*h[i-1]+n[i]&&(h[i]=2*h[i-1]+n[i]),q[i]=Array(h[i]),u[i]=Array(h[i]);for(A=0;A<m;++A)w[A]=c;for(p=0;p<h[c-1];++p)q[c-1][p]=l[p],u[c-1][p]=p;for(A=0;A<c;++A)I[A]=0;1===n[c-1]&&(--w[0],++I[c-1]);for(i=c-2;0<=i;--i){C=A=0;B=I[i+1];for(p=0;p<h[i];p++)C=q[i+1][B]+q[i+1][B+1],C>l[A]?(q[i][p]=C,u[i][p]=m,B+=2):
+(q[i][p]=l[A],u[i][p]=A,++A);I[i]=0;1===n[i]&&b(i)}s=w;k=0;for(r=f.length;k<r;++k)e[f[k].index]=s[k];return e}function ua(a){var c=new (F?Uint16Array:Array)(a.length),b=[],g=[],d=0,e,f,l,s;e=0;for(f=a.length;e<f;e++)b[a[e]]=(b[a[e]]|0)+1;e=1;for(f=16;e<=f;e++)g[e]=d,d+=b[e]|0,d<<=1;e=0;for(f=a.length;e<f;e++){d=g[a[e]];g[a[e]]+=1;l=c[e]=0;for(s=a[e];l<s;l++)c[e]=c[e]<<1|d&1,d>>>=1}return c};var Ba=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];F&&new Uint16Array(Ba);var Ca=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258];F&&new Uint16Array(Ca);var Da=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0];F&&new Uint8Array(Da);var Ea=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577];F&&new Uint16Array(Ea);
+var Fa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];F&&new Uint8Array(Fa);var Ta=new (F?Uint8Array:Array)(288),W,Ua;W=0;for(Ua=Ta.length;W<Ua;++W)Ta[W]=143>=W?8:255>=W?9:279>=W?7:8;ma(Ta);var Va=new (F?Uint8Array:Array)(30),Wa,Xa;Wa=0;for(Xa=Va.length;Wa<Xa;++Wa)Va[Wa]=5;ma(Va);var Ya=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];F&&new Uint16Array(Ya);var Za=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258];F&&new Uint16Array(Za);var $a=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0];F&&new Uint8Array($a);var ab=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577];F&&new Uint16Array(ab);
+var bb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];F&&new Uint8Array(bb);var cb=new (F?Uint8Array:Array)(288),X,db;X=0;for(db=cb.length;X<db;++X)cb[X]=143>=X?8:255>=X?9:279>=X?7:8;ma(cb);var eb=new (F?Uint8Array:Array)(30),fb,gb;fb=0;for(gb=eb.length;fb<gb;++fb)eb[fb]=5;ma(eb);function hb(a,c){this.input=a;this.a=new (F?Uint8Array:Array)(32768);this.d=Y.g;var b={},g;if((c||!(c={}))&&"number"===typeof c.compressionType)this.d=c.compressionType;for(g in c)b[g]=c[g];b.outputBuffer=this.a;this.j=new na(this.input,b)}var Y=pa;
+hb.prototype.f=function(){var a,c,b,g,d,e,f,l=0;f=this.a;a=ib;switch(a){case ib:c=Math.LOG2E*Math.log(32768)-8;break;default:throw Error("invalid compression method");}b=c<<4|a;f[l++]=b;switch(a){case ib:switch(this.d){case Y.NONE:d=0;break;case Y.h:d=1;break;case Y.g:d=2;break;default:throw Error("unsupported compression type");}break;default:throw Error("invalid compression method");}g=d<<6|0;f[l++]=g|31-(256*b+g)%31;var s=this.input;if("string"===typeof s){var k=s.split(""),r,m;r=0;for(m=k.length;r<
+m;r++)k[r]=(k[r].charCodeAt(0)&255)>>>0;s=k}for(var h=1,n=0,w=s.length,q,u=0;0<w;){q=1024<w?1024:w;w-=q;do h+=s[u++],n+=h;while(--q);h%=65521;n%=65521}e=(n<<16|h)>>>0;this.j.c=l;f=this.j.f();l=f.length;F&&(f=new Uint8Array(f.buffer),f.length<=l+4&&(this.a=new Uint8Array(f.length+4),this.a.set(f),f=this.a),f=f.subarray(0,l+4));f[l++]=e>>24&255;f[l++]=e>>16&255;f[l++]=e>>8&255;f[l++]=e&255;return f};ea("Zlib.Deflate",hb);ea("Zlib.Deflate.compress",function(a,c){return(new hb(a,c)).f()});ea("Zlib.Deflate.prototype.compress",hb.prototype.f);var jb={NONE:Y.NONE,FIXED:Y.h,DYNAMIC:Y.g},kb,lb,Z,mb;if(Object.keys)kb=Object.keys(jb);else for(lb in kb=[],Z=0,jb)kb[Z++]=lb;Z=0;for(mb=kb.length;Z<mb;++Z)lb=kb[Z],ea("Zlib.Deflate.CompressionType."+lb,jb[lb]);var ib=8;}).call(this);
diff --git a/texinfo/doc_en.texi b/texinfo/doc_en.texi
index 9ca554a..4875277 100644
--- a/texinfo/doc_en.texi
+++ b/texinfo/doc_en.texi
@@ -1,6 +1,6 @@
 \input texinfo
 @setfilename mathgl_en.info
- at set VERSION 2.1.2
+ at set VERSION 2.1.3
 @settitle MathGL @value{VERSION}
 @syncodeindex pg cp
 @comment %**end of header
diff --git a/texinfo/doc_ru.texi b/texinfo/doc_ru.texi
index 2ce99e6..b72936b 100644
--- a/texinfo/doc_ru.texi
+++ b/texinfo/doc_ru.texi
@@ -1,6 +1,6 @@
 \input texinfo
 @setfilename mathgl_en.info
- at set VERSION 2.1.2
+ at set VERSION 2.1.3
 @settitle MathGL @value{VERSION}
 @syncodeindex pg cp
 @comment %**end of header
diff --git a/texinfo/gunzip.min.js b/texinfo/gunzip.min.js
new file mode 100644
index 0000000..9842bc4
--- /dev/null
+++ b/texinfo/gunzip.min.js
@@ -0,0 +1,29 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */
+(function() {'use strict';function k(a){throw a;}var m=void 0,aa=this;function p(a,c){var d=a.split("."),b=aa;!(d[0]in b)&&b.execScript&&b.execScript("var "+d[0]);for(var e;d.length&&(e=d.shift());)!d.length&&c!==m?b[e]=c:b=b[e]?b[e]:b[e]={}};var s="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;new (s?Uint8Array:Array)(256);var t;for(t=0;256>t;++t)for(var u=t,ba=7,u=u>>>1;u;u>>>=1)--ba;function v(a,c,d){var b,e="number"===typeof c?c:c=0,f="number"===typeof d?d:a.length;b=-1;for(e=f&7;e--;++c)b=b>>>8^w[(b^a[c])&255];for(e=f>>3;e--;c+=8)b=b>>>8^w[(b^a[c])&255],b=b>>>8^w[(b^a[c+1])&255],b=b>>>8^w[(b^a[c+2])&255],b=b>>>8^w[(b^a[c+3])&255],b=b>>>8^w[(b^a[c+4])&255],b=b>>>8^w[(b^a[c+5])&255],b=b>>>8^w[(b^a[c+6])&255],b=b>>>8^w[(b^a[c+7])&255];return(b^4294967295)>>>0}
+var w,x=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
+2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
+2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
+2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
+3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
+936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];w=s?new Uint32Array(x):x;function y(){}y.prototype.getName=function(){return this.name};y.prototype.getData=function(){return this.data};y.prototype.G=function(){return this.H};p("Zlib.GunzipMember",y);p("Zlib.GunzipMember.prototype.getName",y.prototype.getName);p("Zlib.GunzipMember.prototype.getData",y.prototype.getData);p("Zlib.GunzipMember.prototype.getMtime",y.prototype.G);function z(a){var c=a.length,d=0,b=Number.POSITIVE_INFINITY,e,f,g,i,l,n,r,h,j;for(h=0;h<c;++h)a[h]>d&&(d=a[h]),a[h]<b&&(b=a[h]);e=1<<d;f=new (s?Uint32Array:Array)(e);g=1;i=0;for(l=2;g<=d;){for(h=0;h<c;++h)if(a[h]===g){n=0;r=i;for(j=0;j<g;++j)n=n<<1|r&1,r>>=1;for(j=n;j<e;j+=l)f[j]=g<<16|h;++i}++g;i<<=1;l<<=1}return[f,d,b]};var B=[],C;for(C=0;288>C;C++)switch(!0){case 143>=C:B.push([C+48,8]);break;case 255>=C:B.push([C-144+400,9]);break;case 279>=C:B.push([C-256+0,7]);break;case 287>=C:B.push([C-280+192,8]);break;default:k("invalid literal: "+C)}
+function ca(){var a=D;switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,a-
+31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:k("invalid length: "+a)}}var E=[],D,G;
+for(D=3;258>=D;D++)G=ca(),E[D]=G[2]<<24|G[1]<<16|G[0];s&&new Uint32Array(E);function H(a,c){this.i=[];this.j=32768;this.d=this.f=this.c=this.n=0;this.input=s?new Uint8Array(a):a;this.o=!1;this.k=I;this.w=!1;if(c||!(c={}))c.index&&(this.c=c.index),c.bufferSize&&(this.j=c.bufferSize),c.bufferType&&(this.k=c.bufferType),c.resize&&(this.w=c.resize);switch(this.k){case J:this.a=32768;this.b=new (s?Uint8Array:Array)(32768+this.j+258);break;case I:this.a=0;this.b=new (s?Uint8Array:Array)(this.j);this.e=this.D;this.q=this.A;this.l=this.C;break;default:k(Error("invalid inflate mode"))}}
+var J=0,I=1;
+H.prototype.g=function(){for(;!this.o;){var a=K(this,3);a&1&&(this.o=!0);a>>>=1;switch(a){case 0:var c=this.input,d=this.c,b=this.b,e=this.a,f=m,g=m,i=m,l=b.length,n=m;this.d=this.f=0;f=c[d++];f===m&&k(Error("invalid uncompressed block header: LEN (first byte)"));g=f;f=c[d++];f===m&&k(Error("invalid uncompressed block header: LEN (second byte)"));g|=f<<8;f=c[d++];f===m&&k(Error("invalid uncompressed block header: NLEN (first byte)"));i=f;f=c[d++];f===m&&k(Error("invalid uncompressed block header: NLEN (second byte)"));i|=
+f<<8;g===~i&&k(Error("invalid uncompressed block header: length verify"));d+g>c.length&&k(Error("input buffer is broken"));switch(this.k){case J:for(;e+g>b.length;){n=l-e;g-=n;if(s)b.set(c.subarray(d,d+n),e),e+=n,d+=n;else for(;n--;)b[e++]=c[d++];this.a=e;b=this.e();e=this.a}break;case I:for(;e+g>b.length;)b=this.e({t:2});break;default:k(Error("invalid inflate mode"))}if(s)b.set(c.subarray(d,d+g),e),e+=g,d+=g;else for(;g--;)b[e++]=c[d++];this.c=d;this.a=e;this.b=b;break;case 1:this.l(da,ea);break;
+case 2:fa(this);break;default:k(Error("unknown BTYPE: "+a))}}return this.q()};
+var L=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ga=s?new Uint16Array(L):L,ha=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],ia=s?new Uint16Array(ha):ha,ja=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],M=s?new Uint8Array(ja):ja,ka=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],la=s?new Uint16Array(ka):ka,ma=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,
+11,12,12,13,13],O=s?new Uint8Array(ma):ma,P=new (s?Uint8Array:Array)(288),Q,na;Q=0;for(na=P.length;Q<na;++Q)P[Q]=143>=Q?8:255>=Q?9:279>=Q?7:8;var da=z(P),R=new (s?Uint8Array:Array)(30),S,oa;S=0;for(oa=R.length;S<oa;++S)R[S]=5;var ea=z(R);function K(a,c){for(var d=a.f,b=a.d,e=a.input,f=a.c,g;b<c;)g=e[f++],g===m&&k(Error("input buffer is broken")),d|=g<<b,b+=8;g=d&(1<<c)-1;a.f=d>>>c;a.d=b-c;a.c=f;return g}
+function V(a,c){for(var d=a.f,b=a.d,e=a.input,f=a.c,g=c[0],i=c[1],l,n,r;b<i;)l=e[f++],l===m&&k(Error("input buffer is broken")),d|=l<<b,b+=8;n=g[d&(1<<i)-1];r=n>>>16;a.f=d>>r;a.d=b-r;a.c=f;return n&65535}
+function fa(a){function c(a,c,b){var d,e,f,g;for(g=0;g<a;)switch(d=V(this,c),d){case 16:for(f=3+K(this,2);f--;)b[g++]=e;break;case 17:for(f=3+K(this,3);f--;)b[g++]=0;e=0;break;case 18:for(f=11+K(this,7);f--;)b[g++]=0;e=0;break;default:e=b[g++]=d}return b}var d=K(a,5)+257,b=K(a,5)+1,e=K(a,4)+4,f=new (s?Uint8Array:Array)(ga.length),g,i,l,n;for(n=0;n<e;++n)f[ga[n]]=K(a,3);g=z(f);i=new (s?Uint8Array:Array)(d);l=new (s?Uint8Array:Array)(b);a.l(z(c.call(a,d,g,i)),z(c.call(a,b,g,l)))}
+H.prototype.l=function(a,c){var d=this.b,b=this.a;this.r=a;for(var e=d.length-258,f,g,i,l;256!==(f=V(this,a));)if(256>f)b>=e&&(this.a=b,d=this.e(),b=this.a),d[b++]=f;else{g=f-257;l=ia[g];0<M[g]&&(l+=K(this,M[g]));f=V(this,c);i=la[f];0<O[f]&&(i+=K(this,O[f]));b>=e&&(this.a=b,d=this.e(),b=this.a);for(;l--;)d[b]=d[b++-i]}for(;8<=this.d;)this.d-=8,this.c--;this.a=b};
+H.prototype.C=function(a,c){var d=this.b,b=this.a;this.r=a;for(var e=d.length,f,g,i,l;256!==(f=V(this,a));)if(256>f)b>=e&&(d=this.e(),e=d.length),d[b++]=f;else{g=f-257;l=ia[g];0<M[g]&&(l+=K(this,M[g]));f=V(this,c);i=la[f];0<O[f]&&(i+=K(this,O[f]));b+l>e&&(d=this.e(),e=d.length);for(;l--;)d[b]=d[b++-i]}for(;8<=this.d;)this.d-=8,this.c--;this.a=b};
+H.prototype.e=function(){var a=new (s?Uint8Array:Array)(this.a-32768),c=this.a-32768,d,b,e=this.b;if(s)a.set(e.subarray(32768,a.length));else{d=0;for(b=a.length;d<b;++d)a[d]=e[d+32768]}this.i.push(a);this.n+=a.length;if(s)e.set(e.subarray(c,c+32768));else for(d=0;32768>d;++d)e[d]=e[c+d];this.a=32768;return e};
+H.prototype.D=function(a){var c,d=this.input.length/this.c+1|0,b,e,f,g=this.input,i=this.b;a&&("number"===typeof a.t&&(d=a.t),"number"===typeof a.z&&(d+=a.z));2>d?(b=(g.length-this.c)/this.r[2],f=258*(b/2)|0,e=f<i.length?i.length+f:i.length<<1):e=i.length*d;s?(c=new Uint8Array(e),c.set(i)):c=i;return this.b=c};
+H.prototype.q=function(){var a=0,c=this.b,d=this.i,b,e=new (s?Uint8Array:Array)(this.n+(this.a-32768)),f,g,i,l;if(0===d.length)return s?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);f=0;for(g=d.length;f<g;++f){b=d[f];i=0;for(l=b.length;i<l;++i)e[a++]=b[i]}f=32768;for(g=this.a;f<g;++f)e[a++]=c[f];this.i=[];return this.buffer=e};
+H.prototype.A=function(){var a,c=this.a;s?this.w?(a=new Uint8Array(c),a.set(this.b.subarray(0,c))):a=this.b.subarray(0,c):(this.b.length>c&&(this.b.length=c),a=this.b);return this.buffer=a};function W(a){this.input=a;this.c=0;this.m=[];this.s=!1}W.prototype.F=function(){this.s||this.g();return this.m.slice()};
+W.prototype.g=function(){for(var a=this.input.length;this.c<a;){var c=new y,d=m,b=m,e=m,f=m,g=m,i=m,l=m,n=m,r=m,h=this.input,j=this.c;c.u=h[j++];c.v=h[j++];(31!==c.u||139!==c.v)&&k(Error("invalid file signature:"+c.u+","+c.v));c.p=h[j++];switch(c.p){case 8:break;default:k(Error("unknown compression method: "+c.p))}c.h=h[j++];n=h[j++]|h[j++]<<8|h[j++]<<16|h[j++]<<24;c.H=new Date(1E3*n);c.N=h[j++];c.M=h[j++];0<(c.h&4)&&(c.I=h[j++]|h[j++]<<8,j+=c.I);if(0<(c.h&8)){l=[];for(i=0;0<(g=h[j++]);)l[i++]=String.fromCharCode(g);
+c.name=l.join("")}if(0<(c.h&16)){l=[];for(i=0;0<(g=h[j++]);)l[i++]=String.fromCharCode(g);c.J=l.join("")}0<(c.h&2)&&(c.B=v(h,0,j)&65535,c.B!==(h[j++]|h[j++]<<8)&&k(Error("invalid header crc16")));d=h[h.length-4]|h[h.length-3]<<8|h[h.length-2]<<16|h[h.length-1]<<24;h.length-j-4-4<512*d&&(f=d);b=new H(h,{index:j,bufferSize:f});c.data=e=b.g();j=b.c;c.K=r=(h[j++]|h[j++]<<8|h[j++]<<16|h[j++]<<24)>>>0;v(e,m,m)!==r&&k(Error("invalid CRC-32 checksum: 0x"+v(e,m,m).toString(16)+" / 0x"+r.toString(16)));c.L=
+d=(h[j++]|h[j++]<<8|h[j++]<<16|h[j++]<<24)>>>0;(e.length&4294967295)!==d&&k(Error("invalid input size: "+(e.length&4294967295)+" / "+d));this.m.push(c);this.c=j}this.s=!0;var F=this.m,q,N,T=0,U=0,A;q=0;for(N=F.length;q<N;++q)U+=F[q].data.length;if(s){A=new Uint8Array(U);for(q=0;q<N;++q)A.set(F[q].data,T),T+=F[q].data.length}else{A=[];for(q=0;q<N;++q)A[q]=F[q].data;A=Array.prototype.concat.apply([],A)}return A};p("Zlib.Gunzip",W);p("Zlib.Gunzip.prototype.decompress",W.prototype.g);p("Zlib.Gunzip.prototype.getMembers",W.prototype.F);var pa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];s&&new Uint16Array(pa);var qa=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258];s&&new Uint16Array(qa);var ra=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0];s&&new Uint8Array(ra);var sa=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577];s&&new Uint16Array(sa);
+var ta=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];s&&new Uint8Array(ta);var X=new (s?Uint8Array:Array)(288),Y,ua;Y=0;for(ua=X.length;Y<ua;++Y)X[Y]=143>=Y?8:255>=Y?9:279>=Y?7:8;z(X);var Z=new (s?Uint8Array:Array)(30),$,va;$=0;for(va=Z.length;$<va;++$)Z[$]=5;z(Z);}).call(this);
diff --git a/texinfo/inflate.min.js b/texinfo/inflate.min.js
new file mode 100644
index 0000000..a5dee75
--- /dev/null
+++ b/texinfo/inflate.min.js
@@ -0,0 +1,26 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */
+(function() {'use strict';function i(a){throw a;}var l=void 0,aa=this;function p(a,d){var b=a.split("."),c=aa;!(b[0]in c)&&c.execScript&&c.execScript("var "+b[0]);for(var f;b.length&&(f=b.shift());)!b.length&&d!==l?c[f]=d:c=c[f]?c[f]:c[f]={}};var q="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;new (q?Uint8Array:Array)(256);var r;for(r=0;256>r;++r)for(var t=r,ba=7,t=t>>>1;t;t>>>=1)--ba;var ca=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
+2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
+2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
+2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
+3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
+936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];q&&new Uint32Array(ca);function u(a){var d=a.length,b=0,c=Number.POSITIVE_INFINITY,f,e,g,h,j,k,n,m,s;for(m=0;m<d;++m)a[m]>b&&(b=a[m]),a[m]<c&&(c=a[m]);f=1<<b;e=new (q?Uint32Array:Array)(f);g=1;h=0;for(j=2;g<=b;){for(m=0;m<d;++m)if(a[m]===g){k=0;n=h;for(s=0;s<g;++s)k=k<<1|n&1,n>>=1;for(s=k;s<f;s+=j)e[s]=g<<16|m;++h}++g;h<<=1;j<<=1}return[e,b,c]};var v=[],w;for(w=0;288>w;w++)switch(!0){case 143>=w:v.push([w+48,8]);break;case 255>=w:v.push([w-144+400,9]);break;case 279>=w:v.push([w-256+0,7]);break;case 287>=w:v.push([w-280+192,8]);break;default:i("invalid literal: "+w)}
+function da(){var a=x;switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,a-
+31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:i("invalid length: "+a)}}var y=[],x,z;
+for(x=3;258>=x;x++)z=da(),y[x]=z[2]<<24|z[1]<<16|z[0];q&&new Uint32Array(y);function A(a,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=q?new Uint8Array(a):a;this.m=!1;this.i=B;this.r=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.r=d.resize);switch(this.i){case C:this.b=32768;this.c=new (q?Uint8Array:Array)(32768+this.h+258);break;case B:this.b=0;this.c=new (q?Uint8Array:Array)(this.h);this.e=this.z;this.n=this.v;this.j=this.w;break;default:i(Error("invalid inflate mode"))}}
+var C=0,B=1,D={t:C,s:B};
+A.prototype.k=function(){for(;!this.m;){var a=E(this,3);a&1&&(this.m=!0);a>>>=1;switch(a){case 0:var d=this.input,b=this.a,c=this.c,f=this.b,e=l,g=l,h=l,j=c.length,k=l;this.d=this.f=0;e=d[b++];e===l&&i(Error("invalid uncompressed block header: LEN (first byte)"));g=e;e=d[b++];e===l&&i(Error("invalid uncompressed block header: LEN (second byte)"));g|=e<<8;e=d[b++];e===l&&i(Error("invalid uncompressed block header: NLEN (first byte)"));h=e;e=d[b++];e===l&&i(Error("invalid uncompressed block header: NLEN (second byte)"));h|=
+e<<8;g===~h&&i(Error("invalid uncompressed block header: length verify"));b+g>d.length&&i(Error("input buffer is broken"));switch(this.i){case C:for(;f+g>c.length;){k=j-f;g-=k;if(q)c.set(d.subarray(b,b+k),f),f+=k,b+=k;else for(;k--;)c[f++]=d[b++];this.b=f;c=this.e();f=this.b}break;case B:for(;f+g>c.length;)c=this.e({p:2});break;default:i(Error("invalid inflate mode"))}if(q)c.set(d.subarray(b,b+g),f),f+=g,b+=g;else for(;g--;)c[f++]=d[b++];this.a=b;this.b=f;this.c=c;break;case 1:this.j(ea,fa);break;
+case 2:ga(this);break;default:i(Error("unknown BTYPE: "+a))}}return this.n()};
+var F=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],G=q?new Uint16Array(F):F,H=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],I=q?new Uint16Array(H):H,J=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],K=q?new Uint8Array(J):J,L=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ha=q?new Uint16Array(L):L,ia=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,
+13,13],M=q?new Uint8Array(ia):ia,N=new (q?Uint8Array:Array)(288),O,ja;O=0;for(ja=N.length;O<ja;++O)N[O]=143>=O?8:255>=O?9:279>=O?7:8;var ea=u(N),P=new (q?Uint8Array:Array)(30),Q,ka;Q=0;for(ka=P.length;Q<ka;++Q)P[Q]=5;var fa=u(P);function E(a,d){for(var b=a.f,c=a.d,f=a.input,e=a.a,g;c<d;)g=f[e++],g===l&&i(Error("input buffer is broken")),b|=g<<c,c+=8;g=b&(1<<d)-1;a.f=b>>>d;a.d=c-d;a.a=e;return g}
+function R(a,d){for(var b=a.f,c=a.d,f=a.input,e=a.a,g=d[0],h=d[1],j,k,n;c<h;)j=f[e++],j===l&&i(Error("input buffer is broken")),b|=j<<c,c+=8;k=g[b&(1<<h)-1];n=k>>>16;a.f=b>>n;a.d=c-n;a.a=e;return k&65535}
+function ga(a){function d(a,b,c){var d,e,f,g;for(g=0;g<a;)switch(d=R(this,b),d){case 16:for(f=3+E(this,2);f--;)c[g++]=e;break;case 17:for(f=3+E(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+E(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}return c}var b=E(a,5)+257,c=E(a,5)+1,f=E(a,4)+4,e=new (q?Uint8Array:Array)(G.length),g,h,j,k;for(k=0;k<f;++k)e[G[k]]=E(a,3);g=u(e);h=new (q?Uint8Array:Array)(b);j=new (q?Uint8Array:Array)(c);a.j(u(d.call(a,b,g,h)),u(d.call(a,c,g,j)))}
+A.prototype.j=function(a,d){var b=this.c,c=this.b;this.o=a;for(var f=b.length-258,e,g,h,j;256!==(e=R(this,a));)if(256>e)c>=f&&(this.b=c,b=this.e(),c=this.b),b[c++]=e;else{g=e-257;j=I[g];0<K[g]&&(j+=E(this,K[g]));e=R(this,d);h=ha[e];0<M[e]&&(h+=E(this,M[e]));c>=f&&(this.b=c,b=this.e(),c=this.b);for(;j--;)b[c]=b[c++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=c};
+A.prototype.w=function(a,d){var b=this.c,c=this.b;this.o=a;for(var f=b.length,e,g,h,j;256!==(e=R(this,a));)if(256>e)c>=f&&(b=this.e(),f=b.length),b[c++]=e;else{g=e-257;j=I[g];0<K[g]&&(j+=E(this,K[g]));e=R(this,d);h=ha[e];0<M[e]&&(h+=E(this,M[e]));c+j>f&&(b=this.e(),f=b.length);for(;j--;)b[c]=b[c++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=c};
+A.prototype.e=function(){var a=new (q?Uint8Array:Array)(this.b-32768),d=this.b-32768,b,c,f=this.c;if(q)a.set(f.subarray(32768,a.length));else{b=0;for(c=a.length;b<c;++b)a[b]=f[b+32768]}this.g.push(a);this.l+=a.length;if(q)f.set(f.subarray(d,d+32768));else for(b=0;32768>b;++b)f[b]=f[d+b];this.b=32768;return f};
+A.prototype.z=function(a){var d,b=this.input.length/this.a+1|0,c,f,e,g=this.input,h=this.c;a&&("number"===typeof a.p&&(b=a.p),"number"===typeof a.u&&(b+=a.u));2>b?(c=(g.length-this.a)/this.o[2],e=258*(c/2)|0,f=e<h.length?h.length+e:h.length<<1):f=h.length*b;q?(d=new Uint8Array(f),d.set(h)):d=h;return this.c=d};
+A.prototype.n=function(){var a=0,d=this.c,b=this.g,c,f=new (q?Uint8Array:Array)(this.l+(this.b-32768)),e,g,h,j;if(0===b.length)return q?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);e=0;for(g=b.length;e<g;++e){c=b[e];h=0;for(j=c.length;h<j;++h)f[a++]=c[h]}e=32768;for(g=this.b;e<g;++e)f[a++]=d[e];this.g=[];return this.buffer=f};
+A.prototype.v=function(){var a,d=this.b;q?this.r?(a=new Uint8Array(d),a.set(this.c.subarray(0,d))):a=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),a=this.c);return this.buffer=a};var la=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];q&&new Uint16Array(la);var ma=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258];q&&new Uint16Array(ma);var na=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0];q&&new Uint8Array(na);var oa=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577];q&&new Uint16Array(oa);
+var pa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];q&&new Uint8Array(pa);var S=new (q?Uint8Array:Array)(288),T,qa;T=0;for(qa=S.length;T<qa;++T)S[T]=143>=T?8:255>=T?9:279>=T?7:8;u(S);var U=new (q?Uint8Array:Array)(30),V,ra;V=0;for(ra=U.length;V<ra;++V)U[V]=5;u(U);function W(a,d){var b,c;this.input=a;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.A=d.verify);b=a[this.a++];c=a[this.a++];switch(b&15){case sa:this.method=sa;break;default:i(Error("unsupported compression method"))}0!==((b<<8)+c)%31&&i(Error("invalid fcheck flag:"+((b<<8)+c)%31));c&32&&i(Error("fdict flag is not supported"));this.q=new A(a,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})}
+W.prototype.k=function(){var a=this.input,d,b;d=this.q.k();this.a=this.q.a;if(this.A){b=(a[this.a++]<<24|a[this.a++]<<16|a[this.a++]<<8|a[this.a++])>>>0;var c=d;if("string"===typeof c){var f=c.split(""),e,g;e=0;for(g=f.length;e<g;e++)f[e]=(f[e].charCodeAt(0)&255)>>>0;c=f}for(var h=1,j=0,k=c.length,n,m=0;0<k;){n=1024<k?1024:k;k-=n;do h+=c[m++],j+=h;while(--n);h%=65521;j%=65521}b!==(j<<16|h)>>>0&&i(Error("invalid adler-32 checksum"))}return d};p("Zlib.Inflate",W);p("Zlib.Inflate.prototype.decompress",W.prototype.k);var X={ADAPTIVE:D.s,BLOCK:D.t},Y,Z,$,ta;if(Object.keys)Y=Object.keys(X);else for(Z in Y=[],$=0,X)Y[$++]=Z;$=0;for(ta=Y.length;$<ta;++$)Z=Y[$],p("Zlib.Inflate.BufferType."+Z,X[Z]);var sa=8;}).call(this);
diff --git a/texinfo/json.html b/texinfo/json.html
index cfa8bd7..f1ae163 100644
--- a/texinfo/json.html
+++ b/texinfo/json.html
@@ -4,6 +4,7 @@
 
 <head>
 	<script type="text/javascript" src="mathgl.js"></script>
+	<script type="text/javascript" src="inflate.min.js"></script>
 </head>
 
 <body onload="main();">
diff --git a/texinfo/mathgl.js b/texinfo/mathgl.js
index 99d1037..2ea0008 100644
--- a/texinfo/mathgl.js
+++ b/texinfo/mathgl.js
@@ -26,8 +26,8 @@ var main = function()
 	ctx = document.getElementById("canvas").getContext("2d");
 	ctx.lineCap="round";	// global setting
 
-//	mgl_init("json/test.json");
 	mgl_init("json/alpha.json");
+//	mgl_init("json/alpha.jsonz");
 	var t1 = new Date();
 	mgl_draw_good(obj, ctx);
 //	draw_fast(obj, ctx);
@@ -104,10 +104,32 @@ var mglRestore = function()
 var mgl_init = function(name)
 {
 	// now obtain JSON data
-	var req = new XMLHttpRequest();
+	var req = new XMLHttpRequest(), txt;
 	req.open( "GET", name, false );
+	req.overrideMimeType('text\/plain; charset=x-user-defined');
+/*	req.responseType = "arraybuffer";
+	req.onload = function (oEvent) {
+		var arrayBuffer = req.response; // Note: not oReq.responseText
+		console.debug("arrayBuffer=",arrayBuffer);
+		if (arrayBuffer) {
+			var compressed = new Uint8Array(arrayBuffer);
+			console.debug("compressed=",compressed);
+//			var gunzip = new Zlib.Gunzip(compressed);
+//			txt = gunzip.decompress();
+			var inflate = new Zlib.Inflate(arrayBuffer);
+			txt = inflate.decompress();
+		}
+	};*/
 	req.send(null);
-	obj = JSON.parse(req.responseText);
+	if(name[name.length-1]!='z')
+		txt = req.responseText;
+	else
+	{
+console.debug("compressed=",req.responseText);
+		var inflate = new Zlib.Inflate(req.responseText);
+		txt = inflate.decompress();
+	}
+	obj = JSON.parse(txt);
 
 	// copy original data for transformation
 	obj.pp = new Array();
@@ -195,16 +217,20 @@ var mgl_draw_fast = function(obj, ctx, skip)
 	for(var i=0;i<obj.nprim;i++)	// for each primitive
 	{
 		var n1 = obj.prim[i][1], n2 = obj.prim[i][2];
-		ctx.fillStyle = obj.prim[i][10];
-		ctx.fillRect(obj.pp[n1][0], obj.pp[n1][1], 2, 2);
 		if(obj.prim[i][0]==1)
 		{
+			ctx.strokeStyle = obj.prim[i][10];
 			ctx.beginPath();
 			ctx.moveTo(obj.pp[n1][0],obj.pp[n1][1]);
 			ctx.lineTo(obj.pp[n2][0],obj.pp[n2][1]);
 			ctx.lineWidth = obj.prim[i][7];
 			ctx.stroke();
 		}
+		else
+		{
+			ctx.fillStyle = obj.prim[i][10];
+			ctx.fillRect(obj.pp[n1][0], obj.pp[n1][1], 2, 2);
+		}
 	}
 	obj.fast = 0;
 }
diff --git a/texinfo/mgl.cgi.1 b/texinfo/mgl.cgi.1
new file mode 100644
index 0000000..c251ecc
--- /dev/null
+++ b/texinfo/mgl.cgi.1
@@ -0,0 +1,17 @@
+.\" Process this file with
+.\" groff -man -Tascii mgl.cgi.1
+.\"
+.TH MGLCONV 1 "APRIL 2013" MathGL "User Manuals"
+.SH NAME
+mgl.cgi \- Execute MathGL scripts to produce PNG image.
+.SH SYNOPSIS
+.B mgl.cgi
+[CGI_of_MGL]
+.SH DESCRIPTION
+.B mgl.cgi
+reads CGI query with MGL script from standard input and put resulting PNG image into standard output.
+.SH AUTHOR
+mgl.cgi was written by Alexey Balakin, http://mathgl.sourceforge.net/
+.SH "SEE ALSO"
+.BR mglview (1),
+.BR mgl (5)
diff --git a/texinfo/mgl_en.texi b/texinfo/mgl_en.texi
index f52a6a3..8f6a207 100644
--- a/texinfo/mgl_en.texi
+++ b/texinfo/mgl_en.texi
@@ -1,6 +1,6 @@
 \input texinfo
 @setfilename mgl_en.info
- at set VERSION 2.1.2
+ at set VERSION 2.1.3
 @settitle MGL script language for version @value{VERSION}
 @syncodeindex pg cp
 @comment %**end of header
diff --git a/texinfo/mgl_ru.texi b/texinfo/mgl_ru.texi
index dbeead7..82873e3 100644
--- a/texinfo/mgl_ru.texi
+++ b/texinfo/mgl_ru.texi
@@ -2,7 +2,7 @@
 @setfilename mgl_ru.info
 @c @documentlanguage ru
 @documentencoding UTF-8
- at set VERSION 2.1.2
+ at set VERSION 2.1.3
 @settitle Язык MGL для версии @value{VERSION}
 @syncodeindex pg cp
 @comment %**end of header
diff --git a/texinfo/web_en.texi b/texinfo/web_en.texi
index c5fd42e..bd1dd45 100644
--- a/texinfo/web_en.texi
+++ b/texinfo/web_en.texi
@@ -48,7 +48,7 @@ Generally MathGL is GPL library. However, you can use LGPL license for MathGL co
 
 @strong{Latest news}
 @itemize
- at item @emph{28 January 2013.}
+ at item @emph{2 May 2013.}
 New version (v. at value{VERSION}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor bugfixes and improvements, which denoted @ref{News, here}.
 @item @emph{13 December 2012.}
 New version (v.2.1) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are new plots, advanced color schemes, @uref{../json.html, JavaScript drawing}, and many other improvements in both MathGL core and UDAV, which partially denoted @ref{News, here}. Note, there are @strong{incompatible with v.2.0.* changes} in the arguments of some functions.
@@ -71,6 +71,26 @@ Javascript interface was developed with support of @url{www.datadvance.net, $DAT
 
 @itemize
 @item
+ at strong{2 May 2013.}
+New version (v.2.1.3) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor bugfixes and improvements:
+ at itemize @bullet
+ at item Functions @ref{sinfft}, @ref{cosfft}, @ref{hankel} and so on, become multi-threaded.
+ at item Use DFT instead of FFT if GSL support is disabled (much slow!).
+ at item Add Join() function for joining mglData arrays (see @ref{join})
+ at item Add Roots() function for root finding of nonlinear equation (see @ref{roots})
+ at item Add class mglExprC for parsing formula with complex numbers (see @ref{Evaluate expression})
+ at item Correctly read #QNAN values in data files
+ at item Speed up @ref{dots} drawing
+ at item Add flag to disable tick labels at axis origin (see SetOriginTick())
+ at item Add MGL commands @ref{origintick}, @ref{tickshift}
+ at item WriteJSON now use zlib if filename end at 'z' (like "test.jsonz")
+ at item Make separate libmgl-mpi
+ at item Add SetAutoRanges() function (duplicate corresponding options)
+ at item Add JSON sample usage via QtWebKit (thanks to DATADVANCE)
+ at item Bugfixes and memory leaks
+ at end itemize
+
+ at item
 @strong{28 January 2013.}
 New version (v.2.1.2) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor bugfixes and improvements:
 @itemize @bullet
diff --git a/texinfo/web_ru.texi b/texinfo/web_ru.texi
index c5fd42e..bd1dd45 100644
--- a/texinfo/web_ru.texi
+++ b/texinfo/web_ru.texi
@@ -48,7 +48,7 @@ Generally MathGL is GPL library. However, you can use LGPL license for MathGL co
 
 @strong{Latest news}
 @itemize
- at item @emph{28 January 2013.}
+ at item @emph{2 May 2013.}
 New version (v. at value{VERSION}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor bugfixes and improvements, which denoted @ref{News, here}.
 @item @emph{13 December 2012.}
 New version (v.2.1) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are new plots, advanced color schemes, @uref{../json.html, JavaScript drawing}, and many other improvements in both MathGL core and UDAV, which partially denoted @ref{News, here}. Note, there are @strong{incompatible with v.2.0.* changes} in the arguments of some functions.
@@ -71,6 +71,26 @@ Javascript interface was developed with support of @url{www.datadvance.net, $DAT
 
 @itemize
 @item
+ at strong{2 May 2013.}
+New version (v.2.1.3) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor bugfixes and improvements:
+ at itemize @bullet
+ at item Functions @ref{sinfft}, @ref{cosfft}, @ref{hankel} and so on, become multi-threaded.
+ at item Use DFT instead of FFT if GSL support is disabled (much slow!).
+ at item Add Join() function for joining mglData arrays (see @ref{join})
+ at item Add Roots() function for root finding of nonlinear equation (see @ref{roots})
+ at item Add class mglExprC for parsing formula with complex numbers (see @ref{Evaluate expression})
+ at item Correctly read #QNAN values in data files
+ at item Speed up @ref{dots} drawing
+ at item Add flag to disable tick labels at axis origin (see SetOriginTick())
+ at item Add MGL commands @ref{origintick}, @ref{tickshift}
+ at item WriteJSON now use zlib if filename end at 'z' (like "test.jsonz")
+ at item Make separate libmgl-mpi
+ at item Add SetAutoRanges() function (duplicate corresponding options)
+ at item Add JSON sample usage via QtWebKit (thanks to DATADVANCE)
+ at item Bugfixes and memory leaks
+ at end itemize
+
+ at item
 @strong{28 January 2013.}
 New version (v.2.1.2) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor bugfixes and improvements:
 @itemize @bullet
diff --git a/udav/CMakeLists.txt b/udav/CMakeLists.txt
index 90c1df6..9a9c574 100644
--- a/udav/CMakeLists.txt
+++ b/udav/CMakeLists.txt
@@ -6,7 +6,7 @@ set(udav_src anim_dlg.cpp find_dlg.cpp mem_pnl.cpp prop_dlg.cpp textedit.cpp arg
 	open_dlg.cpp qmglsyntax.cpp udav_wnd.cpp dat_pnl.cpp info_dlg.cpp opt_dlg.cpp setup_dlg.cpp
 	files_dlg.cpp plot_pnl.cpp style_dlg.cpp data_dlg.cpp tree_pnl.cpp)
 
-set(udav_moc_hdr anim_dlg.h files_dlg.h info_dlg.h opt_dlg.h qmglsyntax.h text_pnl.h args_dlg.h
+set(udav_moc_hdr anim_dlg.h files_dlg.h info_dlg.h opt_dlg.h text_pnl.h args_dlg.h
 	find_dlg.h mem_pnl.h plot_pnl.h setup_dlg.h udav_wnd.h calc_dlg.h help_pnl.h newcmd_dlg.h
 	prop_dlg.h style_dlg.h dat_pnl.h open_dlg.h textedit.h hint_dlg.h data_dlg.h)
 
diff --git a/udav/udav.desktop b/udav/udav.desktop
index 3f28e31..582d950 100755
--- a/udav/udav.desktop
+++ b/udav/udav.desktop
@@ -1,9 +1,8 @@
 [Desktop Entry]
-Encoding=UTF-8
 Version=1.0
 Type=Application
 Terminal=false
-Icon=udav.png
+Icon=udav
 Name=UDAV
 Exec=udav
 Comment=Data handling and plotting tool
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index ab06731..e3eb175 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -10,7 +10,8 @@ add_executable(mgl.cgi mglcgi.cpp)
 target_link_libraries(mgl.cgi mgl)
 install(
 	TARGETS mgl.cgi
-	RUNTIME DESTINATION bin
+# should be /usr/lib/cgi-bin/
+	RUNTIME DESTINATION ${MGL_CGI_PATH}
 )
 
 if(MGL_HAVE_QT)
diff --git a/utils/mglcgi.cpp b/utils/mglcgi.cpp
index 82fd866..9d0fc9a 100644
--- a/utils/mglcgi.cpp
+++ b/utils/mglcgi.cpp
@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
 		buf[len]=0;
 	}
 	else		buf = getenv("QUERY_STRING");
-	if(buf==0)	{	printf("There is no query. Exit.");	return 0;	}
+	if(buf==0)	{	printf("There is no query. Exit.\n");	return 0;	}
 	str = new char[strlen(buf)+1];
 	mgl_get_value(buf,"mgl",str);
 

-- 
Packaging for mathgl



More information about the debian-science-commits mailing list