Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2435-alglib_3_15/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/3.15.0/ALGLIB-3.15.0/ap.cs @ 17036

Last change on this file since 17036 was 17036, checked in by mkommend, 5 years ago

#2435: Changed rng in ALGLIB to have a separate instance per thread.

File size: 88.2 KB
Line 
1/**************************************************************************
2ALGLIB 3.15.0 (source code generated 2019-02-20)
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    Critical failure, resilts in immediate termination of entire program.
196    ********************************************************************/
197    public static void AE_CRITICAL_ASSERT(bool x)
198    {
199        if( !x )
200            System.Environment.FailFast("ALGLIB: critical error");
201    }
202   
203    /********************************************************************
204    ALGLIB object, parent  class  for  all  internal  AlgoPascal  objects
205    managed by ALGLIB.
206   
207    Any internal AlgoPascal object inherits from this class.
208   
209    User-visible objects inherit from alglibobject (see below).
210    ********************************************************************/
211    public abstract class apobject
212    {
213        public abstract void init();
214        public abstract apobject make_copy();
215    }
216   
217    /********************************************************************
218    ALGLIB object, parent class for all user-visible objects  managed  by
219    ALGLIB.
220   
221    Methods:
222        _deallocate()       deallocation:
223                            * in managed ALGLIB it does nothing
224                            * in native ALGLIB it clears  dynamic  memory
225                              being  hold  by  object  and  sets internal
226                              reference to null.
227        make_copy()         creates deep copy of the object.
228                            Works in both managed and native versions  of
229                            ALGLIB.
230    ********************************************************************/
231    public abstract class alglibobject : IDisposable
232    {
233        public virtual void _deallocate() {}
234        public abstract alglibobject make_copy();
235        public void Dispose()
236        {
237            _deallocate();
238        }
239    }
240   
241    /********************************************************************
242    xparams object, used to pass additional parameters like multithreading
243    settings, and several predefined values
244    ********************************************************************/
245    public class xparams
246    {
247        public ulong flags;
248        public xparams(ulong v)
249        {
250            flags = v;
251        }
252    }
253    private static ulong FLG_THREADING_MASK          = 0x7;
254    private static   int FLG_THREADING_SHIFT         = 0;
255    private static ulong FLG_THREADING_USE_GLOBAL    = 0x0;
256    private static ulong FLG_THREADING_SERIAL        = 0x1;
257    private static ulong FLG_THREADING_PARALLEL      = 0x2;
258    public static xparams serial   = new xparams(FLG_THREADING_SERIAL);
259    public static xparams parallel = new xparams(FLG_THREADING_PARALLEL);
260
261    /********************************************************************
262    Global flags, split into several char-sized variables in order
263    to avoid problem with non-atomic reads/writes (single-byte ops
264    are atomic on all modern architectures);
265   
266    Following variables are included:
267    * threading-related settings
268    ********************************************************************/
269    public static byte global_threading_flags = (byte)(FLG_THREADING_SERIAL>>FLG_THREADING_SHIFT);
270   
271    public static void setglobalthreading(xparams p)
272    {
273        AE_CRITICAL_ASSERT(p!=null);
274        ae_set_global_threading(p.flags);
275    }
276   
277    public static void ae_set_global_threading(ulong flg_value)
278    {
279        flg_value = flg_value&FLG_THREADING_MASK;
280        AE_CRITICAL_ASSERT(flg_value==FLG_THREADING_SERIAL || flg_value==FLG_THREADING_PARALLEL);
281        global_threading_flags = (byte)(flg_value>>FLG_THREADING_SHIFT);
282    }
283   
284    public static ulong ae_get_global_threading()
285    {
286        return ((ulong)global_threading_flags)<<FLG_THREADING_SHIFT;
287    }
288   
289    static ulong ae_get_effective_threading(xparams p)
290    {
291        if( p==null || (p.flags&FLG_THREADING_MASK)==FLG_THREADING_USE_GLOBAL )
292            return ((ulong)global_threading_flags)<<FLG_THREADING_SHIFT;
293        return p.flags&FLG_THREADING_MASK;
294    }
295   
296    /********************************************************************
297    Deallocation of ALGLIB object:
298    * in managed ALGLIB this method just sets refence to null
299    * in native ALGLIB call of this method:
300      1) clears dynamic memory being hold by  object  and  sets  internal
301         reference to null.
302      2) sets to null variable being passed to this method
303   
304    IMPORTANT (1): in  native  edition  of  ALGLIB,  obj becomes unusable
305                   after this call!!!  It  is  possible  to  save  a copy
306                   of reference in another variable (original variable is
307                   set to null), but any attempt to work with this object
308                   will crash your program.
309   
310    IMPORTANT (2): memory owned by object will be recycled by GC  in  any
311                   case. This method just enforces IMMEDIATE deallocation.
312    ********************************************************************/
313    public static void deallocateimmediately<T>(ref T obj) where T : alglib.alglibobject
314    {
315        obj._deallocate();
316        obj = null;
317    }
318
319    /********************************************************************
320    Allocation counter:
321    * in managed ALGLIB it always returns 0 (dummy code)
322    * in native ALGLIB it returns current value of the allocation counter
323      (if it was activated)
324    ********************************************************************/
325    public static long alloc_counter()
326    {
327        return 0;
328    }
329   
330    /********************************************************************
331    Activization of the allocation counter:
332    * in managed ALGLIB it does nothing (dummy code)
333    * in native ALGLIB it turns on allocation counting.
334    ********************************************************************/
335    public static void alloc_counter_activate()
336    {
337    }
338   
339    /********************************************************************
340    This function allows to set one of the debug flags.
341    In managed ALGLIB does nothing (dummy).
342    ********************************************************************/
343    public static void set_dbg_flag(long flag_id, long flag_value)
344    {
345    }
346   
347    /********************************************************************
348    This function allows to get one of the debug counters.
349    In managed ALGLIB does nothing (dummy).
350    ********************************************************************/
351    public static long get_dbg_value(long id)
352    {
353        return 0;
354    }
355   
356    /********************************************************************
357    Activization of the allocation counter:
358    * in managed ALGLIB it does nothing (dummy code)
359    * in native ALGLIB it turns on allocation counting.
360    ********************************************************************/
361    public static void free_disposed_items()
362    {
363    }
364   
365    /************************************************************************
366    This function maps nworkers  number  (which  can  be  positive,  zero  or
367    negative with 0 meaning "all cores", -1 meaning "all cores -1" and so on)
368    to "effective", strictly positive workers count.
369
370    This  function  is  intended  to  be used by debugging/testing code which
371    tests different number of worker threads. It is NOT aligned  in  any  way
372    with ALGLIB multithreading framework (i.e. it can return  non-zero worker
373    count even for single-threaded GPLed ALGLIB).
374    ************************************************************************/
375    public static int get_effective_workers(int nworkers)
376    {
377        int ncores = System.Environment.ProcessorCount;
378        if( nworkers>=1 )
379            return nworkers>ncores ? ncores : nworkers;
380        return ncores+nworkers>=1 ? ncores+nworkers : 1;
381    }
382   
383    /********************************************************************
384    reverse communication structure
385    ********************************************************************/
386    public class rcommstate : apobject
387    {
388        public rcommstate()
389        {
390            init();
391        }
392        public override void init()
393        {
394            stage = -1;
395            ia = new int[0];
396            ba = new bool[0];
397            ra = new double[0];
398            ca = new alglib.complex[0];
399        }
400        public override apobject make_copy()
401        {
402            rcommstate result = new rcommstate();
403            result.stage = stage;
404            result.ia = (int[])ia.Clone();
405            result.ba = (bool[])ba.Clone();
406            result.ra = (double[])ra.Clone();
407            result.ca = (alglib.complex[])ca.Clone();
408            return result;
409        }
410        public int stage;
411        public int[] ia;
412        public bool[] ba;
413        public double[] ra;
414        public alglib.complex[] ca;
415    };
416
417    /********************************************************************
418    internal functions
419    ********************************************************************/
420    public class ap
421    {
422        public static int len<T>(T[] a)
423        { return a.Length; }
424        public static int rows<T>(T[,] a)
425        { return a.GetLength(0); }
426        public static int cols<T>(T[,] a)
427        { return a.GetLength(1); }
428        public static void swap<T>(ref T a, ref T b)
429        {
430            T t = a;
431            a = b;
432            b = t;
433        }
434       
435        public static void assert(bool cond, string s)
436        {
437            if( !cond )
438                throw new alglibexception(s);
439        }
440       
441        public static void assert(bool cond)
442        {
443            assert(cond, "ALGLIB: assertion failed");
444        }
445       
446        /****************************************************************
447        Error tracking for unit testing purposes; utility functions.
448        ****************************************************************/
449        public static string sef_xdesc = "";
450       
451        public static void seterrorflag(ref bool flag, bool cond, string xdesc)
452        {
453            if( cond )
454            {
455                flag = true;
456                sef_xdesc = xdesc;
457            }
458        }
459       
460        /****************************************************************
461        returns dps (digits-of-precision) value corresponding to threshold.
462        dps(0.9)  = dps(0.5)  = dps(0.1) = 0
463        dps(0.09) = dps(0.05) = dps(0.01) = 1
464        and so on
465        ****************************************************************/
466        public static int threshold2dps(double threshold)
467        {
468            int result = 0;
469            double t;
470            for (result = 0, t = 1; t / 10 > threshold*(1+1E-10); result++, t /= 10) ;
471            return result;
472        }
473
474        /****************************************************************
475        prints formatted complex
476        ****************************************************************/
477        public static string format(complex a, int _dps)
478        {
479            int dps = Math.Abs(_dps);
480            string fmt = _dps>=0 ? "F" : "E";
481            string fmtx = String.Format("{{0:"+fmt+"{0}}}", dps);
482            string fmty = String.Format("{{0:"+fmt+"{0}}}", dps);
483            string result = String.Format(fmtx, a.x) + (a.y >= 0 ? "+" : "-") + String.Format(fmty, Math.Abs(a.y)) + "i";
484            result = result.Replace(',', '.');
485            return result;
486        }
487
488        /****************************************************************
489        prints formatted array
490        ****************************************************************/
491        public static string format(bool[] a)
492        {
493            string[] result = new string[len(a)];
494            int i;
495            for(i=0; i<len(a); i++)
496                if( a[i] )
497                    result[i] = "true";
498                else
499                    result[i] = "false";
500            return "{"+String.Join(",",result)+"}";
501        }
502       
503        /****************************************************************
504        prints formatted array
505        ****************************************************************/
506        public static string format(int[] a)
507        {
508            string[] result = new string[len(a)];
509            int i;
510            for (i = 0; i < len(a); i++)
511                result[i] = a[i].ToString();
512            return "{" + String.Join(",", result) + "}";
513        }
514
515        /****************************************************************
516        prints formatted array
517        ****************************************************************/
518        public static string format(double[] a, int _dps)
519        {
520            int dps = Math.Abs(_dps);
521            string sfmt = _dps >= 0 ? "F" : "E";
522            string fmt = String.Format("{{0:" + sfmt + "{0}}}", dps);
523            string[] result = new string[len(a)];
524            int i;
525            for (i = 0; i < len(a); i++)
526            {
527                result[i] = String.Format(fmt, a[i]);
528                result[i] = result[i].Replace(',', '.');
529            }
530            return "{" + String.Join(",", result) + "}";
531        }
532
533        /****************************************************************
534        prints formatted array
535        ****************************************************************/
536        public static string format(complex[] a, int _dps)
537        {
538            int dps = Math.Abs(_dps);
539            string fmt = _dps >= 0 ? "F" : "E";
540            string fmtx = String.Format("{{0:"+fmt+"{0}}}", dps);
541            string fmty = String.Format("{{0:"+fmt+"{0}}}", dps);
542            string[] result = new string[len(a)];
543            int i;
544            for (i = 0; i < len(a); i++)
545            {
546                result[i] = String.Format(fmtx, a[i].x) + (a[i].y >= 0 ? "+" : "-") + String.Format(fmty, Math.Abs(a[i].y)) + "i";
547                result[i] = result[i].Replace(',', '.');
548            }
549            return "{" + String.Join(",", result) + "}";
550        }
551
552        /****************************************************************
553        prints formatted matrix
554        ****************************************************************/
555        public static string format(bool[,] a)
556        {
557            int i, j, m, n;
558            n = cols(a);
559            m = rows(a);
560            bool[] line = new bool[n];
561            string[] result = new string[m];
562            for (i = 0; i < m; i++)
563            {
564                for (j = 0; j < n; j++)
565                    line[j] = a[i, j];
566                result[i] = format(line);
567            }
568            return "{" + String.Join(",", result) + "}";
569        }
570
571        /****************************************************************
572        prints formatted matrix
573        ****************************************************************/
574        public static string format(int[,] a)
575        {
576            int i, j, m, n;
577            n = cols(a);
578            m = rows(a);
579            int[] line = new int[n];
580            string[] result = new string[m];
581            for (i = 0; i < m; i++)
582            {
583                for (j = 0; j < n; j++)
584                    line[j] = a[i, j];
585                result[i] = format(line);
586            }
587            return "{" + String.Join(",", result) + "}";
588        }
589
590        /****************************************************************
591        prints formatted matrix
592        ****************************************************************/
593        public static string format(double[,] a, int dps)
594        {
595            int i, j, m, n;
596            n = cols(a);
597            m = rows(a);
598            double[] line = new double[n];
599            string[] result = new string[m];
600            for (i = 0; i < m; i++)
601            {
602                for (j = 0; j < n; j++)
603                    line[j] = a[i, j];
604                result[i] = format(line, dps);
605            }
606            return "{" + String.Join(",", result) + "}";
607        }
608
609        /****************************************************************
610        prints formatted matrix
611        ****************************************************************/
612        public static string format(complex[,] a, int dps)
613        {
614            int i, j, m, n;
615            n = cols(a);
616            m = rows(a);
617            complex[] line = new complex[n];
618            string[] result = new string[m];
619            for (i = 0; i < m; i++)
620            {
621                for (j = 0; j < n; j++)
622                    line[j] = a[i, j];
623                result[i] = format(line, dps);
624            }
625            return "{" + String.Join(",", result) + "}";
626        }
627
628        /****************************************************************
629        checks that matrix is symmetric.
630        max|A-A^T| is calculated; if it is within 1.0E-14 of max|A|,
631        matrix is considered symmetric
632        ****************************************************************/
633        public static bool issymmetric(double[,] a)
634        {
635            int i, j, n;
636            double err, mx, v1, v2;
637            if( rows(a)!=cols(a) )
638                return false;
639            n = rows(a);
640            if( n==0 )
641                return true;
642            mx = 0;
643            err = 0;
644            for( i=0; i<n; i++)
645            {
646                for(j=i+1; j<n; j++)
647                {
648                    v1 = a[i,j];
649                    v2 = a[j,i];
650                    if( !math.isfinite(v1) )
651                        return false;
652                    if( !math.isfinite(v2) )
653                        return false;
654                    err = Math.Max(err, Math.Abs(v1-v2));
655                    mx  = Math.Max(mx,  Math.Abs(v1));
656                    mx  = Math.Max(mx,  Math.Abs(v2));
657                }
658                v1 = a[i,i];
659                if( !math.isfinite(v1) )
660                    return false;
661                mx = Math.Max(mx, Math.Abs(v1));
662            }
663            if( mx==0 )
664                return true;
665            return err/mx<=1.0E-14;
666        }
667       
668        /****************************************************************
669        checks that matrix is Hermitian.
670        max|A-A^H| is calculated; if it is within 1.0E-14 of max|A|,
671        matrix is considered Hermitian
672        ****************************************************************/
673        public static bool ishermitian(complex[,] a)
674        {
675            int i, j, n;
676            double err, mx;
677            complex v1, v2, vt;
678            if( rows(a)!=cols(a) )
679                return false;
680            n = rows(a);
681            if( n==0 )
682                return true;
683            mx = 0;
684            err = 0;
685            for( i=0; i<n; i++)
686            {
687                for(j=i+1; j<n; j++)
688                {
689                    v1 = a[i,j];
690                    v2 = a[j,i];
691                    if( !math.isfinite(v1.x) )
692                        return false;
693                    if( !math.isfinite(v1.y) )
694                        return false;
695                    if( !math.isfinite(v2.x) )
696                        return false;
697                    if( !math.isfinite(v2.y) )
698                        return false;
699                    vt.x = v1.x-v2.x;
700                    vt.y = v1.y+v2.y;
701                    err = Math.Max(err, math.abscomplex(vt));
702                    mx  = Math.Max(mx,  math.abscomplex(v1));
703                    mx  = Math.Max(mx,  math.abscomplex(v2));
704                }
705                v1 = a[i,i];
706                if( !math.isfinite(v1.x) )
707                    return false;
708                if( !math.isfinite(v1.y) )
709                    return false;
710                err = Math.Max(err, Math.Abs(v1.y));
711                mx = Math.Max(mx, math.abscomplex(v1));
712            }
713            if( mx==0 )
714                return true;
715            return err/mx<=1.0E-14;
716        }
717       
718       
719        /****************************************************************
720        Forces symmetricity by copying upper half of A to the lower one
721        ****************************************************************/
722        public static bool forcesymmetric(double[,] a)
723        {
724            int i, j, n;
725            if( rows(a)!=cols(a) )
726                return false;
727            n = rows(a);
728            if( n==0 )
729                return true;
730            for( i=0; i<n; i++)
731                for(j=i+1; j<n; j++)
732                    a[i,j] = a[j,i];
733            return true;
734        }
735       
736        /****************************************************************
737        Forces Hermiticity by copying upper half of A to the lower one
738        ****************************************************************/
739        public static bool forcehermitian(complex[,] a)
740        {
741            int i, j, n;
742            complex v;
743            if( rows(a)!=cols(a) )
744                return false;
745            n = rows(a);
746            if( n==0 )
747                return true;
748            for( i=0; i<n; i++)
749                for(j=i+1; j<n; j++)
750                {
751                    v = a[j,i];
752                    a[i,j].x = v.x;
753                    a[i,j].y = -v.y;
754                }
755            return true;
756        }
757    };
758   
759    /********************************************************************
760    math functions
761    ********************************************************************/
762    public class math
763    {
764    //public static System.Random RndObject = new System.Random(System.DateTime.Now.Millisecond);
765    [ThreadStatic] //mkommend: added thread static attribute to RNG to have a separate instance per thread and allow modification of the seed
766    public static System.Random rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000*System.DateTime.Now.Second + 60*1000*System.DateTime.Now.Minute);
767
768        public const double machineepsilon = 5E-16;
769        public const double maxrealnumber = 1E300;
770        public const double minrealnumber = 1E-300;
771       
772        public static bool isfinite(double d)
773        {
774            return !System.Double.IsNaN(d) && !System.Double.IsInfinity(d);
775        }
776       
777        public static double randomreal()
778        {
779            double r = 0;
780            if (rndobject == null) rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000 * System.DateTime.Now.Second + 60 * 1000 * System.DateTime.Now.Minute);
781            lock(rndobject){ r = rndobject.NextDouble(); }
782            return r;
783        }
784        public static int randominteger(int N)
785        {
786            int r = 0;
787            if (rndobject == null) rndobject = new System.Random(System.DateTime.Now.Millisecond + 1000 * System.DateTime.Now.Second + 60 * 1000 * System.DateTime.Now.Minute);
788            lock(rndobject){ r = rndobject.Next(N); }
789            return r;
790        }
791        public static double sqr(double X)
792        {
793            return X*X;
794        }       
795        public static double abscomplex(complex z)
796        {
797            double w;
798            double xabs;
799            double yabs;
800            double v;
801   
802            xabs = System.Math.Abs(z.x);
803            yabs = System.Math.Abs(z.y);
804            w = xabs>yabs ? xabs : yabs;
805            v = xabs<yabs ? xabs : yabs;
806            if( v==0 )
807                return w;
808            else
809            {
810                double t = v/w;
811                return w*System.Math.Sqrt(1+t*t);
812            }
813        }
814        public static complex conj(complex z)
815        {
816            return new complex(z.x, -z.y);
817        }   
818        public static complex csqr(complex z)
819        {
820            return new complex(z.x*z.x-z.y*z.y, 2*z.x*z.y);
821        }
822
823    }
824
825    /*
826     * CSV functionality
827     */
828     
829    public static int CSV_DEFAULT      = 0x0;
830    public static int CSV_SKIP_HEADERS = 0x1;
831   
832    /*
833     * CSV operations: reading CSV file to real matrix.
834     *
835     * This function reads CSV  file  and  stores  its  contents  to  double
836     * precision 2D array. Format of the data file must conform to RFC  4180
837     * specification, with additional notes:
838     * - file size should be less than 2GB
839     * - ASCI encoding, UTF-8 without BOM (in header names) are supported
840     * - any character (comma/tab/space) may be used as field separator,  as
841     *   long as it is distinct from one used for decimal point
842     * - multiple subsequent field separators (say, two  spaces) are treated
843     *   as MULTIPLE separators, not one big separator
844     * - both comma and full stop may be used as decimal point. Parser  will
845     *   automatically determine specific character being used.  Both  fixed
846     *   and exponential number formats are  allowed.   Thousand  separators
847     *   are NOT allowed.
848     * - line may end with \n (Unix style) or \r\n (Windows  style),  parser
849     *   will automatically adapt to chosen convention
850     * - escaped fields (ones in double quotes) are not supported
851     *
852     * INPUT PARAMETERS:
853     *     filename        relative/absolute path
854     *     separator       character used to separate fields.  May  be  ' ',
855     *                     ',', '\t'. Other separators are possible too.
856     *     flags           several values combined with bitwise OR:
857     *                     * alglib::CSV_SKIP_HEADERS -  if present, first row
858     *                       contains headers  and  will  be  skipped.   Its
859     *                       contents is used to determine fields count, and
860     *                       that's all.
861     *                     If no flags are specified, default value 0x0  (or
862     *                     alglib::CSV_DEFAULT, which is same) should be used.
863     *                     
864     * OUTPUT PARAMETERS:
865     *     out             2D matrix, CSV file parsed with atof()
866     *     
867     * HANDLING OF SPECIAL CASES:
868     * - file does not exist - alglib::ap_error exception is thrown
869     * - empty file - empty array is returned (no exception)
870     * - skip_first_row=true, only one row in file - empty array is returned
871     * - field contents is not recognized by atof() - field value is replaced
872     *   by 0.0
873     */
874    public static void read_csv(string filename, char separator, int flags, out double[,] matrix)
875    {
876        //
877        // Parameters
878        //
879        bool skip_first_row = (flags&CSV_SKIP_HEADERS)!=0;
880       
881        //
882        // Prepare empty output array
883        //
884        matrix = new double[0,0];
885       
886        //
887        // Read file, normalize file contents:
888        // * replace 0x0 by spaces
889        // * remove trailing spaces and newlines
890        // * append trailing '\n' and '\0' characters
891        // Return if file contains only spaces/newlines.
892        //
893        byte b_space = System.Convert.ToByte(' ');
894        byte b_tab   = System.Convert.ToByte('\t');
895        byte b_lf    = System.Convert.ToByte('\n');
896        byte b_cr    = System.Convert.ToByte('\r');
897        byte b_comma = System.Convert.ToByte(',');
898        byte b_fullstop= System.Convert.ToByte('.');
899        byte[] v0 = System.IO.File.ReadAllBytes(filename);
900        if( v0.Length==0 )
901            return;
902        byte[] v1 = new byte[v0.Length+2];
903        int filesize = v0.Length;
904        for(int i=0; i<filesize; i++)
905            v1[i] = v0[i]==0 ? b_space : v0[i];
906        for(; filesize>0; )
907        {
908            byte c = v1[filesize-1];
909            if( c==b_space || c==b_tab || c==b_cr || c==b_lf )
910            {
911                filesize--;
912                continue;
913            }
914            break;
915        }
916        if( filesize==0 )
917            return;
918        v1[filesize+0] = b_lf;
919        v1[filesize+1] = 0x0;
920        filesize+=2;
921       
922       
923        //
924        // Scan dataset.
925        //
926        int rows_count, cols_count, max_length = 0;
927        cols_count = 1;
928        for(int idx=0; idx<filesize; idx++)
929        {
930            if( v1[idx]==separator )
931                cols_count++;
932            if( v1[idx]==b_lf )
933                break;
934        }
935        rows_count = 0;
936        for(int idx=0; idx<filesize; idx++)
937            if( v1[idx]==b_lf )
938                rows_count++;
939        if( rows_count==1 && skip_first_row ) // empty output, return
940            return;
941        int[] offsets = new int[rows_count*cols_count];
942        int[] lengths = new int[rows_count*cols_count];
943        int cur_row_idx = 0;
944        for(int row_start=0; v1[row_start]!=0x0; )
945        {
946            // determine row length
947            int row_length;
948            for(row_length=0; v1[row_start+row_length]!=b_lf; row_length++);
949           
950            // determine cols count, perform integrity check
951            int cur_cols_cnt=1;
952            for(int idx=0; idx<row_length; idx++)
953                if( v1[row_start+idx]==separator )
954                    cur_cols_cnt++;
955            if( cols_count!=cur_cols_cnt )
956                throw new alglib.alglibexception("read_csv: non-rectangular contents, rows have different sizes");
957           
958            // store offsets and lengths of the fields
959            int cur_offs = 0;
960            int cur_col_idx = 0;
961            for(int idx=0; idx<row_length+1; idx++)
962                if( v1[row_start+idx]==separator || v1[row_start+idx]==b_lf )
963                {
964                    offsets[cur_row_idx*cols_count+cur_col_idx] = row_start+cur_offs;
965                    lengths[cur_row_idx*cols_count+cur_col_idx] = idx-cur_offs;
966                    max_length = idx-cur_offs>max_length ? idx-cur_offs : max_length;
967                    cur_offs = idx+1;
968                    cur_col_idx++;
969                }
970           
971            // advance row start
972            cur_row_idx++;
973            row_start = row_start+row_length+1;
974        }
975       
976        //
977        // Convert
978        //
979        int row0 = skip_first_row ? 1 : 0;
980        int row1 = rows_count;
981        System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture(""); // invariant culture
982        matrix = new double[row1-row0, cols_count];
983        alglib.AE_CRITICAL_ASSERT(culture.NumberFormat.NumberDecimalSeparator==".");
984        for(int ridx=row0; ridx<row1; ridx++)
985            for(int cidx=0; cidx<cols_count; cidx++)
986            {
987                int field_len  = lengths[ridx*cols_count+cidx];
988                int field_offs = offsets[ridx*cols_count+cidx];
989               
990                // replace , by full stop
991                for(int idx=0; idx<field_len; idx++)
992                    if( v1[field_offs+idx]==b_comma )
993                        v1[field_offs+idx] = b_fullstop;
994               
995                // convert
996                string s_val = System.Text.Encoding.ASCII.GetString(v1, field_offs, field_len);
997                double d_val;
998                Double.TryParse(s_val, System.Globalization.NumberStyles.Float, culture, out d_val);
999                matrix[ridx-row0,cidx] = d_val;
1000            }
1001    }
1002   
1003   
1004    /********************************************************************
1005    serializer object (should not be used directly)
1006    ********************************************************************/
1007    public class serializer
1008    {
1009        enum SMODE { DEFAULT, ALLOC, TO_STRING, FROM_STRING, TO_STREAM, FROM_STREAM };
1010        private const int SER_ENTRIES_PER_ROW = 5;
1011        private const int SER_ENTRY_LENGTH    = 11;
1012       
1013        private SMODE mode;
1014        private int entries_needed;
1015        private int entries_saved;
1016        private int bytes_asked;
1017        private int bytes_written;
1018        private int bytes_read;
1019        private char[] out_str;
1020        private char[] in_str;
1021        private System.IO.Stream io_stream;
1022       
1023        // local temporaries
1024        private char[] entry_buf_char;
1025        private byte[] entry_buf_byte;
1026       
1027        public serializer()
1028        {
1029            mode = SMODE.DEFAULT;
1030            entries_needed = 0;
1031            bytes_asked = 0;
1032            entry_buf_byte = new byte[SER_ENTRY_LENGTH+2];
1033            entry_buf_char = new char[SER_ENTRY_LENGTH+2];
1034        }
1035
1036        public void clear_buffers()
1037        {
1038            out_str = null;
1039            in_str = null;
1040            io_stream = null;
1041        }
1042
1043        public void alloc_start()
1044        {
1045            entries_needed = 0;
1046            bytes_asked = 0;
1047            mode = SMODE.ALLOC;
1048        }
1049
1050        public void alloc_entry()
1051        {
1052            if( mode!=SMODE.ALLOC )
1053                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1054            entries_needed++;
1055        }
1056
1057        private int get_alloc_size()
1058        {
1059            int rows, lastrowsize, result;
1060           
1061            // check and change mode
1062            if( mode!=SMODE.ALLOC )
1063                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1064           
1065            // if no entries needes (degenerate case)
1066            if( entries_needed==0 )
1067            {
1068                bytes_asked = 4; /* a pair of chars for \r\n, one for space, one for dot */
1069                return bytes_asked;
1070            }
1071           
1072            // non-degenerate case
1073            rows = entries_needed/SER_ENTRIES_PER_ROW;
1074            lastrowsize = SER_ENTRIES_PER_ROW;
1075            if( entries_needed%SER_ENTRIES_PER_ROW!=0 )
1076            {
1077                lastrowsize = entries_needed%SER_ENTRIES_PER_ROW;
1078                rows++;
1079            }
1080           
1081            // calculate result size
1082            result  = ((rows-1)*SER_ENTRIES_PER_ROW+lastrowsize)*SER_ENTRY_LENGTH;  /* data size */
1083            result +=  (rows-1)*(SER_ENTRIES_PER_ROW-1)+(lastrowsize-1);            /* space symbols */
1084            result += rows*2;                                                       /* newline symbols */
1085            result += 1;                                                            /* trailing dot */
1086            bytes_asked = result;
1087            return result;
1088        }
1089
1090        public void sstart_str()
1091        {
1092            int allocsize = get_alloc_size();
1093           
1094            // clear input/output buffers which may hold pointers to unneeded memory
1095            // NOTE: it also helps us to avoid errors when data are written to incorrect location
1096            clear_buffers();
1097           
1098            // check and change mode
1099            if( mode!=SMODE.ALLOC )
1100                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1101            mode = SMODE.TO_STRING;
1102           
1103            // other preparations
1104            out_str = new char[allocsize];
1105            entries_saved = 0;
1106            bytes_written = 0;
1107        }
1108
1109        public void sstart_stream(System.IO.Stream o_stream)
1110        {   
1111            // clear input/output buffers which may hold pointers to unneeded memory
1112            // NOTE: it also helps us to avoid errors when data are written to incorrect location
1113            clear_buffers();
1114           
1115            // check and change mode
1116            if( mode!=SMODE.ALLOC )
1117                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1118            mode = SMODE.TO_STREAM;
1119            io_stream = o_stream;
1120        }
1121
1122        public void ustart_str(string s)
1123        {
1124            // clear input/output buffers which may hold pointers to unneeded memory
1125            // NOTE: it also helps us to avoid errors when data are written to incorrect location
1126            clear_buffers();
1127           
1128            // check and change mode
1129            if( mode!=SMODE.DEFAULT )
1130                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1131            mode = SMODE.FROM_STRING;
1132           
1133            in_str = s.ToCharArray();
1134            bytes_read = 0;
1135        }
1136
1137        public void ustart_stream(System.IO.Stream i_stream)
1138        {
1139            // clear input/output buffers which may hold pointers to unneeded memory
1140            // NOTE: it also helps us to avoid errors when data are written to incorrect location
1141            clear_buffers();
1142           
1143            // check and change mode
1144            if( mode!=SMODE.DEFAULT )
1145                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1146            mode = SMODE.FROM_STREAM;
1147            io_stream = i_stream;
1148        }
1149
1150        private void serialize_value(bool v0, int v1, double v2, int val_idx)
1151        {
1152            // prepare serialization
1153            char[] arr_out = null;
1154            int cnt_out = 0;
1155            if( mode==SMODE.TO_STRING )
1156            {
1157                arr_out = out_str;
1158                cnt_out = bytes_written;
1159            }
1160            else if( mode==SMODE.TO_STREAM )
1161            {
1162                arr_out = entry_buf_char;
1163                cnt_out = 0;
1164            }
1165            else
1166                throw new alglib.alglibexception("ALGLIB: internal error during serialization");
1167           
1168            // serialize
1169            if( val_idx==0 )
1170                bool2str(  v0, arr_out, ref cnt_out);
1171            else if( val_idx==1 )
1172                int2str(   v1, arr_out, ref cnt_out);
1173            else if( val_idx==2 )
1174                double2str(v2, arr_out, ref cnt_out);
1175            else
1176                throw new alglib.alglibexception("ALGLIB: internal error during serialization");
1177            entries_saved++;
1178            if( entries_saved%SER_ENTRIES_PER_ROW!=0 )
1179            {
1180                arr_out[cnt_out] = ' ';
1181                cnt_out++;
1182            }
1183            else
1184            {
1185                arr_out[cnt_out+0] = '\r';
1186                arr_out[cnt_out+1] = '\n';
1187                cnt_out+=2;
1188            }
1189           
1190            // post-process
1191            if( mode==SMODE.TO_STRING )
1192            {
1193                bytes_written = cnt_out;
1194                return;
1195            }
1196            else if( mode==SMODE.TO_STREAM )
1197            {
1198                for(int k=0; k<cnt_out; k++)
1199                    entry_buf_byte[k] = (byte)entry_buf_char[k];
1200                io_stream.Write(entry_buf_byte, 0, cnt_out);
1201                return;
1202            }
1203            else
1204                throw new alglib.alglibexception("ALGLIB: internal error during serialization");
1205        }
1206
1207        private void unstream_entry_char()
1208        {
1209            if( mode!=SMODE.FROM_STREAM )
1210                throw new alglib.alglibexception("ALGLIB: internal error during unserialization");
1211            int c;
1212            for(;;)
1213            {
1214                c = io_stream.ReadByte();
1215                if( c<0 )
1216                    throw new alglib.alglibexception("ALGLIB: internal error during unserialization");
1217                if( c!=' ' && c!='\t' && c!='\n' && c!='\r' )
1218                    break;
1219            }
1220            entry_buf_char[0] = (char)c;
1221            for(int k=1; k<SER_ENTRY_LENGTH; k++)
1222            {
1223                c = io_stream.ReadByte();
1224                entry_buf_char[k] = (char)c;
1225                if( c<0 || c==' ' || c=='\t' || c=='\n' || c=='\r' )
1226                    throw new alglib.alglibexception("ALGLIB: internal error during unserialization");
1227            }
1228            entry_buf_char[SER_ENTRY_LENGTH] = (char)0;
1229        }
1230
1231        public void serialize_bool(bool v)
1232        {
1233            serialize_value(v, 0, 0, 0);
1234        }
1235
1236        public void serialize_int(int v)
1237        {
1238            serialize_value(false, v, 0, 1);
1239        }
1240
1241        public void serialize_double(double v)
1242        {
1243            serialize_value(false, 0, v, 2);
1244        }
1245
1246        public bool unserialize_bool()
1247        {
1248            if( mode==SMODE.FROM_STRING )
1249                return str2bool(in_str, ref bytes_read);
1250            if( mode==SMODE.FROM_STREAM )
1251            {
1252                unstream_entry_char();
1253                int dummy = 0;
1254                return str2bool(entry_buf_char, ref dummy);
1255            }
1256            throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1257        }
1258
1259        public int unserialize_int()
1260        {
1261            if( mode==SMODE.FROM_STRING )
1262                return str2int(in_str, ref bytes_read);
1263            if( mode==SMODE.FROM_STREAM )
1264            {
1265                unstream_entry_char();
1266                int dummy = 0;
1267                return str2int(entry_buf_char, ref dummy);
1268            }
1269            throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1270        }
1271
1272        public double unserialize_double()
1273        {
1274            if( mode==SMODE.FROM_STRING )
1275                return str2double(in_str, ref bytes_read);
1276            if( mode==SMODE.FROM_STREAM )
1277            {
1278                unstream_entry_char();
1279                int dummy = 0;
1280                return str2double(entry_buf_char, ref dummy);
1281            }
1282            throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1283        }
1284
1285        public void stop()
1286        {
1287            if( mode==SMODE.TO_STRING )
1288            {
1289                out_str[bytes_written] = '.';
1290                bytes_written++;
1291                return;
1292            }
1293            if( mode==SMODE.FROM_STRING )
1294            {
1295                //
1296                // because input string may be from pre-3.11 serializer,
1297                // which does not include trailing dot, we do not test
1298                // string for presence of "." symbol. Anyway, because string
1299                // is not stream, we do not have to read ALL trailing symbols.
1300                //
1301                return;
1302            }
1303            if( mode==SMODE.TO_STREAM )
1304            {
1305                io_stream.WriteByte((byte)'.');
1306                return;
1307            }
1308            if( mode==SMODE.FROM_STREAM )
1309            {
1310                for(;;)
1311                {
1312                    int c = io_stream.ReadByte();
1313                    if( c==' ' || c=='\t' || c=='\n' || c=='\r' )
1314                        continue;
1315                    if( c=='.' )
1316                        break;
1317                    throw new alglib.alglibexception("ALGLIB: internal error during unserialization");
1318                }
1319                return;
1320            }
1321            throw new alglib.alglibexception("ALGLIB: internal error during unserialization");
1322        }
1323
1324        public string get_string()
1325        {
1326            if( mode!=SMODE.TO_STRING )
1327                throw new alglib.alglibexception("ALGLIB: internal error during (un)serialization");
1328             return new string(out_str, 0, bytes_written);
1329        }
1330
1331
1332        /************************************************************************
1333        This function converts six-bit value (from 0 to 63)  to  character  (only
1334        digits, lowercase and uppercase letters, minus and underscore are used).
1335
1336        If v is negative or greater than 63, this function returns '?'.
1337        ************************************************************************/
1338        private static char[] _sixbits2char_tbl = new char[64]{
1339                '0', '1', '2', '3', '4', '5', '6', '7',
1340                '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
1341                'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
1342                'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
1343                'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
1344                'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
1345                'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
1346                'u', 'v', 'w', 'x', 'y', 'z', '-', '_' };
1347        private static char sixbits2char(int v)
1348        {
1349            if( v<0 || v>63 )
1350                return '?';
1351            return _sixbits2char_tbl[v];
1352        }
1353       
1354        /************************************************************************
1355        This function converts character to six-bit value (from 0 to 63).
1356
1357        This function is inverse of ae_sixbits2char()
1358        If c is not correct character, this function returns -1.
1359        ************************************************************************/
1360        private static int[] _char2sixbits_tbl = new int[128] {
1361            -1, -1, -1, -1, -1, -1, -1, -1,
1362            -1, -1, -1, -1, -1, -1, -1, -1,
1363            -1, -1, -1, -1, -1, -1, -1, -1,
1364            -1, -1, -1, -1, -1, -1, -1, -1,
1365            -1, -1, -1, -1, -1, -1, -1, -1,
1366            -1, -1, -1, -1, -1, 62, -1, -1,
1367             0,  1,  2,  3,  4,  5,  6,  7,
1368             8,  9, -1, -1, -1, -1, -1, -1,
1369            -1, 10, 11, 12, 13, 14, 15, 16,
1370            17, 18, 19, 20, 21, 22, 23, 24,
1371            25, 26, 27, 28, 29, 30, 31, 32,
1372            33, 34, 35, -1, -1, -1, -1, 63,
1373            -1, 36, 37, 38, 39, 40, 41, 42,
1374            43, 44, 45, 46, 47, 48, 49, 50,
1375            51, 52, 53, 54, 55, 56, 57, 58,
1376            59, 60, 61, -1, -1, -1, -1, -1 };
1377        private static int char2sixbits(char c)
1378        {
1379            return (c>=0 && c<127) ? _char2sixbits_tbl[c] : -1;
1380        }
1381       
1382        /************************************************************************
1383        This function converts three bytes (24 bits) to four six-bit values
1384        (24 bits again).
1385
1386        src         array
1387        src_offs    offset of three-bytes chunk
1388        dst         array for ints
1389        dst_offs    offset of four-ints chunk
1390        ************************************************************************/
1391        private static void threebytes2foursixbits(byte[] src, int src_offs, int[] dst, int dst_offs)
1392        {
1393            dst[dst_offs+0] =  src[src_offs+0] & 0x3F;
1394            dst[dst_offs+1] = (src[src_offs+0]>>6) | ((src[src_offs+1]&0x0F)<<2);
1395            dst[dst_offs+2] = (src[src_offs+1]>>4) | ((src[src_offs+2]&0x03)<<4);
1396            dst[dst_offs+3] =  src[src_offs+2]>>2;
1397        }
1398
1399        /************************************************************************
1400        This function converts four six-bit values (24 bits) to three bytes
1401        (24 bits again).
1402
1403        src         pointer to four ints
1404        src_offs    offset of the chunk
1405        dst         pointer to three bytes
1406        dst_offs    offset of the chunk
1407        ************************************************************************/
1408        private static void foursixbits2threebytes(int[] src, int src_offs, byte[] dst, int dst_offs)
1409        {
1410            dst[dst_offs+0] =      (byte)(src[src_offs+0] | ((src[src_offs+1]&0x03)<<6));
1411            dst[dst_offs+1] = (byte)((src[src_offs+1]>>2) | ((src[src_offs+2]&0x0F)<<4));
1412            dst[dst_offs+2] = (byte)((src[src_offs+2]>>4) |  (src[src_offs+3]<<2));
1413        }
1414
1415        /************************************************************************
1416        This function serializes boolean value into buffer
1417
1418        v           boolean value to be serialized
1419        buf         buffer, at least 11 characters wide
1420        offs        offset in the buffer
1421       
1422        after return from this function, offs points to the char's past the value
1423        being read.
1424        ************************************************************************/
1425        private static void bool2str(bool v, char[] buf, ref int offs)
1426        {
1427            char c = v ? '1' : '0';
1428            int i;
1429            for(i=0; i<SER_ENTRY_LENGTH; i++)
1430                buf[offs+i] = c;
1431            offs += SER_ENTRY_LENGTH;
1432        }
1433
1434        /************************************************************************
1435        This function unserializes boolean value from buffer
1436
1437        buf         buffer which contains value; leading spaces/tabs/newlines are
1438                    ignored, traling spaces/tabs/newlines are treated as  end  of
1439                    the boolean value.
1440        offs        offset in the buffer
1441       
1442        after return from this function, offs points to the char's past the value
1443        being read.
1444
1445        This function raises an error in case unexpected symbol is found
1446        ************************************************************************/
1447        private static bool str2bool(char[] buf, ref int offs)
1448        {
1449            bool was0, was1;
1450            string emsg = "ALGLIB: unable to read boolean value from stream";
1451           
1452            was0 = false;
1453            was1 = false;
1454            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1455                offs++;
1456            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1457            {
1458                if( buf[offs]=='0' )
1459                {
1460                    was0 = true;
1461                    offs++;
1462                    continue;
1463                }
1464                if( buf[offs]=='1' )
1465                {
1466                    was1 = true;
1467                    offs++;
1468                    continue;
1469                }
1470                throw new alglib.alglibexception(emsg);
1471            }
1472            if( (!was0) && (!was1) )
1473                throw new alglib.alglibexception(emsg);
1474            if( was0 && was1 )
1475                throw new alglib.alglibexception(emsg);
1476            return was1 ? true : false;
1477        }
1478
1479        /************************************************************************
1480        This function serializes integer value into buffer
1481
1482        v           integer value to be serialized
1483        buf         buffer, at least 11 characters wide
1484        offs        offset in the buffer
1485       
1486        after return from this function, offs points to the char's past the value
1487        being read.
1488
1489        This function raises an error in case unexpected symbol is found
1490        ************************************************************************/
1491        private static void int2str(int v, char[] buf, ref int offs)
1492        {
1493            int i;
1494            byte[] _bytes = System.BitConverter.GetBytes((int)v);
1495            byte[]  bytes = new byte[9];
1496            int[] sixbits = new int[12];
1497            byte c;
1498           
1499            //
1500            // copy v to array of bytes, sign extending it and
1501            // converting to little endian order. Additionally,
1502            // we set 9th byte to zero in order to simplify
1503            // conversion to six-bit representation
1504            //
1505            if( !System.BitConverter.IsLittleEndian )
1506                System.Array.Reverse(_bytes);
1507            c = v<0 ? (byte)0xFF : (byte)0x00;
1508            for(i=0; i<sizeof(int); i++)
1509                bytes[i] = _bytes[i];
1510            for(i=sizeof(int); i<8; i++)
1511                bytes[i] = c;
1512            bytes[8] = 0;
1513           
1514            //
1515            // convert to six-bit representation, output
1516            //
1517            // NOTE: last 12th element of sixbits is always zero, we do not output it
1518            //
1519            threebytes2foursixbits(bytes, 0, sixbits, 0);
1520            threebytes2foursixbits(bytes, 3, sixbits, 4);
1521            threebytes2foursixbits(bytes, 6, sixbits, 8);       
1522            for(i=0; i<SER_ENTRY_LENGTH; i++)
1523                buf[offs+i] = sixbits2char(sixbits[i]);
1524            offs += SER_ENTRY_LENGTH;
1525        }
1526
1527        /************************************************************************
1528        This function unserializes integer value from string
1529
1530        buf         buffer which contains value; leading spaces/tabs/newlines are
1531                    ignored, traling spaces/tabs/newlines are treated as  end  of
1532                    the integer value.
1533        offs        offset in the buffer
1534       
1535        after return from this function, offs points to the char's past the value
1536        being read.
1537
1538        This function raises an error in case unexpected symbol is found
1539        ************************************************************************/
1540        private static int str2int(char[] buf, ref int offs)
1541        {
1542            string emsg =       "ALGLIB: unable to read integer value from stream";
1543            string emsg3264 =   "ALGLIB: unable to read integer value from stream (value does not fit into 32 bits)";
1544            int[] sixbits = new int[12];
1545            byte[] bytes = new byte[9];
1546            byte[] _bytes = new byte[sizeof(int)];
1547            int sixbitsread, i;
1548            byte c;
1549           
1550            //
1551            // 1. skip leading spaces
1552            // 2. read and decode six-bit digits
1553            // 3. set trailing digits to zeros
1554            // 4. convert to little endian 64-bit integer representation
1555            // 5. check that we fit into int
1556            // 6. convert to big endian representation, if needed
1557            //
1558            sixbitsread = 0;
1559            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1560                offs++;
1561            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1562            {
1563                int d;
1564                d = char2sixbits(buf[offs]);
1565                if( d<0 || sixbitsread>=SER_ENTRY_LENGTH )
1566                    throw new alglib.alglibexception(emsg);
1567                sixbits[sixbitsread] = d;
1568                sixbitsread++;
1569                offs++;
1570            }
1571            if( sixbitsread==0 )
1572                throw new alglib.alglibexception(emsg);
1573            for(i=sixbitsread; i<12; i++)
1574                sixbits[i] = 0;
1575            foursixbits2threebytes(sixbits, 0, bytes, 0);
1576            foursixbits2threebytes(sixbits, 4, bytes, 3);
1577            foursixbits2threebytes(sixbits, 8, bytes, 6);
1578            c = (bytes[sizeof(int)-1] & 0x80)!=0 ? (byte)0xFF : (byte)0x00;
1579            for(i=sizeof(int); i<8; i++)
1580                if( bytes[i]!=c )
1581                    throw new alglib.alglibexception(emsg3264);
1582            for(i=0; i<sizeof(int); i++)
1583                _bytes[i] = bytes[i];       
1584            if( !System.BitConverter.IsLittleEndian )
1585                System.Array.Reverse(_bytes);
1586            return System.BitConverter.ToInt32(_bytes,0);
1587        }   
1588       
1589       
1590        /************************************************************************
1591        This function serializes double value into buffer
1592
1593        v           double value to be serialized
1594        buf         buffer, at least 11 characters wide
1595        offs        offset in the buffer
1596       
1597        after return from this function, offs points to the char's past the value
1598        being read.
1599        ************************************************************************/
1600        private static void double2str(double v, char[] buf, ref int offs)
1601        {
1602            int i;
1603            int[] sixbits = new int[12];
1604            byte[] bytes = new byte[9];
1605
1606            //
1607            // handle special quantities
1608            //
1609            if( System.Double.IsNaN(v) )
1610            {
1611                buf[offs+0] = '.';
1612                buf[offs+1] = 'n';
1613                buf[offs+2] = 'a';
1614                buf[offs+3] = 'n';
1615                buf[offs+4] = '_';
1616                buf[offs+5] = '_';
1617                buf[offs+6] = '_';
1618                buf[offs+7] = '_';
1619                buf[offs+8] = '_';
1620                buf[offs+9] = '_';
1621                buf[offs+10] = '_';
1622                offs += SER_ENTRY_LENGTH;
1623                return;
1624            }
1625            if( System.Double.IsPositiveInfinity(v) )
1626            {
1627                buf[offs+0] = '.';
1628                buf[offs+1] = 'p';
1629                buf[offs+2] = 'o';
1630                buf[offs+3] = 's';
1631                buf[offs+4] = 'i';
1632                buf[offs+5] = 'n';
1633                buf[offs+6] = 'f';
1634                buf[offs+7] = '_';
1635                buf[offs+8] = '_';
1636                buf[offs+9] = '_';
1637                buf[offs+10] = '_';
1638                offs += SER_ENTRY_LENGTH;
1639                return;
1640            }
1641            if( System.Double.IsNegativeInfinity(v) )
1642            {
1643                buf[offs+0] = '.';
1644                buf[offs+1] = 'n';
1645                buf[offs+2] = 'e';
1646                buf[offs+3] = 'g';
1647                buf[offs+4] = 'i';
1648                buf[offs+5] = 'n';
1649                buf[offs+6] = 'f';
1650                buf[offs+7] = '_';
1651                buf[offs+8] = '_';
1652                buf[offs+9] = '_';
1653                buf[offs+10] = '_';
1654                offs += SER_ENTRY_LENGTH;
1655                return;
1656            }
1657           
1658            //
1659            // process general case:
1660            // 1. copy v to array of chars
1661            // 2. set 9th byte to zero in order to simplify conversion to six-bit representation
1662            // 3. convert to little endian (if needed)
1663            // 4. convert to six-bit representation
1664            //    (last 12th element of sixbits is always zero, we do not output it)
1665            //
1666            byte[] _bytes = System.BitConverter.GetBytes((double)v);
1667            if( !System.BitConverter.IsLittleEndian )
1668                System.Array.Reverse(_bytes);
1669            for(i=0; i<sizeof(double); i++)
1670                bytes[i] = _bytes[i];
1671            for(i=sizeof(double); i<9; i++)
1672                bytes[i] = 0;
1673            threebytes2foursixbits(bytes, 0, sixbits, 0);
1674            threebytes2foursixbits(bytes, 3, sixbits, 4);
1675            threebytes2foursixbits(bytes, 6, sixbits, 8);
1676            for(i=0; i<SER_ENTRY_LENGTH; i++)
1677                buf[offs+i] = sixbits2char(sixbits[i]);
1678            offs += SER_ENTRY_LENGTH;
1679        }
1680
1681        /************************************************************************
1682        This function unserializes double value from string
1683
1684        buf         buffer which contains value; leading spaces/tabs/newlines are
1685                    ignored, traling spaces/tabs/newlines are treated as  end  of
1686                    the double value.
1687        offs        offset in the buffer
1688       
1689        after return from this function, offs points to the char's past the value
1690        being read.
1691
1692        This function raises an error in case unexpected symbol is found
1693        ************************************************************************/
1694        private static double str2double(char[] buf, ref int offs)
1695        {
1696            string emsg = "ALGLIB: unable to read double value from stream";
1697            int[] sixbits = new int[12];
1698            byte[]  bytes = new byte[9];
1699            byte[] _bytes = new byte[sizeof(double)];
1700            int sixbitsread, i;
1701           
1702           
1703            //
1704            // skip leading spaces
1705            //
1706            while( buf[offs]==' ' || buf[offs]=='\t' || buf[offs]=='\n' || buf[offs]=='\r' )
1707                offs++;
1708           
1709             
1710            //
1711            // Handle special cases
1712            //
1713            if( buf[offs]=='.' )
1714            {
1715                string s = new string(buf, offs, SER_ENTRY_LENGTH);
1716                if( s==".nan_______" )
1717                {
1718                    offs += SER_ENTRY_LENGTH;
1719                    return System.Double.NaN;
1720                }
1721                if( s==".posinf____" )
1722                {
1723                    offs += SER_ENTRY_LENGTH;
1724                    return System.Double.PositiveInfinity;
1725                }
1726                if( s==".neginf____" )
1727                {
1728                    offs += SER_ENTRY_LENGTH;
1729                    return System.Double.NegativeInfinity;
1730                }
1731                throw new alglib.alglibexception(emsg);
1732            }
1733           
1734            //
1735            // General case:
1736            // 1. read and decode six-bit digits
1737            // 2. check that all 11 digits were read
1738            // 3. set last 12th digit to zero (needed for simplicity of conversion)
1739            // 4. convert to 8 bytes
1740            // 5. convert to big endian representation, if needed
1741            //
1742            sixbitsread = 0;
1743            while( buf[offs]!=' ' && buf[offs]!='\t' && buf[offs]!='\n' && buf[offs]!='\r' && buf[offs]!=0 )
1744            {
1745                int d;
1746                d = char2sixbits(buf[offs]);
1747                if( d<0 || sixbitsread>=SER_ENTRY_LENGTH )
1748                    throw new alglib.alglibexception(emsg);
1749                sixbits[sixbitsread] = d;
1750                sixbitsread++;
1751                offs++;
1752            }
1753            if( sixbitsread!=SER_ENTRY_LENGTH )
1754                throw new alglib.alglibexception(emsg);
1755            sixbits[SER_ENTRY_LENGTH] = 0;
1756            foursixbits2threebytes(sixbits, 0, bytes, 0);
1757            foursixbits2threebytes(sixbits, 4, bytes, 3);
1758            foursixbits2threebytes(sixbits, 8, bytes, 6);
1759            for(i=0; i<sizeof(double); i++)
1760                _bytes[i] = bytes[i];       
1761            if( !System.BitConverter.IsLittleEndian )
1762                System.Array.Reverse(_bytes);       
1763            return System.BitConverter.ToDouble(_bytes,0);
1764        }
1765    }
1766   
1767    /*
1768     * Parts of alglib.smp class which are shared with GPL version of ALGLIB
1769     */
1770    public partial class smp
1771    {
1772        #pragma warning disable 420
1773        public const int AE_LOCK_CYCLES = 512;
1774        public const int AE_LOCK_TESTS_BEFORE_YIELD = 16;
1775       
1776        /*
1777         * This variable is used to perform spin-wait loops in a platform-independent manner
1778         * (loops which should work same way on Mono and Microsoft NET). You SHOULD NEVER
1779         * change this field - it must be zero during all program life.
1780         */
1781        public static volatile int never_change_it = 0;
1782       
1783        /*************************************************************************
1784        Lock.
1785
1786        This class provides lightweight spin lock
1787        *************************************************************************/
1788        public class ae_lock
1789        {
1790            public volatile int is_locked;
1791        }
1792
1793        /********************************************************************
1794        Shared pool: data structure used to provide thread-safe access to pool
1795        of temporary variables.
1796        ********************************************************************/
1797        public class sharedpoolentry
1798        {
1799            public apobject obj;
1800            public sharedpoolentry next_entry;
1801        }
1802        public class shared_pool : apobject
1803        {
1804            /* lock object which protects pool */
1805            public ae_lock pool_lock;
1806   
1807            /* seed object (used to create new instances of temporaries) */
1808            public volatile apobject seed_object;
1809           
1810            /*
1811             * list of recycled OBJECTS:
1812             * 1. entries in this list store pointers to recycled objects
1813             * 2. every time we retrieve object, we retrieve first entry from this list,
1814             *    move it to recycled_entries and return its obj field to caller/
1815             */
1816            public volatile sharedpoolentry recycled_objects;
1817           
1818            /*
1819             * list of recycled ENTRIES:
1820             * 1. this list holds entries which are not used to store recycled objects;
1821             *    every time recycled object is retrieved, its entry is moved to this list.
1822             * 2. every time object is recycled, we try to fetch entry for him from this list
1823             *    before allocating it with malloc()
1824             */
1825            public volatile sharedpoolentry recycled_entries;
1826           
1827            /* enumeration pointer, points to current recycled object*/
1828            public volatile sharedpoolentry enumeration_counter;
1829           
1830            /* constructor */
1831            public shared_pool()
1832            {
1833                ae_init_lock(ref pool_lock);
1834            }
1835           
1836            /* initializer - creation of empty pool */
1837            public override void init()
1838            {
1839                seed_object = null;
1840                recycled_objects = null;
1841                recycled_entries = null;
1842                enumeration_counter = null;
1843            }
1844           
1845            /* copy constructor (it is NOT thread-safe) */
1846            public override apobject make_copy()
1847            {
1848                sharedpoolentry ptr, buf;
1849                shared_pool result = new shared_pool();
1850               
1851                /* create lock */
1852                ae_init_lock(ref result.pool_lock);
1853   
1854                /* copy seed object */
1855                if( seed_object!=null )
1856                    result.seed_object = seed_object.make_copy();
1857               
1858                /*
1859                 * copy recycled objects:
1860                 * 1. copy to temporary list (objects are inserted to beginning, order is reversed)
1861                 * 2. copy temporary list to output list (order is restored back to normal)
1862                 */
1863                buf = null;
1864                for(ptr=recycled_objects; ptr!=null; ptr=ptr.next_entry)
1865                {
1866                    sharedpoolentry tmp = new sharedpoolentry();
1867                    tmp.obj =  ptr.obj.make_copy();
1868                    tmp.next_entry = buf;
1869                    buf = tmp;
1870                }
1871                result.recycled_objects = null;
1872                for(ptr=buf; ptr!=null;)
1873                {
1874                    sharedpoolentry next_ptr = ptr.next_entry;
1875                    ptr.next_entry = result.recycled_objects;
1876                    result.recycled_objects = ptr;
1877                    ptr = next_ptr;
1878                }
1879   
1880                /* recycled entries are not copied because they do not store any information */
1881                result.recycled_entries = null;
1882   
1883                /* enumeration counter is reset on copying */
1884                result.enumeration_counter = null;
1885   
1886                return result;
1887            }
1888        }
1889       
1890
1891        /************************************************************************
1892        This function performs given number of spin-wait iterations
1893        ************************************************************************/
1894        public static void ae_spin_wait(int cnt)
1895        {
1896            /*
1897             * these strange operations with ae_never_change_it are necessary to
1898             * prevent compiler optimization of the loop.
1899             */
1900            int i;
1901           
1902            /* very unlikely because no one will wait for such amount of cycles */
1903            if( cnt>0x12345678 )
1904                never_change_it = cnt%10;
1905           
1906            /* spin wait, test condition which will never be true */
1907            for(i=0; i<cnt; i++)
1908                if( never_change_it>0 )
1909                    never_change_it--;
1910        }
1911
1912
1913        /************************************************************************
1914        This function causes the calling thread to relinquish the CPU. The thread
1915        is moved to the end of the queue and some other thread gets to run.
1916        ************************************************************************/
1917        public static void ae_yield()
1918        {
1919            System.Threading.Thread.Sleep(0);
1920        }
1921
1922        /************************************************************************
1923        This function initializes ae_lock structure and sets lock in a free mode.
1924        ************************************************************************/
1925        public static void ae_init_lock(ref ae_lock obj)
1926        {
1927            obj = new ae_lock();
1928            obj.is_locked = 0;
1929        }
1930
1931
1932        /************************************************************************
1933        This function acquires lock. In case lock is busy, we perform several
1934        iterations inside tight loop before trying again.
1935        ************************************************************************/
1936        public static void ae_acquire_lock(ae_lock obj)
1937        {
1938            int cnt = 0;
1939            for(;;)
1940            {
1941                if( System.Threading.Interlocked.CompareExchange(ref obj.is_locked, 1, 0)==0 )
1942                    return;
1943                ae_spin_wait(AE_LOCK_CYCLES);
1944                cnt++;
1945                if( cnt%AE_LOCK_TESTS_BEFORE_YIELD==0 )
1946                    ae_yield();
1947            }
1948        }
1949
1950
1951        /************************************************************************
1952        This function releases lock.
1953        ************************************************************************/
1954        public static void ae_release_lock(ae_lock obj)
1955        {
1956            System.Threading.Interlocked.Exchange(ref obj.is_locked, 0);
1957        }
1958
1959
1960        /************************************************************************
1961        This function frees ae_lock structure.
1962        ************************************************************************/
1963        public static void ae_free_lock(ref ae_lock obj)
1964        {
1965            obj = null;
1966        }
1967       
1968       
1969        /************************************************************************
1970        This function returns True, if internal seed object was set.  It  returns
1971        False for un-seeded pool.
1972
1973        dst                 destination pool (initialized by constructor function)
1974
1975        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1976              you should NOT call it when lock can be used by another thread.
1977        ************************************************************************/
1978        public static bool ae_shared_pool_is_initialized(shared_pool dst)
1979        {
1980            return dst.seed_object!=null;
1981        }
1982
1983
1984        /************************************************************************
1985        This function sets internal seed object. All objects owned by the pool
1986        (current seed object, recycled objects) are automatically freed.
1987
1988        dst                 destination pool (initialized by constructor function)
1989        seed_object         new seed object
1990
1991        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
1992              you should NOT call it when lock can be used by another thread.
1993        ************************************************************************/
1994        public static void ae_shared_pool_set_seed(shared_pool dst, alglib.apobject seed_object)
1995        {
1996            dst.seed_object = seed_object.make_copy();
1997            dst.recycled_objects = null;
1998            dst.enumeration_counter = null;
1999        }
2000
2001
2002        /************************************************************************
2003        This  function  retrieves  a  copy  of  the seed object from the pool and
2004        stores it to target variable.
2005
2006        pool                pool
2007        obj                 target variable
2008       
2009        NOTE: this function IS thread-safe.  It  acquires  pool  lock  during its
2010              operation and can be used simultaneously from several threads.
2011        ************************************************************************/
2012        public static void ae_shared_pool_retrieve<T>(shared_pool pool, ref T obj) where T : alglib.apobject
2013        {
2014            alglib.apobject new_obj;
2015           
2016            /* assert that pool was seeded */
2017            alglib.ap.assert(pool.seed_object!=null, "ALGLIB: shared pool is not seeded, PoolRetrieve() failed");
2018           
2019            /* acquire lock */
2020            ae_acquire_lock(pool.pool_lock);
2021           
2022            /* try to reuse recycled objects */
2023            if( pool.recycled_objects!=null )
2024            {
2025                /* retrieve entry/object from list of recycled objects */
2026                sharedpoolentry result = pool.recycled_objects;
2027                pool.recycled_objects = pool.recycled_objects.next_entry;
2028                new_obj = result.obj;
2029                result.obj = null;
2030               
2031                /* move entry to list of recycled entries */
2032                result.next_entry = pool.recycled_entries;
2033                pool.recycled_entries = result;
2034               
2035                /* release lock */
2036                ae_release_lock(pool.pool_lock);
2037               
2038                /* assign object to smart pointer */
2039                obj = (T)new_obj;
2040               
2041                return;
2042            }
2043               
2044            /*
2045             * release lock; we do not need it anymore because
2046             * copy constructor does not modify source variable.
2047             */
2048            ae_release_lock(pool.pool_lock);
2049           
2050            /* create new object from seed */
2051            new_obj = pool.seed_object.make_copy();
2052               
2053            /* assign object to pointer and return */
2054            obj = (T)new_obj;
2055        }
2056
2057
2058        /************************************************************************
2059        This  function  recycles object owned by the source variable by moving it
2060        to internal storage of the shared pool.
2061
2062        Source  variable  must  own  the  object,  i.e.  be  the only place where
2063        reference  to  object  is  stored.  After  call  to  this function source
2064        variable becomes NULL.
2065
2066        pool                pool
2067        obj                 source variable
2068
2069        NOTE: this function IS thread-safe.  It  acquires  pool  lock  during its
2070              operation and can be used simultaneously from several threads.
2071        ************************************************************************/
2072        public static void ae_shared_pool_recycle<T>(shared_pool pool, ref T obj) where T : alglib.apobject
2073        {
2074            sharedpoolentry new_entry;
2075           
2076            /* assert that pool was seeded */
2077            alglib.ap.assert(pool.seed_object!=null, "ALGLIB: shared pool is not seeded, PoolRecycle() failed");
2078           
2079            /* assert that pointer non-null */
2080            alglib.ap.assert(obj!=null, "ALGLIB: obj in ae_shared_pool_recycle() is NULL");
2081           
2082            /* acquire lock */
2083            ae_acquire_lock(pool.pool_lock);
2084           
2085            /* acquire shared pool entry (reuse one from recycled_entries or malloc new one) */
2086            if( pool.recycled_entries!=null )
2087            {
2088                /* reuse previously allocated entry */
2089                new_entry = pool.recycled_entries;
2090                pool.recycled_entries = new_entry.next_entry;
2091            }
2092            else
2093            {
2094                /*
2095                 * Allocate memory for new entry.
2096                 *
2097                 * NOTE: we release pool lock during allocation because new() may raise
2098                 *       exception and we do not want our pool to be left in the locked state.
2099                 */
2100                ae_release_lock(pool.pool_lock);
2101                new_entry = new sharedpoolentry();
2102                ae_acquire_lock(pool.pool_lock);
2103            }
2104           
2105            /* add object to the list of recycled objects */
2106            new_entry.obj = obj;
2107            new_entry.next_entry = pool.recycled_objects;
2108            pool.recycled_objects = new_entry;
2109           
2110            /* release lock object */
2111            ae_release_lock(pool.pool_lock);
2112           
2113            /* release source pointer */
2114            obj = null;
2115        }
2116
2117
2118        /************************************************************************
2119        This function clears internal list of  recycled  objects,  but  does  not
2120        change seed object managed by the pool.
2121
2122        pool                pool
2123
2124        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
2125              you should NOT call it when lock can be used by another thread.
2126        ************************************************************************/
2127        public static void ae_shared_pool_clear_recycled(shared_pool pool)
2128        {
2129            pool.recycled_objects = null;
2130        }
2131
2132
2133        /************************************************************************
2134        This function allows to enumerate recycled elements of the  shared  pool.
2135        It stores reference to the first recycled object in the smart pointer.
2136
2137        IMPORTANT:
2138        * in case target variable owns non-NULL value, it is rewritten
2139        * recycled object IS NOT removed from pool
2140        * target variable DOES NOT become owner of the new value; you can use
2141          reference to recycled object, but you do not own it.
2142        * this function IS NOT thread-safe
2143        * you SHOULD NOT modify shared pool during enumeration (although you  can
2144          modify state of the objects retrieved from pool)
2145        * in case there is no recycled objects in the pool, NULL is stored to obj
2146        * in case pool is not seeded, NULL is stored to obj
2147
2148        pool                pool
2149        obj                 reference
2150        ************************************************************************/
2151        public static void ae_shared_pool_first_recycled<T>(shared_pool pool, ref T obj) where T : alglib.apobject
2152        {   
2153            /* modify internal enumeration counter */
2154            pool.enumeration_counter = pool.recycled_objects;
2155           
2156            /* exit on empty list */
2157            if( pool.enumeration_counter==null )
2158            {
2159                obj = null;
2160                return;
2161            }
2162           
2163            /* assign object to smart pointer */
2164            obj = (T)pool.enumeration_counter.obj;
2165        }
2166
2167
2168        /************************************************************************
2169        This function allows to enumerate recycled elements of the  shared  pool.
2170        It stores pointer to the next recycled object in the smart pointer.
2171
2172        IMPORTANT:
2173        * in case target variable owns non-NULL value, it is rewritten
2174        * recycled object IS NOT removed from pool
2175        * target pointer DOES NOT become owner of the new value
2176        * this function IS NOT thread-safe
2177        * you SHOULD NOT modify shared pool during enumeration (although you  can
2178          modify state of the objects retrieved from pool)
2179        * in case there is no recycled objects left in the pool, NULL is stored.
2180        * in case pool is not seeded, NULL is stored.
2181
2182        pool                pool
2183        obj                 target variable
2184        ************************************************************************/
2185        public static void ae_shared_pool_next_recycled<T>(shared_pool pool, ref T obj) where T : alglib.apobject
2186        {   
2187            /* exit on end of list */
2188            if( pool.enumeration_counter==null )
2189            {
2190                obj = null;
2191                return;
2192            }
2193           
2194            /* modify internal enumeration counter */
2195            pool.enumeration_counter = pool.enumeration_counter.next_entry;
2196           
2197            /* exit on empty list */
2198            if( pool.enumeration_counter==null )
2199            {
2200                obj = null;
2201                return;
2202            }
2203           
2204            /* assign object to smart pointer */
2205            obj = (T)pool.enumeration_counter.obj;
2206        }
2207
2208
2209        /************************************************************************
2210        This function clears internal list of recycled objects and  seed  object.
2211        However, pool still can be used (after initialization with another seed).
2212
2213        pool                pool
2214        state               ALGLIB environment state
2215
2216        NOTE: this function is NOT thread-safe. It does not acquire pool lock, so
2217              you should NOT call it when lock can be used by another thread.
2218        ************************************************************************/
2219        public static void ae_shared_pool_reset(shared_pool pool)
2220        {   
2221            pool.seed_object = null;
2222            pool.recycled_objects = null;
2223            pool.enumeration_counter = null;
2224        }
2225    }
2226}
2227public partial class alglib
2228{
2229    public partial class smp
2230    {
2231        public static int cores_count = 1;
2232        public static volatile int cores_to_use = 1;
2233        public static bool isparallelcontext()
2234        {
2235            return false;
2236        }
2237    }
2238    public class smpselftests
2239    {
2240        public static bool runtests()
2241        {
2242            return true;
2243        }
2244    }
2245    public static void setnworkers(int nworkers)
2246    {
2247        alglib.smp.cores_to_use = nworkers;
2248    }
2249    public static int getnworkers()
2250    {
2251        return alglib.smp.cores_to_use;
2252    }
2253}
Note: See TracBrowser for help on using the repository browser.