1 /**
2 	Ported to dlang 2015 by Laeeth Isharc
3 */
4 /**
5 This is a work in progress and does not yet compile
6 */
7 
8 module kaleidic.api.mathgl.data;
9 /+
10 /// Class for working with data array
11 class MglData
12 {
13     //public : using MglDataA :  : Momentum;
14     long nx; ///< number of points in 1st dimensions ('x' dimension)
15     long ny; ///< number of points in 2nd dimensions ('y' dimension)
16     long nz; ///< number of points in 3d dimensions ('z' dimension)
17     mreal* a; ///< data array
18 	string id; ///< column (or slice) names
19     bool useLink; ///< use external data (i.e. don't free it)
20 
21     /// Initiate by other MglData variable
22     this(const MglData* d)
23     {
24         a = 0;
25         mgl_data_set(this,  & d);
26     } // NOTE: must be constructor for MglData& to exclude copy one
27     
28     static if(HaveRval)
29     {
30     	this(MglData** d)
31     	{
32     		this.nx=d.nx;
33     		this.ny=d.ny;
34     		this.nz=d.nz;
35     		thia.a=d.a;
36     		this.id=d.id;
37     		this.useLink=d.useLink;
38 	    	//this. s = d.s;
39         	//this.temp = d.temp;
40         	this.func = d.func;
41         	this.o = d.o;
42         	d.a = 0;
43         	d.func = 0;
44         }
45     }
46 
47     this(const MglDataA* d)
48     {
49         a = 0;
50         if (d)
51             mgl_data_set(this, d);
52         else
53             mgl_data_create(this, 1, 1, 1);
54     }
55 
56     this(MglData * d) // NOTE: Variable d will be deleted!!!
57     {
58         if (d is null)
59         {
60             nx = d.nx;
61             ny = d.ny;
62             nz = d.nz;
63             a = d.a;
64             d.a = 0;
65             temp = d.temp;
66             func = d.func;
67             o = d.o;
68             s = d.s;
69             id = d.id;
70             useLink = d.useLink;
71             delete d;
72         }
73         else
74         {
75             a = 0;
76             create(1);
77         }
78     }
79 
80     /// Initiate by flat array
81     this(int size, const float * d)
82     {
83         a = 0;
84         set(d, size);
85     }
86     this(int rows, int cols, const float * d)
87     {
88         a = 0;
89         set(d, cols, rows);
90     }
91     this(int size, const double * d)
92     {
93         a = 0;
94         set(d, size);
95     }
96     this(int rows, int cols, const double * d)
97     {
98         a = 0;
99         set(d, cols, rows);
100     }
101     this(const double * d, int size)
102     {
103         a = 0;
104         set(d, size);
105     }
106     this(const double * d, int rows, int cols)
107     {
108         a = 0;
109         set(d, cols, rows);
110     }
111     this(const float * d, int size)
112     {
113         a = 0;
114         set(d, size);
115     }
116     this(const float * d, int rows, int cols)
117     {
118         a = 0;
119         set(d, cols, rows);
120     }
121     /// Read data from file
122     this(string fname)
123     {
124         a = 0;
125         Read(fname);
126     }
127     /// allocate the memory for data array and initialize it zero
128     this(long xx = 1, long yy = 1, long zz = 1)
129     {
130         a = 0;
131         create(xx, yy, zz);
132     }
133     
134     /// Delete the array
135     ~this()
136     {
137         //if (!useLink && a)
138           //  delete[] a;
139     }
140 
141     mreal getVal(long i, long j = 0, long k = 0) const
142     {
143         return mgl_data_get_value(this, i, j, k);
144     }
145 
146     void setVal(mreal f, long i, long j = 0, long k = 0)
147     {
148         mgl_data_set_value(this, f, i, j, k);
149     }
150 
151     /// Get sizes
152     long getNx() const
153     {
154         return nx;
155     }
156 
157     long getNy() const
158     {
159         return ny;
160     }
161 
162     long getNz() const
163     {
164         return nz;
165     }
166 
167     /// Link external data array (don't delete it at exit)
168     void link(mreal* A, long NX, long NY = 1, long NZ = 1)
169     {
170         mgl_data_link(this, A, NX, NY, NZ);
171     }
172 
173     void link(MglData* d)
174     {
175         link(d.a, d.nx, d.ny, d.nz);
176     }
177     /// allocate memory and copy the data from the gsl_vector
178     void set(gsl_vector* m)
179     {
180         mgl_data_set_vector(this, m);
181     }
182 
183     /// allocate memory and copy the data from the gsl_matrix
184     void set(gsl_matrix* m)
185     {
186         mgl_data_set_matrix(this, m);
187     }
188 
189     /// allocate memory and copy the data from the (float *) array
190     void set(in float* A, long NX, long NY = 1, long NZ = 1)
191     {
192         mgl_data_set_float(this, A, NX, NY, NZ);
193     }
194 
195     /// allocate memory and copy the data from the (double *) array
196     void set(const double* A, long NX, long NY = 1, long NZ = 1)
197     {
198         mgl_data_set_double(this, A, NX, NY, NZ);
199     }
200 
201     /// allocate memory and copy the data from the (float **) array
202     void set(in float** A, long N1, long N2)
203     {
204         mgl_data_set_float2(this, A, N1, N2);
205     }
206     /// allocate memory and copy the data from the (double **) array
207     void set(in double** A, long N1, long N2)
208     {
209         mgl_data_set_double2(this, A, N1, N2);
210     }
211     /// allocate memory and copy the data from the (float ***) array
212     void set(in float** A, long N1, long N2, long N3)
213     {
214         mgl_data_set_float3(this, A, N1, N2, N3);
215     }
216     /// allocate memory and copy the data from the (double ***) array
217     void set(in double** A, long N1, long N2, long N3)
218     {
219         mgl_data_set_double3(this, A, N1, N2, N3);
220     }
221     /// allocate memory and scanf the data from the string
222     void set(string str, long NX, long NY = 1, long NZ = 1)
223     {
224         mgl_data_set_values(this, str.toStringz, NX, NY, NZ);
225     }
226 
227     /// Import data from abstract type
228     void set(HCDT dat)
229     {
230         mgl_data_set(this, dat);
231     }
232 
233     void set(const MglDataA* dat)
234     {
235         mgl_data_set(this,  & dat);
236     }
237     /// allocate memory and copy data from std::vector<T>
238     void set(int[]  d)
239     {
240         if (d.length < 1)
241             return;
242         create(d.length);
243         for (long i = 0; i < nx; i++)
244             a[i] = d[i];
245     }
246     void set(float[] d)
247     {
248         if (d.length < 1)
249             return;
250         create(d.length);
251         foreach(i;0..nx)
252             a[i] = d[i];
253     }
254     void set(double[] d)
255     {
256         if (d.length < 1)
257             return;
258         create(d.length);
259         foreach(i;0..nx)
260             a[i] = d[i];
261     }
262 
263     /// create or recreate the array with specified size and fill it by zero
264     void create(long mx, long my = 1, long mz = 1)
265     {
266         mgl_data_create(this, mx, my, mz);
267     }
268 
269     /// Rearange data dimensions
270     void rearrange(long mx, long my = 0, long mz = 0)
271     {
272         mgl_data_rearrange(this, mx, my, mz);
273     }
274 
275     /// Transpose dimensions of the data (generalization of Transpose)
276     void transpose(string dim = "yx")
277     {
278         mgl_data_transpose(this, dim);
279     }
280 
281     /// Extend data dimensions
282     void extend(long n1, long n2 = 0)
283     {
284         mgl_data_extend(this, n1, n2);
285     }
286 
287     /// Reduce size of the data
288     void squeeze(long rx, long ry = 1, long rz = 1, bool smooth = false)
289     {
290         mgl_data_squeeze(this, rx, ry, rz, smooth);
291     }
292 
293     /// Crop the data
294     void crop(long n1, long n2, char dir = 'x')
295     {
296         mgl_data_crop(this, n1, n2, dir);
297     }
298 
299     /// Insert data rows/columns/slices
300     void insert(char dir, long at = 0, long num = 1)
301     {
302         mgl_data_insert(this, dir, at, num);
303     }
304 
305     /// Delete data rows/columns/slices
306     void deleteItems(char dir, long at = 0, long num = 1)
307     {
308         mgl_data_delete(this, dir, at, num);
309     }
310 
311     /// Remove rows with duplicate values in column id
312     void clean(long id)
313     {
314         mgl_data_clean(this, id);
315     }
316 
317     /// Join with another data array
318     void join(const MglDataA* d)
319     {
320         mgl_data_join(this, *d);
321     }
322 
323     /// Modify the data by specified formula
324     void modify(string eq, long dim = 0)
325     {
326         mgl_data_modify(this, eq.toStringz, dim);
327     }
328 
329     /// Modify the data by specified formula
330     void modify(string eq, in MglDataA* vdat, in MglDataA* wdat)
331     {
332         mgl_data_modify_vw(this, eq.to!stringz,  *vdat,  * wdat);
333     }
334     /// Modify the data by specified formula
335     void modify(string eq, const MglDataA* vdat)
336     {
337         mgl_data_modify_vw(this, eq.toStringz,  *vdat, 0);
338     }
339     /// Modify the data by specified formula assuming x,y,z in range [r1,r2]
340     void fill(HMGL gr, string eq, string opt = "")
341     {
342         mgl_data_fill_eq(gr, this, eq.toStringz, 0, 0, opt);
343     }
344 
345     void fill(HMGL gr, string eq, const MglDataA* vdat, string opt = "")
346     {
347         mgl_data_fill_eq(gr, this, eq.toStringz,  *vdat, 0, opt.toStringz);
348     }
349 
350     void fill(HMGL gr, string eq, const MglDataA* vdat, const MglDataA* wdat, string opt = "")
351     {
352         mgl_data_fill_eq(gr, this, eq.toStringz,  *vdat,  * wdat, opt.toStringz);
353     }
354     /// Equidistantly fill the data to range [x1,x2] in direction dir
355     void fill(mreal x1, mreal x2 = mglNaN, char dir = 'x')
356     {
357         mgl_data_fill(this, x1, x2, dir);
358     }
359 
360     /// fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2] using global spline
361     void refillGS(in MglDataA* xdat, const MglDataA*  vdat, mreal x1, mreal x2,
362         long sl =  - 1)
363     {
364         mgl_data_refill_gs(this, *xdat,  & vdat, x1, x2, sl);
365     }
366     /// fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2]
367     void refill(in MglDataA* xdat, in MglDataA* vdat, mreal x1, mreal x2, long sl =  - 1)
368     {
369         mgl_data_refill_x(this, *xdat,  & vdat, x1, x2, sl);
370     }
371     void refill(in MglDataA* xdat, in MglDataA* vdat, MglPoint p1, MglPoint p2,
372         long sl =  - 1)
373     {
374         mgl_data_refill_x(this, *xdat,  & vdat, p1.x, p2.x, sl);
375     }
376     void refill(in MglDataA* xdat, in MglDataA* ydat, in MglDataA* vdat,
377         MglPoint p1, MglPoint p2, long sl =  - 1)
378     {
379         mgl_data_refill_xy(this, *xdat,  & ydat,  & vdat, p1.x, p2.x, p1.y, p2.y,
380             sl);
381     }
382     void refill(in MglDataA* xdat, in MglDataA* ydat, in MglDataA* zdat,
383         in MglDataA* vdat, MglPoint p1, MglPoint p2)
384     {
385         mgl_data_refill_xyz(this, *xdat,  & ydat,  & zdat,  & vdat, p1.x, p2.x,
386             p1.y, p2.y, p1.z, p2.z);
387     }
388     /// fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range of gr
389     void refill(HMGL gr, in MglDataA* xdat, in MglDataA* vdat,
390         long sl =  - 1, string opt = "")
391     {
392         mgl_data_refill_gr(gr, this, *xdat, 0, 0,  & vdat, sl, opt);
393     }
394     void refill(HMGL gr, in MglDataA* xdat, in MglDataA* ydat,
395         in MglDataA* vdat, long sl =  - 1, string opt = "")
396     {
397         mgl_data_refill_gr(gr, this, *xdat,  & ydat, 0,  & vdat, sl, opt);
398     }
399     void refill(HMGL gr, in MglDataA* xdat, in MglDataA* ydat,
400         in MglDataA* zdat, in MglDataA* vdat, string opt = "")
401     {
402         mgl_data_refill_gr(gr, this, *xdat,  & ydat,  & zdat,  & vdat,  - 1, opt);
403     }
404     /// set the data by triangulated surface values assuming x,y,z in axis range of gr
405     void grid(HMGL gr, in MglDataA* x, in MglDataA* y, in MglDataA* z, string opt = "")
406     {
407         mgl_data_grid(gr, this,  *x,  *y,  *z, opt.toStringz);
408     }
409     /// set the data by triangulated surface values assuming x,y,z in range [p1, p2]
410     void grid(in MglDataA* xdat, in MglDataA* ydat, in MglDataA* vdat,
411         MglPoint p1, MglPoint p2)
412     {
413         mgl_data_grid_xy(this, *xdat,  & ydat,  & vdat, p1.x, p2.x, p1.y, p2.y);
414     }
415     /// Put value to data element(s)
416     void put(mreal val, long i = -1, long j = -1, long k = -1)
417     {
418         mgl_data_put_val(this, val, i, j, k);
419     }
420 
421     /// Put array to data element(s)
422     void put(in MglDataA* dat, long i =  - 1, long j =  - 1, long k =  - 1)
423     {
424         mgl_data_put_dat(this,  & dat, i, j, k);
425     }
426     /// set names for columns (slices)
427     void setColumnId(string ids)
428     {
429         mgl_data_set_id(this, ids);
430     }
431 
432     /// Make new id
433     void newId()
434     {
435         id.clear();
436     }
437 
438     /// Read data from tab-separated text file with auto determining size
439     bool read(string fname)
440     {
441         return mgl_data_read(this, fname);
442     }
443 
444     /// Read data from text file with specifeid size
445     bool read(string fname, long mx, long my = 1, long mz = 1)
446     {
447         return mgl_data_read_dim(this, fname.toStringz, mx, my, mz);
448     }
449 
450     /// Import data array from PNG file according color scheme
451     void importData(string fname, string scheme, mreal v1 = 0, mreal v2 = 1)
452     {
453         mgl_data_import(this, fname.toStringz, scheme.toStringz, v1, v2);
454     }
455 
456     /// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
457     bool readRange(string templ, double from, double to, double step = 1, bool as_slice = false)
458     {
459         return mgl_data_read_range(this, templ.toStringz, from, to, step, as_slice);
460     }
461 
462     /// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
463     bool readall(string templ, bool as_slice = false)
464     {
465         return mgl_data_read_all(this, templ.toStringz, as_slice);
466     }
467 
468     /// Read data from text file with size specified at beginning of the file
469     bool readMat(string fname, long dim = 2)
470     {
471         return mgl_data_read_mat(this, fname.toStringz, dim);
472     }
473 
474     /// Read data array from HDF file (parse HDF4 and HDF5 files)
475     int readHDF(string fname, ubyte[] data)
476     {
477         return mgl_data_read_hdf(this, fname.toStringz, data.ptr);
478     }
479 
480     /// Get column (or slice) of the data filled by formulas of named columns
481     MglData Column(string eq) const
482     {
483         return MglData(true, mgl_data_column(this, eq.toStringz));
484     }
485 
486     /// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
487     MglData Momentum(char dir, string how) const
488     {
489         return MglData(true, mgl_data_momentum(this, dir, how.toStringz));
490     }
491 
492     /// Get sub-array of the data with given fixed indexes
493     MglData SubData(long xx, long yy = -1, long zz = -1) const
494     {
495         return MglData(true, mgl_data_subdata(this, xx, yy, zz));
496     }
497 
498     MglData SubData(in MglDataA* xx, in MglDataA* yy, in MglDataA* zz) const
499     {
500         return MglData(true, mgl_data_subdata_ext(this,  & xx,  & yy,  & zz));
501     }
502     MglData SubData(in MglDataA* xx, in MglDataA* yy) const
503     {
504         return MglData(true, mgl_data_subdata_ext(this,  & xx,  & yy, 0));
505     }
506     MglData subData(in MglDataA* xx) const
507     {
508         return MglData(true, mgl_data_subdata_ext(this,  & xx, 0, 0));
509     }
510     /// Get trace of the data array
511     MglData trace() const
512     {
513         return MglData(true, mgl_data_trace(this));
514     }
515 
516     /// create n-th points distribution of this data values in range [v1, v2]
517     MglData hist(long n, mreal v1 = 0, mreal v2 = 1, long nsub = 0) const
518     {
519         return MglData(true, mgl_data_hist(this, n, v1, v2, nsub));
520     }
521 
522     /// create n-th points distribution of this data values in range [v1, v2] with weight w
523     MglData hist(in MglDataA* w, long n, mreal v1 = 0, mreal v2 = 1, long nsub = 0) const
524     {
525         return MglData(true, mgl_data_hist_w(this,  & w, n, v1, v2, nsub));
526     }
527     /// Get array which is result of summation in given direction or directions
528     MglData sum(string dir) const
529     {
530         return MglData(true, mgl_data_sum(this, dir));
531     }
532 
533     /// Get array which is result of maximal values in given direction or directions
534     MglData max(string dir) const
535     {
536         return MglData(true, mgl_data_max_dir(this, dir));
537     }
538 
539     /// Get array which is result of minimal values in given direction or directions
540     MglData min(string dir) const
541     {
542         return MglData(true, mgl_data_min_dir(this, dir));
543     }
544 
545     /// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
546     MglData combine(in MglDataA* dat) const
547     {
548         return MglData(true, mgl_data_combine(this,  & dat));
549     }
550     /// Resize the data to new size of box [x1,x2]*[y1,y2]*[z1,z2]
551     MglData resize(long mx, long my = 0, long mz = 0, mreal x1 = 0, mreal x2 = 1,
552         mreal y1 = 0, mreal y2 = 1, mreal z1 = 0, mreal z2 = 1) const
553     {
554         return MglData(true, mgl_data_resize_box(this, mx, my, mz, x1, x2, y1, y2,
555             z1, z2));
556     }
557 
558     /// Get array which values is result of interpolation this for coordinates from other arrays
559     MglData evaluate(in MglData* idat, bool norm = true) const
560     {
561         return MglData(true, mgl_data_evaluate(this,  & idat, 0, 0, norm));
562     }
563     MglData evaluate(in MglData* idat, in MglData* jdat, bool norm = true) const
564     {
565         return MglData(true, mgl_data_evaluate(this,  & idat,  & jdat, 0, norm));
566     }
567     MglData evaluate(in MglData* idat, in MglData* jdat, in MglData* kdat,
568         bool norm = true) const
569     {
570         return MglData(true, mgl_data_evaluate(this,  & idat,  & jdat,  & kdat, norm));
571     }
572     /// Find roots for set of nonlinear equations defined by textual formula
573     MglData roots(string func, char var = 'x') const
574     {
575         return MglData(true, mgl_data_roots(func, this, var));
576     }
577 
578     /// Find correlation with another data arrays
579     MglData correl(in MglDataA* dat, string dir) const
580     {
581         return MglData(true, mgl_data_correl(this,  & dat, dir));
582     }
583     /// Find auto correlation function
584     MglData autoCorrel(string dir) const
585     {
586         return MglData(true, mgl_data_correl(this, this, dir));
587     }
588 
589     /// Cumulative summation the data in given direction or directions
590     void cumSum(string dir)
591     {
592         mgl_data_cumsum(this, dir);
593     }
594 
595     /// Integrate (cumulative summation) the data in given direction or directions
596     void integral(string dir)
597     {
598         mgl_data_integral(this, dir);
599     }
600 
601     /// Differentiate the data in given direction or directions
602     void diff(string dir)
603     {
604         mgl_data_diff(this, dir);
605     }
606 
607     /// Differentiate the parametrically specified data along direction v1 with v2=const
608     void diff(ref MglDataA v1, ref MglDataA v2)
609     {
610         mgl_data_diff_par(this,  v1,  v2, 0);
611     }
612     /// Differentiate the parametrically specified data along direction v1 with v2,v3=const
613     void diff(ref MglDataA v1,ref MglDataA v2, ref MglDataA v3)
614     {
615         mgl_data_diff_par(this,  v1,  v2,  v3);
616     }
617     /// Double-differentiate (like Laplace operator) the data in given direction
618     void Diff2(string dir)
619     {
620         mgl_data_diff2(this, dir);
621     }
622 
623     /// Swap left and right part of the data in given direction (useful for Fourier spectrum)
624     void Swap(string dir)
625     {
626         mgl_data_swap(this, dir);
627     }
628 
629     /// Roll data along direction dir by num slices
630     void Roll(char dir, long num)
631     {
632         mgl_data_roll(this, dir, num);
633     }
634 
635     /// Mirror the data in given direction (useful for Fourier spectrum)
636     void Mirror(string dir)
637     {
638         mgl_data_mirror(this, dir);
639     }
640 
641     /// Sort rows (or slices) by values of specified column
642     void Sort(long idx, long idy = -1)
643     {
644         mgl_data_sort(this, idx, idy);
645     }
646 
647     /// set as the data envelop
648     void Envelop(char dir = 'x')
649     {
650         mgl_data_envelop(this, dir);
651     }
652 
653     /// Remove phase jump
654     void Sew(string dirs = "xyz", mreal da = 2 * mglPi)
655     {
656         mgl_data_sew(this, dirs, da);
657     }
658 
659     /// Smooth the data on specified direction or directions
660     void Smooth(string dirs = "xyz", mreal delta = 0)
661     {
662         mgl_data_smooth(this, dirs, delta);
663     }
664 
665     /// Normalize the data to range [v1,v2]
666     void Norm(mreal v1 = 0, mreal v2 = 1, bool sym = false, long dim = 0)
667     {
668         mgl_data_norm(this, v1, v2, sym, dim);
669     }
670 
671     /// Normalize the data to range [v1,v2] slice by slice
672     void NormSl(mreal v1 = 0, mreal v2 = 1, char dir = 'z', bool keep_en = true, bool sym = false)
673     {
674         mgl_data_norm_slice(this, v1, v2, dir, keep_en, sym);
675     }
676 
677     /// Apply Hankel transform
678     void Hankel(string dir)
679     {
680         mgl_data_hankel(this, dir);
681     }
682 
683     /// Apply Sin-Fourier transform
684     void SinFFT(string dir)
685     {
686         mgl_data_sinfft(this, dir);
687     }
688 
689     /// Apply Cos-Fourier transform
690     void CosFFT(string dir)
691     {
692         mgl_data_cosfft(this, dir);
693     }
694 
695     /// fill data by 'x'/'k' samples for Hankel ('h') or Fourier ('f') transform
696     void fillSample(string how)
697     {
698         mgl_data_fill_sample(this, how);
699     }
700 
701     /// Return an approximated x-value (root) when dat(x) = val
702     mreal Solve(mreal val, bool use_spline = true, long i0 = 0) const
703     {
704         return mgl_data_solve_1d(this, val, use_spline, i0);
705     }
706 
707     /// Return an approximated value (root) when dat(x) = val
708     MglData solve(mreal val, char dir, bool norm = true) const
709     {
710         return MglData(true, mgl_data_solve(this, val, dir, 0, norm));
711     }
712 
713     MglData solve(mreal val, char dir, in MglData* i0, bool norm = true) const
714     {
715         return MglData(true, mgl_data_solve(this, val, dir,  & i0, norm));
716     }
717 
718     /// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
719     mreal spline(mreal x, mreal y = 0, mreal z = 0) const
720     {
721         return mgl_data_spline(this, x, y, z);
722     }
723 
724     /// Interpolate by cubic spline the data to given point x,\a y,\a z which normalized in range [0, 1]
725     mreal spline1(mreal x, mreal y = 0, mreal z = 0) const
726     {
727         return mgl_data_spline(this, x * (nx - 1), y * (ny - 1), z * (nz - 1));
728     }
729 
730     /// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
731     mreal linear(mreal x, mreal y = 0, mreal z = 0) const
732     {
733         return mgl_data_linear(this, x, y, z);
734     }
735 
736     /// Interpolate by line the data to given point x,\a y,\a z which normalized in range [0, 1]
737     mreal linear1(mreal x, mreal y = 0, mreal z = 0) const
738     {
739         return mgl_data_linear(this, x * (nx - 1), y * (ny - 1), z * (nz - 1));
740     }
741 
742     /// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
743     mreal spline(ref MglPoint dif, mreal x, mreal y = 0, mreal z = 0) const
744     {
745         return mgl_data_spline_ext(this, x, y, z,  & (dif.x),  & (dif.y),  & (dif.z));
746     }
747     /// Interpolate by cubic spline the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
748     mreal spline1(ref MglPoint dif, mreal x, mreal y = 0, mreal z = 0) const
749     {
750         mreal res = mgl_data_spline_ext(this, x * (nx - 1), y * (ny - 1),
751             z * (nz - 1), &(dif.x), &(dif.y), &(dif.z));
752         dif.x *= nx > 1 ? nx - 1 : 1;
753         dif.y *= ny > 1 ? ny - 1 : 1;
754         dif.z *= nz > 1 ? nz - 1 : 1;
755         return res;
756     }
757     /// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
758     mreal linear(ref MglPoint dif, mreal x, mreal y = 0, mreal z = 0) const
759     {
760         return mgl_data_linear_ext(this, x, y, z,  & (dif.x),  & (dif.y),  & (dif.z));
761     }
762     /// Interpolate by line the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
763     mreal linear1(ref MglPoint dif, mreal x, mreal y = 0, mreal z = 0) const
764     {
765         mreal res = mgl_data_linear_ext(this, x * (nx - 1), y * (ny - 1),
766             z * (nz - 1), &(dif.x), &(dif.y), &(dif.z));
767         dif.x *= nx > 1 ? nx - 1 : 1;
768         dif.y *= ny > 1 ? ny - 1 : 1;
769         dif.z *= nz > 1 ? nz - 1 : 1;
770         return res;
771     }
772 /**
773     /// Copy data from other MglData variable
774     in MglDataA* operator = (in MglDataA* d)
775     {
776         if (this !=  & d)
777             mgl_data_set(this,  & d);
778         return d;
779     }
780     in MglData* operator = (in MglData* d)
781     {
782         if (this !=  & d)
783             mgl_data_set(this,  & d);
784         return d;
785     }
786     mreal operator = (mreal val)
787     {
788         mgl_data_fill(this, val, val, 'x');
789         return val;
790     }
791     /// Multiply the data by other one for each element
792     void operator *= (in MglDataA* d)
793     {
794         mgl_data_mul_dat(this,  & d);
795     }
796     /// Divide the data by other one for each element
797     void operator /= (in MglDataA* d)
798     {
799         mgl_data_div_dat(this,  & d);
800     }
801     /// Add the other data
802     void operator += (in MglDataA* d)
803     {
804         mgl_data_add_dat(this,  & d);
805     }
806     /// Subtract the other data
807     void operator -= (in MglDataA* d)
808     {
809         mgl_data_sub_dat(this,  & d);
810     }
811     /// Multiply each element by the number
812     void operator *= (mreal d)
813     {
814         mgl_data_mul_num(this, d);
815     }
816     /// Divide each element by the number
817     void operator /= (mreal d)
818     {
819         mgl_data_div_num(this, d);
820     }
821     /// Add the number
822     void operator += (mreal d)
823     {
824         mgl_data_add_num(this, d);
825     }
826     /// Subtract the number
827     void operator -= (mreal d)
828     {
829         mgl_data_sub_num(this, d);
830     }
831     #ifndef SWIG/// Direct access to the data cell
832     mreal & operator[](long i)
833     {
834         return a[i];
835     }
836     // NOTE see 13.10 for operator(), operator[] -- m.b. I should add it ???
837     #endif debug
838     {
839         /// Get the value in given cell of the data
840         mreal v(long i, long j = 0, long k = 0) const
841         {
842             return a[i + nx * (j + ny * k)];
843         }
844 
845         /// set the value in given cell of the data
846         void set_v(mreal val, long i, long j = 0, long k = 0)
847         {
848             a[i + nx * (j + ny * k)] = val;
849         }
850     }
851     else
852     {
853         /// Get the value in given cell of the data with border checking
854         mreal v(long i, long j = 0, long k = 0) const
855         {
856             return mgl_data_get_value(this, i, j, k);
857         }
858 
859         /// set the value in given cell of the data
860         void set_v(mreal val, long i, long j = 0, long k = 0)
861         {
862             mgl_data_set_value(this, val, i, j, k);
863         }
864     }
865    */
866     mreal vthr(long i) const
867     {
868         return a[i];
869     }
870 
871     // add for speeding up !!!
872     mreal dvx(long i, long j = 0, long k = 0) const
873     {
874         long i0 = i + nx * (j + ny * k);
875         return i > 0 ? (i < nx - 1 ? (a[i0 + 1] - a[i0 - 1]) / 2 : a[i0] - a[i0 - 1])
876             : a[i0 + 1] - a[i0];
877     }
878 
879     mreal dvy(long i, long j = 0, long k = 0) const
880     {
881         long i0 = i + nx * (j + ny * k);
882         return j > 0 ? (j < ny - 1 ? (a[i0 + nx] - a[i0 - nx]) / 2 : a[i0] - a[i0 - nx])
883             : a[i0 + nx] - a[i0];
884     }
885 
886     mreal dvz(long i, long j = 0, long k = 0) const
887     {
888         long i0 = i + nx * (j + ny * k), n = nx * ny;
889         return k > 0 ? (k < nz - 1 ? (a[i0 + n] - a[i0 - n]) / 2 : a[i0] - a[i0 - n])
890             : a[i0 + n] - a[i0];
891     }
892 };
893 //-----------------------------------------------------------------------------
894 static if (!SWIG)
895 {
896 	/*
897 	MglData operator * (in MglDataA* b, in MglDataA* d)
898 	{
899 	    MglData a( & b);
900 	    a *= d;
901 	    return a;
902 	}
903 	MglData operator * (mreal b, in MglDataA* d)
904 	{
905 	    MglData a( & d);
906 	    a *= b;
907 	    return a;
908 	}
909 	MglData operator * (in MglDataA* d, mreal b)
910 	{
911 	    MglData a( & d);
912 	    a *= b;
913 	    return a;
914 	}
915 	MglData operator - (in MglDataA* b, in MglDataA* d)
916 	{
917 	    MglData a( & b);
918 	    a -= d;
919 	    return a;
920 	}
921 	MglData operator - (mreal b, in MglDataA* d)
922 	{
923 	    MglData a( & d);
924 	    a -= b;
925 	    return a;
926 	}
927 	MglData operator - (in MglDataA* d, mreal b)
928 	{
929 	    MglData a( & d);
930 	    a -= b;
931 	    return a;
932 	}
933 	MglData operator + (in MglDataA* b, in MglDataA* d)
934 	{
935 	    MglData a( & b);
936 	    a += d;
937 	    return a;
938 	}
939 	MglData operator + (mreal b, in MglDataA* d)
940 	{
941 	    MglData a( & d);
942 	    a += b;
943 	    return a;
944 	}
945 	MglData operator + (in MglDataA* d, mreal b)
946 	{
947 	    MglData a( & d);
948 	    a += b;
949 	    return a;
950 	}
951 	MglData operator / (in MglDataA* b, in MglDataA* d)
952 	{
953 	    MglData a( & b);
954 	    a /= d;
955 	    return a;
956 	}
957 	MglData operator / (in MglDataA* d, mreal b)
958 	{
959 	    MglData a( & d);
960 	    a /= b;
961 	    return a;
962 	}
963 	bool operator == (in MglData* b, in MglData* d)
964 	{
965 	    if (b.nx != d.nx || b.ny != d.ny || b.nz != d.nz)
966 	        return false;
967 	    return !memcmp(b.a, d.a, b.nx * b.ny * b.nz * sizeof(mreal));
968 	}
969 	bool operator < (in MglDataA* b, in MglDataA* d)
970 	{
971 	    return b.maximal() < d.maximal();
972 	}
973 	bool operator > (in MglDataA* b, in MglDataA* d)
974 	{
975 	    return b.minimal() > d.minimal();
976 	}
977 
978 	*/
979 
980 	mreal mglLinear(const mreal * a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
981 	mreal mglSpline3(const mreal * a, long nx, long ny, long nz, mreal x, mreal y, mreal z, mreal * dx = 0, mreal * dy = 0, mreal * dz = 0);
982 	mreal mglSpline3s(const mreal * a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
983 }
984 
985 /// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for amplitude and phase
986 MglData mglTransformA(in MglDataA* am, in MglDataA* ph, string tr)
987 {
988     return MglData(true, mgl_transform_a( & am,  & ph, tr));
989 }
990 /// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for real and imaginary parts
991 MglData mglTransform(in MglDataA* re, in MglDataA* im, string tr)
992 {
993     return MglData(true, mgl_transform( & re,  & im, tr));
994 }
995 
996 /// Apply Fourier transform for the data and save result into it
997 void mglFourier(ref MglData re, ref MglData im, string dir)
998 {
999     mgl_data_fourier(re,  im, dir);
1000 }
1001 
1002 /// Short time Fourier analysis for real and imaginary parts. Output is amplitude of partial Fourier (result will have size {dn, floor(nx/dn), ny} for dir='x'
1003 MglData mglSTFA(ref MglDataA re, ref MglDataA im, long dn, char dir = 'x')
1004 {
1005     return MglData(true, mgl_data_stfa(re,im, dn, dir));
1006 }
1007 
1008 //-----------------------------------------------------------------------------
1009 /// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
1010 MglData mglPDE(HMGL gr, string ham, ref MglDataA* ini_re,
1011     ref MglDataA* ini_im, mreal dz = 0.1, mreal k0 = 100, string opt = "")
1012 {
1013     return MglData(true, mgl_pde_solve(gr, ham,  & ini_re,  &ini_im, dz, k0, opt));
1014 }
1015 
1016 /// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
1017 MglData mglQO2d(string ham, in MglDataA* ini_re, in MglDataA* ini_im,
1018     in MglDataA* ray, mreal r = 1, mreal k0 = 100)
1019 {
1020     return MglData(true, mgl_qo2d_solve(ham,  & ini_re,  & ini_im,  & ray, r, k0, 0,
1021         0));
1022 }
1023 
1024 MglData mglQO2d(string ham, in MglDataA* ini_re, in MglDataA* ini_im,
1025     in MglDataA* ray, ref MglData xx, ref MglData yy, mreal r = 1, mreal k0 = 100)
1026 {
1027     return MglData(true, mgl_qo2d_solve(ham,  & ini_re,  & ini_im,  & ray, r, k0,  & xx,
1028          & yy));
1029 }
1030 /// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
1031 
1032 MglData mglQO3d(string ham, in MglDataA* ini_re, in MglDataA* ini_im,
1033     in MglDataA* ray, mreal r = 1, mreal k0 = 100)
1034 {
1035     return MglData(true, mgl_qo3d_solve(ham,  & ini_re,  & ini_im,  & ray, r, k0, 0,
1036         0, 0));
1037 }
1038 
1039 MglData mglQO3d(string ham, ref  MglDataA ini_re, ref MglDataA ini_im,
1040     ref MglDataA ray, ref MglData xx, ref MglData yy, ref MglData zz, mreal r = 1, mreal k0 = 100)
1041 {
1042     return MglData(true, mgl_qo3d_solve(ham,  & ini_re,  & ini_im,  & ray, r,
1043         k0,  & xx,  & yy,  & zz));
1044 }
1045 /// Finds ray with starting point r0, p0 (and prepares ray data for mglQO2d)
1046 MglData mglRay(string ham, MglPoint r0, MglPoint p0, mreal dt = 0.1, mreal tmax = 10)
1047 {
1048     return MglData(true, mgl_ray_trace(ham, r0.x, r0.y, r0.z, p0.x, p0.y, p0.z, dt,
1049         tmax));
1050 }
1051 
1052 /// Saves result of ODE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
1053 MglData mglODE(string df, string var, in MglDataA* ini, mreal dt = 0.1,
1054     mreal tmax = 10)
1055 {
1056     return MglData(true, mgl_ode_solve_str(df, var,  & ini, dt, tmax));
1057 }
1058 /// Calculate Jacobian determinant for D{x(u,v), y(u,v)} = dx/du*dy/dv-dx/dv*dy/du
1059 MglData mglJacobian(in MglDataA* x, in MglDataA* y)
1060 {
1061     return MglData(true, mgl_jacobian_2d( & x,  & y));
1062 }
1063 /// Calculate Jacobian determinant for D{x(u,v,w), y(u,v,w), z(u,v,w)}
1064 MglData mglJacobian(in MglDataA* x, in MglDataA* y, in MglDataA* z)
1065 {
1066     return MglData(true, mgl_jacobian_3d( & x,  & y,  & z));
1067 }
1068 /// Do something like Delone triangulation
1069 MglData mglTriangulation(in MglDataA* x, in MglDataA* y, in MglDataA* z)
1070 {
1071     return MglData(true, mgl_triangulation_3d( & x,  & y,  & z));
1072 }
1073 MglData mglTriangulation(in MglDataA* x, in MglDataA* y)
1074 {
1075     return MglData(true, mgl_triangulation_2d( & x,  & y));
1076 }
1077 //-----------------------------------------------------------------------------
1078 /// Get sub-array of the data with given fixed indexes
1079 MglData mglSubData(in MglDataA* dat, long xx, long yy =  - 1, long zz =  - 1)
1080 {
1081     return MglData(true, mgl_data_subdata( & dat, xx, yy, zz));
1082 }
1083 MglData mglSubData(in MglDataA* dat, in MglDataA* xx, in MglDataA* yy,
1084     in MglDataA* zz)
1085 {
1086     return MglData(true, mgl_data_subdata_ext( & dat,  & xx,  & yy,  & zz));
1087 }
1088 MglData mglSubData(in MglDataA* dat, in MglDataA* xx, in MglDataA* yy)
1089 {
1090     return MglData(true, mgl_data_subdata_ext( & dat,  & xx,  & yy, 0));
1091 }
1092 MglData mglSubData(in MglDataA* dat, in MglDataA* xx)
1093 {
1094     return MglData(true, mgl_data_subdata_ext( & dat,  & xx, 0, 0));
1095 }
1096 //-----------------------------------------------------------------------------
1097 /// Prepare coefficients for global spline interpolation
1098 MglData mglGSplineInit(in MglDataA* xdat, in MglDataA* ydat)
1099 {
1100     return MglData(true, mgl_gspline_init(*xdat,  & ydat));
1101 }
1102 /// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
1103 mreal mglGSpline(in MglDataA* coef, mreal dx, mreal * d1 = 0, mreal * d2 = 0)
1104 {
1105     return mgl_gspline( & coef, dx, d1, d2);
1106 }
1107 //-----------------------------------------------------------------------------
1108 /// Wrapper class for expression evaluating
1109 class MglExpr
1110 {
1111     HMEX ex;
1112 
1113 	// copying is not allowed
1114 
1115     this(string expr)
1116     {
1117         ex = mgl_create_expr(expr.toStringz);
1118     }
1119 
1120     static if(HaveRval)
1121     {
1122     	this(MglExpr** d)
1123     	{
1124     		ex=d.ex;
1125 	        d.ex = 0;
1126 	    }
1127     }
1128 
1129     ~this()
1130     {
1131         mgl_delete_expr(ex);
1132     }
1133 
1134     /// Return value of expression for given x,y,z variables
1135     double eval(double x, double y = 0, double z = 0)
1136     {
1137         return mgl_expr_eval(ex, x, y, z);
1138     }
1139 
1140     /// Return value of expression differentiation over variable dir for given x,y,z variables
1141     double diff(char dir, double x, double y = 0, double z = 0)
1142     {
1143         return mgl_expr_diff(ex, dir, x, y, z);
1144     }
1145 
1146     static if(!SWIG)
1147     {
1148     	// Return value of expression for given variables
1149 	    double Eval(mreal var[26])
1150 	    {
1151 	        return mgl_expr_eval_v(ex, var);
1152 	    }
1153 
1154 	    /// Return value of expression differentiation over variable dir for given variables
1155 	    double Diff(char dir, mreal var[26])
1156 	    {
1157 	        return mgl_expr_diff_v(ex, dir, var);
1158 	    }
1159 	}
1160 }
1161 
1162 // Class which presents variable as data array
1163 class MglDataV : MglDataA
1164 {
1165     long nx; ///< number of points in 1st dimensions ('x' dimension)
1166     long ny; ///< number of points in 2nd dimensions ('y' dimension)
1167     long nz; ///< number of points in 3d dimensions ('z' dimension)
1168     mreal di, dj, dk, a0;
1169 
1170     this(long xx = 1, long yy = 1, long zz = 1, mreal x1 = 0, mreal x2 = mglNaN, char dir = 'x')
1171     {
1172     	this.nx=xx;
1173     	this.ny=ny;
1174     	this.nz=nz;
1175         fill(x1, x2, dir);
1176     }
1177 
1178     this(MglDataV d)
1179     {
1180     	this.nx=d.nx;
1181     	this.ny=d.ny;
1182     	this.nz=d.nz;
1183     	this.di=d.di;
1184     	this.dj=d.dj;
1185     	this.dk=d.dk;
1186     	this.a0=d.ao;
1187     }
1188 
1189     static if(HaveRval)
1190     {
1191     	this(MglDataV d)
1192     	{
1193     		this.nx=d.nx;
1194 	    	this.ny=d.ny;
1195 	    	this.nz=d.nz;
1196 	    	this.di=d.di;
1197 	    	this.dj=d.dj;
1198 	    	this.dk=d.dk;
1199 	    	this.a0=d.ao;
1200 	        s = d.s;
1201     	    temp = d.temp;
1202         	func = d.func;
1203         	o = d.o;
1204         	d.func = 0;
1205     	}
1206     }
1207 
1208     /// Get sizes
1209     long getNx() const
1210     {
1211         return nx;
1212     }
1213 
1214     long getNy() const
1215     {
1216         return ny;
1217     }
1218 
1219     long getNz() const
1220     {
1221         return nz;
1222     }
1223 
1224     /// create or recreate the array with specified size and fill it by zero
1225     void create(long mx, long my = 1, long mz = 1)
1226     {
1227         di = mx > 1 ? di * (nx - 1) / (mx - 1) : 0;
1228         dj = my > 1 ? dj * (ny - 1) / (my - 1) : 0;
1229         dk = mz > 1 ? dk * (nz - 1) / (mz - 1) : 0;
1230         nx = mx;
1231         ny = my;
1232         nz = mz;
1233     }
1234 
1235     /// For going throw all elements
1236     void all()
1237     {
1238         di = dj = dk = 1;
1239         a0 = 0;
1240     }
1241 
1242     /// Equidistantly fill the data to range [x1,x2] in direction dir
1243     void fill(mreal x1, mreal x2 = mglNaN, char dir = 'x')
1244     {
1245         di = dj = dk = 0;
1246         a0 = x1;
1247         if (mgl_isnum(x2))
1248         {
1249             if (dir == 'x' && nx > 1)
1250                 di = (x2 - x1) / (nx - 1);
1251             if (dir == 'y' && ny > 1)
1252                 dj = (x2 - x1) / (ny - 1);
1253             if (dir == 'z' && nz > 1)
1254                 dk = (x2 - x1) / (nz - 1);
1255         }
1256     }
1257 
1258     mreal maximal() const
1259     {
1260         return a0 + mgl_max(mgl_max(di * (nx - 1), dj * (ny - 1)), mgl_max(dk * (nz - 1),
1261             0));
1262     }
1263 
1264     mreal minimal() const
1265     {
1266         return a0 + mgl_min(mgl_min(di * (nx - 1), dj * (ny - 1)), mgl_min(dk * (nz - 1),
1267             0));
1268     }
1269 
1270     /*
1271     /// Copy data from other MglDataV variable
1272     const MglDataV & operator = (const MglDataV & d)
1273     {
1274         nx = d.nx;
1275         ny = d.ny;
1276         nz = d.nz;
1277         a0 = d.a0;
1278         di = d.di;
1279         dj = d.dj;
1280         dk = d.dk;
1281         return d;
1282     }
1283     mreal operator = (mreal val)
1284     {
1285         di = dj = dk = 0;
1286         a0 = val;
1287         return val;
1288     }
1289     */
1290 
1291     /// Get the value in given cell of the data without border checking
1292     mreal value(mreal x, mreal y, mreal z, mreal * dx = 0, mreal * dy = 0, mreal * dz = 0) const
1293     {
1294         if (dx)
1295              * dx = di;
1296         if (dy)
1297              * dy = dj;
1298         if (dz)
1299              * dz = dk;
1300         return a0 + di * x + dj * y + dk * z;
1301     }
1302     mreal v(long i, long j = 0, long k = 0) const
1303     {
1304         return a0 + di * i + dj * j + dk * k;
1305     }
1306 
1307     mreal vthr(long ii) const
1308     {
1309         long i = ii % nx, j = (ii / nx) % ny, k = ii / (nx * ny);
1310         return a0 + di * i + dj * j + dk * k;
1311     }
1312 
1313     // add for speeding up !!!
1314     mreal dvx(long, long = 0, long = 0) const
1315     {
1316         return di;
1317     }
1318 
1319     mreal dvy(long, long = 0, long = 0) const
1320     {
1321         return dj;
1322     }
1323 
1324     mreal dvz(long, long = 0, long = 0) const
1325     {
1326         return dk;
1327     }
1328 };
1329 //-----------------------------------------------------------------------------
1330 /// Class which present FFT frequency as data array
1331 class MglDataW : MglDataA
1332 {
1333     long nx; ///< number of points in 1st dimensions ('x' dimension)
1334     long ny; ///< number of points in 2nd dimensions ('y' dimension)
1335     long nz; ///< number of points in 3d dimensions ('z' dimension)
1336     mreal di, dj, dk;
1337 
1338     this(long xx = 1, long yy = 1, long zz = 1, mreal dp = 0, char dir = 'x')
1339     {
1340     	this.nx=xx;
1341     	this.ny=yy;
1342     	this.nz=zz;
1343         freq(dp, dir);
1344     }
1345 
1346     this(const MglDataW d)
1347     {
1348 		this.nx=d.nx;
1349 		this.ny=d.ny;
1350 		this.nz=d.nz;
1351 		this.di=d.di;
1352 		this.dj=d.dj;
1353 		this.dk=d.dk;
1354 	}
1355 
1356     static if (HaveRval)
1357     {
1358     	this(MglDataW* d)
1359     	{
1360 			this.nx=d.nx;
1361 			this.ny=d.ny;
1362 			this.nz=d.nz;
1363 			this.di=d.di;
1364 			this.dj=d.dj;
1365 			this.dk=d.dk;
1366 	        s = d.s;
1367 	        temp = d.temp;
1368 	        func = d.func;
1369 	        o = d.o;
1370 	        d.func = 0;
1371 	    }
1372     }
1373 
1374     /// Get sizes
1375     long getNx() const
1376     {
1377         return nx;
1378     }
1379 
1380     long getNy() const
1381     {
1382         return ny;
1383     }
1384 
1385     long getNz() const
1386     {
1387         return nz;
1388     }
1389 
1390     /// create or recreate the array with specified size and fill it by zero
1391     void create(long mx, long my = 1, long mz = 1)
1392     {
1393         nx = mx;
1394         ny = my;
1395         nz = mz;
1396     }
1397 
1398     /// For going throw all elements
1399     void all()
1400     {
1401         di = dj = dk = 1;
1402     }
1403 
1404     /// Equidistantly fill the data to range [x1,x2] in direction dir
1405     void Freq(mreal dp, char dir = 'x')
1406     {
1407         di = dj = dk = 0;
1408         if (dir == 'x')
1409             di = dp;
1410         if (dir == 'y')
1411             dj = dp;
1412         if (dir == 'z')
1413             dk = dp;
1414     }
1415 
1416     mreal maximal() const
1417     {
1418         return mgl_max(mgl_max(di * (nx - 1), dj * (ny - 1)), mgl_max(dk * (nz - 1),
1419             0));
1420     }
1421 
1422     mreal minimal() const
1423     {
1424         return mgl_min(mgl_min(di * (nx - 1), dj * (ny - 1)), mgl_min(dk * (nz - 1),
1425             0));
1426     }
1427 /*
1428     /// Copy data from other MglDataV variable
1429     const MglDataW & operator = (const MglDataW & d)
1430     {
1431         nx = d.nx;
1432         ny = d.ny;
1433         nz = d.nz;
1434         di = d.di;
1435         dj = d.dj;
1436         dk = d.dk;
1437         return d;
1438     }
1439 */
1440     /// Get the value in given cell of the data without border checking
1441     mreal value(mreal x, mreal y, mreal z, mreal* dx = 0, mreal* dy = 0, mreal* dz = 0) const
1442     {
1443         if (dx)
1444             *dx = di;
1445         if (dy)
1446             *dy = dj;
1447         if (dz)
1448             *dz = dk;
1449         return di * (x < nx / 2 ? x : nx - x) + dj * (y < ny / 2 ? y : ny - y) + dk * (
1450             z < nz / 2 ? z : nz - z);
1451     }
1452 
1453     mreal v(long i, long j = 0, long k = 0) const
1454     {
1455         return di * (i < nx / 2 ? i : nx - i) + dj * (j < ny / 2 ? j : ny - j) + dk * (
1456             k < nz / 2 ? k : nz - k);
1457     }
1458 
1459     mreal vthr(long ii) const
1460     {
1461         long i = ii % nx, j = (ii / nx) % ny, k = ii / (nx * ny);
1462         return di * (i < nx / 2 ? i : nx - i) + dj * (j < ny / 2 ? j : ny - j) + dk * (
1463             k < nz / 2 ? k : nz - k);
1464     }
1465 
1466     // add for speeding up !!!
1467     mreal dvx(long, long = 0, long = 0) const
1468     {
1469         return di;
1470     }
1471 
1472     mreal dvy(long, long = 0, long = 0) const
1473     {
1474         return dj;
1475     }
1476 
1477     mreal dvz(long, long = 0, long = 0) const
1478     {
1479         return dk;
1480     }
1481 }
1482 
1483 // Class which presents variable as data array
1484 class MglDataF : MglDataA
1485 {
1486     long nx; ///< number of points in 1st dimensions ('x' dimension)
1487     long ny; ///< number of points in 2nd dimensions ('y' dimension)
1488     long nz; ///< number of points in 3d dimensions ('z' dimension)
1489 	string str; ///< function as string
1490     MglPoint v1, v2; ///< ranges for coordinates
1491     HMEX ex; ///< parsed variant
1492     mreal dx, dy, dz;
1493     void setD()
1494     {
1495         dx = nx > 1 ? (v2.x - v1.x) / (nx - 1) : 0;
1496         dy = ny > 1 ? (v2.y - v1.y) / (ny - 1) : 0;
1497         dz = nz > 1 ? (v2.z - v1.z) / (nz - 1) : 0;
1498     }
1499 
1500     mreal function(mreal i, mreal j, mreal k, void * par) func;
1501     void* par;
1502 
1503     this(long xx = 1, long yy = 1, long zz = 1)
1504     {
1505     	this.nx=xx;
1506     	this.ny=yy;
1507     	this.nz=zz;
1508     	this.dfunc=0;
1509     	this.par=0;
1510         ex = 0;
1511         v2 = MglPoint(1, 1, 1);
1512         setD();
1513     }
1514 
1515     this(MglDataF d)
1516     {
1517     	this.nx=d.nx;
1518     	this.ny=d.ny;
1519     	this.nz=d.nz;
1520     	this.str=d.str;
1521         this.v1=d.v1;
1522         this.v2=d.v2;
1523         this.dx=d.dx;
1524         this.dy=d.dy;
1525         this.dz=d.dz;
1526         this.dfunc=d.dfunc;
1527         this.par=d.par;
1528         ex = mgl_create_expr(str.c_str());
1529     }
1530 
1531     static if(HaveRval)
1532     {
1533     	this(MglDataF d)
1534     	{
1535 	    	this.nx=d.nx;
1536 	    	this.ny=d.ny;
1537 	    	this.nz=d.nz;
1538 	    	this.str=d.str;
1539 	        this.v1=d.v1;
1540 	        this.v2=d.v2;
1541 	        this.dx=d.dx;
1542 	        this.dy=d.dy;
1543 	        this.dz=d.dz;
1544 	        this.dfunc=d.dfunc;
1545 	        this.par=d.par;
1546 	        s = d.s;
1547 	        temp = d.temp;
1548 	        func = d.func;
1549 	        o = d.o;
1550 	        d.ex = 0;
1551 	        d.func = 0;
1552     	}
1553     }
1554 
1555     ~this()
1556     {
1557         mgl_delete_expr(ex);
1558     }
1559 
1560     /// Get sizes
1561     long getNx() const
1562     {
1563         return nx;
1564     }
1565 
1566     long getNy() const
1567     {
1568         return ny;
1569     }
1570 
1571     long getNz() const
1572     {
1573         return nz;
1574     }
1575 
1576     /// create or recreate the array with specified size and fill it by zero
1577     void create(long mx, long my = 1, long mz = 1)
1578     {
1579         nx = mx;
1580         ny = my;
1581         nz = mz;
1582         setD();
1583     }
1584 
1585     void setRanges(MglPoint p1, MglPoint p2)
1586     {
1587         v1 = p1;
1588         v2 = p2;
1589         setD();
1590     }
1591 
1592     /// set formula to be used as dfunction
1593     void setFormula(string eq)
1594     {
1595         mgl_delete_expr(ex);
1596         dfunc = 0;
1597         par = 0;
1598         if (eq && *eq)
1599         {
1600             ex = mgl_create_expr(eq);
1601             str = eq;
1602         }
1603         else
1604         {
1605             ex = 0;
1606             str = "";
1607         }
1608     }
1609 
1610     /// set dfunction and coordinates range [r1,r2]
1611     void setFunc(mreal function(mreal, mreal, mreal, void * ) f, void * p = NULL)
1612     {
1613         mgl_delete_expr(ex);
1614         ex = 0;
1615         dfunc = f;
1616         par = p;
1617     }
1618 
1619     mreal value(mreal i, mreal j = 0, mreal k = 0, mreal* di = 0, mreal* dj = 0, mreal* dk = 0) const
1620     {
1621         mreal res = 0, x = v1.x + dx * i, y = v1.y + dy * j, z = v1.z + dz * k;
1622         if (di)
1623             *di = 0;
1624         if (dj)
1625             *dj = 0;
1626         if (dk)
1627             *dk = 0;
1628         if (dfunc)
1629         {
1630             res = dfunc(x, y, z, par);
1631             if (di)
1632                 *di = dfunc(x + dx, y, z, par) - res;
1633             if (dj)
1634                 *dj = dfunc(x, y + dy, z, par) - res;
1635             if (dk)
1636                 *dk = dfunc(x, y, z + dz, par) - res;
1637         }
1638         else if (ex)
1639         {
1640             if (di)
1641                 *di = mgl_expr_diff(ex, 'x', x, y, z) * dx;
1642             if (dj)
1643                 *dj = mgl_expr_diff(ex, 'y', x, y, z) * dy;
1644             if (dk)
1645                 *dk = mgl_expr_diff(ex, 'z', x, y, z) * dz;
1646             res = mgl_expr_eval(ex, x, y, z);
1647         }
1648         return res;
1649     }
1650 /*
1651     /// Copy data from other MglDataV variable
1652     const MglDataF & operator = (const MglDataF & d)
1653     {
1654         nx = d.nx;
1655         ny = d.ny;
1656         nz = d.nz;
1657         v1 = d.v1;
1658         v2 = d.v2;
1659         setD();
1660         str = d.str;
1661         ex = mgl_create_expr(str.c_str());
1662         dfunc = d.dfunc;
1663         par = d.par;
1664         return d;
1665     }
1666   */
1667     /// Get the value in given cell of the data without border checking
1668     mreal v(long i, long j = 0, long k = 0) const
1669     {
1670         mreal res = 0, x = v1.x + dx * i, y = v1.y + dy * j, z = v1.z + dz * k;
1671         if (dfunc)
1672             res = dfunc(x, y, z, par);
1673         else if (ex)
1674             res = mgl_expr_eval(ex, x, y, z);
1675         return res;
1676     }
1677 
1678     mreal vthr(long i) const
1679     {
1680         mreal res = 0, x = v1.x + dx * (i % nx), y = v1.y + dy * ((i / nx) % ny),
1681             z = v1.z + dz * (i / (nx * ny));
1682         if (dfunc)
1683             res = dfunc(x, y, z, par);
1684         else if (ex)
1685             res = mgl_expr_eval(ex, x, y, z);
1686         return res;
1687     }
1688 
1689     // add for speeding up !!!
1690     mreal dvx(long i, long j = 0, long k = 0) const
1691     {
1692         mreal res = 0, x = v1.x + dx * i, y = v1.y + dy * j, z = v1.z + dz * k;
1693         if (dfunc)
1694             res = dfunc(x + dx, y, z, par) - dfunc(x, y, z, par);
1695         else if (ex)
1696             res = mgl_expr_eval(ex, x + dx, y, z) - mgl_expr_eval(ex, x, y, z);
1697         return res;
1698     }
1699 
1700     mreal dvy(long i, long j = 0, long k = 0) const
1701     {
1702         mreal res = 0, x = v1.x + dx * i, y = v1.y + dy * j, z = v1.z + dz * k;
1703         if (dfunc)
1704             res = dfunc(x, y + dy, z, par) - dfunc(x, y, z, par);
1705         else if (ex)
1706             res = mgl_expr_eval(ex, x, y + dy, z) - mgl_expr_eval(ex, x, y, z);
1707         return res;
1708     }
1709 
1710     mreal dvz(long i, long j = 0, long k = 0) const
1711     {
1712         mreal res = 0, x = v1.x + dx * i, y = v1.y + dy * j, z = v1.z + dz * k;
1713         if (dfunc)
1714             res = dfunc(x, y, z + dz, par) - dfunc(x, y, z, par);
1715         else if (ex)
1716             res = mgl_expr_eval(ex, x, y, z + dz) - mgl_expr_eval(ex, x, y, z);
1717         return res;
1718     }
1719 }
1720 
1721 // Class which present variable as data array
1722 class MglDataT : MglDataA
1723 {
1724     MglDataA* dat;
1725     long ind;
1726 
1727     this(const MglDataT d)
1728     {
1729     	this.dat=d.dat;
1730     	this.ind=d.ind;
1731         s = d.s;
1732     }
1733 
1734     this(in MglDataA* d, long col = 0)
1735     {
1736     	this.dat=d;
1737     	this.ind=col;
1738     }
1739 
1740     static if(HaveRval)
1741     {
1742     	this(MglDataT* d)
1743     	{
1744     		this.dat=d.dat;
1745     		this.ind=d.ind;
1746 	        s = d.s;
1747 	        temp = d.temp;
1748 	        func = d.func;
1749 	        o = d.o;
1750 	        d.func = 0;
1751 	    }
1752     }
1753 
1754     ~this()
1755     {
1756     }
1757 
1758     /// Get sizes
1759     long getNx() const
1760     {
1761         return dat.getNy();
1762     }
1763 
1764     long getNy() const
1765     {
1766         return dat.getNz();
1767     }
1768 
1769     long getNz() const
1770     {
1771         return 1;
1772     }
1773 
1774     mreal maximal() const
1775     {
1776         return mglSubData(dat, ind).maximal();
1777     }
1778 
1779     mreal minimal() const
1780     {
1781         return mglSubData(dat, ind).minimal();
1782     }
1783 
1784     void setInd(long i, const wchar_t* name)
1785     {
1786         ind = i;
1787         s = name;
1788     }
1789 
1790     void setInd(long i, wchar_t name)
1791     {
1792         ind = i;
1793         s = name;
1794     }
1795 
1796     /// Get the value in given cell of the data without border checking
1797     mreal v(long i, long j = 0, long = 0) const
1798     {
1799         return dat.v(ind, i, j);
1800     }
1801 
1802     mreal vthr(long i) const
1803     {
1804         return dat.vthr(ind + dat.getNx() * i);
1805     }
1806 
1807     // add for speeding up !!!
1808     mreal dvx(long i, long j = 0, long = 0) const
1809     {
1810         return dat.dvy(ind, i, j);
1811     }
1812 
1813     mreal dvy(long i, long j = 0, long = 0) const
1814     {
1815         return dat.dvz(ind, i, j);
1816     }
1817 
1818     mreal dvz(long, long = 0, long = 0) const
1819     {
1820         return 0;
1821     }
1822 }
1823 
1824 class MglDataR : MglDataA
1825 {
1826     MglDataA* dat;
1827     long ind;
1828 
1829     this(const MglDataR d)
1830     {
1831     	this.dat=d.dat;
1832     	this.ind=d.ind;
1833     	s=d.s;
1834     }
1835 
1836     this(in MglDataA d, long row = 0)
1837     {
1838     	this.dat=d;
1839     	this.ind=row;
1840     }
1841 
1842     static if(HaveRval)
1843     {
1844     	this(MglDataR* d)
1845     	{
1846     		this.dat=d.dat;
1847     		this.ind=d.ind;
1848 	        s = d.s;
1849 	        temp = d.temp;
1850 	        func = d.func;
1851 	        o = d.o;
1852 	        d.func = 0;
1853 	    }
1854 	}
1855 	~this()
1856 	{
1857 
1858 	}
1859 
1860     /// Get sizes
1861     long getNx() const
1862     {
1863         return dat.getNx();
1864     }
1865 
1866     long getNy() const
1867     {
1868         return 1;
1869     }
1870 
1871     long getNz() const
1872     {
1873         return 1;
1874     }
1875 
1876     mreal maximal() const
1877     {
1878         return mglSubData(dat, -1, ind).maximal();
1879     }
1880 
1881     mreal minimal() const
1882     {
1883         return mglSubData(dat, -1, ind).minimal();
1884     }
1885 
1886     void setInd(long i, const wchar_t* name)
1887     {
1888         ind = i;
1889         s = name;
1890     }
1891 
1892     void setInd(long i, wchar_t name)
1893     {
1894         ind = i;
1895         s = name;
1896     }
1897 
1898     /// Get the value in given cell of the data without border checking
1899     mreal v(long i, long j= 0, long k= 0) const
1900     {
1901         return dat.v(i, ind, 0);
1902     }
1903 
1904     mreal vthr(long i) const
1905     {
1906         return dat.vthr(i + dat.getNx() * ind);
1907     }
1908 
1909     // add for speeding up !!!
1910     mreal dvx(long i, long j = 0, long k= 0) const
1911     {
1912         return dat.dvx(i, ind, 0);
1913     }
1914 
1915     mreal dvy(long i, long j = 0, long k= 0) const
1916     {
1917         return 0;
1918     }
1919 
1920     mreal dvz(long i, long j= 0, long k = 0) const
1921     {
1922         return 0;
1923     }
1924 }
1925 
1926 
1927 auto mgl2()
1928 {
1929 	return mreal(2);
1930 }
1931 
1932 auto mgl3()
1933 {
1934 	return mreal(3);
1935 }
1936 
1937 auto mgl4()
1938 {
1939 	return mreal(4);
1940 }
1941 
1942 
1943 /// Class for working with complex data array
1944 class MglDataC:MglDataA
1945 {
1946     //public : using MglDataA :  : Momentum;
1947     long nx; ///< number of points in 1st dimensions ('x' dimension)
1948     long ny; ///< number of points in 2nd dimensions ('y' dimension)
1949     long nz; ///< number of points in 3d dimensions ('z' dimension)
1950     dual* a; ///< data array
1951 	string id; ///< column (or slice) names
1952     bool useLink; ///< use external data (i.e. don't free it)
1953 
1954     /// Initiate by other MglDataC variable
1955     this(in MglDataC* d)
1956     {
1957         a = 0;
1958         mgl_datac_set(this,  & d);
1959     } // NOTE: must be constructor for MglDataC& to exclude copy one
1960 
1961     this(in MglDataA* d)
1962     {
1963         a = 0;
1964         mgl_datac_set(this,  & d);
1965     }
1966 
1967     static if(HaveRval)
1968     {
1969     	this(MglDataC**  d)
1970     	{
1971     		this.nx=d.nx;
1972     		this.ny=d.ny;
1973     		this.nz=d.nz;
1974     		this.a=d.a;
1975     		this.id=d.id;
1976     		this.useLink=d.useLink;
1977 	        //this.s = d.s;
1978 	        //this.temp = d.temp;
1979 	        func = d.func;
1980 	        //this.o = d.o;
1981 	        d.a = 0;
1982 	        d.func = 0;
1983 	    }
1984 	}
1985     
1986     this(in MglDataA* re, in MglDataA* im)
1987     {
1988         a = 0;
1989         mgl_datac_set_ri(this,  & re,  *im);
1990     }
1991 
1992     this(HCDT d)
1993     {
1994         a = 0;
1995         mgl_datac_set(this, d);
1996     }
1997 
1998     this(HCDT re, HCDT im)
1999     {
2000         a = 0;
2001         mgl_datac_set_ri(this, re, im);
2002     }
2003 
2004     this(bool, MglDataC * d) // NOTE: Variable d will be deleted!!!
2005     {
2006         if (d)
2007         {
2008             nx = d.nx;
2009             ny = d.ny;
2010             nz = d.nz;
2011             a = d.a;
2012             d.a = 0;
2013             temp = d.temp;
2014             func = d.func;
2015             o = d.o;
2016             s = d.s;
2017             id = d.id;
2018             useLink = d.useLink;
2019             delete d;
2020         }
2021         else
2022         {
2023             a = 0;
2024             Create(1);
2025         }
2026     }
2027 
2028     /// Initiate by flat array
2029     this(int size, const dual * d)
2030     {
2031         a = 0;
2032         set(d, size);
2033     }
2034     this(int rows, int cols, const dual * d)
2035     {
2036         a = 0;
2037         set(d, cols, rows);
2038     }
2039     this(int size, const double * d)
2040     {
2041         a = 0;
2042         set(d, size);
2043     }
2044     this(int rows, int cols, const double * d)
2045     {
2046         a = 0;
2047         set(d, cols, rows);
2048     }
2049     this(int size, const float * d)
2050     {
2051         a = 0;
2052         set(d, size);
2053     }
2054     this(int rows, int cols, const float * d)
2055     {
2056         a = 0;
2057         set(d, cols, rows);
2058     }
2059     this(in dual * d, int size)
2060     {
2061         a = 0;
2062         set(d, size);
2063     }
2064     this(in dual * d, int rows, int cols)
2065     {
2066         a = 0;
2067         set(d, cols, rows);
2068     }
2069     this(in double * d, int size)
2070     {
2071         a = 0;
2072         set(d, size);
2073     }
2074     this(in double * d, int rows, int cols)
2075     {
2076         a = 0;
2077         set(d, cols, rows);
2078     }
2079     this(in float * d, int size)
2080     {
2081         a = 0;
2082         set(d, size);
2083     }
2084     this(in float * d, int rows, int cols)
2085     {
2086         a = 0;
2087         set(d, cols, rows);
2088     }
2089     /// read data from file
2090     this(string fname)
2091     {
2092         a = 0;
2093         read(fname);
2094     }
2095     /// Allocate the memory for data array and initialize it zero
2096     this(long xx = 1, long yy = 1, long zz = 1)
2097     {
2098         a = 0;
2099         Create(xx, yy, zz);
2100     }
2101     /// Delete the array
2102     ~this()
2103     {
2104         //if (!useLink && a)
2105           //  delete[] a;
2106     }
2107 
2108     dual getVal(long i, long j = 0, long k = 0) const
2109     {
2110         return mgl_datac_get_value(this, i, j, k);
2111     }
2112 
2113     void setVal(dual f, long i, long j = 0, long k = 0)
2114     {
2115         mgl_datac_set_value(this, f, i, j, k);
2116     }
2117 
2118     /// get sizes
2119     long getNx() const
2120     {
2121         return nx;
2122     }
2123 
2124     long getNy() const
2125     {
2126         return ny;
2127     }
2128 
2129     long getNz() const
2130     {
2131         return nz;
2132     }
2133 
2134     /// Link external data array (don't delete it at exit)
2135     void link(dual* A, long NX, long NY = 1, long NZ = 1)
2136     {
2137         mgl_datac_link(this, A, NX, NY, NZ);
2138     }
2139 
2140     void link(MglDataC* d)
2141     {
2142         Link(d.a, d.nx, d.ny, d.nz);
2143     }
2144     /// Allocate memory and copy the data from the gsl_vector
2145     void set(gsl_vector* m)
2146     {
2147         mgl_datac_set_vector(this, m);
2148     }
2149 
2150     /// Allocate memory and copy the data from the gsl_matrix
2151     void set(gsl_matrix* m)
2152     {
2153         mgl_datac_set_matrix(this, m);
2154     }
2155 
2156     /// Allocate memory and copy the data from the (float *) array
2157     void set(const float* A, long NX, long NY = 1, long NZ = 1)
2158     {
2159         mgl_datac_set_float(this, A, NX, NY, NZ);
2160     }
2161 
2162     /// Allocate memory and copy the data from the (double *) array
2163     void set(const double* A, long NX, long NY = 1, long NZ = 1)
2164     {
2165         mgl_datac_set_double(this, A, NX, NY, NZ);
2166     }
2167 
2168     /// Allocate memory and copy the data from the (complex *) array
2169     void set(const dual* A, long NX, long NY = 1, long NZ = 1)
2170     {
2171         mgl_datac_set_complex(this, A, NX, NY, NZ);
2172     }
2173 
2174     /// Allocate memory and scanf the data from the string
2175     void set(string str, long NX, long NY = 1, long NZ = 1)
2176     {
2177         mgl_datac_set_values(this, str.toStringz, NX, NY, NZ);
2178     }
2179 
2180     /// Import data from abstract type
2181     void set(HCDT dat)
2182     {
2183         mgl_datac_set(this, dat);
2184     }
2185 
2186     void set(in MglDataA* dat)
2187     {
2188         mgl_datac_set(this,  & dat);
2189     }
2190     void set(in MglDataA* re, in MglDataA* im)
2191     {
2192         mgl_datac_set_ri(this,  & re,  & im);
2193     }
2194     void set(HCDT re, HCDT im)
2195     {
2196         mgl_datac_set_ri(this, re, im);
2197     }
2198 
2199     void setAmpl(in MglDataA* ampl, in MglDataA* phase)
2200     {
2201         mgl_datac_set_ap(this,  & ampl,  & phase);
2202     }
2203     /// Allocate memory and copy data from std::vector<T>
2204     void set(int[] d)
2205     {
2206         if (d.length < 1)
2207             return;
2208         Create(d.length());
2209         foreach(i;0..nx)
2210             a[i] = d[i];
2211     }
2212     void set(float[] d)
2213     {
2214         if (d.length < 1)
2215             return;
2216         create(d.length());
2217         foreach(i;0..nx)
2218             a[i] = d[i];
2219     }
2220     void set(double[] d)
2221     {
2222         if (d.length() < 1)
2223             return;
2224         Create(d.length);
2225         foreach(i;0..nx)
2226             a[i] = d[i];
2227     }
2228     
2229     void set(dual[] d)
2230     {
2231         if (d.length() < 1)
2232             return;
2233         create(d.length);
2234         foreach(i;0..nx)
2235             a[i] = d[i];
2236     }
2237 
2238     /// Create or recreate the array with specified size and fill it by zero
2239     void create(long mx, long my = 1, long mz = 1)
2240     {
2241         mgl_datac_create(this, mx, my, mz);
2242     }
2243 
2244     /// Rearange data dimensions
2245     void rearrange(long mx, long my = 0, long mz = 0)
2246     {
2247         mgl_datac_rearrange(this, mx, my, mz);
2248     }
2249 
2250     /// Transpose dimensions of the data (generalization of Transpose)
2251     void transpose(string dim = "yx")
2252     {
2253         mgl_datac_transpose(this, dim.toStringz);
2254     }
2255 
2256     /// Extend data dimensions
2257     void extend(long n1, long n2 = 0)
2258     {
2259         mgl_datac_extend(this, n1, n2);
2260     }
2261 
2262     /// Reduce size of the data
2263     void squeeze(long rx, long ry = 1, long rz = 1, bool smooth = false)
2264     {
2265         mgl_datac_squeeze(this, rx, ry, rz, smooth);
2266     }
2267 
2268     /// Crop the data
2269     void crop(long n1, long n2, char dir = 'x')
2270     {
2271         mgl_datac_crop(this, n1, n2, dir);
2272     }
2273 
2274     /// Insert data
2275     void insert(char dir, long at = 0, long num = 1)
2276     {
2277         mgl_datac_insert(this, dir, at, num);
2278     }
2279 
2280     /// Delete data
2281     void deleteData(char dir, long at = 0, long num = 1)
2282     {
2283         mgl_datac_delete(this, dir, at, num);
2284     }
2285 
2286     /// Join with another data array
2287     void join(in MglDataA* d)
2288     {
2289         mgl_datac_join(this,  & d);
2290     }
2291 
2292     /// Modify the data by specified formula
2293     void modify(string eq, long dim = 0)
2294     {
2295         mgl_datac_modify(this, eq, dim);
2296     }
2297 
2298     /// Modify the data by specified formula
2299     void modify(const char * eq, in MglDataA* vdat, in MglDataA* wdat)
2300     {
2301         mgl_datac_modify_vw(this, eq,  & vdat,  & wdat);
2302     }
2303     /// Modify the data by specified formula
2304     void modify(const char * eq, in MglDataA* vdat)
2305     {
2306         mgl_datac_modify_vw(this, eq,  & vdat, 0);
2307     }
2308     /// Modify the data by specified formula assuming x,y,z in range [r1,r2]
2309     void fill(mglBase* gr, string eq, string opt = "")
2310     {
2311         mgl_datac_fill_eq(gr, this, eq, 0, 0, opt);
2312     }
2313 
2314     void fill(mglBase * gr, const char * eq, in MglDataA* vdat, string opt = "")
2315     {
2316         mgl_datac_fill_eq(gr, this, eq,  & vdat, 0, opt.toStringz);
2317     }
2318 
2319     void Fill(mglBase * gr, const char * eq, in MglDataA* vdat, in MglDataA* wdat,string opt = "")
2320     {
2321         mgl_datac_fill_eq(gr, this, eq,  & vdat,  & wdat, opt.toStringz);
2322     }
2323     /// Equidistantly fill the data to range [x1,x2] in direction dir
2324     void fill(dual x1, dual x2 = mglNaN, char dir = 'x')
2325     {
2326         mgl_datac_fill(this, x1, x2, dir);
2327     }
2328 
2329     /// Put value to data element(s)
2330     void put(dual val, long i = -1, long j = -1, long k = -1)
2331     {
2332         mgl_datac_put_val(this, val, i, j, k);
2333     }
2334 
2335     /// Put array to data element(s)
2336     void put(in MglDataA* dat, long i =  - 1, long j =  - 1, long k =  - 1)
2337     {
2338         mgl_datac_put_dat(this,  & dat, i, j, k);
2339     }
2340 
2341     /// set names for columns (slices)
2342     void setColumnId(string ids)
2343     {
2344         mgl_datac_set_id(this, ids);
2345     }
2346 
2347     /// Make new id
2348     void newId()
2349     {
2350         id.clear();
2351     }
2352 
2353     /// read data from tab-separated text file with auto determining size
2354     bool read(string fname)
2355     {
2356         return mgl_datac_read(this, fname.toStringz);
2357     }
2358 
2359     /// read data from text file with specifeid size
2360     bool read(string fname, long mx, long my = 1, long mz = 1)
2361     {
2362         return mgl_datac_read_dim(this, fname.toStringz, mx, my, mz);
2363     }
2364 
2365     /// save whole data array (for ns=-1) or only ns-th slice to text file
2366     void save(string fname, long ns = -1) const
2367     {
2368         mgl_datac_save(this, fname.toStringz, ns);
2369     }
2370 
2371     /// read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
2372     bool readRange(string templ, double from, double to,
2373         double step = 1, bool as_slice = false)
2374     {
2375         return mgl_datac_read_range(this, templ.toStringz, from, to, step, as_slice);
2376     }
2377 
2378     /// read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
2379     bool readAll(string templ, bool as_slice = false)
2380     {
2381         return mgl_datac_read_all(this, templ.toStringz, as_slice);
2382     }
2383 
2384     /// read data from text file with size specified at beginning of the file
2385     bool readMat(string fname, long dim = 2)
2386     {
2387         return mgl_datac_read_mat(this, fname.toStringz, dim);
2388     }
2389 
2390     /// read data array from HDF file (parse HDF4 and HDF5 files)
2391     int readHDF(string fname, ubyte[] data)
2392     {
2393         return mgl_datac_read_hdf(this, fname, data.ptr);
2394     }
2395 
2396     /// save data to HDF file
2397     void saveHDF(string fname, ubyte[] data, bool rewrite = false) const
2398     {
2399         mgl_datac_save_hdf(this, fname, data.ptr, rewrite);
2400     }
2401 
2402     /// get real part of data values
2403     MglData getReal() const
2404     {
2405         return MglData(true, mgl_datac_real(this));
2406     }
2407     /// get imaginary part of data values
2408     MglData getImag() const
2409     {
2410         return MglData(true, mgl_datac_imag(this));
2411     }
2412     /// get absolute value of data values
2413     MglData getAbs() const
2414     {
2415         return MglData(true, mgl_datac_abs(this));
2416     }
2417     /// get argument of data values
2418     MglData getArg() const
2419     {
2420         return MglData(true, mgl_datac_arg(this));
2421     }
2422 
2423     /// get column (or slice) of the data filled by formulas of named columns
2424     MglDataC getColumn(string eq) const
2425     {
2426         return MglDataC(true, mgl_datac_column(this, eq.toStringz));
2427     }
2428 
2429     /// get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
2430     MglDataC getMomentum(char dir, string how) const
2431     {
2432         return MglDataC(true, mgl_datac_momentum(this, dir, how.toStringz));
2433     }
2434     /// get sub-array of the data with given fixed indexes
2435     MglDataC subData(long xx, long yy =  - 1, long zz =  - 1) const
2436     {
2437         return MglDataC(true, mgl_datac_subdata(this, xx, yy, zz));
2438     }
2439     MglDataC subData(in MglDataA* xx, in MglDataA* yy, in MglDataA* zz) const
2440     {
2441         return MglDataC(true, mgl_datac_subdata_ext(this,  & xx,  & yy,  & zz));
2442     }
2443     MglDataC subData(in MglDataA* xx, in MglDataA* yy) const
2444     {
2445         return MglDataC(true, mgl_datac_subdata_ext(this,  & xx,  & yy, 0));
2446     }
2447     MglDataC subData(in MglDataA* xx) const
2448     {
2449         return MglDataC(true, mgl_datac_subdata_ext(this,  & xx, 0, 0));
2450     }
2451     /// get trace of the data array
2452     MglDataC trace() const
2453     {
2454         return MglDataC(true, mgl_datac_trace(this));
2455     }
2456     /// get array which is result of summation in given direction or directions
2457     MglDataC sum(string dir) const
2458     {
2459         return MglDataC(true, mgl_datac_sum(this, dir.toStringz));
2460     }
2461     /// get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
2462     MglDataC combine(in MglDataA* dat) const
2463     {
2464         return MglDataC(true, mgl_datac_combine(this,  & dat));
2465     }
2466     /// Resize the data to new size of box [x1,x2]*[y1,y2]*[z1,z2]
2467     MglDataC resize(long mx, long my = 1, long mz = 1, mreal x1 = 0,
2468         mreal x2 = 1, mreal y1 = 0, mreal y2 = 1, mreal z1 = 0, mreal z2 = 1) const
2469     {
2470         return MglDataC(true, mgl_datac_resize_box(this, mx, my, mz, x1, x2, y1, y2,
2471             z1, z2));
2472     }
2473     /// get array which values is result of interpolation this for coordinates from other arrays
2474     MglDataC evaluate(const MglData* idat, bool norm = true) const
2475     {
2476         return MglDataC(true, mgl_datac_evaluate(this,  & idat, 0, 0, norm));
2477     }
2478     MglDataC evaluate(const MglData* idat, const MglData* jdat, bool norm = true) const
2479     {
2480         return MglDataC(true, mgl_datac_evaluate(this,  & idat,  & jdat, 0, norm));
2481     }
2482     MglDataC evaluate(const MglData* idat, const MglData* jdat,
2483         const MglData* kdat, bool norm = true) const
2484     {
2485         return MglDataC(true, mgl_datac_evaluate(this,  & idat,  & jdat,  & kdat, norm));
2486     }
2487 
2488     /// Find correlation with another data arrays
2489     MglDataC correlation(const MglData* dat, const char * dir) const
2490     {
2491         return MglDataC(true, mgl_datac_correl(this,  & dat, dir));
2492     }
2493     /// Find auto correlation function
2494     MglDataC autoCorrelation(const char * dir) const
2495     {
2496         return MglDataC(true, mgl_datac_correl(this, this, dir));
2497     }
2498 
2499     /// Create n-th points distribution of this data values in range [v1, v2]
2500     MglData hist(long n, mreal v1 = 0, mreal v2 = 1, long nsub = 0) const
2501     {
2502         return MglData(true, mgl_data_hist(this, n, v1, v2, nsub));
2503     }
2504     /// Create n-th points distribution of this data values in range [v1, v2] with weight w
2505     MglData hist(in MglDataA* w, long n, mreal v1 = 0, mreal v2 = 1, long nsub = 0) const
2506     {
2507         return MglData(true, mgl_data_hist_w(this,  & w, n, v1, v2, nsub));
2508     }
2509     /// get array which is result of maximal values in given direction or directions
2510     MglData max(const char * dir) const
2511     {
2512         return MglData(true, mgl_data_max_dir(this, dir.toStringz));
2513     }
2514     /// get array which is result of minimal values in given direction or directions
2515     MglData min(const char * dir) const
2516     {
2517         return MglData(true, mgl_data_min_dir(this, dir.toStringz));
2518     }
2519 
2520     /// Cumulative summation the data in given direction or directions
2521     void cumSum(string dir)
2522     {
2523         mgl_datac_cumsum(this, dir.toStringz);
2524     }
2525 
2526     /// Integrate (cumulative summation) the data in given direction or directions
2527     void integral(string dir)
2528     {
2529         mgl_datac_integral(this, dir.toStringz);
2530     }
2531 
2532     /// Differentiate the data in given direction or directions
2533     void diff(string dir)
2534     {
2535         mgl_datac_diff(this, dir.toStringz);
2536     }
2537 
2538     /// Double-differentiate (like laplace operator) the data in given direction
2539     void diff2(string dir)
2540     {
2541         mgl_datac_diff2(this, dir.toStringz);
2542     }
2543 
2544     /// Swap left and right part of the data in given direction (useful for fourier spectrums)
2545     void swap(string dir)
2546     {
2547         mgl_datac_swap(this, dir.toStringz);
2548     }
2549 
2550     /// Roll data along direction dir by num slices
2551     void roll(char dir, long num)
2552     {
2553         mgl_datac_roll(this, dir, num);
2554     }
2555 
2556     /// Mirror the data in given direction (useful for fourier spectrums)
2557     void mirror(string dir)
2558     {
2559         mgl_datac_mirror(this, dir.toStringz);
2560     }
2561 
2562     /// Smooth the data on specified direction or directions
2563     void smooth(string dirs = "xyz", mreal delta = 0)
2564     {
2565         mgl_datac_smooth(this, dirs, delta);
2566     }
2567 
2568     /// Hankel transform
2569     void hankel(string dir)
2570     {
2571         mgl_datac_hankel(this, dir.toStringz);
2572     }
2573 
2574     /// Fourier transform
2575     void fft(string dir)
2576     {
2577         mgl_datac_fft(this, dir.toStringz);
2578     }
2579 
2580     /// Calculate one step of diffraction by finite-difference method with parameter q
2581     void diffraction(string how, mreal q)
2582     {
2583         mgl_datac_diffr(this, how, q);
2584     }
2585 
2586     /// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
2587     dual spline(mreal x, mreal y = 0, mreal z = 0) const
2588     {
2589         return mgl_datac_spline(this, x, y, z);
2590     }
2591     /// Interpolate by cubic spline the data to given point x,\a y,\a z which normalized in range [0, 1]
2592     dual spline1(mreal x, mreal y = 0, mreal z = 0) const
2593     {
2594         return mgl_datac_spline(this, x * (nx - 1), y * (ny - 1), z * (nz - 1));
2595     }
2596     /// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
2597     dual linear(mreal x, mreal y = 0, mreal z = 0) const
2598     {
2599         return mgl_datac_linear(this, x, y, z);
2600     }
2601     /// Interpolate by line the data to given point x,\a y,\a z which normalized in range [0, 1]
2602     dual linear1(mreal x, mreal y = 0, mreal z = 0) const
2603     {
2604         return mgl_datac_linear(this, x * (nx - 1), y * (ny - 1), z * (nz - 1));
2605     }
2606     /// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
2607     dual linear(MglPoint* dif, mreal x, mreal y = 0, mreal z = 0) const
2608     {
2609         dual val, dx, dy, dz;
2610         val = mgl_datac_linear_ext(this, x, y, z,  & dx,  & dy,  & dz);
2611         dif = MglPoint(dx.getReal, dy.getReal, dz.getReal);
2612         return val;
2613     }
2614     /// Interpolate by line the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
2615     dual linear1(MglPoint* dif, mreal x, mreal y = 0, mreal z = 0) const
2616     {
2617         dual val, dx, dy, dz;
2618         val = mgl_datac_linear_ext(this, x, y, z,  & dx,  & dy,  & dz);
2619         dif = MglPoint(dx.getReal, dy.getReal, dz.getReal);
2620         dif.x /= nx > 1 ? nx - 1 : 1;
2621         dif.y /= ny > 1 ? ny - 1 : 1;
2622         dif.z /= nz > 1 ? nz - 1 : 1;
2623         return val;
2624     }
2625     /// Return an approximated x-value (root) when dat(x) = val
2626     mreal solve(mreal val, bool use_spline = true, long i0 = 0) const
2627     {
2628         return mgl_data_solve_1d(this, val, use_spline, i0);
2629     }
2630     /// Return an approximated value (root) when dat(x) = val
2631     MglData solve(mreal val, char dir, bool norm = true) const
2632     {
2633         return MglData(true, mgl_data_solve(this, val, dir, 0, norm));
2634     }
2635     MglData solve(mreal val, char dir, const MglData* i0, bool norm = true) const
2636     {
2637         return MglData(true, mgl_data_solve(this, val, dir,  & i0, norm));
2638     }
2639 
2640     /// Copy data from other MglDataA variable
2641     MglDataA* opAssign(in MglDataA* d)
2642     {
2643         if (this !=  & d)
2644             set( & d);
2645         return d;
2646     
2647     }
2648     auto opAssign(in MglDataC* d)
2649     {
2650         if (this !=  * d)
2651             this=*d;
2652         return d;
2653     }
2654     auto opAssign(dual val)
2655     {
2656         for (long i = 0; i < nx * ny * nz; i++)
2657             a[i] = val;
2658         return val;
2659     }
2660     auto opAssign(mreal val)
2661     {
2662         for (long i = 0; i < nx * ny * nz; i++)
2663             a[i] = val;
2664         return val;
2665     }
2666     static if ((!SWIG) && false)
2667     {
2668     	// Direct access to the data cell
2669     	/+
2670 	    	dual & operator[](long i)
2671 	    	{
2672 	        	return a[i];
2673 		    }
2674 		+/
2675 
2676 	}
2677 
2678     debug
2679     {
2680 		// get the value in given cell of the data with border checking
2681 	    mreal v(long i, long j = 0, long k = 0) const
2682 	    {
2683 	        return mgl_abs(mgl_datac_get_value(this, i, j, k));
2684 	    }
2685 	    /// set the value in given cell of the data
2686 	    void set_v(mreal val, long i, long j = 0, long k = 0)
2687 	    {
2688 	        mgl_datac_set_value(this, val, i, j, k);
2689 	    }
2690 	}
2691 	else
2692 	{
2693 		// get the value in given cell of the data
2694 	    mreal v(long i, long j = 0, long k = 0) const
2695 	    {
2696 	        return abs(a[i + nx * (j + ny * k)]);
2697 	    }
2698 	    /// set the value in given cell of the data
2699 	    void set_v(mreal val, long i, long j = 0, long k = 0)
2700 	    {
2701 	        a[i + nx * (j + ny * k)] = val;
2702 	    }
2703 	}
2704 	
2705 	mreal vthr(long i) const
2706     {
2707         return abs(a[i]);
2708     }
2709 
2710     // add for speeding up !!!
2711     mreal dvx(long i, long j = 0, long k = 0) const
2712     {
2713         long i0 = i + nx * (j + ny * k);
2714         return i > 0 ? abs(i < nx - 1 ? (a[i0 + 1] - a[i0 - 1]) / mgl2 : a[i0] - a[i0 - 1]) : abs(
2715             a[i0 + 1] - a[i0]);
2716     }
2717 
2718     mreal dvy(long i, long j = 0, long k = 0) const
2719     {
2720         long i0 = i + nx * (j + ny * k);
2721         return j > 0 ? abs(j < ny - 1 ? (a[i0 + nx] - a[i0 - nx]) / mgl2 : a[i0] - a[i0 - nx]) : abs(
2722             a[i0 + nx] - a[i0]);
2723     }
2724 
2725     mreal dvz(long i, long j = 0, long k = 0) const
2726     {
2727         long i0 = i + nx * (j + ny * k), n = nx * ny;
2728         return k > 0 ? abs(k < nz - 1 ? (a[i0 + n] - a[i0 - n]) / mgl2 : a[i0] - a[i0 - n]) : abs(
2729             a[i0 + n] - a[i0]);
2730     }
2731 }
2732 static if(!SWIG)
2733 {
2734 	dual mglLinearC(const dual * a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
2735 	dual mglSpline3C(const dual * a, long nx, long ny, long nz, mreal x, mreal y, mreal z, dual * dx = 0, dual * dy = 0, dual * dz = 0);
2736 	dual mglSpline3Cs(const dual * a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
2737 }
2738 
2739 /// saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
2740 MglDataC mglPDEc(mglBase * gr, const char * ham, in MglDataA* ini_re,
2741     in MglDataA* ini_im, mreal dz = 0.1, mreal k0 = 100, string opt= "")
2742 {
2743     return MglDataC(true, mgl_pde_solve_c(gr, ham,  & ini_re,  & ini_im, dz, k0, opt.toStringz));
2744 }
2745 /// saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
2746 MglDataC mglQO2dc(const char * ham, in MglDataA* ini_re, in MglDataA* ini_im, in MglDataA* ray, mreal r = 1,
2747 	mreal k0 = 100)
2748 {
2749     return MglDataC(true, mgl_qo2d_solve_c(ham,  & ini_re,  & ini_im,  & ray, r, k0, 0, 0));
2750 }
2751 
2752 MglDataC mglQO2dc(const char * ham, in MglDataA* ini_re,
2753     in MglDataA* ini_im, in MglDataA* ray, MglData* xx, MglData* yy,
2754     mreal r = 1, mreal k0 = 100)
2755 {
2756     return MglDataC(true, mgl_qo2d_solve_c(ham,  & ini_re,  & ini_im,  & ray, r, k0,
2757          & xx,  & yy));
2758 }
2759 
2760 /// saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
2761 MglDataC mglQO3dc(const char * ham, in MglDataA* ini_re,
2762     in MglDataA* ini_im, in MglDataA* ray, mreal r = 1, mreal k0 = 100)
2763 {
2764     return MglDataC(true, mgl_qo3d_solve_c(ham,  & ini_re,  & ini_im,  & ray, r, k0,
2765         0, 0, 0));
2766 }
2767 
2768 MglDataC mglQO3dc(string ham, in MglDataA* ini_re, in MglDataA* ini_im, in MglDataA* ray, MglData* xx, MglData* yy,
2769     MglData* zz, mreal r = 1, mreal k0 = 100)
2770 {
2771     return MglDataC(true, mgl_qo3d_solve_c(ham.toStringz,  & ini_re,  & ini_im,  & ray, r,
2772         k0,  & xx,  & yy,  & zz));
2773 }
2774 //-----------------------------------------------------------------------------
2775 /// Prepare coefficients for global spline interpolation
2776 MglDataC mglGSplineCInit(in MglDataA* xdat, in MglDataA* ydat)
2777 {
2778     return MglDataC(true, mgl_gsplinec_init( & xdat,  & ydat));
2779 }
2780 /// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
2781 dual mglGSplineC(in MglDataA* coef, mreal dx, dual * d1 = 0, dual * d2 = 0)
2782 {
2783     return mgl_gsplinec( & coef, dx, d1, d2);
2784 }
2785 auto _DN_(T)(T a)
2786 {
2787 	return (cast(MglDataC * ) * (a));
2788 }
2789 auto _DC_()
2790 {
2791 	return (cast(MglDataC * ) * d);
2792 }
2793 
2794 static if(!SWIG)
2795 {
2796 	//Wrapper class for complex expression evaluating
2797 	class mglExprC
2798 	{
2799 	    HAEX ex;
2800 	    this(in mglExprC* inp)
2801 	    {
2802 	    } // copying is not allowed
2803 	    
2804 	    const mglExprC* opAssign(const mglExprC* t)
2805 	    {
2806 	        return t;
2807 	    }
2808 
2809 	    this(string expr)
2810 	    {
2811 	        ex = mgl_create_cexpr(expr.toStringz);
2812 	    }
2813 	     
2814 	     ~ this()
2815 	    {
2816 	        mgl_delete_cexpr(ex);
2817 	    }
2818 
2819 	    // Return value of expression for given x,y,z variables
2820 	    dual Eval(dual x, dual y = 0, dual z = 0)
2821 	    {
2822 	        return mgl_cexpr_eval(ex, x, y, z);
2823 	    }
2824 
2825 	    // Return value of expression for given x,y,z,u,v,w variables
2826 	    dual Eval(dual x, dual y, dual z, dual u, dual v, dual w)
2827 	    {
2828 	        dual var[26];
2829 	        var['x' - 'a'] = x;
2830 	        var['y' - 'a'] = y;
2831 	        var['z' - 'a'] = z;
2832 	        var['u' - 'a'] = u;
2833 	        var['v' - 'a'] = v;
2834 	        var['w' - 'a'] = w;
2835 	        return mgl_cexpr_eval_v(ex, var);
2836 	    }
2837 	    /// Return value of expression for given variables
2838 	    dual Eval(dual var[26])
2839 	    {
2840 	        return mgl_cexpr_eval_v(ex, var);
2841 	    }
2842 	}
2843 }
2844 
2845 /***************************************************************************
2846  * data.h is part of Math Graphic Library
2847  * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin@gmail.ru>       *
2848  *                                                                         *
2849  *   This program is free software; you can redistribute it and/or modify  *
2850  *   it under the terms of the GNU Library General Public License as       *
2851  *   published by the Free Software Foundation; either version 3 of the    *
2852  *   License, or (at your option) any later version.                       *
2853  *                                                                         *
2854  *   This program is distributed in the hope that it will be useful,       *
2855  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
2856  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
2857  *   GNU General Public License for more details.                          *
2858  *                                                                         *
2859  *   You should have received a copy of the GNU Library General Public     *
2860  *   License along with this program; if not, write to the                 *
2861  *   Free Software Foundation, Inc.,                                       *
2862  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
2863  ***************************************************************************/
2864 +/