Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/3.7.0/ALGLIB-3.7.0/ap.cs @ 9268

Last change on this file since 9268 was 9268, checked in by mkommend, 12 years ago

#2007: Added AlgLib 3.7.0 to the external libraries.

File size: 65.0 KB
Line 
1/*************************************************************************
2AP library
3Copyright (c) 2003-2009 Sergey Bochkanov (ALGLIB project).
4
5>>> SOURCE LICENSE >>>
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation (www.fsf.org); either version 2 of the
9License, or (at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16A copy of the GNU General Public License is available at
17http://www.fsf.org/licensing/licenses
18>>> END OF LICENSE >>>
19*************************************************************************/
20using System;
21public partial class alglib
22{
23    /********************************************************************
24    Callback definitions for optimizers/fitters/solvers.
25   
26    Callbacks for unparameterized (general) functions:
27    * ndimensional_func         calculates f(arg), stores result to func
28    * ndimensional_grad         calculates func = f(arg),
29                                grad[i] = df(arg)/d(arg[i])
30    * ndimensional_hess         calculates func = f(arg),
31                                grad[i] = df(arg)/d(arg[i]),
32                                hess[i,j] = d2f(arg)/(d(arg[i])*d(arg[j]))
33   
34    Callbacks for systems of functions:
35    * ndimensional_fvec         calculates vector function f(arg),
36                                stores result to fi
37    * ndimensional_jac          calculates f[i] = fi(arg)
38                                jac[i,j] = df[i](arg)/d(arg[j])
39                               
40    Callbacks for  parameterized  functions,  i.e.  for  functions  which
41    depend on two vectors: P and Q.  Gradient  and Hessian are calculated
42    with respect to P only.
43    * ndimensional_pfunc        calculates f(p,q),
44                                stores result to func
45    * ndimensional_pgrad        calculates func = f(p,q),
46                                grad[i] = df(p,q)/d(p[i])
47    * ndimensional_phess        calculates func = f(p,q),
48                                grad[i] = df(p,q)/d(p[i]),
49                                hess[i,j] = d2f(p,q)/(d(p[i])*d(p[j]))
50
51    Callbacks for progress reports:
52    * ndimensional_rep          reports current position of optimization algo   
53   
54    Callbacks for ODE solvers:
55    * ndimensional_ode_rp       calculates dy/dx for given y[] and x
56   
57    Callbacks for integrators:
58    * integrator1_func          calculates f(x) for given x
59                                (additional parameters xminusa and bminusx
60                                contain x-a and b-x)
61    ********************************************************************/
62    public delegate void ndimensional_func (double[] arg, ref double func, object obj);
63    public delegate void ndimensional_grad (double[] arg, ref double func, double[] grad, object obj);
64    public delegate void ndimensional_hess (double[] arg, ref double func, double[] grad, double[,] hess, object obj);
65   
66    public delegate void ndimensional_fvec (double[] arg, double[] fi, object obj);
67    public delegate void ndimensional_jac  (double[] arg, double[] fi, double[,] jac, object obj);
68   
69    public delegate void ndimensional_pfunc(double[] p, double[] q, ref double func, object obj);
70    public delegate void ndimensional_pgrad(double[] p, double[] q, ref double func, double[] grad, object obj);
71    public delegate void ndimensional_phess(double[] p, double[] q, ref double func, double[] grad, double[,] hess, object obj);
72   
73    public delegate void ndimensional_rep(double[] arg, double func, object obj);
74
75    public delegate void ndimensional_ode_rp (double[] y, double x, double[] dy, object obj);
76
77    public delegate void integrator1_func (double x, double xminusa, double bminusx, ref double f, object obj);
78
79    /********************************************************************
80    Class defining a complex number with double precision.
81    ********************************************************************/
82    public struct complex
83    {
84        public double x;
85        public double y;
86
87        public complex(double _x)
88        {
89            x = _x;
90            y = 0;
91        }
92        public complex(double _x, double _y)
93        {
94            x = _x;
95            y = _y;
96        }
97        public static implicit operator complex(double _x)
98        {
99            return new complex(_x);
100        }
101        public static bool operator==(complex lhs, complex rhs)
102        {
103            return ((double)lhs.x==(double)rhs.x) & ((double)lhs.y==(double)rhs.y);
104        }
105        public static bool operator!=(complex lhs, complex rhs)
106        {
107            return ((double)lhs.x!=(double)rhs.x) | ((double)lhs.y!=(double)rhs.y);
108        }
109        public static complex operator+(complex lhs)
110        {
111            return lhs;
112        }
113        public static complex operator-(complex lhs)
114        {
115            return new complex(-lhs.x,-lhs.y);
116        }
117        public static complex operator+(complex lhs, complex rhs)
118        {
119            return new complex(lhs.x+rhs.x,lhs.y+rhs.y);
120        }
121        public static complex operator-(complex lhs, complex rhs)
122        {
123            return new complex(lhs.x-rhs.x,lhs.y-rhs.y);
124        }
125        public static complex operator*(complex lhs, complex rhs)
126        {
127            return new complex(lhs.x*rhs.x-lhs.y*rhs.y, lhs.x*rhs.y+lhs.y*rhs.x);
128        }
129        public static complex operator/(complex lhs, complex rhs)
130        {
131            complex result;
132            double e;
133            double f;
134            if( System.Math.Abs(rhs.y)<System.Math.Abs(rhs.x) )
135            {
136                e = rhs.y/rhs.x;
137                f = rhs.x+rhs.y*e;
138                result.x = (lhs.x+lhs.y*e)/f;
139                result.y = (lhs.y-lhs.x*e)/f;
140            }
141            else
142            {
143                e = rhs.x/rhs.y;
144                f = rhs.y+rhs.x*e;
145                result.x = (lhs.y+lhs.x*e)/f;
146                result.y = (-lhs.x+lhs.y*e)/f;
147            }
148            return result;
149        }
150        public override int GetHashCode()
151        {
152            return x.GetHashCode() ^ y.GetHashCode();
153        }
154        public override bool Equals(object obj)
155        {
156            if( obj is byte)
157                return Equals(new complex((byte)obj));
158            if( obj is sbyte)
159                return Equals(new complex((sbyte)obj));
160            if( obj is short)
161                return Equals(new complex((short)obj));
162            if( obj is ushort)
163                return Equals(new complex((ushort)obj));
164            if( obj is int)
165                return Equals(new complex((int)obj));
166            if( obj is uint)
167                return Equals(new complex((uint)obj));
168            if( obj is long)
169                return Equals(new complex((long)obj));
170            if( obj is ulong)
171                return Equals(new complex((ulong)obj));
172            if( obj is float)
173                return Equals(new complex((float)obj));
174            if( obj is double)
175                return Equals(new complex((double)obj));
176            if( obj is decimal)
177                return Equals(new complex((double)(decimal)obj));
178            return base.Equals(obj);
179        }   
180    }   
181   
182    /********************************************************************
183    Class defining an ALGLIB exception
184    ********************************************************************/
185    public class alglibexception : System.Exception
186    {
187        public string msg;
188        public alglibexception(string s)
189        {
190            msg = s;
191        }
192       
193    }
194   
195    /********************************************************************
196    ALGLIB object, parent class for all AlgoPascal objects managed by ALGLIB.
197    Any AlgoPascal object inherits from this class.
198    ********************************************************************/
199    public abstract class apobject
200    {
201        public abstract void init();
202        public abstract apobject make_copy();
203    }
204   
205    /********************************************************************
206    reverse communication structure
207    ********************************************************************/
208    public class rcommstate : apobject
209    {
210        public rcommstate()
211        {
212            init();
213        }
214        public override void init()
215        {
216            stage = -1;
217            ia = new int[0];
218            ba = new bool[0];
219            ra = new double[0];
220            ca = new alglib.complex[0];
221        }
222        public override apobject make_copy()
223        {
224            rcommstate result = new rcommstate();
225            result.stage = stage;
226            result.ia = (int[])ia.Clone();
227            result.ba = (bool[])ba.Clone();
228            result.ra = (double[])ra.Clone();
229            result.ca = (alglib.complex[])ca.Clone();
230            return result;
231        }
232        public int stage;
233        public int[] ia;
234        public bool[] ba;
235        public double[] ra;
236        public alglib.complex[] ca;
237    };
238
239    /********************************************************************
240    internal functions
241    ********************************************************************/
242    public class ap
243    {
244        public static int len<T>(T[] a)
245        { return a.Length; }
246        public static int rows<T>(T[,] a)
247        { return a.GetLength(0); }
248        public static int cols<T>(T[,] a)
249        { return a.GetLength(1); }
250        public static void swap<T>(ref T a, ref T b)
251        {
252            T t = a;
253            a = b;
254            b = t;
255        }
256       
257        public static void assert(bool cond, string s)
258        {
259            if( !cond )
260                throw new alglibexception(s);
261        }
262       
263        public static void assert(bool cond)
264        {
265            assert(cond, "ALGLIB: assertion failed");
266        }
267       
268        /****************************************************************
269        returns dps (digits-of-precision) value corresponding to threshold.
270        dps(0.9)  = dps(0.5)  = dps(0.1) = 0
271        dps(0.09) = dps(0.05) = dps(0.01) = 1
272        and so on
273        ****************************************************************/
274        public static int threshold2dps(double threshold)
275        {
276            int result = 0;
277            double t;
278            for (result = 0, t = 1; t / 10 > threshold*(1+1E-10); result++, t /= 10) ;
279            return result;
280        }
281
282        /****************************************************************
283        prints formatted complex
284        ****************************************************************/
285        public static string format(complex a, int _dps)
286        {
287            int dps = Math.Abs(_dps);
288            string fmt = _dps>=0 ? "F" : "E";
289            string fmtx = String.Format("{{0:"+fmt+"{0}}}", dps);
290            string fmty = String.Format("{{0:"+fmt+"{0}}}", dps);
291            string result = String.Format(fmtx, a.x) + (a.y >= 0 ? "+" : "-") + String.Format(fmty, Math.Abs(a.y)) + "i";
292            result = result.Replace(',', '.');
293            return result;
294        }
295
296        /****************************************************************
297        prints formatted array
298        ****************************************************************/
299        public static string format(bool[] a)
300        {
301            string[] result = new string[len(a)];
302            int i;
303            for(i=0; i<len(a); i++)
304                if( a[i] )
305                    result[i] = "true";
306                else
307                    result[i] = "false";
308            return "{"+String.Join(",",result)+"}";
309        }
310       
311        /****************************************************************
312        prints formatted array
313        ****************************************************************/
314        public static string format(int[] a)
315        {
316            string[] result = new string[len(a)];
317            int i;
318            for (i = 0; i < len(a); i++)
319                result[i] = a[i].ToString();
320            return "{" + String.Join(",", result) + "}";
321        }
322
323        /****************************************************************
324        prints formatted array
325        ****************************************************************/
326        public static string format(double[] a, int _dps)
327        {
328            int dps = Math.Abs(_dps);
329            string sfmt = _dps >= 0 ? "F" : "E";
330            string fmt = String.Format("{{0:" + sfmt + "{0}}}", dps);
331            string[] result = new string[len(a)];
332            int i;
333            for (i = 0; i < len(a); i++)
334            {
335                result[i] = String.Format(fmt, a[i]);
336                result[i] = result[i].Replace(',', '.');
337            }
338            return "{" + String.Join(",", result) + "}";
339        }
340
341        /****************************************************************
342        prints formatted array
343        ****************************************************************/
344        public static string format(complex[] a, int _dps)
345        {
346            int dps = Math.Abs(_dps);
347            string fmt = _dps >= 0 ? "F" : "E";
348            string fmtx = String.Format("{{0:"+fmt+"{0}}}", dps);
349            string fmty = String.Format("{{0:"+fmt+"{0}}}", dps);
350            string[] result = new string[len(a)];
351            int i;
352            for (i = 0; i < len(a); i++)
353            {
354                result[i] = String.Format(fmtx, a[i].x) + (a[i].y >= 0 ? "+" : "-") + String.Format(fmty, Math.Abs(a[i].y)) + "i";
355                result[i] = result[i].Replace(',', '.');
356            }
357            return "{" + String.Join(",", result) + "}";
358        }
359
360        /****************************************************************
361        prints formatted matrix
362        ****************************************************************/
363        public static string format(bool[,] a)
364        {
365            int i, j, m, n;
366            n = cols(a);
367            m = rows(a);
368            bool[] line = new bool[n];
369            string[] result = new string[m];
370            for (i = 0; i < m; i++)
371            {
372                for (j = 0; j < n; j++)
373                    line[j] = a[i, j];
374                result[i] = format(line);
375            }
376            return "{" + String.Join(",", result) + "}";
377        }
378
379        /****************************************************************
380        prints formatted matrix
381        ****************************************************************/
382        public static string format(int[,] a)
383        {
384            int i, j, m, n;
385            n = cols(a);
386            m = rows(a);
387            int[] line = new int[n];
388            string[] result = new string[m];
389            for (i = 0; i < m; i++)
390            {
391                for (j = 0; j < n; j++)
392                    line[j] = a[i, j];
393                result[i] = format(line);
394            }
395            return "{" + String.Join(",", result) + "}";
396        }
397
398        /****************************************************************
399        prints formatted matrix
400        ****************************************************************/
401        public static string format(double[,] a, int dps)
402        {
403            int i, j, m, n;
404            n = cols(a);
405            m = rows(a);
406            double[] line = new double[n];
407            string[] result = new string[m];
408            for (i = 0; i < m; i++)
409            {
410                for (j = 0; j < n; j++)
411                    line[j] = a[i, j];
412                result[i] = format(line, dps);
413            }
414            return "{" + String.Join(",", result) + "}";
415        }
416
417        /****************************************************************
418        prints formatted matrix
419        ****************************************************************/
420        public static string format(complex[,] a, int dps)
421        {
422            int i, j, m, n;
423            n = cols(a);
424            m = rows(a);
425            complex[] line = new complex[n];
426            string[] result = new string[m];
427            for (i = 0; i < m; i++)
428            {
429                for (j = 0; j < n; j++)
430                    line[j] = a[i, j];
431                result[i] = format(line, dps);
432            }
433            return "{" + String.Join(",", result) + "}";
434        }
435
436        /****************************************************************
437        checks that matrix is symmetric.
438        max|A-A^T| is calculated; if it is within 1.0E-14 of max|A|,
439        matrix is considered symmetric
440        ****************************************************************/
441        public static bool issymmetric(double[,] a)
442        {
443            int i, j, n;
444            double err, mx, v1, v2;
445            if( rows(a)!=cols(a) )
446                return false;
447            n = rows(a);
448            if( n==0 )
449                return true;
450            mx = 0;
451            err = 0;
452            for( i=0; i<n; i++)
453            {
454                for(j=i+1; j<n; j++)
455                {
456                    v1 = a[i,j];
457                    v2 = a[j,i];
458                    if( !math.isfinite(v1) )
459                        return false;
460                    if( !math.isfinite(v2) )
461                        return false;
462                    err = Math.Max(err, Math.Abs(v1-v2));
463                    mx  = Math.Max(mx,  Math.Abs(v1));
464                    mx  = Math.Max(mx,  Math.Abs(v2));
465                }
466                v1 = a[i,i];
467                if( !math.isfinite(v1) )
468                    return false;
469                mx = Math.Max(mx, Math.Abs(v1));
470            }
471            if( mx==0 )
472                return true;
473            return err/mx<=1.0E-14;
474        }
475       
476        /****************************************************************
477        checks that matrix is Hermitian.
478        max|A-A^H| is calculated; if it is within 1.0E-14 of max|A|,
479        matrix is considered Hermitian
480        ****************************************************************/
481        public static bool ishermitian(complex[,] a)
482        {
483            int i, j, n;
484            double err, mx;
485            complex v1, v2, vt;
486            if( rows(a)!=cols(a) )
487                return false;
488            n = rows(a);
489            if( n==0 )
490                return true;
491            mx = 0;
492            err = 0;
493            for( i=0; i<n; i++)
494            {
495                for(j=i+1; j<n; j++)
496                {
497                    v1 = a[i,j];
498                    v2 = a[j,i];
499                    if( !math.isfinite(v1.x) )
500                        return false;
501                    if( !math.isfinite(v1.y) )
502                        return false;
503                    if( !math.isfinite(v2.x) )
504                        return false;
505                    if( !math.isfinite(v2.y) )
506                        return false;
507                    vt.x = v1.x-v2.x;
508                    vt.y = v1.y+v2.y;
509                    err = Math.Max(err, math.abscomplex(vt));
510                    mx  = Math.Max(mx,  math.abscomplex(v1));
511                    mx  = Math.Max(mx,  math.abscomplex(v2));
512                }
513                v1 = a[i,i];
514                if( !math.isfinite(v1.x) )
515                    return false;
516                if( !math.isfinite(v1.y) )
517                    return false;
518                err = Math.Max(err, Math.Abs(v1.y));
519                mx = Math.Max(mx, math.abscomplex(v1));
520            }
521            if( mx==0 )
522                return true;
523            return err/mx<=1.0E-14;
524        }
525       
526       
527        /****************************************************************
528        Forces symmetricity by copying upper half of A to the lower one
529        ****************************************************************/
530        public static bool forcesymmetric(double[,] a)
531        {
532            int i, j, n;
533            if( rows(a)!=cols(a) )
534                return false;
535            n = rows(a);
536            if( n==0 )
537                return true;
538            for( i=0; i<n; i++)
539                for(j=i+1; j<n; j++)
540                    a[i,j] = a[j,i];
541            return true;
542        }
543       
544        /****************************************************************
545        Forces Hermiticity by copying upper half of A to the lower one
546        ****************************************************************/
547        public static bool forcehermitian(complex[,] a)
548        {
549            int i, j, n;
550            complex v;
551            if( rows(a)!=cols(a) )
552                return false;
553            n = rows(a);
554            if( n==0 )
555                return true;
556            for( i=0; i<n; i++)
557                for(j=i+1; j<n; j++)
558                {
559                    v = a[j,i];
560                    a[i,j].x = v.x;
561                    a[i,j].y = -v.y;
562                }
563            return true;
564        }
565    };
566   
567    /********************************************************************
568    math functions
569    ********************************************************************/
570    public class math
571    {
572        //public static System.Random RndObject = new System.Random(System.DateTime.Now.Millisecond);
573        public static System.Random rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000*System.DateTime.Now.Second + 60*1000*System.DateTime.Now.Minute);
574
575        public const double machineepsilon = 5E-16;
576        public const double maxrealnumber = 1E300;
577        public const double minrealnumber = 1E-300;
578       
579        public static bool isfinite(double d)
580        {
581            return !System.Double.IsNaN(d) && !System.Double.IsInfinity(d);
582        }
583       
584        public static double randomreal()
585        {
586            double r = 0;
587            lock(rndobject){ r = rndobject.NextDouble(); }
588            return r;
589        }
590        public static int randominteger(int N)
591        {
592            int r = 0;
593            lock(rndobject){ r = rndobject.Next(N); }
594            return r;
595        }
596        public static double sqr(double X)
597        {
598            return X*X;
599        }       
600        public static double abscomplex(complex z)
601        {
602            double w;
603            double xabs;
604            double yabs;
605            double v;
606   
607            xabs = System.Math.Abs(z.x);
608            yabs = System.Math.Abs(z.y);
609            w = xabs>yabs ? xabs : yabs;
610            v = xabs<yabs ? xabs : yabs;
611            if( v==0 )
612                return w;
613            else
614            {
615                double t = v/w;
616                return w*System.Math.Sqrt(1+t*t);
617            }
618        }
619        public static complex conj(complex z)
620        {
621            return new complex(z.x, -z.y);
622        }   
623        public static complex csqr(complex z)
624        {
625            return new complex(z.x*z.x-z.y*z.y, 2*z.x*z.y);
626        }
627
628    }
629   
630   
631    /********************************************************************
632    serializer object (should not be used directly)
633    ********************************************************************/
634    public class serializer
635    {
636        enum SMODE { DEFAULT, ALLOC, TO_STRING, FROM_STRING };
637        private const int SER_ENTRIES_PER_ROW = 5;
638        private const int SER_ENTRY_LENGTH    = 11;
639       
640        private SMODE mode;
641        private int entries_needed;
642        private int entries_saved;
643        private int bytes_asked;
644        private int bytes_written;
645        private int bytes_read;
646        private char[] out_str;
647        private char[] in_str;
648       
649        public serializer()
650        {
651            mode = SMODE.DEFAULT;
652            entries_needed = 0;
653            bytes_asked = 0;
654        }
655
656        public void alloc_start()
657        {
658            entries_needed = 0;
659            bytes_asked = 0;
660            mode = SMODE.ALLOC;
661        }
662
663        public void alloc_entry()
664        {
665            if( mode!=SMODE.ALLOC )
666                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
667            entries_needed++;
668        }
669
670        private int get_alloc_size()
671        {
672            int rows, lastrowsize, result;
673           
674            // check and change mode
675            if( mode!=SMODE.ALLOC )
676                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
677           
678            // if no entries needes (degenerate case)
679            if( entries_needed==0 )
680            {
681                bytes_asked = 1;
682                return bytes_asked;
683            }
684           
685            // non-degenerate case
686            rows = entries_needed/SER_ENTRIES_PER_ROW;
687            lastrowsize = SER_ENTRIES_PER_ROW;
688            if( entries_needed%SER_ENTRIES_PER_ROW!=0 )
689            {
690                lastrowsize = entries_needed%SER_ENTRIES_PER_ROW;
691                rows++;
692            }
693           
694            // calculate result size
695            result  = ((rows-1)*SER_ENTRIES_PER_ROW+lastrowsize)*SER_ENTRY_LENGTH;
696            result +=  (rows-1)*(SER_ENTRIES_PER_ROW-1)+(lastrowsize-1);
697            result += rows*2;
698            bytes_asked = result;
699            return result;
700        }
701
702        public void sstart_str()
703        {
704            int allocsize = get_alloc_size();
705           
706            // check and change mode
707            if( mode!=SMODE.ALLOC )
708                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
709            mode = SMODE.TO_STRING;
710           
711            // other preparations
712            out_str = new char[allocsize];
713            entries_saved = 0;
714            bytes_written = 0;
715        }
716
717        public void ustart_str(string s)
718        {
719            // check and change mode
720            if( mode!=SMODE.DEFAULT )
721                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
722            mode = SMODE.FROM_STRING;
723           
724            in_str = s.ToCharArray();
725            bytes_read = 0;
726        }
727
728        public void serialize_bool(bool v)
729        {
730            if( mode!=SMODE.TO_STRING )
731                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
732            bool2str(v, out_str, ref bytes_written);
733            entries_saved++;
734            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
735            {
736                out_str[bytes_written] = ' ';
737                bytes_written++;
738            }
739            else
740            {
741                out_str[bytes_written+0] = '\r';
742                out_str[bytes_written+1] = '\n';
743                bytes_written+=2;
744            }           
745        }
746
747        public void serialize_int(int v)
748        {
749            if( mode!=SMODE.TO_STRING )
750                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
751            int2str(v, out_str, ref bytes_written);
752            entries_saved++;
753            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
754            {
755                out_str[bytes_written] = ' ';
756                bytes_written++;
757            }
758            else
759            {
760                out_str[bytes_written+0] = '\r';
761                out_str[bytes_written+1] = '\n';
762                bytes_written+=2;
763            }
764        }
765
766        public void serialize_double(double v)
767        {
768            if( mode!=SMODE.TO_STRING )
769                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
770            double2str(v, out_str, ref bytes_written);
771            entries_saved++;
772            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
773            {
774                out_str[bytes_written] = ' ';
775                bytes_written++;
776            }
777            else
778            {
779                out_str[bytes_written+0] = '\r';
780                out_str[bytes_written+1] = '\n';
781                bytes_written+=2;
782            }
783        }
784
785        public bool unserialize_bool()
786        {
787            if( mode!=SMODE.FROM_STRING )
788                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
789            return str2bool(in_str, ref bytes_read);
790        }
791
792        public int unserialize_int()
793        {
794            if( mode!=SMODE.FROM_STRING )
795                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
796            return str2int(in_str, ref bytes_read);
797        }
798
799        public double unserialize_double()
800        {
801            if( mode!=SMODE.FROM_STRING )
802                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
803            return str2double(in_str, ref bytes_read);
804        }
805
806        public void stop()
807        {
808        }
809
810        public string get_string()
811        {
812            return new string(out_str, 0, bytes_written);
813        }
814
815
816        /************************************************************************
817        This function converts six-bit value (from 0 to 63)  to  character  (only
818        digits, lowercase and uppercase letters, minus and underscore are used).
819
820        If v is negative or greater than 63, this function returns '?'.
821        ************************************************************************/
822        private static char[] _sixbits2char_tbl = new char[64]{
823                '0', '1', '2', '3', '4', '5', '6', '7',
824                '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
825                'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
826                'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
827                'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
828                'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
829                'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
830                'u', 'v', 'w', 'x', 'y', 'z', '-', '_' };
831        private static char sixbits2char(int v)
832        {
833            if( v<0 || v>63 )
834                return '?';
835            return _sixbits2char_tbl[v];
836        }
837       
838        /************************************************************************
839        This function converts character to six-bit value (from 0 to 63).
840
841        This function is inverse of ae_sixbits2char()
842        If c is not correct character, this function returns -1.
843        ************************************************************************/
844        private static int[] _char2sixbits_tbl = new int[128] {
845            -1, -1, -1, -1, -1, -1, -1, -1,
846            -1, -1, -1, -1, -1, -1, -1, -1,
847            -1, -1, -1, -1, -1, -1, -1, -1,
848            -1, -1, -1, -1, -1, -1, -1, -1,
849            -1, -1, -1, -1, -1, -1, -1, -1,
850            -1, -1, -1, -1, -1, 62, -1, -1,
851             0,  1,  2,  3,  4,  5,  6,  7,
852             8,  9, -1, -1, -1, -1, -1, -1,
853            -1, 10, 11, 12, 13, 14, 15, 16,
854            17, 18, 19, 20, 21, 22, 23, 24,
855            25, 26, 27, 28, 29, 30, 31, 32,
856            33, 34, 35, -1, -1, -1, -1, 63,
857            -1, 36, 37, 38, 39, 40, 41, 42,
858            43, 44, 45, 46, 47, 48, 49, 50,
859            51, 52, 53, 54, 55, 56, 57, 58,
860            59, 60, 61, -1, -1, -1, -1, -1 };
861        private static int char2sixbits(char c)
862        {
863            return (c>=0 && c<127) ? _char2sixbits_tbl[c] : -1;
864        }
865       
866        /************************************************************************
867        This function converts three bytes (24 bits) to four six-bit values
868        (24 bits again).
869
870        src         array
871        src_offs    offset of three-bytes chunk
872        dst         array for ints
873        dst_offs    offset of four-ints chunk
874        ************************************************************************/
875        private static void threebytes2foursixbits(byte[] src, int src_offs, int[] dst, int dst_offs)
876        {
877            dst[dst_offs+0] =  src[src_offs+0] & 0x3F;
878            dst[dst_offs+1] = (src[src_offs+0]>>6) | ((src[src_offs+1]&0x0F)<<2);
879            dst[dst_offs+2] = (src[src_offs+1]>>4) | ((src[src_offs+2]&0x03)<<4);
880            dst[dst_offs+3] =  src[src_offs+2]>>2;
881        }
882
883        /************************************************************************
884        This function converts four six-bit values (24 bits) to three bytes
885        (24 bits again).
886
887        src         pointer to four ints
888        src_offs    offset of the chunk
889        dst         pointer to three bytes
890        dst_offs    offset of the chunk
891        ************************************************************************/
892        private static void foursixbits2threebytes(int[] src, int src_offs, byte[] dst, int dst_offs)
893        {
894            dst[dst_offs+0] =      (byte)(src[src_offs+0] | ((src[src_offs+1]&0x03)<<6));
895            dst[dst_offs+1] = (byte)((src[src_offs+1]>>2) | ((src[src_offs+2]&0x0F)<<4));
896            dst[dst_offs+2] = (byte)((src[src_offs+2]>>4) |  (src[src_offs+3]<<2));
897        }
898
899        /************************************************************************
900        This function serializes boolean value into buffer
901
902        v           boolean value to be serialized
903        buf         buffer, at least 11 characters wide
904        offs        offset in the buffer
905       
906        after return from this function, offs points to the char's past the value
907        being read.
908        ************************************************************************/
909        private static void bool2str(bool v, char[] buf, ref int offs)
910        {
911            char c = v ? '1' : '0';
912            int i;
913            for(i=0; i<SER_ENTRY_LENGTH; i++)
914                buf[offs+i] = c;
915            offs += SER_ENTRY_LENGTH;
916        }
917
918        /************************************************************************
919        This function unserializes boolean value from buffer
920
921        buf         buffer which contains value; leading spaces/tabs/newlines are
922                    ignored, traling spaces/tabs/newlines are treated as  end  of
923                    the boolean value.
924        offs        offset in the buffer
925       
926        after return from this function, offs points to the char's past the value
927        being read.
928
929        This function raises an error in case unexpected symbol is found
930        ************************************************************************/
931        private static bool str2bool(char[] buf, ref int offs)
932        {
933            bool was0, was1;
934            string emsg = "ALGLIB: unable to read boolean value from stream";
935           
936            was0 = false;
937            was1 = false;
938            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
939                offs++;
940            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
941            {
942                if( buf[offs]=='0' )
943                {
944                    was0 = true;
945                    offs++;
946                    continue;
947                }
948                if( buf[offs]=='1' )
949                {
950                    was1 = true;
951                    offs++;
952                    continue;
953                }
954                throw new alglib.alglibexception(emsg);
955            }
956            if( (!was0) && (!was1) )
957                throw new alglib.alglibexception(emsg);
958            if( was0 && was1 )
959                throw new alglib.alglibexception(emsg);
960            return was1 ? true : false;
961        }
962
963        /************************************************************************
964        This function serializes integer value into buffer
965
966        v           integer value to be serialized
967        buf         buffer, at least 11 characters wide
968        offs        offset in the buffer
969       
970        after return from this function, offs points to the char's past the value
971        being read.
972
973        This function raises an error in case unexpected symbol is found
974        ************************************************************************/
975        private static void int2str(int v, char[] buf, ref int offs)
976        {
977            int i;
978            byte[] _bytes = System.BitConverter.GetBytes((int)v);
979            byte[]  bytes = new byte[9];
980            int[] sixbits = new int[12];
981            byte c;
982           
983            //
984            // copy v to array of bytes, sign extending it and
985            // converting to little endian order. Additionally,
986            // we set 9th byte to zero in order to simplify
987            // conversion to six-bit representation
988            //
989            if( !System.BitConverter.IsLittleEndian )
990                System.Array.Reverse(_bytes);
991            c = v<0 ? (byte)0xFF : (byte)0x00;
992            for(i=0; i<sizeof(int); i++)
993                bytes[i] = _bytes[i];
994            for(i=sizeof(int); i<8; i++)
995                bytes[i] = c;
996            bytes[8] = 0;
997           
998            //
999            // convert to six-bit representation, output
1000            //
1001            // NOTE: last 12th element of sixbits is always zero, we do not output it
1002            //
1003            threebytes2foursixbits(bytes, 0, sixbits, 0);
1004            threebytes2foursixbits(bytes, 3, sixbits, 4);
1005            threebytes2foursixbits(bytes, 6, sixbits, 8);       
1006            for(i=0; i<SER_ENTRY_LENGTH; i++)
1007                buf[offs+i] = sixbits2char(sixbits[i]);
1008            offs += SER_ENTRY_LENGTH;
1009        }
1010
1011        /************************************************************************
1012        This function unserializes integer value from string
1013
1014        buf         buffer which contains value; leading spaces/tabs/newlines are
1015                    ignored, traling spaces/tabs/newlines are treated as  end  of
1016                    the integer value.
1017        offs        offset in the buffer
1018       
1019        after return from this function, offs points to the char's past the value
1020        being read.
1021
1022        This function raises an error in case unexpected symbol is found
1023        ************************************************************************/
1024        private static int str2int(char[] buf, ref int offs)
1025        {
1026            string emsg =       "ALGLIB: unable to read integer value from stream";
1027            string emsg3264 =   "ALGLIB: unable to read integer value from stream (value does not fit into 32 bits)";
1028            int[] sixbits = new int[12];
1029            byte[] bytes = new byte[9];
1030            byte[] _bytes = new byte[sizeof(int)];
1031            int sixbitsread, i;
1032            byte c;
1033           
1034            //
1035            // 1. skip leading spaces
1036            // 2. read and decode six-bit digits
1037            // 3. set trailing digits to zeros
1038            // 4. convert to little endian 64-bit integer representation
1039            // 5. check that we fit into int
1040            // 6. convert to big endian representation, if needed
1041            //
1042            sixbitsread = 0;
1043            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1044                offs++;
1045            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1046            {
1047                int d;
1048                d = char2sixbits(buf[offs]);
1049                if( d<0 || sixbitsread>=SER_ENTRY_LENGTH )
1050                    throw new alglib.alglibexception(emsg);
1051                sixbits[sixbitsread] = d;
1052                sixbitsread++;
1053                offs++;
1054            }
1055            if( sixbitsread==0 )
1056                throw new alglib.alglibexception(emsg);
1057            for(i=sixbitsread; i<12; i++)
1058                sixbits[i] = 0;
1059            foursixbits2threebytes(sixbits, 0, bytes, 0);
1060            foursixbits2threebytes(sixbits, 4, bytes, 3);
1061            foursixbits2threebytes(sixbits, 8, bytes, 6);
1062            c = (bytes[sizeof(int)-1] & 0x80)!=0 ? (byte)0xFF : (byte)0x00;
1063            for(i=sizeof(int); i<8; i++)
1064                if( bytes[i]!=c )
1065                    throw new alglib.alglibexception(emsg3264);
1066            for(i=0; i<sizeof(int); i++)
1067                _bytes[i] = bytes[i];       
1068            if( !System.BitConverter.IsLittleEndian )
1069                System.Array.Reverse(_bytes);
1070            return System.BitConverter.ToInt32(_bytes,0);
1071        }   
1072       
1073       
1074        /************************************************************************
1075        This function serializes double value into buffer
1076
1077        v           double value to be serialized
1078        buf         buffer, at least 11 characters wide
1079        offs        offset in the buffer
1080       
1081        after return from this function, offs points to the char's past the value
1082        being read.
1083        ************************************************************************/
1084        private static void double2str(double v, char[] buf, ref int offs)
1085        {
1086            int i;
1087            int[] sixbits = new int[12];
1088            byte[] bytes = new byte[9];
1089
1090            //
1091            // handle special quantities
1092            //
1093            if( System.Double.IsNaN(v) )
1094            {
1095                buf[offs+0] = '.';
1096                buf[offs+1] = 'n';
1097                buf[offs+2] = 'a';
1098                buf[offs+3] = 'n';
1099                buf[offs+4] = '_';
1100                buf[offs+5] = '_';
1101                buf[offs+6] = '_';
1102                buf[offs+7] = '_';
1103                buf[offs+8] = '_';
1104                buf[offs+9] = '_';
1105                buf[offs+10] = '_';
1106                offs += SER_ENTRY_LENGTH;
1107                return;
1108            }
1109            if( System.Double.IsPositiveInfinity(v) )
1110            {
1111                buf[offs+0] = '.';
1112                buf[offs+1] = 'p';
1113                buf[offs+2] = 'o';
1114                buf[offs+3] = 's';
1115                buf[offs+4] = 'i';
1116                buf[offs+5] = 'n';
1117                buf[offs+6] = 'f';
1118                buf[offs+7] = '_';
1119                buf[offs+8] = '_';
1120                buf[offs+9] = '_';
1121                buf[offs+10] = '_';
1122                offs += SER_ENTRY_LENGTH;
1123                return;
1124            }
1125            if( System.Double.IsNegativeInfinity(v) )
1126            {
1127                buf[offs+0] = '.';
1128                buf[offs+1] = 'n';
1129                buf[offs+2] = 'e';
1130                buf[offs+3] = 'g';
1131                buf[offs+4] = 'i';
1132                buf[offs+5] = 'n';
1133                buf[offs+6] = 'f';
1134                buf[offs+7] = '_';
1135                buf[offs+8] = '_';
1136                buf[offs+9] = '_';
1137                buf[offs+10] = '_';
1138                offs += SER_ENTRY_LENGTH;
1139                return;
1140            }
1141           
1142            //
1143            // process general case:
1144            // 1. copy v to array of chars
1145            // 2. set 9th byte to zero in order to simplify conversion to six-bit representation
1146            // 3. convert to little endian (if needed)
1147            // 4. convert to six-bit representation
1148            //    (last 12th element of sixbits is always zero, we do not output it)
1149            //
1150            byte[] _bytes = System.BitConverter.GetBytes((double)v);
1151            if( !System.BitConverter.IsLittleEndian )
1152                System.Array.Reverse(_bytes);
1153            for(i=0; i<sizeof(double); i++)
1154                bytes[i] = _bytes[i];
1155            for(i=sizeof(double); i<9; i++)
1156                bytes[i] = 0;
1157            threebytes2foursixbits(bytes, 0, sixbits, 0);
1158            threebytes2foursixbits(bytes, 3, sixbits, 4);
1159            threebytes2foursixbits(bytes, 6, sixbits, 8);
1160            for(i=0; i<SER_ENTRY_LENGTH; i++)
1161                buf[offs+i] = sixbits2char(sixbits[i]);
1162            offs += SER_ENTRY_LENGTH;
1163        }
1164
1165        /************************************************************************
1166        This function unserializes double value from string
1167
1168        buf         buffer which contains value; leading spaces/tabs/newlines are
1169                    ignored, traling spaces/tabs/newlines are treated as  end  of
1170                    the double value.
1171        offs        offset in the buffer
1172       
1173        after return from this function, offs points to the char's past the value
1174        being read.
1175
1176        This function raises an error in case unexpected symbol is found
1177        ************************************************************************/
1178        private static double str2double(char[] buf, ref int offs)
1179        {
1180            string emsg = "ALGLIB: unable to read double value from stream";
1181            int[] sixbits = new int[12];
1182            byte[]  bytes = new byte[9];
1183            byte[] _bytes = new byte[sizeof(double)];
1184            int sixbitsread, i;
1185           
1186           
1187            //
1188            // skip leading spaces
1189            //
1190            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1191                offs++;
1192           
1193             
1194            //
1195            // Handle special cases
1196            //
1197            if( buf[offs]=='.' )
1198            {
1199                string s = new string(buf, offs, SER_ENTRY_LENGTH);
1200                if( s==".nan_______" )
1201                {
1202                    offs += SER_ENTRY_LENGTH;
1203                    return System.Double.NaN;
1204                }
1205                if( s==".posinf____" )
1206                {
1207                    offs += SER_ENTRY_LENGTH;
1208                    return System.Double.PositiveInfinity;
1209                }
1210                if( s==".neginf____" )
1211                {
1212                    offs += SER_ENTRY_LENGTH;
1213                    return System.Double.NegativeInfinity;
1214                }
1215                throw new alglib.alglibexception(emsg);
1216            }
1217           
1218            //
1219            // General case:
1220            // 1. read and decode six-bit digits
1221            // 2. check that all 11 digits were read
1222            // 3. set last 12th digit to zero (needed for simplicity of conversion)
1223            // 4. convert to 8 bytes
1224            // 5. convert to big endian representation, if needed
1225            //
1226            sixbitsread = 0;
1227            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1228            {
1229                int d;
1230                d = char2sixbits(buf[offs]);
1231                if( d<0 || sixbitsread>=SER_ENTRY_LENGTH )
1232                    throw new alglib.alglibexception(emsg);
1233                sixbits[sixbitsread] = d;
1234                sixbitsread++;
1235                offs++;
1236            }
1237            if( sixbitsread!=SER_ENTRY_LENGTH )
1238                throw new alglib.alglibexception(emsg);
1239            sixbits[SER_ENTRY_LENGTH] = 0;
1240            foursixbits2threebytes(sixbits, 0, bytes, 0);
1241            foursixbits2threebytes(sixbits, 4, bytes, 3);
1242            foursixbits2threebytes(sixbits, 8, bytes, 6);
1243            for(i=0; i<sizeof(double); i++)
1244                _bytes[i] = bytes[i];       
1245            if( !System.BitConverter.IsLittleEndian )
1246                System.Array.Reverse(_bytes);       
1247            return System.BitConverter.ToDouble(_bytes,0);
1248        }
1249    }
1250
1251    /*
1252     * Parts of alglib.smp class which are shared with GPL version of ALGLIB
1253     */
1254    public partial class smp
1255    {
1256        #pragma warning disable 420
1257        public const int AE_LOCK_CYCLES = 512;
1258       
1259        /*
1260         * This variable is used to perform spin-wait loops in a platform-independent manner
1261         * (loops which should work same way on Mono and Microsoft NET). You SHOULD NEVER
1262         * change this field - it must be zero during all program life.
1263         */
1264        public static volatile int never_change_it = 0;
1265       
1266        /*************************************************************************
1267        Lock.
1268
1269        This class provides lightweight spin lock
1270        *************************************************************************/
1271        public class ae_lock
1272        {
1273            public volatile int is_locked;
1274        }
1275
1276        /********************************************************************
1277        Shared pool: data structure used to provide thread-safe access to pool
1278        of temporary variables.
1279        ********************************************************************/
1280        public class sharedpoolentry
1281        {
1282            public apobject obj;
1283            public sharedpoolentry next_entry;
1284        }
1285        public class shared_pool : apobject
1286        {
1287            /* lock object which protects pool */
1288            public ae_lock pool_lock;
1289   
1290            /* seed object (used to create new instances of temporaries) */
1291            public volatile apobject seed_object;
1292           
1293            /*
1294             * list of recycled OBJECTS:
1295             * 1. entries in this list store pointers to recycled objects
1296             * 2. every time we retrieve object, we retrieve first entry from this list,
1297             *    move it to recycled_entries and return its obj field to caller/
1298             */
1299            public volatile sharedpoolentry recycled_objects;
1300           
1301            /*
1302             * list of recycled ENTRIES:
1303             * 1. this list holds entries which are not used to store recycled objects;
1304             *    every time recycled object is retrieved, its entry is moved to this list.
1305             * 2. every time object is recycled, we try to fetch entry for him from this list
1306             *    before allocating it with malloc()
1307             */
1308            public volatile sharedpoolentry recycled_entries;
1309           
1310            /* enumeration pointer, points to current recycled object*/
1311            public volatile sharedpoolentry enumeration_counter;
1312           
1313            /* constructor */
1314            public shared_pool()
1315            {
1316                ae_init_lock(ref pool_lock);
1317            }
1318           
1319            /* initializer - creation of empty pool */
1320            public override void init()
1321            {
1322                seed_object = null;
1323                recycled_objects = null;
1324                recycled_entries = null;
1325                enumeration_counter = null;
1326            }
1327           
1328            /* copy constructor (it is NOT thread-safe) */
1329            public override apobject make_copy()
1330            {
1331                sharedpoolentry ptr, buf;
1332                shared_pool result = new shared_pool();
1333               
1334                /* create lock */
1335                ae_init_lock(ref result.pool_lock);
1336   
1337                /* copy seed object */
1338                if( seed_object!=null )
1339                    result.seed_object = seed_object.make_copy();
1340               
1341                /*
1342                 * copy recycled objects:
1343                 * 1. copy to temporary list (objects are inserted to beginning, order is reversed)
1344                 * 2. copy temporary list to output list (order is restored back to normal)
1345                 */
1346                buf = null;
1347                for(ptr=recycled_objects; ptr!=null; ptr=ptr.next_entry)
1348                {
1349                    sharedpoolentry tmp = new sharedpoolentry();
1350                    tmp.obj =  ptr.obj.make_copy();
1351                    tmp.next_entry = buf;
1352                    buf = tmp;
1353                }
1354                result.recycled_objects = null;
1355                for(ptr=buf; ptr!=null;)
1356                {
1357                    sharedpoolentry next_ptr = ptr.next_entry;
1358                    ptr.next_entry = result.recycled_objects;
1359                    result.recycled_objects = ptr;
1360                    ptr = next_ptr;
1361                }
1362   
1363                /* recycled entries are not copied because they do not store any information */
1364                result.recycled_entries = null;
1365   
1366                /* enumeration counter is reset on copying */
1367                result.enumeration_counter = null;
1368   
1369                return result;
1370            }
1371        }
1372       
1373
1374        /************************************************************************
1375        This function performs given number of spin-wait iterations
1376        ************************************************************************/
1377        public static void ae_spin_wait(int cnt)
1378        {
1379            /*int i, v;
1380            v = 0;
1381            for(i=0; i<cnt; i++)
1382                System.Threading.Interlocked.Exchange(ref v, i);*/
1383            for(int i=0; i<cnt && never_change_it==0; i++)
1384                if( never_change_it!=0 )
1385                    never_change_it = i;
1386            if( never_change_it!=0 )
1387                never_change_it = 0;
1388        }
1389
1390        /************************************************************************
1391        This function initializes ae_lock structure and sets lock in a free mode.
1392        ************************************************************************/
1393        public static void ae_init_lock(ref ae_lock obj)
1394        {
1395            obj = new ae_lock();
1396            obj.is_locked = 0;
1397        }
1398
1399
1400        /************************************************************************
1401        This function acquires lock. In case lock is busy, we perform several
1402        iterations inside tight loop before trying again.
1403        ************************************************************************/
1404        public static void ae_acquire_lock(ae_lock obj)
1405        {
1406            for(;;)
1407            {
1408                if( System.Threading.Interlocked.CompareExchange(ref obj.is_locked, 1, 0)==0 )
1409                    return;
1410                ae_spin_wait(AE_LOCK_CYCLES);
1411            }
1412        }
1413
1414
1415        /************************************************************************
1416        This function releases lock.
1417        ************************************************************************/
1418        public static void ae_release_lock(ae_lock obj)
1419        {
1420            System.Threading.Interlocked.Exchange(ref obj.is_locked, 0);
1421        }
1422
1423
1424        /************************************************************************
1425        This function frees ae_lock structure.
1426        ************************************************************************/
1427        public static void ae_free_lock(ref ae_lock obj)
1428        {
1429            obj = null;
1430        }
1431       
1432       
1433        /************************************************************************
1434        This function sets internal seed object. All objects owned by the pool
1435        (current seed object, recycled objects) are automatically freed.
1436
1437        dst                 destination pool (initialized by constructor function)
1438        seed_object         new seed object
1439
1440        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1441              you should NOT call it when lock can be used by another thread.
1442        ************************************************************************/
1443        public static void ae_shared_pool_set_seed(shared_pool dst, alglib.apobject seed_object)
1444        {
1445            dst.seed_object = seed_object.make_copy();
1446            dst.recycled_objects = null;
1447            dst.enumeration_counter = null;
1448        }
1449
1450
1451        /************************************************************************
1452        This  function  retrieves  a  copy  of  the seed object from the pool and
1453        stores it to target variable.
1454
1455        pool                pool
1456        obj                 target variable
1457       
1458        NOTE: this function IS thread-safe.  It  acquires  pool  lock  during its
1459              operation and can be used simultaneously from several threads.
1460        ************************************************************************/
1461        public static void ae_shared_pool_retrieve<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1462        {
1463            alglib.apobject new_obj;
1464           
1465            /* assert that pool was seeded */
1466            alglib.ap.assert(pool.seed_object!=null, "ALGLIB: shared pool is not seeded, PoolRetrieve() failed");
1467           
1468            /* acquire lock */
1469            ae_acquire_lock(pool.pool_lock);
1470           
1471            /* try to reuse recycled objects */
1472            if( pool.recycled_objects!=null )
1473            {
1474                /* retrieve entry/object from list of recycled objects */
1475                sharedpoolentry result = pool.recycled_objects;
1476                pool.recycled_objects = pool.recycled_objects.next_entry;
1477                new_obj = result.obj;
1478                result.obj = null;
1479               
1480                /* move entry to list of recycled entries */
1481                result.next_entry = pool.recycled_entries;
1482                pool.recycled_entries = result;
1483               
1484                /* release lock */
1485                ae_release_lock(pool.pool_lock);
1486               
1487                /* assign object to smart pointer */
1488                obj = (T)new_obj;
1489               
1490                return;
1491            }
1492               
1493            /*
1494             * release lock; we do not need it anymore because
1495             * copy constructor does not modify source variable.
1496             */
1497            ae_release_lock(pool.pool_lock);
1498           
1499            /* create new object from seed */
1500            new_obj = pool.seed_object.make_copy();
1501               
1502            /* assign object to pointer and return */
1503            obj = (T)new_obj;
1504        }
1505
1506
1507        /************************************************************************
1508        This  function  recycles object owned by the source variable by moving it
1509        to internal storage of the shared pool.
1510
1511        Source  variable  must  own  the  object,  i.e.  be  the only place where
1512        reference  to  object  is  stored.  After  call  to  this function source
1513        variable becomes NULL.
1514
1515        pool                pool
1516        obj                 source variable
1517
1518        NOTE: this function IS thread-safe.  It  acquires  pool  lock  during its
1519              operation and can be used simultaneously from several threads.
1520        ************************************************************************/
1521        public static void ae_shared_pool_recycle<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1522        {
1523            sharedpoolentry new_entry;
1524           
1525            /* assert that pool was seeded */
1526            alglib.ap.assert(pool.seed_object!=null, "ALGLIB: shared pool is not seeded, PoolRecycle() failed");
1527           
1528            /* assert that pointer non-null */
1529            alglib.ap.assert(obj!=null, "ALGLIB: obj in ae_shared_pool_recycle() is NULL");
1530           
1531            /* acquire lock */
1532            ae_acquire_lock(pool.pool_lock);
1533           
1534            /* acquire shared pool entry (reuse one from recycled_entries or malloc new one) */
1535            if( pool.recycled_entries!=null )
1536            {
1537                /* reuse previously allocated entry */
1538                new_entry = pool.recycled_entries;
1539                pool.recycled_entries = new_entry.next_entry;
1540            }
1541            else
1542            {
1543                /*
1544                 * Allocate memory for new entry.
1545                 *
1546                 * NOTE: we release pool lock during allocation because new() may raise
1547                 *       exception and we do not want our pool to be left in the locked state.
1548                 */
1549                ae_release_lock(pool.pool_lock);
1550                new_entry = new sharedpoolentry();
1551                ae_acquire_lock(pool.pool_lock);
1552            }
1553           
1554            /* add object to the list of recycled objects */
1555            new_entry.obj = obj;
1556            new_entry.next_entry = pool.recycled_objects;
1557            pool.recycled_objects = new_entry;
1558           
1559            /* release lock object */
1560            ae_release_lock(pool.pool_lock);
1561           
1562            /* release source pointer */
1563            obj = null;
1564        }
1565
1566
1567        /************************************************************************
1568        This function clears internal list of  recycled  objects,  but  does  not
1569        change seed object managed by the pool.
1570
1571        pool                pool
1572
1573        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1574              you should NOT call it when lock can be used by another thread.
1575        ************************************************************************/
1576        public static void ae_shared_pool_clear_recycled(shared_pool pool)
1577        {
1578            pool.recycled_objects = null;
1579        }
1580
1581
1582        /************************************************************************
1583        This function allows to enumerate recycled elements of the  shared  pool.
1584        It stores reference to the first recycled object in the smart pointer.
1585
1586        IMPORTANT:
1587        * in case target variable owns non-NULL value, it is rewritten
1588        * recycled object IS NOT removed from pool
1589        * target variable DOES NOT become owner of the new value; you can use
1590          reference to recycled object, but you do not own it.
1591        * this function IS NOT thread-safe
1592        * you SHOULD NOT modify shared pool during enumeration (although you  can
1593          modify state of the objects retrieved from pool)
1594        * in case there is no recycled objects in the pool, NULL is stored to obj
1595        * in case pool is not seeded, NULL is stored to obj
1596
1597        pool                pool
1598        obj                 reference
1599        ************************************************************************/
1600        public static void ae_shared_pool_first_recycled<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1601        {   
1602            /* modify internal enumeration counter */
1603            pool.enumeration_counter = pool.recycled_objects;
1604           
1605            /* exit on empty list */
1606            if( pool.enumeration_counter==null )
1607            {
1608                obj = null;
1609                return;
1610            }
1611           
1612            /* assign object to smart pointer */
1613            obj = (T)pool.enumeration_counter.obj;
1614        }
1615
1616
1617        /************************************************************************
1618        This function allows to enumerate recycled elements of the  shared  pool.
1619        It stores pointer to the next recycled object in the smart pointer.
1620
1621        IMPORTANT:
1622        * in case target variable owns non-NULL value, it is rewritten
1623        * recycled object IS NOT removed from pool
1624        * target pointer DOES NOT become owner of the new value
1625        * this function IS NOT thread-safe
1626        * you SHOULD NOT modify shared pool during enumeration (although you  can
1627          modify state of the objects retrieved from pool)
1628        * in case there is no recycled objects left in the pool, NULL is stored.
1629        * in case pool is not seeded, NULL is stored.
1630
1631        pool                pool
1632        obj                 target variable
1633        ************************************************************************/
1634        public static void ae_shared_pool_next_recycled<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1635        {   
1636            /* exit on end of list */
1637            if( pool.enumeration_counter==null )
1638            {
1639                obj = null;
1640                return;
1641            }
1642           
1643            /* modify internal enumeration counter */
1644            pool.enumeration_counter = pool.enumeration_counter.next_entry;
1645           
1646            /* exit on empty list */
1647            if( pool.enumeration_counter==null )
1648            {
1649                obj = null;
1650                return;
1651            }
1652           
1653            /* assign object to smart pointer */
1654            obj = (T)pool.enumeration_counter.obj;
1655        }
1656
1657
1658        /************************************************************************
1659        This function clears internal list of recycled objects and  seed  object.
1660        However, pool still can be used (after initialization with another seed).
1661
1662        pool                pool
1663        state               ALGLIB environment state
1664
1665        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1666              you should NOT call it when lock can be used by another thread.
1667        ************************************************************************/
1668        public static void ae_shared_pool_reset(shared_pool pool)
1669        {   
1670            pool.seed_object = null;
1671            pool.recycled_objects = null;
1672            pool.enumeration_counter = null;
1673        }
1674    }
1675}
1676public partial class alglib
1677{
1678    public partial class smp
1679    {
1680        public static int cores_count = 1;
1681    }
1682    public class smpselftests
1683    {
1684        public static bool runtests()
1685        {
1686            return true;
1687        }
1688    }
1689}
Note: See TracBrowser for help on using the repository browser.