Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/3.9.0/ALGLIB-3.9.0/ap.cs @ 12790

Last change on this file since 12790 was 12790, checked in by gkronber, 9 years ago

#2435: updated alglib to version 3.9.0

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