1 /***************************************************************************
2  * data_io.cpp is part of Math Graphic Library
3  * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru>       *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Lesser General Public License  as       *
7  *   published by the Free Software Foundation; either version 3 of the    *
8  *   License, or (at your option) any later version.                       *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU Lesser General Public     *
16  *   License along with this program; if not, write to the                 *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #include <ctype.h>
21 
22 #ifndef WIN32
23 #include <glob.h>
24 #endif
25 
26 #include "mgl2/data.h"
27 #include "mgl2/datac.h"
28 #include "mgl2/eval.h"
29 #include "mgl2/thread.h"
30 
31 #if MGL_HAVE_HDF5
32 //#define H5_NO_DEPRECATED_SYMBOLS
33 #define H5_USE_16_API
34 #include <hdf5.h>
35 #endif
36 #if MGL_HAVE_HDF4
37 #define intf hdf4_intf
38 #include <mfhdf.h>
39 #undef intf
40 #endif
41 
isn(char ch)42 inline bool isn(char ch)	{return ch=='\n';}
43 //-----------------------------------------------------------------------------
mgl_create_data()44 HMDT MGL_EXPORT mgl_create_data()	{	return new mglData;	}
mgl_create_data_size(long nx,long ny,long nz)45 HMDT MGL_EXPORT mgl_create_data_size(long nx, long ny, long nz){	return new mglData(nx,ny,nz);	}
mgl_create_data_file(const char * fname)46 HMDT MGL_EXPORT mgl_create_data_file(const char *fname)		{	return new mglData(fname);	}
mgl_delete_data(HMDT d)47 void MGL_EXPORT mgl_delete_data(HMDT d)	{	if(d)	delete d;	}
48 //-----------------------------------------------------------------------------
mgl_create_data_()49 uintptr_t MGL_EXPORT mgl_create_data_()
50 {	return uintptr_t(mgl_create_data());	}
mgl_create_data_size_(int * nx,int * ny,int * nz)51 uintptr_t MGL_EXPORT mgl_create_data_size_(int *nx, int *ny, int *nz)
52 {	return uintptr_t(mgl_create_data_size(*nx,*ny,*nz));	}
mgl_create_data_file_(const char * fname,int l)53 uintptr_t MGL_EXPORT mgl_create_data_file_(const char *fname,int l)
54 {	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
55 	uintptr_t r = uintptr_t(mgl_create_data_file(s));	delete []s;	return r;	}
mgl_delete_data_(uintptr_t * d)56 void MGL_EXPORT mgl_delete_data_(uintptr_t *d)
57 {	mgl_delete_data(_DT_);	}
58 //-----------------------------------------------------------------------------
mglFromStr(HMDT d,char * buf,long NX,long NY,long NZ)59 void mglFromStr(HMDT d,char *buf,long NX,long NY,long NZ)
60 {
61 	if(NX<1 || NY <1 || NZ<1)	return;
62 	mgl_data_create(d, NX,NY,NZ);
63 	const std::string loc = setlocale(LC_NUMERIC, "C");
64 	std::vector<char *> lines;
65 	std::vector<std::vector<mreal> > numbs;
66 	while(*buf && *buf<=' ')	buf++;
67 	lines.push_back(buf);
68 	for(char *s=buf; *s; s++)	if(isn(*s))
69 	{	lines.push_back(s+1);	*s = 0;	s++;	}
70 	numbs.resize(lines.size());
71 	long nl = long(lines.size());
72 #pragma omp parallel for
73 	for(long k=0;k<nl;k++)
74 	{
75 		char *b = lines[k];
76 		long nb = strlen(b);
77 		for(long j=0;j<nb;j++)
78 		{
79 			while(j<nb && b[j]<=' ')	j++;	// skip first spaces
80 			if(j>=nb)	break;
81 			if(b[j]=='#')
82 			{
83 				std::string id;
84 				if(j<nb-1 && b[j+1]=='#')	for(long i=j+2;i<nb;i++)
85 					if(b[i]>='a' && b[i]<='z')	id.push_back(b[i]);
86 				d->SetColumnId(id.c_str());
87 				break;
88 			}
89 			const char *s=b+j;
90 			while(j<nb && b[j]>' ' && b[j]!=',' && b[j]!=';')	j++;
91 			b[j]=0;
92 			numbs[k].push_back(strstr(s,"NAN")?NAN:atof(s));
93 		}
94 	}
95 	long i=0, n=NX*NY*NZ;
96 	for(long k=0;k<nl && i<n;k++)
97 	{
98 		const std::vector<mreal> &vals = numbs[k];
99 		long c = vals.size();
100 		if(c>n-i)	c = n-i;
101 		memcpy(d->a+i,&(vals[0]),c*sizeof(mreal));
102 		i += c;
103 	}
104 	setlocale(LC_NUMERIC, loc.c_str());
105 }
106 //-----------------------------------------------------------------------------
mgl_data_set(HMDT d,HCDT a)107 void MGL_EXPORT mgl_data_set(HMDT d, HCDT a)
108 {
109 	if(!a)	return;
110 //	d->temp = a->temp;	d->s = a->s;	d->func = a->func;	d->o = a->o;
111 
112 	mgl_data_create(d, a->GetNx(), a->GetNy(), a->GetNz());
113 	const mglData *dd = dynamic_cast<const mglData *>(a);	// faster for mglData
114 	if(dd)	// this one should be much faster
115 		memcpy(d->a, dd->a, d->nx*d->ny*d->nz*sizeof(mreal));
116 	else	// very inefficient!!!
117 #pragma omp parallel for collapse(3)
118 		for(long k=0;k<d->nz;k++)	for(long j=0;j<d->ny;j++)	for(long i=0;i<d->nx;i++)
119 			d->a[i+d->nx*(j+d->ny*k)] = a->v(i,j,k);
120 }
mgl_data_set_(uintptr_t * d,uintptr_t * a)121 void MGL_EXPORT mgl_data_set_(uintptr_t *d, uintptr_t *a)	{	mgl_data_set(_DT_,_DA_(a));	}
122 //-----------------------------------------------------------------------------
mgl_data_set_values(HMDT d,const char * v,long NX,long NY,long NZ)123 void MGL_EXPORT mgl_data_set_values(HMDT d, const char *v,long NX,long NY,long NZ)
124 {
125 	if(NX<1 || NY <1 || NZ<1)	return;
126 	long n=strlen(v)+1;
127 	char *buf = new char[n];
128 	memcpy(buf,v,n);
129 	mglFromStr(d,buf,NX,NY,NZ);
130 	delete []buf;
131 }
mgl_data_set_values_(uintptr_t * d,const char * val,int * nx,int * ny,int * nz,int l)132 void MGL_EXPORT mgl_data_set_values_(uintptr_t *d, const char *val, int *nx, int *ny, int *nz, int l)
133 {	char *s=new char[l+1];	memcpy(s,val,l);	s[l]=0;
134 	mgl_data_set_values(_DT_,s,*nx,*ny,*nz);	delete []s;	}
135 //-----------------------------------------------------------------------------
mgl_data_set_vector(HMDT d,gsl_vector * v)136 void MGL_EXPORT mgl_data_set_vector(HMDT d, gsl_vector *v)
137 {
138 #if MGL_HAVE_GSL
139 	if(!v || v->size<1)	return;
140 	mgl_data_create(d, v->size,1,1);
141 #pragma omp parallel for
142 	for(long i=0;i<d->nx;i++)	d->a[i] = v->data[i*v->stride];
143 #endif
144 }
145 //-----------------------------------------------------------------------------
mgl_data_set_matrix(HMDT d,gsl_matrix * m)146 void MGL_EXPORT mgl_data_set_matrix(HMDT d, gsl_matrix *m)
147 {
148 #if MGL_HAVE_GSL
149 	if(!m || m->size1<1 || m->size2<1)	return;
150 	mgl_data_create(d, m->size1,m->size2,1);
151 #pragma omp parallel for collapse(2)
152 	for(long j=0;j<d->ny;j++)	for(long i=0;i<d->nx;i++)
153 		d->a[i+j*d->nx] = m->data[i * m->tda + j];
154 #endif
155 }
156 //-----------------------------------------------------------------------------
mgl_data_set_float(HMDT d,const float * A,long NX,long NY,long NZ)157 void MGL_EXPORT mgl_data_set_float(HMDT d, const float *A,long NX,long NY,long NZ)
158 {
159 	if(NX<=0 || NY<=0 || NZ<=0)	return;
160 	mgl_data_create(d, NX,NY,NZ);	if(!A)	return;
161 #if MGL_USE_DOUBLE
162 #pragma omp parallel for
163 	for(long i=0;i<NX*NY*NZ;i++)	d->a[i] = A[i];
164 #else
165 	memcpy(d->a,A,NX*NY*NZ*sizeof(float));
166 #endif
167 }
168 //-----------------------------------------------------------------------------
mgl_data_set_double(HMDT d,const double * A,long NX,long NY,long NZ)169 void MGL_EXPORT mgl_data_set_double(HMDT d, const double *A,long NX,long NY,long NZ)
170 {
171 	if(NX<=0 || NY<=0 || NZ<=0)	return;
172 	mgl_data_create(d, NX,NY,NZ);	if(!A)	return;
173 #if MGL_USE_DOUBLE
174 	memcpy(d->a,A,NX*NY*NZ*sizeof(double));
175 #else
176 #pragma omp parallel for
177 	for(long i=0;i<NX*NY*NZ;i++)	d->a[i] = A[i];
178 #endif
179 }
180 //-----------------------------------------------------------------------------
mgl_data_set_float2(HMDT d,float const * const * A,long N1,long N2)181 void MGL_EXPORT mgl_data_set_float2(HMDT d, float const * const *A,long N1,long N2)
182 {
183 	if(N1<=0 || N2<=0)	return;
184 	mgl_data_create(d, N2,N1,1);	if(!A)	return;
185 #if MGL_USE_DOUBLE
186 #pragma omp parallel for collapse(2)
187 	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	d->a[j+i*N2] = A[i][j];
188 #else
189 #pragma omp parallel for
190 	for(long i=0;i<N1;i++)	memcpy(d->a+i*N2,A[i],N2*sizeof(float));
191 #endif
192 }
193 //-----------------------------------------------------------------------------
mgl_data_set_double2(HMDT d,double const * const * A,long N1,long N2)194 void MGL_EXPORT mgl_data_set_double2(HMDT d, double const *const *A,long N1,long N2)
195 {
196 	if(N1<=0 || N2<=0)	return;
197 	mgl_data_create(d, N2,N1,1);	if(!A)	return;
198 #if MGL_USE_DOUBLE
199 #pragma omp parallel for
200 	for(long i=0;i<N1;i++)	memcpy(d->a+i*N2,A[i],N2*sizeof(double));
201 #else
202 #pragma omp parallel for collapse(2)
203 	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	d->a[j+i*N2] = A[i][j];
204 #endif
205 }
206 //-----------------------------------------------------------------------------
mgl_data_set_float3(HMDT d,float const * const * const * A,long N1,long N2,long N3)207 void MGL_EXPORT mgl_data_set_float3(HMDT d, float const * const * const *A,long N1,long N2,long N3)
208 {
209 	if(N1<=0 || N2<=0 || N3<=0)	return;
210 	mgl_data_create(d, N3,N2,N1);	if(!A)	return;
211 #if MGL_USE_DOUBLE
212 #pragma omp parallel for collapse(3)
213 	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	for(long k=0;k<N3;k++)
214 		d->a[k+N3*(j+i*N2)] = A[i][j][k];
215 #else
216 #pragma omp parallel for collapse(2)
217 	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)
218 		memcpy(d->a+N3*(j+i*N2),A[i][j],N3*sizeof(float));
219 #endif
220 }
221 //-----------------------------------------------------------------------------
mgl_data_set_double3(HMDT d,double const * const * const * A,long N1,long N2,long N3)222 void MGL_EXPORT mgl_data_set_double3(HMDT d, double const * const * const *A,long N1,long N2,long N3)
223 {
224 	if(N1<=0 || N2<=0 || N3<=0)	return;
225 	mgl_data_create(d, N3,N2,N1);	if(!A)	return;
226 #if MGL_USE_DOUBLE
227 #pragma omp parallel for collapse(2)
228 	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)
229 		memcpy(d->a+N3*(j+i*N2),A[i][j],N3*sizeof(double));
230 #else
231 #pragma omp parallel for collapse(3)
232 	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	for(long k=0;k<N3;k++)
233 		d->a[k+N3*(j+i*N2)] = A[i][j][k];
234 #endif
235 }
236 //-----------------------------------------------------------------------------
mgl_data_set_float1_(uintptr_t * d,const float * A,int * NX)237 void MGL_EXPORT mgl_data_set_float1_(uintptr_t *d, const float *A,int *NX)
238 {	mgl_data_set_float(_DT_,A,*NX,1,1);	}
mgl_data_set_double1_(uintptr_t * d,const double * A,int * NX)239 void MGL_EXPORT mgl_data_set_double1_(uintptr_t *d, const double *A,int *NX)
240 {	mgl_data_set_double(_DT_,A,*NX,1,1);	}
mgl_data_set_float_(uintptr_t * d,const float * A,int * NX,int * NY,int * NZ)241 void MGL_EXPORT mgl_data_set_float_(uintptr_t *d, const float *A,int *NX,int *NY,int *NZ)
242 {	mgl_data_set_float(_DT_,A,*NX,*NY,*NZ);	}
mgl_data_set_double_(uintptr_t * d,const double * A,int * NX,int * NY,int * NZ)243 void MGL_EXPORT mgl_data_set_double_(uintptr_t *d, const double *A,int *NX,int *NY,int *NZ)
244 {	mgl_data_set_double(_DT_,A,*NX,*NY,*NZ);	}
mgl_data_set_float2_(uintptr_t * d,const float * A,int * N1,int * N2)245 void MGL_EXPORT mgl_data_set_float2_(uintptr_t *d, const float *A,int *N1,int *N2)
246 {	mgl_data_set_float(_DT_,A,*N1,*N2,1);	}
mgl_data_set_double2_(uintptr_t * d,const double * A,int * N1,int * N2)247 void MGL_EXPORT mgl_data_set_double2_(uintptr_t *d, const double *A,int *N1,int *N2)
248 {	mgl_data_set_double(_DT_,A,*N1,*N2,1);	}
mgl_data_set_float3_(uintptr_t * d,const float * A,int * N1,int * N2,int * N3)249 void MGL_EXPORT mgl_data_set_float3_(uintptr_t *d, const float *A,int *N1,int *N2,int *N3)
250 {	mgl_data_set_float(_DT_,A,*N1,*N2,*N3);	}
mgl_data_set_double3_(uintptr_t * d,const double * A,int * N1,int * N2,int * N3)251 void MGL_EXPORT mgl_data_set_double3_(uintptr_t *d, const double *A,int *N1,int *N2,int *N3)
252 {	mgl_data_set_double(_DT_,A,*N1,*N2,*N3);	}
253 //-----------------------------------------------------------------------------
mgl_data_rearrange(HMDT d,long mx,long my,long mz)254 void MGL_EXPORT mgl_data_rearrange(HMDT d, long mx,long my,long mz)
255 {
256 	if(mx<1)	return;	// wrong mx
257 	if(my<1)	{	my = d->nx*d->ny*d->nz/mx;	mz = 1;	}
258 	else if(mz<1)	mz = (d->nx*d->ny*d->nz)/(mx*my);
259 	long m = mx*my*mz;
260 	if(m==0 || m>d->nx*d->ny*d->nz)	return;	// too high desired dimensions
261 	d->nx = mx;	d->ny = my;	d->nz = mz;	d->NewId();
262 }
mgl_data_rearrange_(uintptr_t * d,int * mx,int * my,int * mz)263 void MGL_EXPORT mgl_data_rearrange_(uintptr_t *d, int *mx, int *my, int *mz)
264 {	mgl_data_rearrange(_DT_,*mx,*my,*mz);	}
265 //-----------------------------------------------------------------------------
mgl_data_get_id(HCDT d)266 MGL_EXPORT_PURE const char *mgl_data_get_id(HCDT d)	{	return d->id.s;	}
mgl_data_set_id(mglDataA * d,const char * ids)267 void MGL_EXPORT mgl_data_set_id(mglDataA *d, const char *ids)	{	d->id = ids;	}
mgl_data_set_id_(uintptr_t * d,const char * eq,int l)268 void MGL_EXPORT mgl_data_set_id_(uintptr_t *d, const char *eq,int l)
269 {	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
270 	mgl_data_set_id(_DT_, s);	delete []s;	}
271 //-----------------------------------------------------------------------------
mgl_data_set_name_w(mglDataA * dat,const wchar_t * name)272 void MGL_EXPORT mgl_data_set_name_w(mglDataA *dat, const wchar_t *name)
273 {	dat->s = name;	}
mgl_data_get_name_w(HCDT dat)274 MGL_EXPORT_PURE const wchar_t *mgl_data_get_name_w(HCDT dat)
275 {	return dat->s.w;	}
mgl_data_set_name(mglDataA * dat,const char * name)276 void MGL_EXPORT mgl_data_set_name(mglDataA *dat, const char *name)
277 {	MGL_TO_WCS(name,dat->Name(wcs));	}
mgl_data_set_name_(uintptr_t * d,const char * name,int l)278 void MGL_EXPORT mgl_data_set_name_(uintptr_t *d, const char *name,int l)
279 {	char *s=new char[l+1];	memcpy(s,name,l);	s[l]=0;
280 	mgl_data_set_name(_DT_,s);		delete []s;	}
mgl_data_set_func(mglDataA * dat,void (* func)(void *),void * par)281 void MGL_EXPORT mgl_data_set_func(mglDataA *dat, void (*func)(void *), void *par)
282 {	dat->func = func;	dat->o = par;	}
283 //-----------------------------------------------------------------------------
284 /// Get section separated by symbol ch. This is analog of QString::section().
mgl_str_args(const std::string & str,char ch)285 std::vector<std::string> MGL_EXPORT mgl_str_args(const std::string &str, char ch)
286 {
287 	std::vector<size_t> pos;	pos.push_back(0);
288 	for(size_t p=0; p != std::string::npos;)
289 	{	p=str.find(ch,p+1);	pos.push_back(p?p+1:0);	}
290 	std::vector<std::string> res;
291 	for(size_t i=0;i<pos.size()-1;i++)
292 		res.push_back(str.substr(pos[i],pos[i+1]-pos[i]-1));
293 	return res;
294 }
295 //-----------------------------------------------------------------------------
296 /// Get section separated by symbol ch. This is analog of QString::section().
mgl_str_arg(const std::string & str,char ch,int n1,int n2)297 std::string MGL_EXPORT mgl_str_arg(const std::string &str, char ch, int n1, int n2)
298 {
299 	std::vector<size_t> pos;	pos.push_back(0);
300 	for(size_t p=0; p != std::string::npos;)
301 	{	p=str.find(ch,p+1);	pos.push_back(p?p+1:0);	}
302 	std::string res;
303 	if(n2<0)	n2=n1;
304 	if(n1<0 || n1>=long(pos.size())-1 || n2<n1)	return res;
305 	if(n2>=long(pos.size()))	n2=pos.size()-1;
306 	res = str.substr(pos[n1],pos[n2+1]-pos[n1]-1);
307 	if(res.size()==1 && res[0]==ch)	res.clear();
308 	return res;
309 }
310 //-----------------------------------------------------------------------------
311 /// Get section separated by symbol ch. This is analog of QString::section().
mgl_wcs_args(const std::wstring & str,wchar_t ch)312 std::vector<std::wstring> MGL_EXPORT mgl_wcs_args(const std::wstring &str, wchar_t ch)
313 {
314 	std::vector<size_t> pos;	pos.push_back(0);
315 	for(size_t p=0; p != std::string::npos;)
316 	{	p=str.find(ch,p+1);	pos.push_back(p?p+1:0);	}
317 	std::vector<std::wstring> res;
318 	for(size_t i=0;i<pos.size()-1;i++)
319 		res.push_back(str.substr(pos[i],pos[i+1]-pos[i]-1));
320 	return res;
321 }
322 //-----------------------------------------------------------------------------
323 /// Get section separated by symbol ch. This is analog of QString::section().
mgl_wcs_arg(const std::wstring & str,wchar_t ch,int n1,int n2)324 std::wstring MGL_EXPORT mgl_wcs_arg(const std::wstring &str, wchar_t ch, int n1, int n2)
325 {
326 	std::vector<size_t> pos;	pos.push_back(0);
327 	for(size_t p=0; p != std::string::npos;)
328 	{	p=str.find(ch,p+1);	pos.push_back(p?p+1:0);	}
329 	std::wstring res;
330 	if(n2<0)	n2=n1;
331 	if(n1<0 || n1>=long(pos.size())-1 || n2<n1)	return res;
332 	if(n2>=long(pos.size()))	n2=pos.size()-1;
333 	res = str.substr(pos[n1],pos[n2+1]-pos[n1]-1);
334 	if(res.size()==1 && res[0]==ch)	res.clear();
335 	return res;
336 }
337 //-----------------------------------------------------------------------------
338 /// Get string from number.
mgl_str_num(double val)339 std::string MGL_EXPORT mgl_str_num(double val)
340 {	char buf[32];	snprintf(buf,32,"%g",val);	return std::string(buf);	}
mgl_str_num(dual val)341 std::string MGL_EXPORT mgl_str_num(dual val)
342 {
343 	char buf[64];
344 	double re = real(val), im = imag(val);
345 	if(re==0 && im>0)	snprintf(buf,64,"i%g",im);
346 	else if(re && im<0)	snprintf(buf,64,"-i%g",-im);
347 	else if(im>0)	snprintf(buf,64,"%g+i%g",re,im);
348 	else if(im<0)	snprintf(buf,64,"%g-i%g",re,-im);
349 	else	snprintf(buf,64,"%g",re);
350 	return std::string(buf);
351 }
352 //-----------------------------------------------------------------------------
mgl_data_to_string(HCDT d,long ns)353 std::string MGL_EXPORT mgl_data_to_string(HCDT d, long ns)
354 {
355 	long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
356 	const std::string loc = setlocale(LC_NUMERIC, "C");
357 	std::string out;
358 	if(ns<0 || (ns>=nz && nz>1))	for(long k=0;k<nz;k++)
359 	{	// save whole data
360 		std::string id = d->GetColumnId();
361 		if(!id.empty())	out += "## "+id+'\n';
362 		for(long i=0;i<ny;i++)
363 		{
364 			for(long j=0;j<nx-1;j++)	out += mgl_str_num(d->v(j,i,k))+'\t';
365 			out += mgl_str_num(d->v(nx-1,i,k))+'\n';
366 		}
367 		out += "\n";
368 	}
369 	else
370 	{	// save selected slice
371 		if(nz>1)	for(long i=0;i<ny;i++)
372 		{
373 			for(long j=0;j<nx-1;j++)	out += mgl_str_num(d->v(j,i,ns))+'\t';
374 			out += mgl_str_num(d->v(nx-1,i,ns))+'\n';
375 		}
376 		else if(ns<ny)	for(long j=0;j<nx;j++)	out += mgl_str_num(d->v(j,ns))+'\t';
377 	}
378 	setlocale(LC_NUMERIC, loc.c_str());
379 	return out;
380 }
mgl_data_save(HCDT d,const char * fname,long ns)381 void MGL_EXPORT mgl_data_save(HCDT d, const char *fname,long ns)
382 {
383 	FILE *fp = fopen(fname,"w");
384 	if(fp)	{	fprintf(fp,"%s",mgl_data_to_string(d,ns).c_str());	fclose(fp);	}
385 }
mgl_data_save_(uintptr_t * d,const char * fname,int * ns,int l)386 void MGL_EXPORT mgl_data_save_(uintptr_t *d, const char *fname,int *ns,int l)
387 {	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
388 	mgl_data_save(_DT_,s,*ns);		delete []s;	}
389 //-----------------------------------------------------------------------------
mgl_read_gz(gzFile fp)390 MGL_NO_EXPORT char *mgl_read_gz(gzFile fp)
391 {
392 	long size=1024,n=0,m;
393 	char *buf=(char*)malloc(size);
394 	while((m=gzread(fp,buf+size*n,size))>0)
395 	{
396 		if(m<size)	{	buf[size*n+m]=0;	break;	}
397 		n++;		buf=(char*)realloc(buf,size*(n+1));
398 		memset(buf+size*n,0,size);
399 	}
400 	return buf;
401 }
402 //-----------------------------------------------------------------------------
mgl_data_read_bin(HMDT dat,const char * fname,int kind)403 int MGL_EXPORT mgl_data_read_bin(HMDT dat, const char *fname, int kind)
404 {
405 	FILE *fp = fopen(fname,"rb");
406 	if(!fp)	return 0;
407 	fseek(fp,0,SEEK_END);
408 	long len=ftell(fp), n=0;	// file length, and number of elements
409 	fseek(fp,0,SEEK_SET);
410 	switch(kind)
411 	{
412 		case 0:	// double type
413 			n = len/sizeof(double);
414 			if(n>0)
415 			{
416 				double *a = new double[n];
417 				n = fread(a,sizeof(double),n,fp);
418 				dat->Create(n);
419 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
420 			}
421 			break;
422 		case 1:	// float type
423 			n = len/sizeof(float);
424 			if(n>0)
425 			{
426 				float *a = new float[n];
427 				n = fread(a,sizeof(float),n,fp);
428 				dat->Create(n);
429 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
430 			}
431 			break;
432 		case 2:	// long double type
433 			n = len/sizeof(long double);
434 			if(n>0)
435 			{
436 				long double *a = new long double[n];
437 				n = fread(a,sizeof(long double),n,fp);
438 				dat->Create(n);
439 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
440 			}
441 			break;
442 		case 3:	// long int type
443 			n = len/sizeof(long);
444 			if(n>0)
445 			{
446 				long *a = new long[n];
447 				n = fread(a,sizeof(long),n,fp);
448 				dat->Create(n);
449 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
450 			}
451 			break;
452 		case 4:	// int type
453 			n = len/sizeof(int);
454 			if(n>0)
455 			{
456 				int *a = new int[n];
457 				n = fread(a,sizeof(int),n,fp);
458 				dat->Create(n);
459 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
460 			}
461 			break;
462 		case 5:	// short int type
463 			n = len/sizeof(short);
464 			if(n>0)
465 			{
466 				short *a = new short[n];
467 				n = fread(a,sizeof(short),n,fp);
468 				dat->Create(n);
469 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
470 			}
471 			break;
472 		case 6:	// char type
473 			n = len/sizeof(char);
474 			if(n>0)
475 			{
476 				char *a = new char[n];
477 				n = fread(a,sizeof(char),n,fp);
478 				dat->Create(n);
479 				for(long i=0;i<n;i++)	dat->a[i]=a[i];
480 			}
481 			break;
482 	}
483 	return 1;
484 }
mgl_data_read_bin_(uintptr_t * d,const char * fname,int * kind,int l)485 int MGL_EXPORT mgl_data_read_bin_(uintptr_t *d, const char *fname,int *kind,int l)
486 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
487 	int r = mgl_data_read_bin(_DT_, s, *kind);	delete []s;		return r;	}
488 //-----------------------------------------------------------------------------
mgl_data_read(HMDT d,const char * fname)489 int MGL_EXPORT mgl_data_read(HMDT d, const char *fname)
490 {
491 	long l=1,m=1,k=1,i;
492 	gzFile fp = gzopen(fname,"r");
493 	if(!fp)
494 	{
495 		if(!d->a)	mgl_data_create(d, 1,1,1);
496 		return	0;
497 	}
498 	char *buf = mgl_read_gz(fp), *tbuf=buf;
499 	while(*buf && *buf<=' ')	buf++;	// remove leading spaces
500 	long nb = strlen(buf);	gzclose(fp);
501 
502 	bool first=false;
503 	for(i=nb-1;i>=0;i--)	if(buf[i]>' ')	break;
504 	buf[i+1]=0;	nb = i+1;		// remove tailing spaces
505 	for(i=0;i<nb-1 && !isn(buf[i]);i++)	// determine nx
506 	{
507 		while(buf[i]=='#')	{	while(!isn(buf[i]) && i<nb)	i++;	}
508 		char ch = buf[i];
509 		if(ch>' ' && !first)	first=true;
510 		if(first && (ch==' ' || ch=='\t' || ch==',' || ch==';') && buf[i+1]>' ') k++;
511 	}
512 	first = false;
513 	for(i=0;i<nb-1;i++)					// determine ny
514 	{
515 		char ch = buf[i];
516 		if(ch=='#')	while(!isn(buf[i]) && i<nb)	i++;
517 		if(isn(ch))
518 		{
519 			while(buf[i+1]==' ' || buf[i+1]=='\t') i++;
520 			if(isn(buf[i+1]))	{first=true;	break;	}
521 			m++;
522 		}
523 		if(ch=='\f')	break;
524 	}
525 	if(first)	for(i=0;i<nb-1;i++)		// determine nz
526 	{
527 		char ch = buf[i];
528 		if(ch=='#')	while(!isn(buf[i]) && i<nb)	i++;
529 		if(isn(ch))
530 		{
531 			while(buf[i+1]==' ' || buf[i+1]=='\t') i++;
532 			if(isn(buf[i+1]))	l++;
533 		}
534 	}
535 	else	for(i=0;i<nb-1;i++)	if(buf[i]=='\f')	l++;
536 	mglFromStr(d,buf,k,m,l);
537 	free(tbuf);	return 1;
538 }
mgl_data_read_(uintptr_t * d,const char * fname,int l)539 int MGL_EXPORT mgl_data_read_(uintptr_t *d, const char *fname,int l)
540 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
541 	int r = mgl_data_read(_DT_, s);	delete []s;		return r;	}
542 //-----------------------------------------------------------------------------
mgl_data_scan_file(HMDT d,const char * fname,const char * templ)543 int MGL_EXPORT mgl_data_scan_file(HMDT d,const char *fname, const char *templ)
544 {
545 	// first scan for all "%g"
546 	char *buf=new char[strlen(templ)+1],*s=buf;
547 	strcpy(buf,templ);
548 	std::vector<std::string> strs;
549 	for(size_t i=0;buf[i];i++)
550 	{
551 		if(buf[i]=='%' && buf[i+1]=='%')	i++;
552 		else if(buf[i]=='%' && buf[i+1]=='g')
553 		{	buf[i]=0;	strs.push_back(s);	s = buf+i+2;	}
554 	}
555 	delete []buf;
556 	if(strs.size()<1)	return 0;
557 	// read proper lines from file
558 	std::vector<const char *> bufs;
559 	gzFile fp = gzopen(fname,"r");
560 	if(!fp)
561 	{
562 		if(!d->a)	mgl_data_create(d, 1,1,1);
563 		return	0;
564 	}
565 	s = mgl_read_gz(fp);	gzclose(fp);
566 	size_t len = strs[0].length();
567 	const char *s0 = strs[0].c_str();
568 	if(!strncmp(s, s0, len))	bufs.push_back(s);
569 	for(long i=0;s[i];i++)	if(s[i]=='\n')
570 	{
571 		while(s[i+1]=='\n')	i++;
572 		s[i]=0;	i++;
573 		if(!strncmp(s+i, s0, len))	bufs.push_back(s+i);
574 		if(!s[i])	break;
575 	}
576 	// parse lines and collect data
577 	size_t nx=strs.size(), ny=bufs.size();
578 	if(ny<1)
579 	{
580 		if(!d->a)	mgl_data_create(d, 1,1,1);
581 		return	0;
582 	}
583 	d->Create(nx,ny);
584 	for(size_t j=0;j<ny;j++)
585 	{
586 		const char *c = bufs[j];
587 		for(size_t i=0;i<nx;i++)
588 		{
589 			const char *p = strstr(c,strs[i].c_str());
590 			if(!p)	break;
591 			p += strs[i].length();	c=p;
592 			d->a[i+nx*j] = atof(p);
593 		}
594 	}
595 	free(s);	return 1;
596 }
mgl_data_scan_file_(uintptr_t * d,const char * fname,const char * templ,int l,int m)597 int MGL_EXPORT mgl_data_scan_file_(uintptr_t *d,const char *fname, const char *templ,int l,int m)
598 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
599 	char *t=new char[m+1];		memcpy(t,templ,m);	t[m]=0;
600 	int r = mgl_data_scan_file(_DT_, s,t);	delete []s;	delete []t;	return r;	}
601 //-----------------------------------------------------------------------------
mgl_data_create(HMDT d,long mx,long my,long mz)602 void MGL_EXPORT mgl_data_create(HMDT d,long mx,long my,long mz)
603 {
604 	d->nx = mx>0 ? mx:1;	d->ny = my>0 ? my:1;	d->nz = mz>0 ? mz:1;
605 	if(d->a && !d->link)	delete [](d->a);
606 	d->a = new mreal[d->nx*d->ny*d->nz];
607 	d->NewId();	d->link=false;
608 	memset(d->a,0,d->nx*d->ny*d->nz*sizeof(mreal));
609 }
mgl_data_create_(uintptr_t * d,int * nx,int * ny,int * nz)610 void MGL_EXPORT mgl_data_create_(uintptr_t *d, int *nx,int *ny,int *nz)
611 {	mgl_data_create(_DT_,*nx,*ny,*nz);	}
612 //-----------------------------------------------------------------------------
mgl_data_link(HMDT d,mreal * A,long mx,long my,long mz)613 void MGL_EXPORT mgl_data_link(HMDT d, mreal *A, long mx,long my,long mz)
614 {
615 	if(!A)	return;
616 	if(!d->link && d->a)	delete [](d->a);
617 	d->nx = mx>0 ? mx:1;	d->ny = my>0 ? my:1;	d->nz = mz>0 ? mz:1;
618 	d->link=true;	d->a=A;	d->NewId();
619 }
mgl_data_link_(uintptr_t * d,mreal * A,int * nx,int * ny,int * nz)620 void MGL_EXPORT mgl_data_link_(uintptr_t *d, mreal *A, int *nx,int *ny,int *nz)
621 {	mgl_data_link(_DT_,A,*nx,*ny,*nz);	}
622 //-----------------------------------------------------------------------------
mgl_data_read_dim(HMDT d,const char * fname,long mx,long my,long mz)623 int MGL_EXPORT mgl_data_read_dim(HMDT d, const char *fname,long mx,long my,long mz)
624 {
625 	if(mx<=0 || my<=0 || mz<=0)	return 0;
626 	gzFile fp = gzopen(fname,"r");
627 	if(!fp)	return 0;
628 	char *buf = mgl_read_gz(fp);
629 	gzclose(fp);
630 	mglFromStr(d,buf,mx,my,mz);
631 	free(buf);	return 1;
632 }
mgl_data_read_dim_(uintptr_t * d,const char * fname,int * mx,int * my,int * mz,int l)633 int MGL_EXPORT mgl_data_read_dim_(uintptr_t *d, const char *fname,int *mx,int *my,int *mz,int l)
634 {	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
635 	int r = mgl_data_read_dim(_DT_,s,*mx,*my,*mz);	delete []s;	return r;	}
636 //-----------------------------------------------------------------------------
mgl_data_read_mat(HMDT d,const char * fname,long dim)637 int MGL_EXPORT mgl_data_read_mat(HMDT d, const char *fname, long dim)
638 {
639 	if(dim<=0 || dim>3)	return 0;
640 	gzFile fp = gzopen(fname,"r");
641 	if(!fp)	return 0;
642 	long nx=1, ny=1, nz=1;
643 	char *buf = mgl_read_gz(fp);
644 	long nb = strlen(buf);	gzclose(fp);
645 
646 	long j=0;
647 	if(buf[j]=='#')	while(!isn(buf[j]))	j++;	// skip comment
648 	while(j<nb && buf[j]<=' ')	j++;
649 	if(dim==1)
650 	{
651 		sscanf(buf+j,"%ld",&nx);
652 		while(j<nb && buf[j]!='\n')	j++;
653 		j++;
654 //		while(buf[j]>' ')	j++;
655 	}
656 	else if(dim==2)
657 	{
658 		sscanf(buf+j,"%ld%ld",&nx,&ny);
659 		while(j<nb && buf[j]!='\n')	j++;
660 		j++;
661 		char *b=buf+j;
662 		long l=0;
663 		for(long i=0;b[i];i++)
664 		{
665 			while(b[i]=='#')	{	while(!isn(b[i]) && b[i])	i++;	}
666 			if(b[i]=='\n')	l++;
667 		}
668 		if(l==nx*ny || l==nx*ny+1)	// try to read 3d data (i.e. columns of matrix nx*ny)
669 		{
670 			nz=ny;	ny=nx;	nx=1;	l=0;
671 			bool first = false;
672 			for(long i=0;b[i] && !isn(b[i]);i++)	// determine nx
673 			{
674 				while(b[i]=='#')	{	while(!isn(b[i]) && b[i])	i++;	}
675 				char ch = b[i];
676 				if(ch>' ' && !first)	first=true;
677 				if(first && (ch==' ' || ch=='\t' || ch==',' || ch==';') && b[i+1]>' ') nx++;
678 			}
679 		}
680 	}
681 	else if(dim==3)
682 	{
683 		sscanf(buf+j,"%ld%ld%ld",&nx,&ny,&nz);
684 		while(j<nb && buf[j]!='\n')	j++;
685 		j++;
686 /*		while(buf[j]>' ' && j<nb)	j++;
687 		while(buf[j]<=' ' && j<nb)	j++;
688 		while(buf[j]>' ' && j<nb)	j++;
689 		while(buf[j]<=' ' && j<nb)	j++;
690 		while(buf[j]>' ' && j<nb)	j++;*/
691 	}
692 	mglFromStr(d,buf+j,nx,ny,nz);
693 	free(buf);	return 1;
694 }
mgl_data_read_mat_(uintptr_t * d,const char * fname,int * dim,int l)695 int MGL_EXPORT mgl_data_read_mat_(uintptr_t *d, const char *fname,int *dim,int l)
696 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
697 	int r = mgl_data_read_mat(_DT_,s,*dim);	delete []s;	return r;	}
698 //-----------------------------------------------------------------------------
mgl_data_max(HCDT d)699 mreal MGL_EXPORT mgl_data_max(HCDT d)
700 {
701 	mreal m1=-INFINITY;
702 	long nn=d->GetNN();
703 #pragma omp parallel
704 	{
705 		mreal m=-INFINITY;
706 #pragma omp for nowait
707 		for(long i=0;i<nn;i++)
708 		{	mreal v = d->vthr(i);	m = m<v ? v:m;	}
709 #pragma omp critical(max_dat)
710 		{	m1 = m1>m ? m1:m;	}
711 	}
712 	return m1;
713 }
mgl_data_max_(uintptr_t * d)714 mreal MGL_EXPORT mgl_data_max_(uintptr_t *d)	{	return mgl_data_max(_DT_);	}
715 //-----------------------------------------------------------------------------
mgl_data_min(HCDT d)716 mreal MGL_EXPORT mgl_data_min(HCDT d)
717 {
718 	mreal m1=INFINITY;
719 	long nn=d->GetNN();
720 #pragma omp parallel
721 	{
722 		mreal m=INFINITY;
723 #pragma omp for nowait
724 		for(long i=0;i<nn;i++)
725 		{	mreal v = d->vthr(i);	m = m>v ? v:m;	}
726 #pragma omp critical(min_dat)
727 		{	m1 = m1<m ? m1:m;	}
728 	}
729 	return m1;
730 }
mgl_data_min_(uintptr_t * d)731 mreal MGL_EXPORT mgl_data_min_(uintptr_t *d)	{	return mgl_data_min(_DT_);	}
732 //-----------------------------------------------------------------------------
mgl_data_neg_max(HCDT d)733 mreal MGL_EXPORT mgl_data_neg_max(HCDT d)
734 {
735 	mreal m1=0;
736 	long nn=d->GetNN();
737 #pragma omp parallel
738 	{
739 		mreal m=0;
740 #pragma omp for nowait
741 		for(long i=0;i<nn;i++)
742 		{	mreal v = d->vthr(i);	m = m<v && v<0 ? v:m;	}
743 #pragma omp critical(nmax_dat)
744 		{	m1 = m1>m ? m1:m;	}
745 	}
746 	return m1;
747 }
mgl_data_neg_max_(uintptr_t * d)748 mreal MGL_EXPORT mgl_data_neg_max_(uintptr_t *d)	{	return mgl_data_neg_max(_DT_);	}
749 //-----------------------------------------------------------------------------
mgl_data_pos_min(HCDT d)750 mreal MGL_EXPORT mgl_data_pos_min(HCDT d)
751 {
752 	mreal m1=INFINITY;
753 	long nn=d->GetNN();
754 #pragma omp parallel
755 	{
756 		mreal m=INFINITY;
757 #pragma omp for nowait
758 		for(long i=0;i<nn;i++)
759 		{	mreal v = d->vthr(i);	m = m>v && v>0 ? v:m;	}
760 #pragma omp critical(pmin_dat)
761 		{	m1 = m1<m ? m1:m;	}
762 	}
763 	return m1;
764 }
mgl_data_pos_min_(uintptr_t * d)765 mreal MGL_EXPORT mgl_data_pos_min_(uintptr_t *d)	{	return mgl_data_pos_min(_DT_);	}
766 //-----------------------------------------------------------------------------
mgl_data_max_int(HCDT d,long * i,long * j,long * k)767 mreal MGL_EXPORT mgl_data_max_int(HCDT d, long *i, long *j, long *k)
768 {
769 	mreal m1=-INFINITY;
770 	long nx=d->GetNx(), ny=d->GetNy(), nn=d->GetNN();
771 #pragma omp parallel
772 	{
773 		mreal m=-INFINITY;
774 		long im=-1,jm=-1,km=-1;
775 #pragma omp for nowait
776 		for(long ii=0;ii<nn;ii++)
777 		{
778 			mreal v = d->vthr(ii);
779 			if(m < v)
780 			{	m=v;	im=ii%nx;	jm=(ii/nx)%ny;	km=ii/(nx*ny);   }
781 		}
782 #pragma omp critical(max_int)
783 		if(m1 < m)	{	m1=m;	*i=im;	*j=jm;	*k=km;   }
784 	}
785 	return m1;
786 }
mgl_data_max_int_(uintptr_t * d,int * i,int * j,int * k)787 mreal MGL_EXPORT mgl_data_max_int_(uintptr_t *d, int *i, int *j, int *k)
788 {	long ii,jj,kk;	mreal res=mgl_data_max_int(_DT_,&ii,&jj,&kk);
789 	*i=ii;	*j=jj;	*k=kk;	return res;	}
790 //-----------------------------------------------------------------------------
mgl_data_min_int(HCDT d,long * i,long * j,long * k)791 mreal MGL_EXPORT mgl_data_min_int(HCDT d, long *i, long *j, long *k)
792 {
793 	mreal m1=INFINITY;
794 	long nx=d->GetNx(), ny=d->GetNy(), nn=d->GetNN();
795 #pragma omp parallel
796 	{
797 		mreal m=INFINITY;
798 		long im=-1,jm=-1,km=-1;
799 #pragma omp for nowait
800 		for(long ii=0;ii<nn;ii++)
801 		{
802 			mreal v = d->vthr(ii);
803 			if(m > v)
804 			{	m=v;	im=ii%nx;	jm=(ii/nx)%ny;	km=ii/(nx*ny);   }
805 		}
806 #pragma omp critical(min_int)
807 		if(m1 > m)	{	m1=m;	*i=im;	*j=jm;	*k=km;   }
808 	}
809 	return m1;
810 }
mgl_data_min_int_(uintptr_t * d,int * i,int * j,int * k)811 mreal MGL_EXPORT mgl_data_min_int_(uintptr_t *d, int *i, int *j, int *k)
812 {	long ii,jj,kk;	mreal res=mgl_data_min_int(_DT_,&ii,&jj,&kk);
813 	*i=ii;	*j=jj;	*k=kk;	return res;	}
814 //-----------------------------------------------------------------------------
mgl_data_max_first(HCDT d,char dir,long from,long * p1,long * p2)815 long MGL_EXPORT mgl_data_max_first(HCDT d, char dir, long from, long *p1, long *p2)
816 {
817 	long n=d->GetNx(), n1=d->GetNy(), n2=d->GetNz(), d1=n, d2=n*n1, dd=1;
818 	if(dir=='y')	{	n=n1;	n1=dd=d1;	d1=1;	}
819 	if(dir=='z')	{	n=n2;	n2=n1;	n1=d1;	d1=1;	dd=d2;	d2=n2;	}
820 	bool find=false;
821 	if(from>=0)
822 	{
823 		for(long i=from+1;i<n-1;i++)
824 		{
825 #pragma omp parallel for collapse(2)
826 			for(long i1=0;i1<n1;i1++)	for(long i2=0;i2<n2;i2++)
827 			{
828 				long ii=i*dd+i1*d1+i2*d2;
829 				if(d->vthr(ii)>=d->vthr(ii+dd) && d->vthr(ii)>=d->vthr(ii-dd))
830 				{	find=true;	if(p1)	*p1=i1;	if(p2)	*p2=i2;	}
831 			}
832 			if(find)	return i;
833 		}
834 	}
835 	else
836 	{
837 		for(long i=n+from-1;i>0;i--)
838 		{
839 			for(long i1=0;i1<n1;i1++)	for(long i2=0;i2<n2;i2++)
840 			{
841 				long ii=i*dd+i1*d1+i2*d2;
842 				if(d->vthr(ii)>=d->vthr(ii+dd) && d->vthr(ii)>=d->vthr(ii-dd))
843 				{	find=true;	if(p1)	*p1=i1;	if(p2)	*p2=i2;	}
844 			}
845 			if(find)	return i;
846 		}
847 	}
848 	return -1;
849 }
mgl_data_max_first_(uintptr_t * d,const char * dir,long * from,long * p1,long * p2,int)850 long MGL_EXPORT mgl_data_max_first_(uintptr_t *d, const char *dir, long *from, long *p1, long *p2,int)
851 {	return mgl_data_max_first(_DT_,*dir,*from,p1,p2);	}
852 //-----------------------------------------------------------------------------
mgl_data_max_real(HCDT d,mreal * x,mreal * y,mreal * z)853 mreal MGL_EXPORT mgl_data_max_real(HCDT d, mreal *x, mreal *y, mreal *z)
854 {
855 	long im=-1,jm=-1,km=-1;
856 	long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
857 	mreal m=mgl_data_max_int(d,&im,&jm,&km), v, v1, v2;
858 	*x=im;	*y=jm;	*z=km;
859 
860 	v = d->v(im,jm,km);
861 	if(nx>2)
862 	{
863 		if(im==0)	im=1;
864 		if(im==nx-1)im=nx-2;
865 		v1 = d->v(im+1,jm,km);	v2 = d->v(im-1,jm,km);
866 		*x = (v1+v2-2*v)==0 ? im : im+(v2-v1)/(v1+v2-2*v)/2;
867 	}
868 	if(ny>2)
869 	{
870 		if(jm==0)	jm=1;
871 		if(jm==ny-1)jm=ny-2;
872 		v1 = d->v(im,jm+1,km);	v2 = d->v(im,jm-1,km);
873 		*y = (v1+v2-2*v)==0 ? jm : jm+(v2-v1)/(v1+v2-2*v)/2;
874 	}
875 	if(nz>2)
876 	{
877 		if(km==0)	km=1;
878 		if(km==nz-1)km=nz-2;
879 		v1 = d->v(im,jm,km+1);	v2 = d->v(im,jm,km-1);
880 		*z = (v1+v2-2*v)==0 ? km : km+(v2-v1)/(v1+v2-2*v)/2;
881 	}
882 	return m;
883 }
mgl_data_max_real_(uintptr_t * d,mreal * x,mreal * y,mreal * z)884 mreal MGL_EXPORT mgl_data_max_real_(uintptr_t *d, mreal *x, mreal *y, mreal *z)
885 {	return mgl_data_max_real(_DT_,x,y,z);	}
886 //-----------------------------------------------------------------------------
mgl_data_min_real(HCDT d,mreal * x,mreal * y,mreal * z)887 mreal MGL_EXPORT mgl_data_min_real(HCDT d, mreal *x, mreal *y, mreal *z)
888 {
889 	long im=-1,jm=-1,km=-1;
890 	long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
891 	mreal m=mgl_data_min_int(d,&im,&jm,&km), v, v1, v2;
892 	*x=im;	*y=jm;	*z=km;
893 
894 	v = d->v(im,jm,km);
895 	if(nx>2)
896 	{
897 		if(im==0)	im=1;
898 		if(im==nx-1)im=nx-2;
899 		v1 = d->v(im+1,jm,km);	v2 = d->v(im-1,jm,km);
900 		*x = (v1+v2-2*v)==0 ? im : im+(v2-v1)/(v1+v2-2*v)/2;
901 	}
902 	if(ny>2)
903 	{
904 		if(jm==0)	jm=1;
905 		if(jm==ny-1)jm=ny-2;
906 		v1 = d->v(im,jm+1,km);	v2 = d->v(im,jm-1,km);
907 		*y = (v1+v2-2*v)==0 ? jm : jm+(v2-v1)/(v1+v2-2*v)/2;
908 	}
909 	if(nz>2)
910 	{
911 		if(km==0)	km=1;
912 		if(km==nz-1)km=nz-2;
913 		v1 = d->v(im,jm,km+1);	v2 = d->v(im,jm,km-1);
914 		*z = (v1+v2-2*v)==0 ? km : km+(v2-v1)/(v1+v2-2*v)/2;
915 	}
916 	return m;
917 }
mgl_data_min_real_(uintptr_t * d,mreal * x,mreal * y,mreal * z)918 mreal MGL_EXPORT mgl_data_min_real_(uintptr_t *d, mreal *x, mreal *y, mreal *z)
919 {	return mgl_data_min_real(_DT_,x,y,z);	}
920 //-----------------------------------------------------------------------------
mgl_data_fill(HMDT d,mreal x1,mreal x2,char dir)921 void MGL_EXPORT mgl_data_fill(HMDT d, mreal x1,mreal x2,char dir)
922 {
923 	if(mgl_isnan(x2))	x2=x1;
924 	if(dir<'x' || dir>'z')	dir='x';
925 	long nx=d->nx,ny=d->ny,nz=d->nz;
926 	if(dir=='x')
927 	{
928 		mreal dx = d->nx>1 ? (x2-x1)/(d->nx-1):0;
929 #pragma omp parallel for collapse(2)
930 		for(long j=0;j<ny*nz;j++)	for(long i=1;i<nx;i++)	d->a[i+nx*j] = x1+dx*i;
931 #pragma omp parallel for
932 		for(long j=0;j<ny*nz;j++)	d->a[nx*j] = x1;
933 	}
934 	if(dir=='y')
935 	{
936 		mreal dx = d->ny>1 ? (x2-x1)/(d->ny-1):0;
937 #pragma omp parallel for collapse(3)
938 		for(long k=0;k<nz;k++)	for(long j=1;j<ny;j++)	for(long i=0;i<nx;i++)	d->a[i+nx*(j+ny*k)] = x1+dx*j;
939 #pragma omp parallel for collapse(2)
940 		for(long j=0;j<nz;j++)	for(long i=0;i<nx;i++)	d->a[i+nx*ny*j] = x1;
941 	}
942 	if(dir=='z')
943 	{
944 		mreal dx = d->nz>1 ? (x2-x1)/(d->nz-1):0;
945 #pragma omp parallel for collapse(2)
946 		for(long j=1;j<nz;j++)	for(long i=0;i<nx*ny;i++)	d->a[i+nx*ny*j] = x1+dx*j;
947 #pragma omp parallel for
948 		for(long j=0;j<nx*ny;j++)	d->a[j] = x1;
949 	}
950 }
mgl_data_fill_(uintptr_t * d,mreal * x1,mreal * x2,const char * dir,int)951 void MGL_EXPORT mgl_data_fill_(uintptr_t *d, mreal *x1,mreal *x2,const char *dir,int)
952 {	mgl_data_fill(_DT_,*x1,*x2,*dir);	}
953 //-----------------------------------------------------------------------------
mgl_data_norm(HMDT d,mreal v1,mreal v2,int sym,long dim)954 void MGL_EXPORT mgl_data_norm(HMDT d, mreal v1,mreal v2,int sym,long dim)
955 {
956 	long s,nn=d->nx*d->ny*d->nz;
957 	mreal a1=INFINITY,a2=-INFINITY,v,*a=d->a;
958 	s = dim*d->ny*(d->nz>1 ? d->nx : 1);
959 	for(long i=s;i<nn;i++)	// determines borders of existing data
960 	{	a1 = a1>a[i] ? a[i]:a1;	a2 = a2<a[i] ? a[i]:a2;	}
961 	if(a1==a2)  {  if(a1!=0)	a1=0.;  else a2=1;  }
962 	if(v1>v2)	{	v=v1;	v1=v2;	v2=v;	}	// swap if uncorrect
963 	if(sym)				// use symmetric
964 	{
965 		v2 = -v1>v2 ? -v1:v2;	v1 = -v2;
966 		a2 = -a1>a2 ? -a1:a2;	a1 = -a2;
967 	}
968 	v2 = (v2-v1)/(a2-a1);	v1 = v1-a1*v2;
969 #pragma omp parallel for
970 	for(long i=s;i<nn;i++)	a[i] = v1 + v2*a[i];
971 }
mgl_data_norm_(uintptr_t * d,mreal * v1,mreal * v2,int * sym,int * dim)972 void MGL_EXPORT mgl_data_norm_(uintptr_t *d, mreal *v1,mreal *v2,int *sym,int *dim)
973 {	mgl_data_norm(_DT_,*v1,*v2,*sym,*dim);	}
974 //-----------------------------------------------------------------------------
mgl_data_squeeze(HMDT d,long rx,long ry,long rz,long smooth)975 void MGL_EXPORT mgl_data_squeeze(HMDT d, long rx,long ry,long rz,long smooth)
976 {
977 	long kx,ky,kz, nx=d->nx, ny=d->ny, nz=d->nz;
978 	mreal *b;
979 
980 	// simple checking
981 	if(rx>=nx)	rx=nx-1;
982 	if(rx<1)	rx=1;
983 	if(ry>=ny)	ry=ny-1;
984 	if(ry<1)	ry=1;
985 	if(rz>=nz)	rz=nz-1;
986 	if(rz<1)	rz=1;
987 	// new sizes
988 	kx = 1+(nx-1)/rx;	ky = 1+(ny-1)/ry;	kz = 1+(nz-1)/rz;
989 	b = new mreal[kx*ky*kz];
990 	if(!smooth)
991 #pragma omp parallel for collapse(3)
992 		for(long k=0;k<kz;k++)	for(long j=0;j<ky;j++)	for(long i=0;i<kx;i++)
993 			b[i+kx*(j+ky*k)] = d->a[i*rx+nx*(j*ry+ny*rz*k)];
994 	else
995 #pragma omp parallel for collapse(3)
996 		for(long k=0;k<kz;k++)	for(long j=0;j<ky;j++)	for(long i=0;i<kx;i++)
997 		{
998 			long dx,dy,dz,i1,j1,k1;
999 			dx = (i+1)*rx<=nx ? rx : nx-i*rx;
1000 			dy = (j+1)*ry<=ny ? ry : ny-j*ry;
1001 			dz = (k+1)*rz<=nz ? rz : nz-k*rz;
1002 			mreal s = 0;
1003 			for(k1=k*rz;k1<k*rz+dz;k1++)	for(j1=j*ry;j1<j*ry+dz;j1++)	for(i1=i*rx;i1<i*rx+dx;i1++)
1004 				s += d->a[i1+nx*(j1+ny*k1)];
1005 			b[i+kx*(j+ky*k)] = s/(dx*dy*dz);
1006 		}
1007 	if(!d->link)	delete [](d->a);
1008 	d->a=b;	d->nx = kx;  d->ny = ky;  d->nz = kz;	d->NewId();	d->link=false;
1009 }
mgl_data_squeeze_(uintptr_t * d,int * rx,int * ry,int * rz,int * smooth)1010 void MGL_EXPORT mgl_data_squeeze_(uintptr_t *d, int *rx,int *ry,int *rz,int *smooth)
1011 {	mgl_data_squeeze(_DT_,*rx,*ry,*rz,*smooth);	}
1012 //-----------------------------------------------------------------------------
mgl_data_extend(HMDT d,long n1,long n2)1013 void MGL_EXPORT mgl_data_extend(HMDT d, long n1, long n2)
1014 {
1015 	long nx=d->nx, ny=d->ny, nz=d->nz;
1016 	if(nz>2 || n1==0)	return;
1017 	long mx, my, mz;
1018 	mreal *b=0;
1019 	if(n1>0) // extend to higher dimension(s)
1020 	{
1021 		n2 = n2>0 ? n2:1;
1022 		mx = nx;	my = ny>1?ny:n1;	mz = ny>1 ? n1 : n2;
1023 		b = new mreal[mx*my*mz];
1024 		if(ny>1)
1025 #pragma omp parallel for
1026 			for(long i=0;i<n1;i++)	memcpy(b+i*nx*ny, d->a, nx*ny*sizeof(mreal));
1027 		else
1028 #pragma omp parallel for
1029 			for(long i=0;i<n1*n2;i++)	memcpy(b+i*nx, d->a, nx*sizeof(mreal));
1030 	}
1031 	else
1032 	{
1033 		mx = -n1;	my = n2<0 ? -n2 : nx;	mz = n2<0 ? nx : ny;
1034 		if(n2>0 && ny==1)	mz = n2;
1035 		b = new mreal[mx*my*mz];
1036 		if(n2<0)
1037 #pragma omp parallel for collapse(2)
1038 			for(long j=0;j<nx;j++)	for(long i=0;i<mx*my;i++)
1039 				b[i+mx*my*j] = d->a[j];
1040 		else
1041 #pragma omp parallel for collapse(2)
1042 			for(long j=0;j<nx*ny;j++)	for(long i=0;i<mx;i++)
1043 				b[i+mx*j] = d->a[j];
1044 		if(n2>0 && ny==1)
1045 #pragma omp parallel for
1046 			for(long i=0;i<n2;i++)
1047 				memcpy(b+i*mx*my, d->a, mx*my*sizeof(mreal));
1048 	}
1049 	if(!d->link)	delete [](d->a);
1050 	d->a=b;	d->nx=mx;	d->ny=my;	d->nz=mz;
1051 	d->NewId();		d->link=false;
1052 }
mgl_data_extend_(uintptr_t * d,int * n1,int * n2)1053 void MGL_EXPORT mgl_data_extend_(uintptr_t *d, int *n1, int *n2)
1054 {	mgl_data_extend(_DT_,*n1,*n2);	}
1055 //-----------------------------------------------------------------------------
mgl_data_transpose(HMDT d,const char * dim)1056 void MGL_EXPORT mgl_data_transpose(HMDT d, const char *dim)
1057 {
1058 	long nx=d->nx, ny=d->ny, nz=d->nz, n;
1059 	mreal *b=new mreal[nx*ny*nz], *a=d->a;
1060 	if(!strcmp(dim,"xzy") || !strcmp(dim,"zy"))
1061 	{
1062 #pragma omp parallel for collapse(3)
1063 		for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
1064 			b[i+nx*(k+nz*j)] = a[i+nx*(j+ny*k)];
1065 		n=nz;	nz=ny;	ny=n;
1066 	}
1067 	else if(!strcmp(dim,"yxz") || !strcmp(dim,"yx"))
1068 	{
1069 #pragma omp parallel for collapse(3)
1070 		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
1071 			b[j+ny*(i+nx*k)] = a[i+nx*(j+ny*k)];
1072 		n=nx;	nx=ny;	ny=n;
1073 	}
1074 	else if(!strcmp(dim,"yzx"))
1075 	{
1076 #pragma omp parallel for collapse(3)
1077 		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
1078 			b[j+ny*(k+nz*i)] = a[i+nx*(j+ny*k)];
1079 		n=nx;	nx=ny;	ny=nz;	nz=n;
1080 	}
1081 	else if(!strcmp(dim,"zxy"))
1082 	{
1083 #pragma omp parallel for collapse(3)
1084 		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)
1085 			b[k+nz*(i+nx*j)] = a[i+nx*(j+ny*k)];
1086 		n=nx;	nx=nz;	nz=ny;	ny=n;
1087 	}
1088 	else if(!strcmp(dim,"zyx") || !strcmp(dim,"zx"))
1089 	{
1090 #pragma omp parallel for collapse(3)
1091 		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)
1092 			b[k+nz*(j+ny*i)] = a[i+nx*(j+ny*k)];
1093 		n=nz;	nz=nx;	nx=n;
1094 	}
1095 	else	memcpy(b,a,nx*ny*nz*sizeof(mreal));
1096 	memcpy(a,b,nx*ny*nz*sizeof(mreal));	delete []b;
1097 	n=d->nx;	d->nx=nx;	d->ny=ny;	d->nz=nz;
1098 	if(nx!=n)	d->NewId();
1099 }
mgl_data_transpose_(uintptr_t * d,const char * dim,int l)1100 void MGL_EXPORT mgl_data_transpose_(uintptr_t *d, const char *dim,int l)
1101 {	char *s=new char[l+1];	memcpy(s,dim,l);	s[l]=0;
1102 	mgl_data_transpose(_DT_,s);	delete []s;	}
1103 //-----------------------------------------------------------------------------
mgl_modify(void * par)1104 static void *mgl_modify(void *par)
1105 {
1106 	mglThreadD *t=(mglThreadD *)par;
1107 	const mglFormula *f = (const mglFormula *)(t->v);
1108 	long nx=t->p[0],ny=t->p[1],nz=t->p[2];
1109 	mreal *b=t->a, dx,dy,dz;
1110 	const mreal *v=t->b, *w=t->c;
1111 	dx=nx>1?1/(nx-1.):0;	dy=ny>1?1/(ny-1.):0;	dz=nz>1?1/(nz-1.):0;
1112 #if !MGL_HAVE_PTHREAD
1113 #pragma omp parallel for
1114 #endif
1115 	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
1116 	{
1117 		long i=i0%nx, j=((i0/nx)%ny), k=i0/(nx*ny);
1118 		b[i0] = f->Calc(i*dx, j*dy, k*dz, b[i0], v?v[i0]:0, w?w[i0]:0);
1119 	}
1120 	return 0;
1121 }
mgl_data_modify(HMDT d,const char * eq,long dim)1122 void MGL_EXPORT mgl_data_modify(HMDT d, const char *eq,long dim)
1123 {
1124 	long nx=d->nx, ny=d->ny, nz=d->nz, par[3]={nx,ny,nz};
1125 	if(dim<=0)	mgl_data_modify_vw(d,eq,0,0);	// fastest variant for whole array
1126 	else if(nz>1)	// 3D array
1127 	{
1128 		mglFormula f(eq);
1129 		par[2] -= dim;	if(par[2]<0)	par[2]=0;
1130 		mglStartThread(mgl_modify,0,nx*ny*par[2],d->a+nx*ny*dim,0,0,par,&f);
1131 	}
1132 	else		// 2D or 1D array
1133 	{
1134 		mglFormula f(eq);
1135 		par[1] -= dim;	if(par[1]<0)	par[1]=0;
1136 		mglStartThread(mgl_modify,0,nx*par[1],d->a+nx*dim,0,0,par,&f);
1137 	}
1138 }
mgl_data_modify_(uintptr_t * d,const char * eq,int * dim,int l)1139 void MGL_EXPORT mgl_data_modify_(uintptr_t *d, const char *eq,int *dim,int l)
1140 {	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
1141 	mgl_data_modify(_DT_,s,*dim);	delete []s;	}
1142 //-----------------------------------------------------------------------------
mgl_data_modify_vw(HMDT d,const char * eq,HCDT vdat,HCDT wdat)1143 void MGL_EXPORT mgl_data_modify_vw(HMDT d, const char *eq,HCDT vdat,HCDT wdat)
1144 {
1145 	std::wstring s=d->Name();	d->Name(L"u");
1146 	mglDataV x(d->nx,d->ny,d->nz, 0,1,'x');	x.Name(L"x");
1147 	mglDataV y(d->nx,d->ny,d->nz, 0,1,'y');	y.Name(L"y");
1148 	mglDataV z(d->nx,d->ny,d->nz, 0,1,'z');	z.Name(L"z");
1149 	mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x');	i.Name(L"i");
1150 	mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y');	j.Name(L"j");
1151 	mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z');	k.Name(L"k");
1152 	mglDataV r(d->nx,d->ny,d->nz);	r.Name(L"#$mgl");
1153 	mglData v(vdat), w(wdat);	v.Name(L"v");	w.Name(L"w");
1154 	std::vector<mglDataA*> list;
1155 	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(d);
1156 	list.push_back(&v);	list.push_back(&w);	list.push_back(&r);
1157 	list.push_back(&i);	list.push_back(&j);	list.push_back(&k);
1158 	d->Move(mglFormulaCalc(eq,list));	d->Name(s.c_str());
1159 }
mgl_data_modify_vw_(uintptr_t * d,const char * eq,uintptr_t * v,uintptr_t * w,int l)1160 void MGL_EXPORT mgl_data_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l)
1161 {	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
1162 	mgl_data_modify_vw(_DT_,s,_DA_(v),_DA_(w));	delete []s;	}
1163 //-----------------------------------------------------------------------------
1164 #if MGL_HAVE_HDF4
mgl_data_read_hdf4(HMDT d,const char * fname,const char * data)1165 int MGL_EXPORT mgl_data_read_hdf4(HMDT d,const char *fname,const char *data)
1166 {
1167 	int32 sd = SDstart(fname,DFACC_READ), nn, i;
1168 	if(sd==-1)	return 0;	// is not a HDF4 file
1169 	char name[64];
1170 	SDfileinfo(sd,&nn,&i);
1171 	for(i=0;i<nn;i++)
1172 	{
1173 		int32 sds, rank, dims[32], type, attr, in[2]={0,0};
1174 		sds = SDselect(sd,i);
1175 		SDgetinfo(sds,name,&rank,dims,&type,&attr);
1176 		if(!strcmp(name,data))	// as I understand there are possible many datas with the same name
1177 		{
1178 			if(rank==1)			{	dims[2]=dims[0];	dims[0]=dims[1]=1;	}
1179 			else if(rank==2)	{	dims[2]=dims[1];	dims[1]=dims[0];	dims[0]=1;	}
1180 //			else if(rank>3)		continue;
1181 			long mm=dims[0]*dims[1]*dims[2];
1182 			if(type==DFNT_FLOAT32)
1183 			{
1184 				float *b = new float[mm];
1185 				SDreaddata(sds,in,0,dims,b);
1186 				mgl_data_set_float(d,b,dims[2],dims[1],dims[0]);
1187 				delete []b;
1188 			}
1189 			if(type==DFNT_FLOAT64)
1190 			{
1191 				double *b = new double[mm];
1192 				SDreaddata(sds,in,0,dims,b);
1193 				mgl_data_set_double(d,b,dims[2],dims[1],dims[0]);
1194 				delete []b;
1195 			}
1196 		}
1197 		SDendaccess(sds);
1198 	}
1199 	SDend(sd);
1200 	return 1;
1201 }
1202 #else
mgl_data_read_hdf4(HMDT,const char *,const char *)1203 int MGL_EXPORT mgl_data_read_hdf4(HMDT ,const char *,const char *)
1204 {	mgl_set_global_warn(_("HDF4 support was disabled. Please, enable it and rebuild MathGL."));	return 0;	}
1205 #endif
1206 //-----------------------------------------------------------------------------
1207 #if MGL_HAVE_HDF5
mgl_dual_save_hdf(mdual val,const char * fname,const char * data,int rewrite)1208 void MGL_EXPORT mgl_dual_save_hdf(mdual val,const char *fname,const char *data,int rewrite)
1209 {
1210 	hid_t hf,hd,hs;
1211 	hsize_t dims[4]={1,2};
1212 	long rank = 2, res;
1213 	H5Eset_auto(0,0);
1214 	res=H5Fis_hdf5(fname);
1215 	if(res>0 && !rewrite)	hf = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
1216 	else	hf = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
1217 	if(hf<0)	return;
1218 	hs = H5Screate_simple(rank, dims, 0);
1219 #if MGL_USE_DOUBLE
1220 	hid_t mem_type_id = H5T_NATIVE_DOUBLE;
1221 #else
1222 	hid_t mem_type_id = H5T_NATIVE_FLOAT;
1223 #endif
1224 	hd = H5Dcreate(hf, data, mem_type_id, hs, H5P_DEFAULT);
1225 	H5Dwrite(hd, mem_type_id, hs, hs, H5P_DEFAULT, &val);
1226 	H5Dclose(hd);	H5Sclose(hs);	H5Fclose(hf);
1227 }
1228 //-----------------------------------------------------------------------------
mgl_real_save_hdf(double val,const char * fname,const char * data,int rewrite)1229 void MGL_EXPORT mgl_real_save_hdf(double val,const char *fname,const char *data,int rewrite)
1230 {
1231 	hid_t hf,hd,hs;
1232 	hsize_t dims[3]={1,1,1};
1233 	long rank = 1, res;
1234 	H5Eset_auto(0,0);
1235 	res=H5Fis_hdf5(fname);
1236 	if(res>0 && !rewrite)	hf = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
1237 	else	hf = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
1238 	if(hf<0)	return;
1239 	hs = H5Screate_simple(rank, dims, 0);
1240 	hid_t mem_type_id = H5T_NATIVE_DOUBLE;
1241 	hd = H5Dcreate(hf, data, mem_type_id, hs, H5P_DEFAULT);
1242 	H5Dwrite(hd, mem_type_id, hs, hs, H5P_DEFAULT, &val);
1243 	H5Dclose(hd);	H5Sclose(hs);	H5Fclose(hf);
1244 }
1245 //-----------------------------------------------------------------------------
mgl_int_save_hdf(long val,const char * fname,const char * data,int rewrite)1246 void MGL_EXPORT mgl_int_save_hdf(long val,const char *fname,const char *data,int rewrite)
1247 {
1248 	hid_t hf,hd,hs;
1249 	hsize_t dims[3]={1,1,1};
1250 	long rank = 1, res;
1251 	H5Eset_auto(0,0);
1252 	res=H5Fis_hdf5(fname);
1253 	if(res>0 && !rewrite)	hf = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
1254 	else	hf = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
1255 	if(hf<0)	return;
1256 	hs = H5Screate_simple(rank, dims, 0);
1257 	hid_t mem_type_id = H5T_NATIVE_LONG;
1258 	hd = H5Dcreate(hf, data, mem_type_id, hs, H5P_DEFAULT);
1259 	H5Dwrite(hd, mem_type_id, hs, hs, H5P_DEFAULT, &val);
1260 	H5Dclose(hd);	H5Sclose(hs);	H5Fclose(hf);
1261 }
1262 //-----------------------------------------------------------------------------
mgl_data_save_hdf(HCDT dat,const char * fname,const char * data,int rewrite)1263 void MGL_EXPORT mgl_data_save_hdf(HCDT dat,const char *fname,const char *data,int rewrite)
1264 {
1265 	const mglData *d = dynamic_cast<const mglData *>(dat);	// NOTE: slow for non-mglData
1266 	if(!d)	{	mglData d(dat);	mgl_data_save_hdf(&d,fname,data,rewrite);	return;	}
1267 	hid_t hf,hd,hs;
1268 	hsize_t dims[3];
1269 	long rank = 3, res;
1270 	H5Eset_auto(0,0);
1271 	res=H5Fis_hdf5(fname);
1272 	if(res>0 && !rewrite)	hf = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
1273 	else	hf = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
1274 	if(hf<0)	return;
1275 	if(d->nz==1 && d->ny == 1)	{	rank=1;	dims[0]=d->nx;	}
1276 	else if(d->nz==1)	{	rank=2;	dims[0]=d->ny;	dims[1]=d->nx;	}
1277 	else	{	rank=3;	dims[0]=d->nz;	dims[1]=d->ny;	dims[2]=d->nx;	}
1278 	hs = H5Screate_simple(rank, dims, 0);
1279 #if MGL_USE_DOUBLE
1280 	hid_t mem_type_id = H5T_NATIVE_DOUBLE;
1281 #else
1282 	hid_t mem_type_id = H5T_NATIVE_FLOAT;
1283 #endif
1284 	hd = H5Dcreate(hf, data, mem_type_id, hs, H5P_DEFAULT);
1285 	H5Dwrite(hd, mem_type_id, hs, hs, H5P_DEFAULT, d->a);
1286 	H5Dclose(hd);	H5Sclose(hs);	H5Fclose(hf);
1287 }
1288 //-----------------------------------------------------------------------------
mgl_data_read_hdf(HMDT d,const char * fname,const char * data)1289 int MGL_EXPORT mgl_data_read_hdf(HMDT d,const char *fname,const char *data)
1290 {
1291 	hid_t hf,hd,hs;
1292 	long rank, res = H5Fis_hdf5(fname);
1293 	if(res<=0)	return mgl_data_read_hdf4(d,fname,data);
1294 	hf = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
1295 	if(hf<0)	return 0;
1296 	hd = H5Dopen(hf,data);
1297 	if(hd<0)	{	H5Fclose(hf);	return 0;	}
1298 	hs = H5Dget_space(hd);
1299 	if(hs<0)	{	H5Dclose(hd);	H5Fclose(hf);	return 0;	}
1300 	rank = H5Sget_simple_extent_ndims(hs);
1301 	if(rank>0 && rank<=3)
1302 	{
1303 		hsize_t dims[3];
1304 		H5Sget_simple_extent_dims(hs,dims,0);
1305 		if(rank==1)			{	dims[2]=dims[0];	dims[0]=dims[1]=1;	}
1306 		else if(rank==2)	{	dims[2]=dims[1];	dims[1]=dims[0];	dims[0]=1;	}
1307 //		else if(rank>3)		continue;
1308 		mgl_data_create(d,dims[2],dims[1],dims[0]);
1309 #if MGL_USE_DOUBLE
1310 		H5Dread(hd, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, d->a);
1311 #else
1312 		H5Dread(hd, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, d->a);
1313 #endif
1314 	}
1315 	H5Sclose(hs);	H5Dclose(hd);	H5Fclose(hf);	return 1;
1316 }
1317 //-----------------------------------------------------------------------------
mgl_datas_hdf_str(const char * fname)1318 MGL_EXPORT const char * const * mgl_datas_hdf_str(const char *fname)
1319 {
1320 	static std::vector<std::string> names;
1321 	static const char **res=0;
1322 	hid_t hf,hg,hd,ht;
1323 	hf = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);	names.clear();
1324 	if(!hf)	return 0;
1325 	hg = H5Gopen(hf,"/");
1326 	hsize_t num;
1327 	char name[256];
1328 	H5Gget_num_objs(hg, &num);	// replace by H5G_info_t t; H5Gget_info(hg,&t); num=t.nlinks;
1329 	for(hsize_t i=0;i<num;i++)
1330 	{
1331 		if(H5Gget_objtype_by_idx(hg, i)!=H5G_DATASET)	continue;
1332 		H5Gget_objname_by_idx(hg, i, name, 256);	// replace by H5Lget_name_by_idx(hg,".",i,0,0,name,256,0) ?!
1333 		hd = H5Dopen(hf,name);
1334 		ht = H5Dget_type(hd);
1335 		if(H5Tget_class(ht)==H5T_FLOAT || H5Tget_class(ht)==H5T_INTEGER)	names.push_back(name);
1336 		H5Dclose(hd);	H5Tclose(ht);
1337 	}
1338 	H5Gclose(hg);	H5Fclose(hf);	names.push_back("");
1339 	if(res)	delete []res;
1340 	size_t nn = names.size();
1341 	res = new const char*[nn+1];
1342 	for(size_t i=0;i<nn;i++)	res[i]=names[i].c_str();
1343 	res[nn]=NULL;	return res;
1344 }
1345 
mgl_datas_hdf(const char * fname,char * buf,long size)1346 long MGL_EXPORT mgl_datas_hdf(const char *fname, char *buf, long size)
1347 {
1348 	const char * const *res = mgl_datas_hdf_str(fname);
1349 	if(!res)	return 0;
1350 	long n=0, len=1;
1351 	while(res[n][0])	{	len += strlen(res[n])+1;	n++;	}
1352 	if(len>size)	return -long(len);
1353 	strcpy(buf,res[0]);
1354 	for(long i=1;i<n;i++)	{	strcat(buf,"\t");	strcat(buf,res[i]);	}
1355 	return n;
1356 }
1357 #else
mgl_data_save_hdf(HCDT,const char *,const char *,int)1358 void MGL_EXPORT mgl_data_save_hdf(HCDT ,const char *,const char *,int )
1359 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	}
mgl_datas_hdf_str(const char * fname)1360 MGL_EXPORT const char * const * mgl_datas_hdf_str(const char *fname)
1361 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
mgl_datas_hdf(const char *,char *,long)1362 long MGL_EXPORT mgl_datas_hdf(const char *, char *, long )
1363 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
mgl_data_read_hdf(HMDT,const char *,const char *)1364 int MGL_EXPORT mgl_data_read_hdf(HMDT ,const char *,const char *)
1365 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
mgl_dual_save_hdf(mdual val,const char * fname,const char * data,int rewrite)1366 void MGL_EXPORT mgl_dual_save_hdf(mdual val,const char *fname,const char *data,int rewrite)
1367 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	}
mgl_real_save_hdf(double val,const char * fname,const char * data,int rewrite)1368 void MGL_EXPORT mgl_real_save_hdf(double val,const char *fname,const char *data,int rewrite)
1369 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	}
mgl_int_save_hdf(long val,const char * fname,const char * data,int rewrite)1370 void MGL_EXPORT mgl_int_save_hdf(long val,const char *fname,const char *data,int rewrite)
1371 {	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	}
1372 #endif
1373 //-----------------------------------------------------------------------------
mgl_data_read_hdf_(uintptr_t * d,const char * fname,const char * data,int l,int n)1374 int MGL_EXPORT mgl_data_read_hdf_(uintptr_t *d, const char *fname, const char *data,int l,int n)
1375 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1376 	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
1377 	int r = mgl_data_read_hdf(_DT_,s,t);	delete []s;	delete []t;	return r;	}
mgl_data_save_hdf_(uintptr_t * d,const char * fname,const char * data,int * rewrite,int l,int n)1378 void MGL_EXPORT mgl_data_save_hdf_(uintptr_t *d, const char *fname, const char *data, int *rewrite,int l,int n)
1379 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1380 	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
1381 	mgl_data_save_hdf(_DT_,s,t,*rewrite);	delete []s;	delete []t;	}
mgl_datas_hdf_(const char * fname,char * buf,int l,int size)1382 long MGL_EXPORT mgl_datas_hdf_(const char *fname, char *buf, int l, int size)
1383 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1384 	int r = mgl_datas_hdf(s,buf,size);	delete []s;	return r;	}
mgl_real_save_hdf_(double * val,const char * fname,const char * data,int * rewrite,int l,int n)1385 void MGL_EXPORT mgl_real_save_hdf_(double *val,const char *fname,const char *data,int *rewrite,int l,int n)
1386 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1387 	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
1388 	mgl_real_save_hdf(*val,s,t,*rewrite);	delete []s;	delete []t;	}
mgl_int_save_hdf_(long * val,const char * fname,const char * data,int * rewrite,int l,int n)1389 void MGL_EXPORT mgl_int_save_hdf_(long *val,const char *fname,const char *data,int *rewrite,int l,int n)
1390 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1391 	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
1392 	mgl_int_save_hdf(*val,s,t,*rewrite);	delete []s;	delete []t;	}
1393 //-----------------------------------------------------------------------------
mgl_add_file(long & kx,long & ky,long & kz,mreal * & b,mglData * d,bool as_slice)1394 bool MGL_EXPORT mgl_add_file(long &kx,long &ky, long &kz, mreal *&b, mglData *d,bool as_slice)
1395 {
1396 	if(as_slice && d->nz==1)
1397 	{
1398 		if(kx==d->nx && d->ny==1)
1399 		{
1400 			b = (mreal *)realloc(b,kx*(ky+1)*sizeof(mreal));
1401 			memcpy(b+kx*ky,d->a,kx*sizeof(mreal));		ky++;
1402 		}
1403 		else if(kx==d->nx && ky==d->ny)
1404 		{
1405 			b = (mreal *)realloc(b,kx*ky*(kz+1)*sizeof(mreal));
1406 			memcpy(b+kx*ky*kz,d->a,kx*ky*sizeof(mreal));	kz++;
1407 		}
1408 		else	return false;
1409 	}
1410 	else
1411 	{
1412 		if(d->ny*d->nz==1 && ky*kz==1)
1413 		{
1414 			b = (mreal *)realloc(b,(kx+d->nx)*sizeof(mreal));
1415 			memcpy(b+kx,d->a,d->nx*sizeof(mreal));	kx+=d->nx;
1416 		}
1417 		else if(kx==d->nx && kz==1 && d->nz==1)
1418 		{
1419 			b = (mreal *)realloc(b,kx*(ky+d->ny)*sizeof(mreal));
1420 			memcpy(b+kx*ky,d->a,kx*d->ny*sizeof(mreal));	ky+=d->ny;
1421 		}
1422 		else if(kx==d->nx && ky==d->ny)
1423 		{
1424 			b = (mreal *)realloc(b,kx*kx*(kz+d->nz)*sizeof(mreal));
1425 			memcpy(b+kx*ky*kz,d->a,kx*ky*d->nz*sizeof(mreal));	kz+=d->nz;
1426 		}
1427 		else	return false;
1428 	}
1429 	return true;
1430 }
1431 //-----------------------------------------------------------------------------
mgl_data_read_range(HMDT dat,const char * templ,double from,double to,double step,int as_slice)1432 int MGL_EXPORT mgl_data_read_range(HMDT dat, const char *templ, double from, double to, double step, int as_slice)
1433 {
1434 	mglData d;
1435 	mreal t = from, *b;
1436 	long kx,ky,kz,n=strlen(templ)+20;
1437 	char *fname = new char[n];
1438 
1439 	//read first file
1440 	do{	snprintf(fname,n,templ,t);	fname[n-1]=0;	t+= step;	} while(!mgl_data_read(&d,fname) && t<=to);
1441 
1442 	if(t>to)	{	delete []fname;	return 0;	}
1443 	kx = d.nx;	ky = d.ny;	kz = d.nz;
1444 	b = (mreal *)malloc(kx*ky*kz*sizeof(mreal));
1445 	memcpy(b,d.a,kx*ky*kz*sizeof(mreal));
1446 
1447 	// read other files
1448 	for(;t<=to;t+=step)
1449 	{
1450 		snprintf(fname,n,templ,t);	fname[n-1]=0;
1451 		if(mgl_data_read(&d,fname))
1452 			if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))
1453 			{	delete []fname;	free(b);	return 0;	}
1454 	}
1455 	dat->Set(b,kx,ky,kz);
1456 	delete []fname;	free(b);
1457 	return 1;
1458 }
mgl_data_read_range_(uintptr_t * d,const char * fname,mreal * from,mreal * to,mreal * step,int * as_slice,int l)1459 int MGL_EXPORT mgl_data_read_range_(uintptr_t *d, const char *fname, mreal *from, mreal *to, mreal *step, int *as_slice,int l)
1460 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1461 	int r = mgl_data_read_range(_DT_,s,*from,*to,*step,*as_slice);	delete []s;	return r;	}
1462 //-----------------------------------------------------------------------------
mgl_data_read_all(HMDT dat,const char * templ,int as_slice)1463 int MGL_EXPORT mgl_data_read_all(HMDT dat, const char *templ, int as_slice)
1464 {
1465 #ifndef WIN32
1466 	mglData d;
1467 	glob_t res;
1468 	size_t i;
1469 	mreal *b;
1470 	long kx,ky,kz;
1471 	glob (templ, GLOB_TILDE, NULL, &res);
1472 
1473 	//read first file
1474 	for(i=0;i<res.gl_pathc;i++)
1475 		if(mgl_data_read(&d,res.gl_pathv[i]))	break;
1476 
1477 	if(i>=res.gl_pathc)
1478 	{	globfree (&res);	return 0;	}
1479 	kx = d.nx;	ky = d.ny;	kz = d.nz;
1480 	b = (mreal *)malloc(kx*ky*kz*sizeof(mreal));
1481 	memcpy(b,d.a,kx*ky*kz*sizeof(mreal));
1482 
1483 	for(;i<res.gl_pathc;i++)
1484 	{
1485 		if(mgl_data_read(&d,res.gl_pathv[i]))
1486 			if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))
1487 			{	globfree (&res);	free(b);	return 0;	}
1488 	}
1489 	dat->Set(b,kx,ky,kz);
1490 
1491 	globfree (&res);	free(b);
1492 	return 1;
1493 #else
1494 	return 0;
1495 #endif
1496 }
mgl_data_read_all_(uintptr_t * d,const char * fname,int * as_slice,int l)1497 int MGL_EXPORT mgl_data_read_all_(uintptr_t *d, const char *fname, int *as_slice,int l)
1498 {	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
1499 	int r = mgl_data_read_all(_DT_,s,*as_slice);	delete []s;	return r;	}
1500 //-----------------------------------------------------------------------------
mgl_data_column(HCDT dat,const char * eq)1501 HMDT MGL_EXPORT mgl_data_column(HCDT dat, const char *eq)
1502 {
1503 	std::vector<mglDataA*> list;
1504 	const char *id = dat->GetColumnId();
1505 	size_t len = strlen(id);
1506 	for(size_t i=0;i<len;i++)
1507 	{
1508 		mglDataT *col = new mglDataT(*dat);
1509 		col->SetInd(i,id[i]);
1510 		list.push_back(col);
1511 	}
1512 	if(list.size()==0)	return 0;	// no named columns
1513 	mglDataV *t = new mglDataV(dat->GetNy(),dat->GetNz());
1514 	t->Name(L"#$mgl");	list.push_back(t);
1515 	HMDT r = mglFormulaCalc(eq,list);
1516 	for(size_t i=0;i<list.size();i++)	delete list[i];
1517 	return r;
1518 }
mgl_data_column_(uintptr_t * d,const char * eq,int l)1519 uintptr_t MGL_EXPORT mgl_data_column_(uintptr_t *d, const char *eq,int l)
1520 {	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
1521 	uintptr_t r = uintptr_t(mgl_data_column(_DT_,s));
1522 	delete []s;	return r;	}
1523 //-----------------------------------------------------------------------------
mgl_data_limit(HMDT d,mreal v)1524 void MGL_EXPORT mgl_data_limit(HMDT d, mreal v)
1525 {
1526 	long n = d->GetNN();
1527 	mreal *a = d->a;
1528 #pragma omp parallel for
1529 	for(long i=0;i<n;i++)
1530 	{	mreal b = fabs(a[i]);	if(b>v)	a[i] *= v/b;	}
1531 }
mgl_data_limit_(uintptr_t * d,mreal * v)1532 void MGL_EXPORT mgl_data_limit_(uintptr_t *d, mreal *v)
1533 {	mgl_data_limit(_DT_, *v);	}
1534 //-----------------------------------------------------------------------------
mgl_data_coil(HMDT d,mreal v1,mreal v2,int sep)1535 void MGL_EXPORT mgl_data_coil(HMDT d, mreal v1, mreal v2, int sep)
1536 {
1537 	long n = d->GetNN();
1538 	if(mgl_isnan(v2))	v2=-v1;
1539 	if(v2<v1)	{	mreal tmp=v1;	v1=v2;	v2=tmp;	}
1540 	mreal *a = d->a, dv = v2-v1;
1541 	if(dv==0)	return;
1542 	long *kk=new long[n];
1543 #pragma omp parallel for
1544 	for(long i=0;i<n;i++)
1545 	{
1546 		kk[i] = mgl_int((a[i]-v1)/dv-0.5);
1547 		a[i] -= kk[i]*dv;
1548 	}
1549 	if(sep)
1550 	{
1551 #pragma omp parallel for
1552 		for(long i=1;i<n;i++)	if(kk[i]!=kk[i-1])	a[i] = NAN;
1553 	}
1554 	delete []kk;
1555 }
mgl_data_coil_(uintptr_t * d,mreal * v1,mreal * v2,int * sep)1556 void MGL_EXPORT mgl_data_coil_(uintptr_t *d, mreal *v1, mreal *v2, int *sep)
1557 {	mgl_data_coil(_DT_, *v1, *v2, *sep);	}
1558 //-----------------------------------------------------------------------------
1559 /// Read binary data and swap big-endian to little-endian if swap=true
mgl_fread(FILE * fp,void * vals,size_t size,size_t num,int swap)1560 size_t MGL_EXPORT mgl_fread(FILE *fp, void *vals, size_t size, size_t num, int swap)
1561 {
1562 	char *ptr = (char*)vals;
1563 	size_t r = fread(ptr,size,num,fp);
1564 	if(r && swap)
1565 	{
1566 		char buf[8], ch;
1567 		if(size==4)	for(size_t i=0;i<r;i++)
1568 		{
1569 			memcpy(buf,ptr+i*size,size);
1570 			ch=buf[0];	buf[0]=buf[3];	buf[3]=ch;
1571 			ch=buf[1];	buf[1]=buf[2];	buf[2]=ch;
1572 		}
1573 		else if(size==2)	for(size_t i=0;i<r;i++)
1574 		{
1575 			memcpy(buf,ptr+i*size,size);
1576 			ch=buf[0];	buf[0]=buf[1];	buf[1]=ch;
1577 		}
1578 		else if(size==8)	for(size_t i=0;i<r;i++)
1579 		{
1580 			memcpy(buf,ptr+i*size,size);
1581 			ch=buf[0];	buf[0]=buf[7];	buf[7]=ch;
1582 			ch=buf[1];	buf[1]=buf[6];	buf[6]=ch;
1583 			ch=buf[2];	buf[2]=buf[5];	buf[5]=ch;
1584 			ch=buf[3];	buf[3]=buf[4];	buf[4]=ch;
1585 		}
1586 	}
1587 	return r;
1588 }
1589 //-----------------------------------------------------------------------------
1590 /// Read data array from Tektronix WFM file
1591 /** Parse Tektronix TDS5000/B, TDS6000/B/C, TDS/CSA7000/B, MSO70000/C, DSA70000/B/C DPO70000/B/C DPO7000/ MSO/DPO5000. */
mgl_data_read_wfm(HMDT d,const char * fname,long num,long step,long start)1592 int MGL_EXPORT mgl_data_read_wfm(HMDT d,const char *fname, long num, long step/*=1*/, long start/*=0*/)
1593 {
1594 /*	if(step<1)	step=1;
1595 	if(start<0)	start=0;
1596 	FILE *fp = fopen(fname,"rb");
1597 	if(!fp)	return 0;	// couldn't open file
1598 	unsigned short byte_order;
1599 	fread(&byte_order,2,1,fp);
1600 	bool byteorder;	// TODO
1601 */	return 0;
1602 }
mgl_data_read_wfm_(uintptr_t * d,const char * fname,long * num,long * step,long * start,int l)1603 int MGL_EXPORT mgl_data_read_wfm_(uintptr_t *d, const char *fname, long *num, long *step, long *start,int l)
1604 {	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
1605 	int r = mgl_data_read_wfm(_DT_,s,*num,*step,*start);
1606 	delete []s;	return r;	}
1607 /// Read data array from Matlab MAT file (parse versions 4 and 5)
mgl_data_read_matlab(HMDT d,const char * fname,const char * data)1608 int MGL_EXPORT mgl_data_read_matlab(HMDT d,const char *fname,const char *data)
1609 {
1610 	// TODO
1611 /**/return 0;
1612 }
mgl_data_read_matlab_(uintptr_t * d,const char * fname,const char * data,int l,int n)1613 int MGL_EXPORT mgl_data_read_matlab_(uintptr_t *d, const char *fname, const char *data,int l,int n)
1614 {	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
1615 	char *t=new char[n+1];	memcpy(t,data,n);	t[n]=0;
1616 	int r = mgl_data_read_matlab(_DT_,s,t);	delete []s;	delete []t;	return r;	}
1617 //-----------------------------------------------------------------------------
1618