Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ScopedAlgorithms/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/3.7.0/ALGLIB-3.7.0/ap.cs @ 16007

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

#2007: Adapated rng of AlgLib 3.7.0 to the changes in #1968.

File size: 65.6 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      [ThreadStatic] //mkommend: added thread static attribute to RNG to have a separate instance per thread and allow modification of the seed
574      public static System.Random rndobject;
575
576        public const double machineepsilon = 5E-16;
577        public const double maxrealnumber = 1E300;
578        public const double minrealnumber = 1E-300;
579       
580        public static bool isfinite(double d)
581        {
582            if (rndobject == null) rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000 * System.DateTime.Now.Second + 60 * 1000 * System.DateTime.Now.Minute);
583            return !System.Double.IsNaN(d) && !System.Double.IsInfinity(d);
584        }
585       
586        public static double randomreal()
587        {
588            double r = 0;
589            if (rndobject == null) rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000 * System.DateTime.Now.Second + 60 * 1000 * System.DateTime.Now.Minute);
590            lock(rndobject){ r = rndobject.NextDouble(); }
591            return r;
592        }
593        public static int randominteger(int N)
594        {
595            int r = 0;
596            if (rndobject == null) rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000 * System.DateTime.Now.Second + 60 * 1000 * System.DateTime.Now.Minute);
597            lock(rndobject){ r = rndobject.Next(N); }
598            return r;
599        }
600        public static double sqr(double X)
601        {
602            return X*X;
603        }       
604        public static double abscomplex(complex z)
605        {
606            double w;
607            double xabs;
608            double yabs;
609            double v;
610   
611            xabs = System.Math.Abs(z.x);
612            yabs = System.Math.Abs(z.y);
613            w = xabs>yabs ? xabs : yabs;
614            v = xabs<yabs ? xabs : yabs;
615            if( v==0 )
616                return w;
617            else
618            {
619                double t = v/w;
620                return w*System.Math.Sqrt(1+t*t);
621            }
622        }
623        public static complex conj(complex z)
624        {
625            return new complex(z.x, -z.y);
626        }   
627        public static complex csqr(complex z)
628        {
629            return new complex(z.x*z.x-z.y*z.y, 2*z.x*z.y);
630        }
631
632    }
633   
634   
635    /********************************************************************
636    serializer object (should not be used directly)
637    ********************************************************************/
638    public class serializer
639    {
640        enum SMODE { DEFAULT, ALLOC, TO_STRING, FROM_STRING };
641        private const int SER_ENTRIES_PER_ROW = 5;
642        private const int SER_ENTRY_LENGTH    = 11;
643       
644        private SMODE mode;
645        private int entries_needed;
646        private int entries_saved;
647        private int bytes_asked;
648        private int bytes_written;
649        private int bytes_read;
650        private char[] out_str;
651        private char[] in_str;
652       
653        public serializer()
654        {
655            mode = SMODE.DEFAULT;
656            entries_needed = 0;
657            bytes_asked = 0;
658        }
659
660        public void alloc_start()
661        {
662            entries_needed = 0;
663            bytes_asked = 0;
664            mode = SMODE.ALLOC;
665        }
666
667        public void alloc_entry()
668        {
669            if( mode!=SMODE.ALLOC )
670                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
671            entries_needed++;
672        }
673
674        private int get_alloc_size()
675        {
676            int rows, lastrowsize, result;
677           
678            // check and change mode
679            if( mode!=SMODE.ALLOC )
680                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
681           
682            // if no entries needes (degenerate case)
683            if( entries_needed==0 )
684            {
685                bytes_asked = 1;
686                return bytes_asked;
687            }
688           
689            // non-degenerate case
690            rows = entries_needed/SER_ENTRIES_PER_ROW;
691            lastrowsize = SER_ENTRIES_PER_ROW;
692            if( entries_needed%SER_ENTRIES_PER_ROW!=0 )
693            {
694                lastrowsize = entries_needed%SER_ENTRIES_PER_ROW;
695                rows++;
696            }
697           
698            // calculate result size
699            result  = ((rows-1)*SER_ENTRIES_PER_ROW+lastrowsize)*SER_ENTRY_LENGTH;
700            result +=  (rows-1)*(SER_ENTRIES_PER_ROW-1)+(lastrowsize-1);
701            result += rows*2;
702            bytes_asked = result;
703            return result;
704        }
705
706        public void sstart_str()
707        {
708            int allocsize = get_alloc_size();
709           
710            // check and change mode
711            if( mode!=SMODE.ALLOC )
712                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
713            mode = SMODE.TO_STRING;
714           
715            // other preparations
716            out_str = new char[allocsize];
717            entries_saved = 0;
718            bytes_written = 0;
719        }
720
721        public void ustart_str(string s)
722        {
723            // check and change mode
724            if( mode!=SMODE.DEFAULT )
725                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
726            mode = SMODE.FROM_STRING;
727           
728            in_str = s.ToCharArray();
729            bytes_read = 0;
730        }
731
732        public void serialize_bool(bool v)
733        {
734            if( mode!=SMODE.TO_STRING )
735                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
736            bool2str(v, out_str, ref bytes_written);
737            entries_saved++;
738            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
739            {
740                out_str[bytes_written] = ' ';
741                bytes_written++;
742            }
743            else
744            {
745                out_str[bytes_written+0] = '\r';
746                out_str[bytes_written+1] = '\n';
747                bytes_written+=2;
748            }           
749        }
750
751        public void serialize_int(int v)
752        {
753            if( mode!=SMODE.TO_STRING )
754                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
755            int2str(v, out_str, ref bytes_written);
756            entries_saved++;
757            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
758            {
759                out_str[bytes_written] = ' ';
760                bytes_written++;
761            }
762            else
763            {
764                out_str[bytes_written+0] = '\r';
765                out_str[bytes_written+1] = '\n';
766                bytes_written+=2;
767            }
768        }
769
770        public void serialize_double(double v)
771        {
772            if( mode!=SMODE.TO_STRING )
773                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
774            double2str(v, out_str, ref bytes_written);
775            entries_saved++;
776            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
777            {
778                out_str[bytes_written] = ' ';
779                bytes_written++;
780            }
781            else
782            {
783                out_str[bytes_written+0] = '\r';
784                out_str[bytes_written+1] = '\n';
785                bytes_written+=2;
786            }
787        }
788
789        public bool unserialize_bool()
790        {
791            if( mode!=SMODE.FROM_STRING )
792                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
793            return str2bool(in_str, ref bytes_read);
794        }
795
796        public int unserialize_int()
797        {
798            if( mode!=SMODE.FROM_STRING )
799                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
800            return str2int(in_str, ref bytes_read);
801        }
802
803        public double unserialize_double()
804        {
805            if( mode!=SMODE.FROM_STRING )
806                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
807            return str2double(in_str, ref bytes_read);
808        }
809
810        public void stop()
811        {
812        }
813
814        public string get_string()
815        {
816            return new string(out_str, 0, bytes_written);
817        }
818
819
820        /************************************************************************
821        This function converts six-bit value (from 0 to 63)  to  character  (only
822        digits, lowercase and uppercase letters, minus and underscore are used).
823
824        If v is negative or greater than 63, this function returns '?'.
825        ************************************************************************/
826        private static char[] _sixbits2char_tbl = new char[64]{
827                '0', '1', '2', '3', '4', '5', '6', '7',
828                '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
829                'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
830                'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
831                'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
832                'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
833                'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
834                'u', 'v', 'w', 'x', 'y', 'z', '-', '_' };
835        private static char sixbits2char(int v)
836        {
837            if( v<0 || v>63 )
838                return '?';
839            return _sixbits2char_tbl[v];
840        }
841       
842        /************************************************************************
843        This function converts character to six-bit value (from 0 to 63).
844
845        This function is inverse of ae_sixbits2char()
846        If c is not correct character, this function returns -1.
847        ************************************************************************/
848        private static int[] _char2sixbits_tbl = new int[128] {
849            -1, -1, -1, -1, -1, -1, -1, -1,
850            -1, -1, -1, -1, -1, -1, -1, -1,
851            -1, -1, -1, -1, -1, -1, -1, -1,
852            -1, -1, -1, -1, -1, -1, -1, -1,
853            -1, -1, -1, -1, -1, -1, -1, -1,
854            -1, -1, -1, -1, -1, 62, -1, -1,
855             0,  1,  2,  3,  4,  5,  6,  7,
856             8,  9, -1, -1, -1, -1, -1, -1,
857            -1, 10, 11, 12, 13, 14, 15, 16,
858            17, 18, 19, 20, 21, 22, 23, 24,
859            25, 26, 27, 28, 29, 30, 31, 32,
860            33, 34, 35, -1, -1, -1, -1, 63,
861            -1, 36, 37, 38, 39, 40, 41, 42,
862            43, 44, 45, 46, 47, 48, 49, 50,
863            51, 52, 53, 54, 55, 56, 57, 58,
864            59, 60, 61, -1, -1, -1, -1, -1 };
865        private static int char2sixbits(char c)
866        {
867            return (c>=0 && c<127) ? _char2sixbits_tbl[c] : -1;
868        }
869       
870        /************************************************************************
871        This function converts three bytes (24 bits) to four six-bit values
872        (24 bits again).
873
874        src         array
875        src_offs    offset of three-bytes chunk
876        dst         array for ints
877        dst_offs    offset of four-ints chunk
878        ************************************************************************/
879        private static void threebytes2foursixbits(byte[] src, int src_offs, int[] dst, int dst_offs)
880        {
881            dst[dst_offs+0] =  src[src_offs+0] & 0x3F;
882            dst[dst_offs+1] = (src[src_offs+0]>>6) | ((src[src_offs+1]&0x0F)<<2);
883            dst[dst_offs+2] = (src[src_offs+1]>>4) | ((src[src_offs+2]&0x03)<<4);
884            dst[dst_offs+3] =  src[src_offs+2]>>2;
885        }
886
887        /************************************************************************
888        This function converts four six-bit values (24 bits) to three bytes
889        (24 bits again).
890
891        src         pointer to four ints
892        src_offs    offset of the chunk
893        dst         pointer to three bytes
894        dst_offs    offset of the chunk
895        ************************************************************************/
896        private static void foursixbits2threebytes(int[] src, int src_offs, byte[] dst, int dst_offs)
897        {
898            dst[dst_offs+0] =      (byte)(src[src_offs+0] | ((src[src_offs+1]&0x03)<<6));
899            dst[dst_offs+1] = (byte)((src[src_offs+1]>>2) | ((src[src_offs+2]&0x0F)<<4));
900            dst[dst_offs+2] = (byte)((src[src_offs+2]>>4) |  (src[src_offs+3]<<2));
901        }
902
903        /************************************************************************
904        This function serializes boolean value into buffer
905
906        v           boolean value to be serialized
907        buf         buffer, at least 11 characters wide
908        offs        offset in the buffer
909       
910        after return from this function, offs points to the char's past the value
911        being read.
912        ************************************************************************/
913        private static void bool2str(bool v, char[] buf, ref int offs)
914        {
915            char c = v ? '1' : '0';
916            int i;
917            for(i=0; i<SER_ENTRY_LENGTH; i++)
918                buf[offs+i] = c;
919            offs += SER_ENTRY_LENGTH;
920        }
921
922        /************************************************************************
923        This function unserializes boolean value from buffer
924
925        buf         buffer which contains value; leading spaces/tabs/newlines are
926                    ignored, traling spaces/tabs/newlines are treated as  end  of
927                    the boolean value.
928        offs        offset in the buffer
929       
930        after return from this function, offs points to the char's past the value
931        being read.
932
933        This function raises an error in case unexpected symbol is found
934        ************************************************************************/
935        private static bool str2bool(char[] buf, ref int offs)
936        {
937            bool was0, was1;
938            string emsg = "ALGLIB: unable to read boolean value from stream";
939           
940            was0 = false;
941            was1 = false;
942            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
943                offs++;
944            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
945            {
946                if( buf[offs]=='0' )
947                {
948                    was0 = true;
949                    offs++;
950                    continue;
951                }
952                if( buf[offs]=='1' )
953                {
954                    was1 = true;
955                    offs++;
956                    continue;
957                }
958                throw new alglib.alglibexception(emsg);
959            }
960            if( (!was0) && (!was1) )
961                throw new alglib.alglibexception(emsg);
962            if( was0 && was1 )
963                throw new alglib.alglibexception(emsg);
964            return was1 ? true : false;
965        }
966
967        /************************************************************************
968        This function serializes integer value into buffer
969
970        v           integer value to be serialized
971        buf         buffer, at least 11 characters wide
972        offs        offset in the buffer
973       
974        after return from this function, offs points to the char's past the value
975        being read.
976
977        This function raises an error in case unexpected symbol is found
978        ************************************************************************/
979        private static void int2str(int v, char[] buf, ref int offs)
980        {
981            int i;
982            byte[] _bytes = System.BitConverter.GetBytes((int)v);
983            byte[]  bytes = new byte[9];
984            int[] sixbits = new int[12];
985            byte c;
986           
987            //
988            // copy v to array of bytes, sign extending it and
989            // converting to little endian order. Additionally,
990            // we set 9th byte to zero in order to simplify
991            // conversion to six-bit representation
992            //
993            if( !System.BitConverter.IsLittleEndian )
994                System.Array.Reverse(_bytes);
995            c = v<0 ? (byte)0xFF : (byte)0x00;
996            for(i=0; i<sizeof(int); i++)
997                bytes[i] = _bytes[i];
998            for(i=sizeof(int); i<8; i++)
999                bytes[i] = c;
1000            bytes[8] = 0;
1001           
1002            //
1003            // convert to six-bit representation, output
1004            //
1005            // NOTE: last 12th element of sixbits is always zero, we do not output it
1006            //
1007            threebytes2foursixbits(bytes, 0, sixbits, 0);
1008            threebytes2foursixbits(bytes, 3, sixbits, 4);
1009            threebytes2foursixbits(bytes, 6, sixbits, 8);       
1010            for(i=0; i<SER_ENTRY_LENGTH; i++)
1011                buf[offs+i] = sixbits2char(sixbits[i]);
1012            offs += SER_ENTRY_LENGTH;
1013        }
1014
1015        /************************************************************************
1016        This function unserializes integer value from string
1017
1018        buf         buffer which contains value; leading spaces/tabs/newlines are
1019                    ignored, traling spaces/tabs/newlines are treated as  end  of
1020                    the integer value.
1021        offs        offset in the buffer
1022       
1023        after return from this function, offs points to the char's past the value
1024        being read.
1025
1026        This function raises an error in case unexpected symbol is found
1027        ************************************************************************/
1028        private static int str2int(char[] buf, ref int offs)
1029        {
1030            string emsg =       "ALGLIB: unable to read integer value from stream";
1031            string emsg3264 =   "ALGLIB: unable to read integer value from stream (value does not fit into 32 bits)";
1032            int[] sixbits = new int[12];
1033            byte[] bytes = new byte[9];
1034            byte[] _bytes = new byte[sizeof(int)];
1035            int sixbitsread, i;
1036            byte c;
1037           
1038            //
1039            // 1. skip leading spaces
1040            // 2. read and decode six-bit digits
1041            // 3. set trailing digits to zeros
1042            // 4. convert to little endian 64-bit integer representation
1043            // 5. check that we fit into int
1044            // 6. convert to big endian representation, if needed
1045            //
1046            sixbitsread = 0;
1047            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1048                offs++;
1049            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1050            {
1051                int d;
1052                d = char2sixbits(buf[offs]);
1053                if( d<0 || sixbitsread>=SER_ENTRY_LENGTH )
1054                    throw new alglib.alglibexception(emsg);
1055                sixbits[sixbitsread] = d;
1056                sixbitsread++;
1057                offs++;
1058            }
1059            if( sixbitsread==0 )
1060                throw new alglib.alglibexception(emsg);
1061            for(i=sixbitsread; i<12; i++)
1062                sixbits[i] = 0;
1063            foursixbits2threebytes(sixbits, 0, bytes, 0);
1064            foursixbits2threebytes(sixbits, 4, bytes, 3);
1065            foursixbits2threebytes(sixbits, 8, bytes, 6);
1066            c = (bytes[sizeof(int)-1] & 0x80)!=0 ? (byte)0xFF : (byte)0x00;
1067            for(i=sizeof(int); i<8; i++)
1068                if( bytes[i]!=c )
1069                    throw new alglib.alglibexception(emsg3264);
1070            for(i=0; i<sizeof(int); i++)
1071                _bytes[i] = bytes[i];       
1072            if( !System.BitConverter.IsLittleEndian )
1073                System.Array.Reverse(_bytes);
1074            return System.BitConverter.ToInt32(_bytes,0);
1075        }   
1076       
1077       
1078        /************************************************************************
1079        This function serializes double value into buffer
1080
1081        v           double value to be serialized
1082        buf         buffer, at least 11 characters wide
1083        offs        offset in the buffer
1084       
1085        after return from this function, offs points to the char's past the value
1086        being read.
1087        ************************************************************************/
1088        private static void double2str(double v, char[] buf, ref int offs)
1089        {
1090            int i;
1091            int[] sixbits = new int[12];
1092            byte[] bytes = new byte[9];
1093
1094            //
1095            // handle special quantities
1096            //
1097            if( System.Double.IsNaN(v) )
1098            {
1099                buf[offs+0] = '.';
1100                buf[offs+1] = 'n';
1101                buf[offs+2] = 'a';
1102                buf[offs+3] = 'n';
1103                buf[offs+4] = '_';
1104                buf[offs+5] = '_';
1105                buf[offs+6] = '_';
1106                buf[offs+7] = '_';
1107                buf[offs+8] = '_';
1108                buf[offs+9] = '_';
1109                buf[offs+10] = '_';
1110                offs += SER_ENTRY_LENGTH;
1111                return;
1112            }
1113            if( System.Double.IsPositiveInfinity(v) )
1114            {
1115                buf[offs+0] = '.';
1116                buf[offs+1] = 'p';
1117                buf[offs+2] = 'o';
1118                buf[offs+3] = 's';
1119                buf[offs+4] = 'i';
1120                buf[offs+5] = 'n';
1121                buf[offs+6] = 'f';
1122                buf[offs+7] = '_';
1123                buf[offs+8] = '_';
1124                buf[offs+9] = '_';
1125                buf[offs+10] = '_';
1126                offs += SER_ENTRY_LENGTH;
1127                return;
1128            }
1129            if( System.Double.IsNegativeInfinity(v) )
1130            {
1131                buf[offs+0] = '.';
1132                buf[offs+1] = 'n';
1133                buf[offs+2] = 'e';
1134                buf[offs+3] = 'g';
1135                buf[offs+4] = 'i';
1136                buf[offs+5] = 'n';
1137                buf[offs+6] = 'f';
1138                buf[offs+7] = '_';
1139                buf[offs+8] = '_';
1140                buf[offs+9] = '_';
1141                buf[offs+10] = '_';
1142                offs += SER_ENTRY_LENGTH;
1143                return;
1144            }
1145           
1146            //
1147            // process general case:
1148            // 1. copy v to array of chars
1149            // 2. set 9th byte to zero in order to simplify conversion to six-bit representation
1150            // 3. convert to little endian (if needed)
1151            // 4. convert to six-bit representation
1152            //    (last 12th element of sixbits is always zero, we do not output it)
1153            //
1154            byte[] _bytes = System.BitConverter.GetBytes((double)v);
1155            if( !System.BitConverter.IsLittleEndian )
1156                System.Array.Reverse(_bytes);
1157            for(i=0; i<sizeof(double); i++)
1158                bytes[i] = _bytes[i];
1159            for(i=sizeof(double); i<9; i++)
1160                bytes[i] = 0;
1161            threebytes2foursixbits(bytes, 0, sixbits, 0);
1162            threebytes2foursixbits(bytes, 3, sixbits, 4);
1163            threebytes2foursixbits(bytes, 6, sixbits, 8);
1164            for(i=0; i<SER_ENTRY_LENGTH; i++)
1165                buf[offs+i] = sixbits2char(sixbits[i]);
1166            offs += SER_ENTRY_LENGTH;
1167        }
1168
1169        /************************************************************************
1170        This function unserializes double value from string
1171
1172        buf         buffer which contains value; leading spaces/tabs/newlines are
1173                    ignored, traling spaces/tabs/newlines are treated as  end  of
1174                    the double value.
1175        offs        offset in the buffer
1176       
1177        after return from this function, offs points to the char's past the value
1178        being read.
1179
1180        This function raises an error in case unexpected symbol is found
1181        ************************************************************************/
1182        private static double str2double(char[] buf, ref int offs)
1183        {
1184            string emsg = "ALGLIB: unable to read double value from stream";
1185            int[] sixbits = new int[12];
1186            byte[]  bytes = new byte[9];
1187            byte[] _bytes = new byte[sizeof(double)];
1188            int sixbitsread, i;
1189           
1190           
1191            //
1192            // skip leading spaces
1193            //
1194            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1195                offs++;
1196           
1197             
1198            //
1199            // Handle special cases
1200            //
1201            if( buf[offs]=='.' )
1202            {
1203                string s = new string(buf, offs, SER_ENTRY_LENGTH);
1204                if( s==".nan_______" )
1205                {
1206                    offs += SER_ENTRY_LENGTH;
1207                    return System.Double.NaN;
1208                }
1209                if( s==".posinf____" )
1210                {
1211                    offs += SER_ENTRY_LENGTH;
1212                    return System.Double.PositiveInfinity;
1213                }
1214                if( s==".neginf____" )
1215                {
1216                    offs += SER_ENTRY_LENGTH;
1217                    return System.Double.NegativeInfinity;
1218                }
1219                throw new alglib.alglibexception(emsg);
1220            }
1221           
1222            //
1223            // General case:
1224            // 1. read and decode six-bit digits
1225            // 2. check that all 11 digits were read
1226            // 3. set last 12th digit to zero (needed for simplicity of conversion)
1227            // 4. convert to 8 bytes
1228            // 5. convert to big endian representation, if needed
1229            //
1230            sixbitsread = 0;
1231            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1232            {
1233                int d;
1234                d = char2sixbits(buf[offs]);
1235                if( d<0 || sixbitsread>=SER_ENTRY_LENGTH )
1236                    throw new alglib.alglibexception(emsg);
1237                sixbits[sixbitsread] = d;
1238                sixbitsread++;
1239                offs++;
1240            }
1241            if( sixbitsread!=SER_ENTRY_LENGTH )
1242                throw new alglib.alglibexception(emsg);
1243            sixbits[SER_ENTRY_LENGTH] = 0;
1244            foursixbits2threebytes(sixbits, 0, bytes, 0);
1245            foursixbits2threebytes(sixbits, 4, bytes, 3);
1246            foursixbits2threebytes(sixbits, 8, bytes, 6);
1247            for(i=0; i<sizeof(double); i++)
1248                _bytes[i] = bytes[i];       
1249            if( !System.BitConverter.IsLittleEndian )
1250                System.Array.Reverse(_bytes);       
1251            return System.BitConverter.ToDouble(_bytes,0);
1252        }
1253    }
1254
1255    /*
1256     * Parts of alglib.smp class which are shared with GPL version of ALGLIB
1257     */
1258    public partial class smp
1259    {
1260        #pragma warning disable 420
1261        public const int AE_LOCK_CYCLES = 512;
1262       
1263        /*
1264         * This variable is used to perform spin-wait loops in a platform-independent manner
1265         * (loops which should work same way on Mono and Microsoft NET). You SHOULD NEVER
1266         * change this field - it must be zero during all program life.
1267         */
1268        public static volatile int never_change_it = 0;
1269       
1270        /*************************************************************************
1271        Lock.
1272
1273        This class provides lightweight spin lock
1274        *************************************************************************/
1275        public class ae_lock
1276        {
1277            public volatile int is_locked;
1278        }
1279
1280        /********************************************************************
1281        Shared pool: data structure used to provide thread-safe access to pool
1282        of temporary variables.
1283        ********************************************************************/
1284        public class sharedpoolentry
1285        {
1286            public apobject obj;
1287            public sharedpoolentry next_entry;
1288        }
1289        public class shared_pool : apobject
1290        {
1291            /* lock object which protects pool */
1292            public ae_lock pool_lock;
1293   
1294            /* seed object (used to create new instances of temporaries) */
1295            public volatile apobject seed_object;
1296           
1297            /*
1298             * list of recycled OBJECTS:
1299             * 1. entries in this list store pointers to recycled objects
1300             * 2. every time we retrieve object, we retrieve first entry from this list,
1301             *    move it to recycled_entries and return its obj field to caller/
1302             */
1303            public volatile sharedpoolentry recycled_objects;
1304           
1305            /*
1306             * list of recycled ENTRIES:
1307             * 1. this list holds entries which are not used to store recycled objects;
1308             *    every time recycled object is retrieved, its entry is moved to this list.
1309             * 2. every time object is recycled, we try to fetch entry for him from this list
1310             *    before allocating it with malloc()
1311             */
1312            public volatile sharedpoolentry recycled_entries;
1313           
1314            /* enumeration pointer, points to current recycled object*/
1315            public volatile sharedpoolentry enumeration_counter;
1316           
1317            /* constructor */
1318            public shared_pool()
1319            {
1320                ae_init_lock(ref pool_lock);
1321            }
1322           
1323            /* initializer - creation of empty pool */
1324            public override void init()
1325            {
1326                seed_object = null;
1327                recycled_objects = null;
1328                recycled_entries = null;
1329                enumeration_counter = null;
1330            }
1331           
1332            /* copy constructor (it is NOT thread-safe) */
1333            public override apobject make_copy()
1334            {
1335                sharedpoolentry ptr, buf;
1336                shared_pool result = new shared_pool();
1337               
1338                /* create lock */
1339                ae_init_lock(ref result.pool_lock);
1340   
1341                /* copy seed object */
1342                if( seed_object!=null )
1343                    result.seed_object = seed_object.make_copy();
1344               
1345                /*
1346                 * copy recycled objects:
1347                 * 1. copy to temporary list (objects are inserted to beginning, order is reversed)
1348                 * 2. copy temporary list to output list (order is restored back to normal)
1349                 */
1350                buf = null;
1351                for(ptr=recycled_objects; ptr!=null; ptr=ptr.next_entry)
1352                {
1353                    sharedpoolentry tmp = new sharedpoolentry();
1354                    tmp.obj =  ptr.obj.make_copy();
1355                    tmp.next_entry = buf;
1356                    buf = tmp;
1357                }
1358                result.recycled_objects = null;
1359                for(ptr=buf; ptr!=null;)
1360                {
1361                    sharedpoolentry next_ptr = ptr.next_entry;
1362                    ptr.next_entry = result.recycled_objects;
1363                    result.recycled_objects = ptr;
1364                    ptr = next_ptr;
1365                }
1366   
1367                /* recycled entries are not copied because they do not store any information */
1368                result.recycled_entries = null;
1369   
1370                /* enumeration counter is reset on copying */
1371                result.enumeration_counter = null;
1372   
1373                return result;
1374            }
1375        }
1376       
1377
1378        /************************************************************************
1379        This function performs given number of spin-wait iterations
1380        ************************************************************************/
1381        public static void ae_spin_wait(int cnt)
1382        {
1383            /*int i, v;
1384            v = 0;
1385            for(i=0; i<cnt; i++)
1386                System.Threading.Interlocked.Exchange(ref v, i);*/
1387            for(int i=0; i<cnt && never_change_it==0; i++)
1388                if( never_change_it!=0 )
1389                    never_change_it = i;
1390            if( never_change_it!=0 )
1391                never_change_it = 0;
1392        }
1393
1394        /************************************************************************
1395        This function initializes ae_lock structure and sets lock in a free mode.
1396        ************************************************************************/
1397        public static void ae_init_lock(ref ae_lock obj)
1398        {
1399            obj = new ae_lock();
1400            obj.is_locked = 0;
1401        }
1402
1403
1404        /************************************************************************
1405        This function acquires lock. In case lock is busy, we perform several
1406        iterations inside tight loop before trying again.
1407        ************************************************************************/
1408        public static void ae_acquire_lock(ae_lock obj)
1409        {
1410            for(;;)
1411            {
1412                if( System.Threading.Interlocked.CompareExchange(ref obj.is_locked, 1, 0)==0 )
1413                    return;
1414                ae_spin_wait(AE_LOCK_CYCLES);
1415            }
1416        }
1417
1418
1419        /************************************************************************
1420        This function releases lock.
1421        ************************************************************************/
1422        public static void ae_release_lock(ae_lock obj)
1423        {
1424            System.Threading.Interlocked.Exchange(ref obj.is_locked, 0);
1425        }
1426
1427
1428        /************************************************************************
1429        This function frees ae_lock structure.
1430        ************************************************************************/
1431        public static void ae_free_lock(ref ae_lock obj)
1432        {
1433            obj = null;
1434        }
1435       
1436       
1437        /************************************************************************
1438        This function sets internal seed object. All objects owned by the pool
1439        (current seed object, recycled objects) are automatically freed.
1440
1441        dst                 destination pool (initialized by constructor function)
1442        seed_object         new seed object
1443
1444        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1445              you should NOT call it when lock can be used by another thread.
1446        ************************************************************************/
1447        public static void ae_shared_pool_set_seed(shared_pool dst, alglib.apobject seed_object)
1448        {
1449            dst.seed_object = seed_object.make_copy();
1450            dst.recycled_objects = null;
1451            dst.enumeration_counter = null;
1452        }
1453
1454
1455        /************************************************************************
1456        This  function  retrieves  a  copy  of  the seed object from the pool and
1457        stores it to target variable.
1458
1459        pool                pool
1460        obj                 target variable
1461       
1462        NOTE: this function IS thread-safe.  It  acquires  pool  lock  during its
1463              operation and can be used simultaneously from several threads.
1464        ************************************************************************/
1465        public static void ae_shared_pool_retrieve<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1466        {
1467            alglib.apobject new_obj;
1468           
1469            /* assert that pool was seeded */
1470            alglib.ap.assert(pool.seed_object!=null, "ALGLIB: shared pool is not seeded, PoolRetrieve() failed");
1471           
1472            /* acquire lock */
1473            ae_acquire_lock(pool.pool_lock);
1474           
1475            /* try to reuse recycled objects */
1476            if( pool.recycled_objects!=null )
1477            {
1478                /* retrieve entry/object from list of recycled objects */
1479                sharedpoolentry result = pool.recycled_objects;
1480                pool.recycled_objects = pool.recycled_objects.next_entry;
1481                new_obj = result.obj;
1482                result.obj = null;
1483               
1484                /* move entry to list of recycled entries */
1485                result.next_entry = pool.recycled_entries;
1486                pool.recycled_entries = result;
1487               
1488                /* release lock */
1489                ae_release_lock(pool.pool_lock);
1490               
1491                /* assign object to smart pointer */
1492                obj = (T)new_obj;
1493               
1494                return;
1495            }
1496               
1497            /*
1498             * release lock; we do not need it anymore because
1499             * copy constructor does not modify source variable.
1500             */
1501            ae_release_lock(pool.pool_lock);
1502           
1503            /* create new object from seed */
1504            new_obj = pool.seed_object.make_copy();
1505               
1506            /* assign object to pointer and return */
1507            obj = (T)new_obj;
1508        }
1509
1510
1511        /************************************************************************
1512        This  function  recycles object owned by the source variable by moving it
1513        to internal storage of the shared pool.
1514
1515        Source  variable  must  own  the  object,  i.e.  be  the only place where
1516        reference  to  object  is  stored.  After  call  to  this function source
1517        variable becomes NULL.
1518
1519        pool                pool
1520        obj                 source variable
1521
1522        NOTE: this function IS thread-safe.  It  acquires  pool  lock  during its
1523              operation and can be used simultaneously from several threads.
1524        ************************************************************************/
1525        public static void ae_shared_pool_recycle<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1526        {
1527            sharedpoolentry new_entry;
1528           
1529            /* assert that pool was seeded */
1530            alglib.ap.assert(pool.seed_object!=null, "ALGLIB: shared pool is not seeded, PoolRecycle() failed");
1531           
1532            /* assert that pointer non-null */
1533            alglib.ap.assert(obj!=null, "ALGLIB: obj in ae_shared_pool_recycle() is NULL");
1534           
1535            /* acquire lock */
1536            ae_acquire_lock(pool.pool_lock);
1537           
1538            /* acquire shared pool entry (reuse one from recycled_entries or malloc new one) */
1539            if( pool.recycled_entries!=null )
1540            {
1541                /* reuse previously allocated entry */
1542                new_entry = pool.recycled_entries;
1543                pool.recycled_entries = new_entry.next_entry;
1544            }
1545            else
1546            {
1547                /*
1548                 * Allocate memory for new entry.
1549                 *
1550                 * NOTE: we release pool lock during allocation because new() may raise
1551                 *       exception and we do not want our pool to be left in the locked state.
1552                 */
1553                ae_release_lock(pool.pool_lock);
1554                new_entry = new sharedpoolentry();
1555                ae_acquire_lock(pool.pool_lock);
1556            }
1557           
1558            /* add object to the list of recycled objects */
1559            new_entry.obj = obj;
1560            new_entry.next_entry = pool.recycled_objects;
1561            pool.recycled_objects = new_entry;
1562           
1563            /* release lock object */
1564            ae_release_lock(pool.pool_lock);
1565           
1566            /* release source pointer */
1567            obj = null;
1568        }
1569
1570
1571        /************************************************************************
1572        This function clears internal list of  recycled  objects,  but  does  not
1573        change seed object managed by the pool.
1574
1575        pool                pool
1576
1577        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1578              you should NOT call it when lock can be used by another thread.
1579        ************************************************************************/
1580        public static void ae_shared_pool_clear_recycled(shared_pool pool)
1581        {
1582            pool.recycled_objects = null;
1583        }
1584
1585
1586        /************************************************************************
1587        This function allows to enumerate recycled elements of the  shared  pool.
1588        It stores reference to the first recycled object in the smart pointer.
1589
1590        IMPORTANT:
1591        * in case target variable owns non-NULL value, it is rewritten
1592        * recycled object IS NOT removed from pool
1593        * target variable DOES NOT become owner of the new value; you can use
1594          reference to recycled object, but you do not own it.
1595        * this function IS NOT thread-safe
1596        * you SHOULD NOT modify shared pool during enumeration (although you  can
1597          modify state of the objects retrieved from pool)
1598        * in case there is no recycled objects in the pool, NULL is stored to obj
1599        * in case pool is not seeded, NULL is stored to obj
1600
1601        pool                pool
1602        obj                 reference
1603        ************************************************************************/
1604        public static void ae_shared_pool_first_recycled<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1605        {   
1606            /* modify internal enumeration counter */
1607            pool.enumeration_counter = pool.recycled_objects;
1608           
1609            /* exit on empty list */
1610            if( pool.enumeration_counter==null )
1611            {
1612                obj = null;
1613                return;
1614            }
1615           
1616            /* assign object to smart pointer */
1617            obj = (T)pool.enumeration_counter.obj;
1618        }
1619
1620
1621        /************************************************************************
1622        This function allows to enumerate recycled elements of the  shared  pool.
1623        It stores pointer to the next recycled object in the smart pointer.
1624
1625        IMPORTANT:
1626        * in case target variable owns non-NULL value, it is rewritten
1627        * recycled object IS NOT removed from pool
1628        * target pointer DOES NOT become owner of the new value
1629        * this function IS NOT thread-safe
1630        * you SHOULD NOT modify shared pool during enumeration (although you  can
1631          modify state of the objects retrieved from pool)
1632        * in case there is no recycled objects left in the pool, NULL is stored.
1633        * in case pool is not seeded, NULL is stored.
1634
1635        pool                pool
1636        obj                 target variable
1637        ************************************************************************/
1638        public static void ae_shared_pool_next_recycled<T>(shared_pool pool, ref T obj) where T : alglib.apobject
1639        {   
1640            /* exit on end of list */
1641            if( pool.enumeration_counter==null )
1642            {
1643                obj = null;
1644                return;
1645            }
1646           
1647            /* modify internal enumeration counter */
1648            pool.enumeration_counter = pool.enumeration_counter.next_entry;
1649           
1650            /* exit on empty list */
1651            if( pool.enumeration_counter==null )
1652            {
1653                obj = null;
1654                return;
1655            }
1656           
1657            /* assign object to smart pointer */
1658            obj = (T)pool.enumeration_counter.obj;
1659        }
1660
1661
1662        /************************************************************************
1663        This function clears internal list of recycled objects and  seed  object.
1664        However, pool still can be used (after initialization with another seed).
1665
1666        pool                pool
1667        state               ALGLIB environment state
1668
1669        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1670              you should NOT call it when lock can be used by another thread.
1671        ************************************************************************/
1672        public static void ae_shared_pool_reset(shared_pool pool)
1673        {   
1674            pool.seed_object = null;
1675            pool.recycled_objects = null;
1676            pool.enumeration_counter = null;
1677        }
1678    }
1679}
1680public partial class alglib
1681{
1682    public partial class smp
1683    {
1684        public static int cores_count = 1;
1685    }
1686    public class smpselftests
1687    {
1688        public static bool runtests()
1689        {
1690            return true;
1691        }
1692    }
1693}
Note: See TracBrowser for help on using the repository browser.