Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.6/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/3.1.0/ALGLIB-3.1.0/alglibmisc.cs @ 7585

Last change on this file since 7585 was 4977, checked in by gkronber, 14 years ago

Added new alglib classes (version 3.1.0) #875

File size: 87.4 KB
Line 
1/*************************************************************************
2Copyright (c) Sergey Bochkanov (ALGLIB project).
3
4>>> SOURCE LICENSE >>>
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation (www.fsf.org); either version 2 of the
8License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15A copy of the GNU General Public License is available at
16http://www.fsf.org/licensing/licenses
17>>> END OF LICENSE >>>
18*************************************************************************/
19#pragma warning disable 162
20#pragma warning disable 219
21using System;
22
23public partial class alglib
24{
25
26
27    /*************************************************************************
28    Portable high quality random number generator state.
29    Initialized with HQRNDRandomize() or HQRNDSeed().
30
31    Fields:
32        S1, S2      -   seed values
33        V           -   precomputed value
34        MagicV      -   'magic' value used to determine whether State structure
35                        was correctly initialized.
36    *************************************************************************/
37    public class hqrndstate
38    {
39        //
40        // Public declarations
41        //
42
43        public hqrndstate()
44        {
45            _innerobj = new hqrnd.hqrndstate();
46        }
47
48        //
49        // Although some of declarations below are public, you should not use them
50        // They are intended for internal use only
51        //
52        private hqrnd.hqrndstate _innerobj;
53        public hqrnd.hqrndstate innerobj { get { return _innerobj; } }
54        public hqrndstate(hqrnd.hqrndstate obj)
55        {
56            _innerobj = obj;
57        }
58    }
59
60    /*************************************************************************
61    HQRNDState  initialization  with  random  values  which come from standard
62    RNG.
63
64      -- ALGLIB --
65         Copyright 02.12.2009 by Bochkanov Sergey
66    *************************************************************************/
67    public static void hqrndrandomize(out hqrndstate state)
68    {
69        state = new hqrndstate();
70        hqrnd.hqrndrandomize(state.innerobj);
71        return;
72    }
73
74    /*************************************************************************
75    HQRNDState initialization with seed values
76
77      -- ALGLIB --
78         Copyright 02.12.2009 by Bochkanov Sergey
79    *************************************************************************/
80    public static void hqrndseed(int s1, int s2, out hqrndstate state)
81    {
82        state = new hqrndstate();
83        hqrnd.hqrndseed(s1, s2, state.innerobj);
84        return;
85    }
86
87    /*************************************************************************
88    This function generates random real number in (0,1),
89    not including interval boundaries
90
91    State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
92
93      -- ALGLIB --
94         Copyright 02.12.2009 by Bochkanov Sergey
95    *************************************************************************/
96    public static double hqrnduniformr(hqrndstate state)
97    {
98
99        double result = hqrnd.hqrnduniformr(state.innerobj);
100        return result;
101    }
102
103    /*************************************************************************
104    This function generates random integer number in [0, N)
105
106    1. N must be less than HQRNDMax-1.
107    2. State structure must be initialized with HQRNDRandomize() or HQRNDSeed()
108
109      -- ALGLIB --
110         Copyright 02.12.2009 by Bochkanov Sergey
111    *************************************************************************/
112    public static int hqrnduniformi(hqrndstate state, int n)
113    {
114
115        int result = hqrnd.hqrnduniformi(state.innerobj, n);
116        return result;
117    }
118
119    /*************************************************************************
120    Random number generator: normal numbers
121
122    This function generates one random number from normal distribution.
123    Its performance is equal to that of HQRNDNormal2()
124
125    State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
126
127      -- ALGLIB --
128         Copyright 02.12.2009 by Bochkanov Sergey
129    *************************************************************************/
130    public static double hqrndnormal(hqrndstate state)
131    {
132
133        double result = hqrnd.hqrndnormal(state.innerobj);
134        return result;
135    }
136
137    /*************************************************************************
138    Random number generator: random X and Y such that X^2+Y^2=1
139
140    State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
141
142      -- ALGLIB --
143         Copyright 02.12.2009 by Bochkanov Sergey
144    *************************************************************************/
145    public static void hqrndunit2(hqrndstate state, out double x, out double y)
146    {
147        x = 0;
148        y = 0;
149        hqrnd.hqrndunit2(state.innerobj, ref x, ref y);
150        return;
151    }
152
153    /*************************************************************************
154    Random number generator: normal numbers
155
156    This function generates two independent random numbers from normal
157    distribution. Its performance is equal to that of HQRNDNormal()
158
159    State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
160
161      -- ALGLIB --
162         Copyright 02.12.2009 by Bochkanov Sergey
163    *************************************************************************/
164    public static void hqrndnormal2(hqrndstate state, out double x1, out double x2)
165    {
166        x1 = 0;
167        x2 = 0;
168        hqrnd.hqrndnormal2(state.innerobj, ref x1, ref x2);
169        return;
170    }
171
172    /*************************************************************************
173    Random number generator: exponential distribution
174
175    State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
176
177      -- ALGLIB --
178         Copyright 11.08.2007 by Bochkanov Sergey
179    *************************************************************************/
180    public static double hqrndexponential(hqrndstate state, double lambdav)
181    {
182
183        double result = hqrnd.hqrndexponential(state.innerobj, lambdav);
184        return result;
185    }
186
187}
188public partial class alglib
189{
190
191
192    /*************************************************************************
193
194    *************************************************************************/
195    public class kdtree
196    {
197        //
198        // Public declarations
199        //
200
201        public kdtree()
202        {
203            _innerobj = new nearestneighbor.kdtree();
204        }
205
206        //
207        // Although some of declarations below are public, you should not use them
208        // They are intended for internal use only
209        //
210        private nearestneighbor.kdtree _innerobj;
211        public nearestneighbor.kdtree innerobj { get { return _innerobj; } }
212        public kdtree(nearestneighbor.kdtree obj)
213        {
214            _innerobj = obj;
215        }
216    }
217
218    /*************************************************************************
219    KD-tree creation
220
221    This subroutine creates KD-tree from set of X-values and optional Y-values
222
223    INPUT PARAMETERS
224        XY      -   dataset, array[0..N-1,0..NX+NY-1].
225                    one row corresponds to one point.
226                    first NX columns contain X-values, next NY (NY may be zero)
227                    columns may contain associated Y-values
228        N       -   number of points, N>=1
229        NX      -   space dimension, NX>=1.
230        NY      -   number of optional Y-values, NY>=0.
231        NormType-   norm type:
232                    * 0 denotes infinity-norm
233                    * 1 denotes 1-norm
234                    * 2 denotes 2-norm (Euclidean norm)
235
236    OUTPUT PARAMETERS
237        KDT     -   KD-tree
238
239
240    NOTES
241
242    1. KD-tree  creation  have O(N*logN) complexity and O(N*(2*NX+NY))  memory
243       requirements.
244    2. Although KD-trees may be used with any combination of N  and  NX,  they
245       are more efficient than brute-force search only when N >> 4^NX. So they
246       are most useful in low-dimensional tasks (NX=2, NX=3). NX=1  is another
247       inefficient case, because  simple  binary  search  (without  additional
248       structures) is much more efficient in such tasks than KD-trees.
249
250      -- ALGLIB --
251         Copyright 28.02.2010 by Bochkanov Sergey
252    *************************************************************************/
253    public static void kdtreebuild(double[,] xy, int n, int nx, int ny, int normtype, out kdtree kdt)
254    {
255        kdt = new kdtree();
256        nearestneighbor.kdtreebuild(xy, n, nx, ny, normtype, kdt.innerobj);
257        return;
258    }
259    public static void kdtreebuild(double[,] xy, int nx, int ny, int normtype, out kdtree kdt)
260    {
261        int n;
262
263        kdt = new kdtree();
264        n = ap.rows(xy);
265        nearestneighbor.kdtreebuild(xy, n, nx, ny, normtype, kdt.innerobj);
266
267        return;
268    }
269
270    /*************************************************************************
271    KD-tree creation
272
273    This  subroutine  creates  KD-tree  from set of X-values, integer tags and
274    optional Y-values
275
276    INPUT PARAMETERS
277        XY      -   dataset, array[0..N-1,0..NX+NY-1].
278                    one row corresponds to one point.
279                    first NX columns contain X-values, next NY (NY may be zero)
280                    columns may contain associated Y-values
281        Tags    -   tags, array[0..N-1], contains integer tags associated
282                    with points.
283        N       -   number of points, N>=1
284        NX      -   space dimension, NX>=1.
285        NY      -   number of optional Y-values, NY>=0.
286        NormType-   norm type:
287                    * 0 denotes infinity-norm
288                    * 1 denotes 1-norm
289                    * 2 denotes 2-norm (Euclidean norm)
290
291    OUTPUT PARAMETERS
292        KDT     -   KD-tree
293
294    NOTES
295
296    1. KD-tree  creation  have O(N*logN) complexity and O(N*(2*NX+NY))  memory
297       requirements.
298    2. Although KD-trees may be used with any combination of N  and  NX,  they
299       are more efficient than brute-force search only when N >> 4^NX. So they
300       are most useful in low-dimensional tasks (NX=2, NX=3). NX=1  is another
301       inefficient case, because  simple  binary  search  (without  additional
302       structures) is much more efficient in such tasks than KD-trees.
303
304      -- ALGLIB --
305         Copyright 28.02.2010 by Bochkanov Sergey
306    *************************************************************************/
307    public static void kdtreebuildtagged(double[,] xy, int[] tags, int n, int nx, int ny, int normtype, out kdtree kdt)
308    {
309        kdt = new kdtree();
310        nearestneighbor.kdtreebuildtagged(xy, tags, n, nx, ny, normtype, kdt.innerobj);
311        return;
312    }
313    public static void kdtreebuildtagged(double[,] xy, int[] tags, int nx, int ny, int normtype, out kdtree kdt)
314    {
315        int n;
316        if( (ap.rows(xy)!=ap.len(tags)))
317            throw new alglibexception("Error while calling 'kdtreebuildtagged': looks like one of arguments has wrong size");
318        kdt = new kdtree();
319        n = ap.rows(xy);
320        nearestneighbor.kdtreebuildtagged(xy, tags, n, nx, ny, normtype, kdt.innerobj);
321
322        return;
323    }
324
325    /*************************************************************************
326    K-NN query: K nearest neighbors
327
328    INPUT PARAMETERS
329        KDT         -   KD-tree
330        X           -   point, array[0..NX-1].
331        K           -   number of neighbors to return, K>=1
332        SelfMatch   -   whether self-matches are allowed:
333                        * if True, nearest neighbor may be the point itself
334                          (if it exists in original dataset)
335                        * if False, then only points with non-zero distance
336                          are returned
337                        * if not given, considered True
338
339    RESULT
340        number of actual neighbors found (either K or N, if K>N).
341
342    This  subroutine  performs  query  and  stores  its result in the internal
343    structures of the KD-tree. You can use  following  subroutines  to  obtain
344    these results:
345    * KDTreeQueryResultsX() to get X-values
346    * KDTreeQueryResultsXY() to get X- and Y-values
347    * KDTreeQueryResultsTags() to get tag values
348    * KDTreeQueryResultsDistances() to get distances
349
350      -- ALGLIB --
351         Copyright 28.02.2010 by Bochkanov Sergey
352    *************************************************************************/
353    public static int kdtreequeryknn(kdtree kdt, double[] x, int k, bool selfmatch)
354    {
355
356        int result = nearestneighbor.kdtreequeryknn(kdt.innerobj, x, k, selfmatch);
357        return result;
358    }
359    public static int kdtreequeryknn(kdtree kdt, double[] x, int k)
360    {
361        bool selfmatch;
362
363
364        selfmatch = true;
365        int result = nearestneighbor.kdtreequeryknn(kdt.innerobj, x, k, selfmatch);
366
367        return result;
368    }
369
370    /*************************************************************************
371    R-NN query: all points within R-sphere centered at X
372
373    INPUT PARAMETERS
374        KDT         -   KD-tree
375        X           -   point, array[0..NX-1].
376        R           -   radius of sphere (in corresponding norm), R>0
377        SelfMatch   -   whether self-matches are allowed:
378                        * if True, nearest neighbor may be the point itself
379                          (if it exists in original dataset)
380                        * if False, then only points with non-zero distance
381                          are returned
382                        * if not given, considered True
383
384    RESULT
385        number of neighbors found, >=0
386
387    This  subroutine  performs  query  and  stores  its result in the internal
388    structures of the KD-tree. You can use  following  subroutines  to  obtain
389    actual results:
390    * KDTreeQueryResultsX() to get X-values
391    * KDTreeQueryResultsXY() to get X- and Y-values
392    * KDTreeQueryResultsTags() to get tag values
393    * KDTreeQueryResultsDistances() to get distances
394
395      -- ALGLIB --
396         Copyright 28.02.2010 by Bochkanov Sergey
397    *************************************************************************/
398    public static int kdtreequeryrnn(kdtree kdt, double[] x, double r, bool selfmatch)
399    {
400
401        int result = nearestneighbor.kdtreequeryrnn(kdt.innerobj, x, r, selfmatch);
402        return result;
403    }
404    public static int kdtreequeryrnn(kdtree kdt, double[] x, double r)
405    {
406        bool selfmatch;
407
408
409        selfmatch = true;
410        int result = nearestneighbor.kdtreequeryrnn(kdt.innerobj, x, r, selfmatch);
411
412        return result;
413    }
414
415    /*************************************************************************
416    K-NN query: approximate K nearest neighbors
417
418    INPUT PARAMETERS
419        KDT         -   KD-tree
420        X           -   point, array[0..NX-1].
421        K           -   number of neighbors to return, K>=1
422        SelfMatch   -   whether self-matches are allowed:
423                        * if True, nearest neighbor may be the point itself
424                          (if it exists in original dataset)
425                        * if False, then only points with non-zero distance
426                          are returned
427                        * if not given, considered True
428        Eps         -   approximation factor, Eps>=0. eps-approximate  nearest
429                        neighbor  is  a  neighbor  whose distance from X is at
430                        most (1+eps) times distance of true nearest neighbor.
431
432    RESULT
433        number of actual neighbors found (either K or N, if K>N).
434
435    NOTES
436        significant performance gain may be achieved only when Eps  is  is  on
437        the order of magnitude of 1 or larger.
438
439    This  subroutine  performs  query  and  stores  its result in the internal
440    structures of the KD-tree. You can use  following  subroutines  to  obtain
441    these results:
442    * KDTreeQueryResultsX() to get X-values
443    * KDTreeQueryResultsXY() to get X- and Y-values
444    * KDTreeQueryResultsTags() to get tag values
445    * KDTreeQueryResultsDistances() to get distances
446
447      -- ALGLIB --
448         Copyright 28.02.2010 by Bochkanov Sergey
449    *************************************************************************/
450    public static int kdtreequeryaknn(kdtree kdt, double[] x, int k, bool selfmatch, double eps)
451    {
452
453        int result = nearestneighbor.kdtreequeryaknn(kdt.innerobj, x, k, selfmatch, eps);
454        return result;
455    }
456    public static int kdtreequeryaknn(kdtree kdt, double[] x, int k, double eps)
457    {
458        bool selfmatch;
459
460
461        selfmatch = true;
462        int result = nearestneighbor.kdtreequeryaknn(kdt.innerobj, x, k, selfmatch, eps);
463
464        return result;
465    }
466
467    /*************************************************************************
468    X-values from last query
469
470    INPUT PARAMETERS
471        KDT     -   KD-tree
472        X       -   possibly pre-allocated buffer. If X is too small to store
473                    result, it is resized. If size(X) is enough to store
474                    result, it is left unchanged.
475
476    OUTPUT PARAMETERS
477        X       -   rows are filled with X-values
478
479    NOTES
480    1. points are ordered by distance from the query point (first = closest)
481    2. if  XY is larger than required to store result, only leading part  will
482       be overwritten; trailing part will be left unchanged. So  if  on  input
483       XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
484       XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
485       you want function  to  resize  array  according  to  result  size,  use
486       function with same name and suffix 'I'.
487
488    SEE ALSO
489    * KDTreeQueryResultsXY()            X- and Y-values
490    * KDTreeQueryResultsTags()          tag values
491    * KDTreeQueryResultsDistances()     distances
492
493      -- ALGLIB --
494         Copyright 28.02.2010 by Bochkanov Sergey
495    *************************************************************************/
496    public static void kdtreequeryresultsx(kdtree kdt, ref double[,] x)
497    {
498
499        nearestneighbor.kdtreequeryresultsx(kdt.innerobj, ref x);
500        return;
501    }
502
503    /*************************************************************************
504    X- and Y-values from last query
505
506    INPUT PARAMETERS
507        KDT     -   KD-tree
508        XY      -   possibly pre-allocated buffer. If XY is too small to store
509                    result, it is resized. If size(XY) is enough to store
510                    result, it is left unchanged.
511
512    OUTPUT PARAMETERS
513        XY      -   rows are filled with points: first NX columns with
514                    X-values, next NY columns - with Y-values.
515
516    NOTES
517    1. points are ordered by distance from the query point (first = closest)
518    2. if  XY is larger than required to store result, only leading part  will
519       be overwritten; trailing part will be left unchanged. So  if  on  input
520       XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
521       XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
522       you want function  to  resize  array  according  to  result  size,  use
523       function with same name and suffix 'I'.
524
525    SEE ALSO
526    * KDTreeQueryResultsX()             X-values
527    * KDTreeQueryResultsTags()          tag values
528    * KDTreeQueryResultsDistances()     distances
529
530      -- ALGLIB --
531         Copyright 28.02.2010 by Bochkanov Sergey
532    *************************************************************************/
533    public static void kdtreequeryresultsxy(kdtree kdt, ref double[,] xy)
534    {
535
536        nearestneighbor.kdtreequeryresultsxy(kdt.innerobj, ref xy);
537        return;
538    }
539
540    /*************************************************************************
541    Tags from last query
542
543    INPUT PARAMETERS
544        KDT     -   KD-tree
545        Tags    -   possibly pre-allocated buffer. If X is too small to store
546                    result, it is resized. If size(X) is enough to store
547                    result, it is left unchanged.
548
549    OUTPUT PARAMETERS
550        Tags    -   filled with tags associated with points,
551                    or, when no tags were supplied, with zeros
552
553    NOTES
554    1. points are ordered by distance from the query point (first = closest)
555    2. if  XY is larger than required to store result, only leading part  will
556       be overwritten; trailing part will be left unchanged. So  if  on  input
557       XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
558       XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
559       you want function  to  resize  array  according  to  result  size,  use
560       function with same name and suffix 'I'.
561
562    SEE ALSO
563    * KDTreeQueryResultsX()             X-values
564    * KDTreeQueryResultsXY()            X- and Y-values
565    * KDTreeQueryResultsDistances()     distances
566
567      -- ALGLIB --
568         Copyright 28.02.2010 by Bochkanov Sergey
569    *************************************************************************/
570    public static void kdtreequeryresultstags(kdtree kdt, ref int[] tags)
571    {
572
573        nearestneighbor.kdtreequeryresultstags(kdt.innerobj, ref tags);
574        return;
575    }
576
577    /*************************************************************************
578    Distances from last query
579
580    INPUT PARAMETERS
581        KDT     -   KD-tree
582        R       -   possibly pre-allocated buffer. If X is too small to store
583                    result, it is resized. If size(X) is enough to store
584                    result, it is left unchanged.
585
586    OUTPUT PARAMETERS
587        R       -   filled with distances (in corresponding norm)
588
589    NOTES
590    1. points are ordered by distance from the query point (first = closest)
591    2. if  XY is larger than required to store result, only leading part  will
592       be overwritten; trailing part will be left unchanged. So  if  on  input
593       XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
594       XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
595       you want function  to  resize  array  according  to  result  size,  use
596       function with same name and suffix 'I'.
597
598    SEE ALSO
599    * KDTreeQueryResultsX()             X-values
600    * KDTreeQueryResultsXY()            X- and Y-values
601    * KDTreeQueryResultsTags()          tag values
602
603      -- ALGLIB --
604         Copyright 28.02.2010 by Bochkanov Sergey
605    *************************************************************************/
606    public static void kdtreequeryresultsdistances(kdtree kdt, ref double[] r)
607    {
608
609        nearestneighbor.kdtreequeryresultsdistances(kdt.innerobj, ref r);
610        return;
611    }
612
613    /*************************************************************************
614    X-values from last query; 'interactive' variant for languages like  Python
615    which   support    constructs   like  "X = KDTreeQueryResultsXI(KDT)"  and
616    interactive mode of interpreter.
617
618    This function allocates new array on each call,  so  it  is  significantly
619    slower than its 'non-interactive' counterpart, but it is  more  convenient
620    when you call it from command line.
621
622      -- ALGLIB --
623         Copyright 28.02.2010 by Bochkanov Sergey
624    *************************************************************************/
625    public static void kdtreequeryresultsxi(kdtree kdt, out double[,] x)
626    {
627        x = new double[0,0];
628        nearestneighbor.kdtreequeryresultsxi(kdt.innerobj, ref x);
629        return;
630    }
631
632    /*************************************************************************
633    XY-values from last query; 'interactive' variant for languages like Python
634    which   support    constructs   like "XY = KDTreeQueryResultsXYI(KDT)" and
635    interactive mode of interpreter.
636
637    This function allocates new array on each call,  so  it  is  significantly
638    slower than its 'non-interactive' counterpart, but it is  more  convenient
639    when you call it from command line.
640
641      -- ALGLIB --
642         Copyright 28.02.2010 by Bochkanov Sergey
643    *************************************************************************/
644    public static void kdtreequeryresultsxyi(kdtree kdt, out double[,] xy)
645    {
646        xy = new double[0,0];
647        nearestneighbor.kdtreequeryresultsxyi(kdt.innerobj, ref xy);
648        return;
649    }
650
651    /*************************************************************************
652    Tags  from  last  query;  'interactive' variant for languages like  Python
653    which  support  constructs  like "Tags = KDTreeQueryResultsTagsI(KDT)" and
654    interactive mode of interpreter.
655
656    This function allocates new array on each call,  so  it  is  significantly
657    slower than its 'non-interactive' counterpart, but it is  more  convenient
658    when you call it from command line.
659
660      -- ALGLIB --
661         Copyright 28.02.2010 by Bochkanov Sergey
662    *************************************************************************/
663    public static void kdtreequeryresultstagsi(kdtree kdt, out int[] tags)
664    {
665        tags = new int[0];
666        nearestneighbor.kdtreequeryresultstagsi(kdt.innerobj, ref tags);
667        return;
668    }
669
670    /*************************************************************************
671    Distances from last query; 'interactive' variant for languages like Python
672    which  support  constructs   like  "R = KDTreeQueryResultsDistancesI(KDT)"
673    and interactive mode of interpreter.
674
675    This function allocates new array on each call,  so  it  is  significantly
676    slower than its 'non-interactive' counterpart, but it is  more  convenient
677    when you call it from command line.
678
679      -- ALGLIB --
680         Copyright 28.02.2010 by Bochkanov Sergey
681    *************************************************************************/
682    public static void kdtreequeryresultsdistancesi(kdtree kdt, out double[] r)
683    {
684        r = new double[0];
685        nearestneighbor.kdtreequeryresultsdistancesi(kdt.innerobj, ref r);
686        return;
687    }
688
689}
690public partial class alglib
691{
692    public class hqrnd
693    {
694        /*************************************************************************
695        Portable high quality random number generator state.
696        Initialized with HQRNDRandomize() or HQRNDSeed().
697
698        Fields:
699            S1, S2      -   seed values
700            V           -   precomputed value
701            MagicV      -   'magic' value used to determine whether State structure
702                            was correctly initialized.
703        *************************************************************************/
704        public class hqrndstate
705        {
706            public int s1;
707            public int s2;
708            public double v;
709            public int magicv;
710        };
711
712
713
714
715        public const int hqrndmax = 2147483563;
716        public const int hqrndm1 = 2147483563;
717        public const int hqrndm2 = 2147483399;
718        public const int hqrndmagic = 1634357784;
719
720
721        /*************************************************************************
722        HQRNDState  initialization  with  random  values  which come from standard
723        RNG.
724
725          -- ALGLIB --
726             Copyright 02.12.2009 by Bochkanov Sergey
727        *************************************************************************/
728        public static void hqrndrandomize(hqrndstate state)
729        {
730            hqrndseed(math.randominteger(hqrndm1), math.randominteger(hqrndm2), state);
731        }
732
733
734        /*************************************************************************
735        HQRNDState initialization with seed values
736
737          -- ALGLIB --
738             Copyright 02.12.2009 by Bochkanov Sergey
739        *************************************************************************/
740        public static void hqrndseed(int s1,
741            int s2,
742            hqrndstate state)
743        {
744            state.s1 = s1%(hqrndm1-1)+1;
745            state.s2 = s2%(hqrndm2-1)+1;
746            state.v = (double)1/(double)hqrndmax;
747            state.magicv = hqrndmagic;
748        }
749
750
751        /*************************************************************************
752        This function generates random real number in (0,1),
753        not including interval boundaries
754
755        State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
756
757          -- ALGLIB --
758             Copyright 02.12.2009 by Bochkanov Sergey
759        *************************************************************************/
760        public static double hqrnduniformr(hqrndstate state)
761        {
762            double result = 0;
763
764            result = state.v*hqrndintegerbase(state);
765            return result;
766        }
767
768
769        /*************************************************************************
770        This function generates random integer number in [0, N)
771
772        1. N must be less than HQRNDMax-1.
773        2. State structure must be initialized with HQRNDRandomize() or HQRNDSeed()
774
775          -- ALGLIB --
776             Copyright 02.12.2009 by Bochkanov Sergey
777        *************************************************************************/
778        public static int hqrnduniformi(hqrndstate state,
779            int n)
780        {
781            int result = 0;
782            int mx = 0;
783
784           
785            //
786            // Correct handling of N's close to RNDBaseMax
787            // (avoiding skewed distributions for RNDBaseMax<>K*N)
788            //
789            ap.assert(n>0, "HQRNDUniformI: N<=0!");
790            ap.assert(n<hqrndmax-1, "HQRNDUniformI: N>=RNDBaseMax-1!");
791            mx = hqrndmax-1-(hqrndmax-1)%n;
792            do
793            {
794                result = hqrndintegerbase(state)-1;
795            }
796            while( result>=mx );
797            result = result%n;
798            return result;
799        }
800
801
802        /*************************************************************************
803        Random number generator: normal numbers
804
805        This function generates one random number from normal distribution.
806        Its performance is equal to that of HQRNDNormal2()
807
808        State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
809
810          -- ALGLIB --
811             Copyright 02.12.2009 by Bochkanov Sergey
812        *************************************************************************/
813        public static double hqrndnormal(hqrndstate state)
814        {
815            double result = 0;
816            double v1 = 0;
817            double v2 = 0;
818
819            hqrndnormal2(state, ref v1, ref v2);
820            result = v1;
821            return result;
822        }
823
824
825        /*************************************************************************
826        Random number generator: random X and Y such that X^2+Y^2=1
827
828        State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
829
830          -- ALGLIB --
831             Copyright 02.12.2009 by Bochkanov Sergey
832        *************************************************************************/
833        public static void hqrndunit2(hqrndstate state,
834            ref double x,
835            ref double y)
836        {
837            double v = 0;
838            double mx = 0;
839            double mn = 0;
840
841            x = 0;
842            y = 0;
843
844            do
845            {
846                hqrndnormal2(state, ref x, ref y);
847            }
848            while( !((double)(x)!=(double)(0) | (double)(y)!=(double)(0)) );
849            mx = Math.Max(Math.Abs(x), Math.Abs(y));
850            mn = Math.Min(Math.Abs(x), Math.Abs(y));
851            v = mx*Math.Sqrt(1+math.sqr(mn/mx));
852            x = x/v;
853            y = y/v;
854        }
855
856
857        /*************************************************************************
858        Random number generator: normal numbers
859
860        This function generates two independent random numbers from normal
861        distribution. Its performance is equal to that of HQRNDNormal()
862
863        State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
864
865          -- ALGLIB --
866             Copyright 02.12.2009 by Bochkanov Sergey
867        *************************************************************************/
868        public static void hqrndnormal2(hqrndstate state,
869            ref double x1,
870            ref double x2)
871        {
872            double u = 0;
873            double v = 0;
874            double s = 0;
875
876            x1 = 0;
877            x2 = 0;
878
879            while( true )
880            {
881                u = 2*hqrnduniformr(state)-1;
882                v = 2*hqrnduniformr(state)-1;
883                s = math.sqr(u)+math.sqr(v);
884                if( (double)(s)>(double)(0) & (double)(s)<(double)(1) )
885                {
886                   
887                    //
888                    // two Sqrt's instead of one to
889                    // avoid overflow when S is too small
890                    //
891                    s = Math.Sqrt(-(2*Math.Log(s)))/Math.Sqrt(s);
892                    x1 = u*s;
893                    x2 = v*s;
894                    return;
895                }
896            }
897        }
898
899
900        /*************************************************************************
901        Random number generator: exponential distribution
902
903        State structure must be initialized with HQRNDRandomize() or HQRNDSeed().
904
905          -- ALGLIB --
906             Copyright 11.08.2007 by Bochkanov Sergey
907        *************************************************************************/
908        public static double hqrndexponential(hqrndstate state,
909            double lambdav)
910        {
911            double result = 0;
912
913            ap.assert((double)(lambdav)>(double)(0), "HQRNDExponential: LambdaV<=0!");
914            result = -(Math.Log(hqrnduniformr(state))/lambdav);
915            return result;
916        }
917
918
919        /*************************************************************************
920
921        L'Ecuyer, Efficient and portable combined random number generators
922        *************************************************************************/
923        private static int hqrndintegerbase(hqrndstate state)
924        {
925            int result = 0;
926            int k = 0;
927
928            ap.assert(state.magicv==hqrndmagic, "HQRNDIntegerBase: State is not correctly initialized!");
929            k = state.s1/53668;
930            state.s1 = 40014*(state.s1-k*53668)-k*12211;
931            if( state.s1<0 )
932            {
933                state.s1 = state.s1+2147483563;
934            }
935            k = state.s2/52774;
936            state.s2 = 40692*(state.s2-k*52774)-k*3791;
937            if( state.s2<0 )
938            {
939                state.s2 = state.s2+2147483399;
940            }
941           
942            //
943            // Result
944            //
945            result = state.s1-state.s2;
946            if( result<1 )
947            {
948                result = result+2147483562;
949            }
950            return result;
951        }
952
953
954    }
955    public class nearestneighbor
956    {
957        public class kdtree
958        {
959            public int n;
960            public int nx;
961            public int ny;
962            public int normtype;
963            public int distmatrixtype;
964            public double[,] xy;
965            public int[] tags;
966            public double[] boxmin;
967            public double[] boxmax;
968            public double[] curboxmin;
969            public double[] curboxmax;
970            public double curdist;
971            public int[] nodes;
972            public double[] splits;
973            public double[] x;
974            public int kneeded;
975            public double rneeded;
976            public bool selfmatch;
977            public double approxf;
978            public int kcur;
979            public int[] idx;
980            public double[] r;
981            public double[] buf;
982            public int debugcounter;
983            public kdtree()
984            {
985                xy = new double[0,0];
986                tags = new int[0];
987                boxmin = new double[0];
988                boxmax = new double[0];
989                curboxmin = new double[0];
990                curboxmax = new double[0];
991                nodes = new int[0];
992                splits = new double[0];
993                x = new double[0];
994                idx = new int[0];
995                r = new double[0];
996                buf = new double[0];
997            }
998        };
999
1000
1001
1002
1003        public const int splitnodesize = 6;
1004
1005
1006        /*************************************************************************
1007        KD-tree creation
1008
1009        This subroutine creates KD-tree from set of X-values and optional Y-values
1010
1011        INPUT PARAMETERS
1012            XY      -   dataset, array[0..N-1,0..NX+NY-1].
1013                        one row corresponds to one point.
1014                        first NX columns contain X-values, next NY (NY may be zero)
1015                        columns may contain associated Y-values
1016            N       -   number of points, N>=1
1017            NX      -   space dimension, NX>=1.
1018            NY      -   number of optional Y-values, NY>=0.
1019            NormType-   norm type:
1020                        * 0 denotes infinity-norm
1021                        * 1 denotes 1-norm
1022                        * 2 denotes 2-norm (Euclidean norm)
1023                       
1024        OUTPUT PARAMETERS
1025            KDT     -   KD-tree
1026           
1027           
1028        NOTES
1029
1030        1. KD-tree  creation  have O(N*logN) complexity and O(N*(2*NX+NY))  memory
1031           requirements.
1032        2. Although KD-trees may be used with any combination of N  and  NX,  they
1033           are more efficient than brute-force search only when N >> 4^NX. So they
1034           are most useful in low-dimensional tasks (NX=2, NX=3). NX=1  is another
1035           inefficient case, because  simple  binary  search  (without  additional
1036           structures) is much more efficient in such tasks than KD-trees.
1037
1038          -- ALGLIB --
1039             Copyright 28.02.2010 by Bochkanov Sergey
1040        *************************************************************************/
1041        public static void kdtreebuild(double[,] xy,
1042            int n,
1043            int nx,
1044            int ny,
1045            int normtype,
1046            kdtree kdt)
1047        {
1048            int[] tags = new int[0];
1049            int i = 0;
1050
1051            ap.assert(n>=1, "KDTreeBuild: N<1!");
1052            ap.assert(nx>=1, "KDTreeBuild: NX<1!");
1053            ap.assert(ny>=0, "KDTreeBuild: NY<0!");
1054            ap.assert(normtype>=0 & normtype<=2, "KDTreeBuild: incorrect NormType!");
1055            ap.assert(ap.rows(xy)>=n, "KDTreeBuild: rows(X)<N!");
1056            ap.assert(ap.cols(xy)>=nx+ny, "KDTreeBuild: cols(X)<NX+NY!");
1057            ap.assert(apserv.apservisfinitematrix(xy, n, nx+ny), "KDTreeBuild: X contains infinite or NaN values!");
1058            tags = new int[n];
1059            for(i=0; i<=n-1; i++)
1060            {
1061                tags[i] = 0;
1062            }
1063            kdtreebuildtagged(xy, tags, n, nx, ny, normtype, kdt);
1064        }
1065
1066
1067        /*************************************************************************
1068        KD-tree creation
1069
1070        This  subroutine  creates  KD-tree  from set of X-values, integer tags and
1071        optional Y-values
1072
1073        INPUT PARAMETERS
1074            XY      -   dataset, array[0..N-1,0..NX+NY-1].
1075                        one row corresponds to one point.
1076                        first NX columns contain X-values, next NY (NY may be zero)
1077                        columns may contain associated Y-values
1078            Tags    -   tags, array[0..N-1], contains integer tags associated
1079                        with points.
1080            N       -   number of points, N>=1
1081            NX      -   space dimension, NX>=1.
1082            NY      -   number of optional Y-values, NY>=0.
1083            NormType-   norm type:
1084                        * 0 denotes infinity-norm
1085                        * 1 denotes 1-norm
1086                        * 2 denotes 2-norm (Euclidean norm)
1087
1088        OUTPUT PARAMETERS
1089            KDT     -   KD-tree
1090
1091        NOTES
1092
1093        1. KD-tree  creation  have O(N*logN) complexity and O(N*(2*NX+NY))  memory
1094           requirements.
1095        2. Although KD-trees may be used with any combination of N  and  NX,  they
1096           are more efficient than brute-force search only when N >> 4^NX. So they
1097           are most useful in low-dimensional tasks (NX=2, NX=3). NX=1  is another
1098           inefficient case, because  simple  binary  search  (without  additional
1099           structures) is much more efficient in such tasks than KD-trees.
1100
1101          -- ALGLIB --
1102             Copyright 28.02.2010 by Bochkanov Sergey
1103        *************************************************************************/
1104        public static void kdtreebuildtagged(double[,] xy,
1105            int[] tags,
1106            int n,
1107            int nx,
1108            int ny,
1109            int normtype,
1110            kdtree kdt)
1111        {
1112            int i = 0;
1113            int j = 0;
1114            int maxnodes = 0;
1115            int nodesoffs = 0;
1116            int splitsoffs = 0;
1117            int i_ = 0;
1118            int i1_ = 0;
1119
1120            ap.assert(n>=1, "KDTreeBuildTagged: N<1!");
1121            ap.assert(nx>=1, "KDTreeBuildTagged: NX<1!");
1122            ap.assert(ny>=0, "KDTreeBuildTagged: NY<0!");
1123            ap.assert(normtype>=0 & normtype<=2, "KDTreeBuildTagged: incorrect NormType!");
1124            ap.assert(ap.rows(xy)>=n, "KDTreeBuildTagged: rows(X)<N!");
1125            ap.assert(ap.cols(xy)>=nx+ny, "KDTreeBuildTagged: cols(X)<NX+NY!");
1126            ap.assert(apserv.apservisfinitematrix(xy, n, nx+ny), "KDTreeBuildTagged: X contains infinite or NaN values!");
1127           
1128            //
1129            // initialize
1130            //
1131            kdt.n = n;
1132            kdt.nx = nx;
1133            kdt.ny = ny;
1134            kdt.normtype = normtype;
1135            kdt.distmatrixtype = 0;
1136            kdt.xy = new double[n, 2*nx+ny];
1137            kdt.tags = new int[n];
1138            kdt.idx = new int[n];
1139            kdt.r = new double[n];
1140            kdt.x = new double[nx];
1141            kdt.buf = new double[Math.Max(n, nx)];
1142           
1143            //
1144            // Initial fill
1145            //
1146            for(i=0; i<=n-1; i++)
1147            {
1148                for(i_=0; i_<=nx-1;i_++)
1149                {
1150                    kdt.xy[i,i_] = xy[i,i_];
1151                }
1152                i1_ = (0) - (nx);
1153                for(i_=nx; i_<=2*nx+ny-1;i_++)
1154                {
1155                    kdt.xy[i,i_] = xy[i,i_+i1_];
1156                }
1157                kdt.tags[i] = tags[i];
1158            }
1159           
1160            //
1161            // Determine bounding box
1162            //
1163            kdt.boxmin = new double[nx];
1164            kdt.boxmax = new double[nx];
1165            kdt.curboxmin = new double[nx];
1166            kdt.curboxmax = new double[nx];
1167            for(i_=0; i_<=nx-1;i_++)
1168            {
1169                kdt.boxmin[i_] = kdt.xy[0,i_];
1170            }
1171            for(i_=0; i_<=nx-1;i_++)
1172            {
1173                kdt.boxmax[i_] = kdt.xy[0,i_];
1174            }
1175            for(i=1; i<=n-1; i++)
1176            {
1177                for(j=0; j<=nx-1; j++)
1178                {
1179                    kdt.boxmin[j] = Math.Min(kdt.boxmin[j], kdt.xy[i,j]);
1180                    kdt.boxmax[j] = Math.Max(kdt.boxmax[j], kdt.xy[i,j]);
1181                }
1182            }
1183           
1184            //
1185            // prepare tree structure
1186            // * MaxNodes=N because we guarantee no trivial splits, i.e.
1187            //   every split will generate two non-empty boxes
1188            //
1189            maxnodes = n;
1190            kdt.nodes = new int[splitnodesize*2*maxnodes];
1191            kdt.splits = new double[2*maxnodes];
1192            nodesoffs = 0;
1193            splitsoffs = 0;
1194            for(i_=0; i_<=nx-1;i_++)
1195            {
1196                kdt.curboxmin[i_] = kdt.boxmin[i_];
1197            }
1198            for(i_=0; i_<=nx-1;i_++)
1199            {
1200                kdt.curboxmax[i_] = kdt.boxmax[i_];
1201            }
1202            kdtreegeneratetreerec(kdt, ref nodesoffs, ref splitsoffs, 0, n, 8);
1203           
1204            //
1205            // Set current query size to 0
1206            //
1207            kdt.kcur = 0;
1208        }
1209
1210
1211        /*************************************************************************
1212        K-NN query: K nearest neighbors
1213
1214        INPUT PARAMETERS
1215            KDT         -   KD-tree
1216            X           -   point, array[0..NX-1].
1217            K           -   number of neighbors to return, K>=1
1218            SelfMatch   -   whether self-matches are allowed:
1219                            * if True, nearest neighbor may be the point itself
1220                              (if it exists in original dataset)
1221                            * if False, then only points with non-zero distance
1222                              are returned
1223                            * if not given, considered True
1224
1225        RESULT
1226            number of actual neighbors found (either K or N, if K>N).
1227
1228        This  subroutine  performs  query  and  stores  its result in the internal
1229        structures of the KD-tree. You can use  following  subroutines  to  obtain
1230        these results:
1231        * KDTreeQueryResultsX() to get X-values
1232        * KDTreeQueryResultsXY() to get X- and Y-values
1233        * KDTreeQueryResultsTags() to get tag values
1234        * KDTreeQueryResultsDistances() to get distances
1235
1236          -- ALGLIB --
1237             Copyright 28.02.2010 by Bochkanov Sergey
1238        *************************************************************************/
1239        public static int kdtreequeryknn(kdtree kdt,
1240            double[] x,
1241            int k,
1242            bool selfmatch)
1243        {
1244            int result = 0;
1245
1246            ap.assert(k>=1, "KDTreeQueryKNN: K<1!");
1247            ap.assert(ap.len(x)>=kdt.nx, "KDTreeQueryKNN: Length(X)<NX!");
1248            ap.assert(apserv.isfinitevector(x, kdt.nx), "KDTreeQueryKNN: X contains infinite or NaN values!");
1249            result = kdtreequeryaknn(kdt, x, k, selfmatch, 0.0);
1250            return result;
1251        }
1252
1253
1254        /*************************************************************************
1255        R-NN query: all points within R-sphere centered at X
1256
1257        INPUT PARAMETERS
1258            KDT         -   KD-tree
1259            X           -   point, array[0..NX-1].
1260            R           -   radius of sphere (in corresponding norm), R>0
1261            SelfMatch   -   whether self-matches are allowed:
1262                            * if True, nearest neighbor may be the point itself
1263                              (if it exists in original dataset)
1264                            * if False, then only points with non-zero distance
1265                              are returned
1266                            * if not given, considered True
1267
1268        RESULT
1269            number of neighbors found, >=0
1270
1271        This  subroutine  performs  query  and  stores  its result in the internal
1272        structures of the KD-tree. You can use  following  subroutines  to  obtain
1273        actual results:
1274        * KDTreeQueryResultsX() to get X-values
1275        * KDTreeQueryResultsXY() to get X- and Y-values
1276        * KDTreeQueryResultsTags() to get tag values
1277        * KDTreeQueryResultsDistances() to get distances
1278
1279          -- ALGLIB --
1280             Copyright 28.02.2010 by Bochkanov Sergey
1281        *************************************************************************/
1282        public static int kdtreequeryrnn(kdtree kdt,
1283            double[] x,
1284            double r,
1285            bool selfmatch)
1286        {
1287            int result = 0;
1288            int i = 0;
1289            int j = 0;
1290
1291            ap.assert((double)(r)>(double)(0), "KDTreeQueryRNN: incorrect R!");
1292            ap.assert(ap.len(x)>=kdt.nx, "KDTreeQueryRNN: Length(X)<NX!");
1293            ap.assert(apserv.isfinitevector(x, kdt.nx), "KDTreeQueryRNN: X contains infinite or NaN values!");
1294           
1295            //
1296            // Prepare parameters
1297            //
1298            kdt.kneeded = 0;
1299            if( kdt.normtype!=2 )
1300            {
1301                kdt.rneeded = r;
1302            }
1303            else
1304            {
1305                kdt.rneeded = math.sqr(r);
1306            }
1307            kdt.selfmatch = selfmatch;
1308            kdt.approxf = 1;
1309            kdt.kcur = 0;
1310           
1311            //
1312            // calculate distance from point to current bounding box
1313            //
1314            kdtreeinitbox(kdt, x);
1315           
1316            //
1317            // call recursive search
1318            // results are returned as heap
1319            //
1320            kdtreequerynnrec(kdt, 0);
1321           
1322            //
1323            // pop from heap to generate ordered representation
1324            //
1325            // last element is not pop'ed because it is already in
1326            // its place
1327            //
1328            result = kdt.kcur;
1329            j = kdt.kcur;
1330            for(i=kdt.kcur; i>=2; i--)
1331            {
1332                tsort.tagheappopi(ref kdt.r, ref kdt.idx, ref j);
1333            }
1334            return result;
1335        }
1336
1337
1338        /*************************************************************************
1339        K-NN query: approximate K nearest neighbors
1340
1341        INPUT PARAMETERS
1342            KDT         -   KD-tree
1343            X           -   point, array[0..NX-1].
1344            K           -   number of neighbors to return, K>=1
1345            SelfMatch   -   whether self-matches are allowed:
1346                            * if True, nearest neighbor may be the point itself
1347                              (if it exists in original dataset)
1348                            * if False, then only points with non-zero distance
1349                              are returned
1350                            * if not given, considered True
1351            Eps         -   approximation factor, Eps>=0. eps-approximate  nearest
1352                            neighbor  is  a  neighbor  whose distance from X is at
1353                            most (1+eps) times distance of true nearest neighbor.
1354
1355        RESULT
1356            number of actual neighbors found (either K or N, if K>N).
1357           
1358        NOTES
1359            significant performance gain may be achieved only when Eps  is  is  on
1360            the order of magnitude of 1 or larger.
1361
1362        This  subroutine  performs  query  and  stores  its result in the internal
1363        structures of the KD-tree. You can use  following  subroutines  to  obtain
1364        these results:
1365        * KDTreeQueryResultsX() to get X-values
1366        * KDTreeQueryResultsXY() to get X- and Y-values
1367        * KDTreeQueryResultsTags() to get tag values
1368        * KDTreeQueryResultsDistances() to get distances
1369
1370          -- ALGLIB --
1371             Copyright 28.02.2010 by Bochkanov Sergey
1372        *************************************************************************/
1373        public static int kdtreequeryaknn(kdtree kdt,
1374            double[] x,
1375            int k,
1376            bool selfmatch,
1377            double eps)
1378        {
1379            int result = 0;
1380            int i = 0;
1381            int j = 0;
1382
1383            ap.assert(k>0, "KDTreeQueryAKNN: incorrect K!");
1384            ap.assert((double)(eps)>=(double)(0), "KDTreeQueryAKNN: incorrect Eps!");
1385            ap.assert(ap.len(x)>=kdt.nx, "KDTreeQueryAKNN: Length(X)<NX!");
1386            ap.assert(apserv.isfinitevector(x, kdt.nx), "KDTreeQueryAKNN: X contains infinite or NaN values!");
1387           
1388            //
1389            // Prepare parameters
1390            //
1391            k = Math.Min(k, kdt.n);
1392            kdt.kneeded = k;
1393            kdt.rneeded = 0;
1394            kdt.selfmatch = selfmatch;
1395            if( kdt.normtype==2 )
1396            {
1397                kdt.approxf = 1/math.sqr(1+eps);
1398            }
1399            else
1400            {
1401                kdt.approxf = 1/(1+eps);
1402            }
1403            kdt.kcur = 0;
1404           
1405            //
1406            // calculate distance from point to current bounding box
1407            //
1408            kdtreeinitbox(kdt, x);
1409           
1410            //
1411            // call recursive search
1412            // results are returned as heap
1413            //
1414            kdtreequerynnrec(kdt, 0);
1415           
1416            //
1417            // pop from heap to generate ordered representation
1418            //
1419            // last element is non pop'ed because it is already in
1420            // its place
1421            //
1422            result = kdt.kcur;
1423            j = kdt.kcur;
1424            for(i=kdt.kcur; i>=2; i--)
1425            {
1426                tsort.tagheappopi(ref kdt.r, ref kdt.idx, ref j);
1427            }
1428            return result;
1429        }
1430
1431
1432        /*************************************************************************
1433        X-values from last query
1434
1435        INPUT PARAMETERS
1436            KDT     -   KD-tree
1437            X       -   possibly pre-allocated buffer. If X is too small to store
1438                        result, it is resized. If size(X) is enough to store
1439                        result, it is left unchanged.
1440
1441        OUTPUT PARAMETERS
1442            X       -   rows are filled with X-values
1443
1444        NOTES
1445        1. points are ordered by distance from the query point (first = closest)
1446        2. if  XY is larger than required to store result, only leading part  will
1447           be overwritten; trailing part will be left unchanged. So  if  on  input
1448           XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
1449           XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
1450           you want function  to  resize  array  according  to  result  size,  use
1451           function with same name and suffix 'I'.
1452
1453        SEE ALSO
1454        * KDTreeQueryResultsXY()            X- and Y-values
1455        * KDTreeQueryResultsTags()          tag values
1456        * KDTreeQueryResultsDistances()     distances
1457
1458          -- ALGLIB --
1459             Copyright 28.02.2010 by Bochkanov Sergey
1460        *************************************************************************/
1461        public static void kdtreequeryresultsx(kdtree kdt,
1462            ref double[,] x)
1463        {
1464            int i = 0;
1465            int k = 0;
1466            int i_ = 0;
1467            int i1_ = 0;
1468
1469            if( kdt.kcur==0 )
1470            {
1471                return;
1472            }
1473            if( ap.rows(x)<kdt.kcur | ap.cols(x)<kdt.nx )
1474            {
1475                x = new double[kdt.kcur, kdt.nx];
1476            }
1477            k = kdt.kcur;
1478            for(i=0; i<=k-1; i++)
1479            {
1480                i1_ = (kdt.nx) - (0);
1481                for(i_=0; i_<=kdt.nx-1;i_++)
1482                {
1483                    x[i,i_] = kdt.xy[kdt.idx[i],i_+i1_];
1484                }
1485            }
1486        }
1487
1488
1489        /*************************************************************************
1490        X- and Y-values from last query
1491
1492        INPUT PARAMETERS
1493            KDT     -   KD-tree
1494            XY      -   possibly pre-allocated buffer. If XY is too small to store
1495                        result, it is resized. If size(XY) is enough to store
1496                        result, it is left unchanged.
1497
1498        OUTPUT PARAMETERS
1499            XY      -   rows are filled with points: first NX columns with
1500                        X-values, next NY columns - with Y-values.
1501
1502        NOTES
1503        1. points are ordered by distance from the query point (first = closest)
1504        2. if  XY is larger than required to store result, only leading part  will
1505           be overwritten; trailing part will be left unchanged. So  if  on  input
1506           XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
1507           XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
1508           you want function  to  resize  array  according  to  result  size,  use
1509           function with same name and suffix 'I'.
1510
1511        SEE ALSO
1512        * KDTreeQueryResultsX()             X-values
1513        * KDTreeQueryResultsTags()          tag values
1514        * KDTreeQueryResultsDistances()     distances
1515
1516          -- ALGLIB --
1517             Copyright 28.02.2010 by Bochkanov Sergey
1518        *************************************************************************/
1519        public static void kdtreequeryresultsxy(kdtree kdt,
1520            ref double[,] xy)
1521        {
1522            int i = 0;
1523            int k = 0;
1524            int i_ = 0;
1525            int i1_ = 0;
1526
1527            if( kdt.kcur==0 )
1528            {
1529                return;
1530            }
1531            if( ap.rows(xy)<kdt.kcur | ap.cols(xy)<kdt.nx+kdt.ny )
1532            {
1533                xy = new double[kdt.kcur, kdt.nx+kdt.ny];
1534            }
1535            k = kdt.kcur;
1536            for(i=0; i<=k-1; i++)
1537            {
1538                i1_ = (kdt.nx) - (0);
1539                for(i_=0; i_<=kdt.nx+kdt.ny-1;i_++)
1540                {
1541                    xy[i,i_] = kdt.xy[kdt.idx[i],i_+i1_];
1542                }
1543            }
1544        }
1545
1546
1547        /*************************************************************************
1548        Tags from last query
1549
1550        INPUT PARAMETERS
1551            KDT     -   KD-tree
1552            Tags    -   possibly pre-allocated buffer. If X is too small to store
1553                        result, it is resized. If size(X) is enough to store
1554                        result, it is left unchanged.
1555
1556        OUTPUT PARAMETERS
1557            Tags    -   filled with tags associated with points,
1558                        or, when no tags were supplied, with zeros
1559
1560        NOTES
1561        1. points are ordered by distance from the query point (first = closest)
1562        2. if  XY is larger than required to store result, only leading part  will
1563           be overwritten; trailing part will be left unchanged. So  if  on  input
1564           XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
1565           XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
1566           you want function  to  resize  array  according  to  result  size,  use
1567           function with same name and suffix 'I'.
1568
1569        SEE ALSO
1570        * KDTreeQueryResultsX()             X-values
1571        * KDTreeQueryResultsXY()            X- and Y-values
1572        * KDTreeQueryResultsDistances()     distances
1573
1574          -- ALGLIB --
1575             Copyright 28.02.2010 by Bochkanov Sergey
1576        *************************************************************************/
1577        public static void kdtreequeryresultstags(kdtree kdt,
1578            ref int[] tags)
1579        {
1580            int i = 0;
1581            int k = 0;
1582
1583            if( kdt.kcur==0 )
1584            {
1585                return;
1586            }
1587            if( ap.len(tags)<kdt.kcur )
1588            {
1589                tags = new int[kdt.kcur];
1590            }
1591            k = kdt.kcur;
1592            for(i=0; i<=k-1; i++)
1593            {
1594                tags[i] = kdt.tags[kdt.idx[i]];
1595            }
1596        }
1597
1598
1599        /*************************************************************************
1600        Distances from last query
1601
1602        INPUT PARAMETERS
1603            KDT     -   KD-tree
1604            R       -   possibly pre-allocated buffer. If X is too small to store
1605                        result, it is resized. If size(X) is enough to store
1606                        result, it is left unchanged.
1607
1608        OUTPUT PARAMETERS
1609            R       -   filled with distances (in corresponding norm)
1610
1611        NOTES
1612        1. points are ordered by distance from the query point (first = closest)
1613        2. if  XY is larger than required to store result, only leading part  will
1614           be overwritten; trailing part will be left unchanged. So  if  on  input
1615           XY = [[A,B],[C,D]], and result is [1,2],  then  on  exit  we  will  get
1616           XY = [[1,2],[C,D]]. This is done purposely to increase performance;  if
1617           you want function  to  resize  array  according  to  result  size,  use
1618           function with same name and suffix 'I'.
1619
1620        SEE ALSO
1621        * KDTreeQueryResultsX()             X-values
1622        * KDTreeQueryResultsXY()            X- and Y-values
1623        * KDTreeQueryResultsTags()          tag values
1624
1625          -- ALGLIB --
1626             Copyright 28.02.2010 by Bochkanov Sergey
1627        *************************************************************************/
1628        public static void kdtreequeryresultsdistances(kdtree kdt,
1629            ref double[] r)
1630        {
1631            int i = 0;
1632            int k = 0;
1633
1634            if( kdt.kcur==0 )
1635            {
1636                return;
1637            }
1638            if( ap.len(r)<kdt.kcur )
1639            {
1640                r = new double[kdt.kcur];
1641            }
1642            k = kdt.kcur;
1643           
1644            //
1645            // unload norms
1646            //
1647            // Abs() call is used to handle cases with negative norms
1648            // (generated during KFN requests)
1649            //
1650            if( kdt.normtype==0 )
1651            {
1652                for(i=0; i<=k-1; i++)
1653                {
1654                    r[i] = Math.Abs(kdt.r[i]);
1655                }
1656            }
1657            if( kdt.normtype==1 )
1658            {
1659                for(i=0; i<=k-1; i++)
1660                {
1661                    r[i] = Math.Abs(kdt.r[i]);
1662                }
1663            }
1664            if( kdt.normtype==2 )
1665            {
1666                for(i=0; i<=k-1; i++)
1667                {
1668                    r[i] = Math.Sqrt(Math.Abs(kdt.r[i]));
1669                }
1670            }
1671        }
1672
1673
1674        /*************************************************************************
1675        X-values from last query; 'interactive' variant for languages like  Python
1676        which   support    constructs   like  "X = KDTreeQueryResultsXI(KDT)"  and
1677        interactive mode of interpreter.
1678
1679        This function allocates new array on each call,  so  it  is  significantly
1680        slower than its 'non-interactive' counterpart, but it is  more  convenient
1681        when you call it from command line.
1682
1683          -- ALGLIB --
1684             Copyright 28.02.2010 by Bochkanov Sergey
1685        *************************************************************************/
1686        public static void kdtreequeryresultsxi(kdtree kdt,
1687            ref double[,] x)
1688        {
1689            x = new double[0,0];
1690
1691            kdtreequeryresultsx(kdt, ref x);
1692        }
1693
1694
1695        /*************************************************************************
1696        XY-values from last query; 'interactive' variant for languages like Python
1697        which   support    constructs   like "XY = KDTreeQueryResultsXYI(KDT)" and
1698        interactive mode of interpreter.
1699
1700        This function allocates new array on each call,  so  it  is  significantly
1701        slower than its 'non-interactive' counterpart, but it is  more  convenient
1702        when you call it from command line.
1703
1704          -- ALGLIB --
1705             Copyright 28.02.2010 by Bochkanov Sergey
1706        *************************************************************************/
1707        public static void kdtreequeryresultsxyi(kdtree kdt,
1708            ref double[,] xy)
1709        {
1710            xy = new double[0,0];
1711
1712            kdtreequeryresultsxy(kdt, ref xy);
1713        }
1714
1715
1716        /*************************************************************************
1717        Tags  from  last  query;  'interactive' variant for languages like  Python
1718        which  support  constructs  like "Tags = KDTreeQueryResultsTagsI(KDT)" and
1719        interactive mode of interpreter.
1720
1721        This function allocates new array on each call,  so  it  is  significantly
1722        slower than its 'non-interactive' counterpart, but it is  more  convenient
1723        when you call it from command line.
1724
1725          -- ALGLIB --
1726             Copyright 28.02.2010 by Bochkanov Sergey
1727        *************************************************************************/
1728        public static void kdtreequeryresultstagsi(kdtree kdt,
1729            ref int[] tags)
1730        {
1731            tags = new int[0];
1732
1733            kdtreequeryresultstags(kdt, ref tags);
1734        }
1735
1736
1737        /*************************************************************************
1738        Distances from last query; 'interactive' variant for languages like Python
1739        which  support  constructs   like  "R = KDTreeQueryResultsDistancesI(KDT)"
1740        and interactive mode of interpreter.
1741
1742        This function allocates new array on each call,  so  it  is  significantly
1743        slower than its 'non-interactive' counterpart, but it is  more  convenient
1744        when you call it from command line.
1745
1746          -- ALGLIB --
1747             Copyright 28.02.2010 by Bochkanov Sergey
1748        *************************************************************************/
1749        public static void kdtreequeryresultsdistancesi(kdtree kdt,
1750            ref double[] r)
1751        {
1752            r = new double[0];
1753
1754            kdtreequeryresultsdistances(kdt, ref r);
1755        }
1756
1757
1758        /*************************************************************************
1759        Rearranges nodes [I1,I2) using partition in D-th dimension with S as threshold.
1760        Returns split position I3: [I1,I3) and [I3,I2) are created as result.
1761
1762        This subroutine doesn't create tree structures, just rearranges nodes.
1763        *************************************************************************/
1764        private static void kdtreesplit(kdtree kdt,
1765            int i1,
1766            int i2,
1767            int d,
1768            double s,
1769            ref int i3)
1770        {
1771            int i = 0;
1772            int j = 0;
1773            int ileft = 0;
1774            int iright = 0;
1775            double v = 0;
1776
1777            i3 = 0;
1778
1779           
1780            //
1781            // split XY/Tags in two parts:
1782            // * [ILeft,IRight] is non-processed part of XY/Tags
1783            //
1784            // After cycle is done, we have Ileft=IRight. We deal with
1785            // this element separately.
1786            //
1787            // After this, [I1,ILeft) contains left part, and [ILeft,I2)
1788            // contains right part.
1789            //
1790            ileft = i1;
1791            iright = i2-1;
1792            while( ileft<iright )
1793            {
1794                if( (double)(kdt.xy[ileft,d])<=(double)(s) )
1795                {
1796                   
1797                    //
1798                    // XY[ILeft] is on its place.
1799                    // Advance ILeft.
1800                    //
1801                    ileft = ileft+1;
1802                }
1803                else
1804                {
1805                   
1806                    //
1807                    // XY[ILeft,..] must be at IRight.
1808                    // Swap and advance IRight.
1809                    //
1810                    for(i=0; i<=2*kdt.nx+kdt.ny-1; i++)
1811                    {
1812                        v = kdt.xy[ileft,i];
1813                        kdt.xy[ileft,i] = kdt.xy[iright,i];
1814                        kdt.xy[iright,i] = v;
1815                    }
1816                    j = kdt.tags[ileft];
1817                    kdt.tags[ileft] = kdt.tags[iright];
1818                    kdt.tags[iright] = j;
1819                    iright = iright-1;
1820                }
1821            }
1822            if( (double)(kdt.xy[ileft,d])<=(double)(s) )
1823            {
1824                ileft = ileft+1;
1825            }
1826            else
1827            {
1828                iright = iright-1;
1829            }
1830            i3 = ileft;
1831        }
1832
1833
1834        /*************************************************************************
1835        Recursive kd-tree generation subroutine.
1836
1837        PARAMETERS
1838            KDT         tree
1839            NodesOffs   unused part of Nodes[] which must be filled by tree
1840            SplitsOffs  unused part of Splits[]
1841            I1, I2      points from [I1,I2) are processed
1842           
1843        NodesOffs[] and SplitsOffs[] must be large enough.
1844
1845          -- ALGLIB --
1846             Copyright 28.02.2010 by Bochkanov Sergey
1847        *************************************************************************/
1848        private static void kdtreegeneratetreerec(kdtree kdt,
1849            ref int nodesoffs,
1850            ref int splitsoffs,
1851            int i1,
1852            int i2,
1853            int maxleafsize)
1854        {
1855            int n = 0;
1856            int nx = 0;
1857            int ny = 0;
1858            int i = 0;
1859            int j = 0;
1860            int oldoffs = 0;
1861            int i3 = 0;
1862            int cntless = 0;
1863            int cntgreater = 0;
1864            double minv = 0;
1865            double maxv = 0;
1866            int minidx = 0;
1867            int maxidx = 0;
1868            int d = 0;
1869            double ds = 0;
1870            double s = 0;
1871            double v = 0;
1872            int i_ = 0;
1873            int i1_ = 0;
1874
1875            ap.assert(i2>i1, "KDTreeGenerateTreeRec: internal error");
1876           
1877            //
1878            // Generate leaf if needed
1879            //
1880            if( i2-i1<=maxleafsize )
1881            {
1882                kdt.nodes[nodesoffs+0] = i2-i1;
1883                kdt.nodes[nodesoffs+1] = i1;
1884                nodesoffs = nodesoffs+2;
1885                return;
1886            }
1887           
1888            //
1889            // Load values for easier access
1890            //
1891            nx = kdt.nx;
1892            ny = kdt.ny;
1893           
1894            //
1895            // select dimension to split:
1896            // * D is a dimension number
1897            //
1898            d = 0;
1899            ds = kdt.curboxmax[0]-kdt.curboxmin[0];
1900            for(i=1; i<=nx-1; i++)
1901            {
1902                v = kdt.curboxmax[i]-kdt.curboxmin[i];
1903                if( (double)(v)>(double)(ds) )
1904                {
1905                    ds = v;
1906                    d = i;
1907                }
1908            }
1909           
1910            //
1911            // Select split position S using sliding midpoint rule,
1912            // rearrange points into [I1,I3) and [I3,I2)
1913            //
1914            s = kdt.curboxmin[d]+0.5*ds;
1915            i1_ = (i1) - (0);
1916            for(i_=0; i_<=i2-i1-1;i_++)
1917            {
1918                kdt.buf[i_] = kdt.xy[i_+i1_,d];
1919            }
1920            n = i2-i1;
1921            cntless = 0;
1922            cntgreater = 0;
1923            minv = kdt.buf[0];
1924            maxv = kdt.buf[0];
1925            minidx = i1;
1926            maxidx = i1;
1927            for(i=0; i<=n-1; i++)
1928            {
1929                v = kdt.buf[i];
1930                if( (double)(v)<(double)(minv) )
1931                {
1932                    minv = v;
1933                    minidx = i1+i;
1934                }
1935                if( (double)(v)>(double)(maxv) )
1936                {
1937                    maxv = v;
1938                    maxidx = i1+i;
1939                }
1940                if( (double)(v)<(double)(s) )
1941                {
1942                    cntless = cntless+1;
1943                }
1944                if( (double)(v)>(double)(s) )
1945                {
1946                    cntgreater = cntgreater+1;
1947                }
1948            }
1949            if( cntless>0 & cntgreater>0 )
1950            {
1951               
1952                //
1953                // normal midpoint split
1954                //
1955                kdtreesplit(kdt, i1, i2, d, s, ref i3);
1956            }
1957            else
1958            {
1959               
1960                //
1961                // sliding midpoint
1962                //
1963                if( cntless==0 )
1964                {
1965                   
1966                    //
1967                    // 1. move split to MinV,
1968                    // 2. place one point to the left bin (move to I1),
1969                    //    others - to the right bin
1970                    //
1971                    s = minv;
1972                    if( minidx!=i1 )
1973                    {
1974                        for(i=0; i<=2*kdt.nx+kdt.ny-1; i++)
1975                        {
1976                            v = kdt.xy[minidx,i];
1977                            kdt.xy[minidx,i] = kdt.xy[i1,i];
1978                            kdt.xy[i1,i] = v;
1979                        }
1980                        j = kdt.tags[minidx];
1981                        kdt.tags[minidx] = kdt.tags[i1];
1982                        kdt.tags[i1] = j;
1983                    }
1984                    i3 = i1+1;
1985                }
1986                else
1987                {
1988                   
1989                    //
1990                    // 1. move split to MaxV,
1991                    // 2. place one point to the right bin (move to I2-1),
1992                    //    others - to the left bin
1993                    //
1994                    s = maxv;
1995                    if( maxidx!=i2-1 )
1996                    {
1997                        for(i=0; i<=2*kdt.nx+kdt.ny-1; i++)
1998                        {
1999                            v = kdt.xy[maxidx,i];
2000                            kdt.xy[maxidx,i] = kdt.xy[i2-1,i];
2001                            kdt.xy[i2-1,i] = v;
2002                        }
2003                        j = kdt.tags[maxidx];
2004                        kdt.tags[maxidx] = kdt.tags[i2-1];
2005                        kdt.tags[i2-1] = j;
2006                    }
2007                    i3 = i2-1;
2008                }
2009            }
2010           
2011            //
2012            // Generate 'split' node
2013            //
2014            kdt.nodes[nodesoffs+0] = 0;
2015            kdt.nodes[nodesoffs+1] = d;
2016            kdt.nodes[nodesoffs+2] = splitsoffs;
2017            kdt.splits[splitsoffs+0] = s;
2018            oldoffs = nodesoffs;
2019            nodesoffs = nodesoffs+splitnodesize;
2020            splitsoffs = splitsoffs+1;
2021           
2022            //
2023            // Recirsive generation:
2024            // * update CurBox
2025            // * call subroutine
2026            // * restore CurBox
2027            //
2028            kdt.nodes[oldoffs+3] = nodesoffs;
2029            v = kdt.curboxmax[d];
2030            kdt.curboxmax[d] = s;
2031            kdtreegeneratetreerec(kdt, ref nodesoffs, ref splitsoffs, i1, i3, maxleafsize);
2032            kdt.curboxmax[d] = v;
2033            kdt.nodes[oldoffs+4] = nodesoffs;
2034            v = kdt.curboxmin[d];
2035            kdt.curboxmin[d] = s;
2036            kdtreegeneratetreerec(kdt, ref nodesoffs, ref splitsoffs, i3, i2, maxleafsize);
2037            kdt.curboxmin[d] = v;
2038        }
2039
2040
2041        /*************************************************************************
2042        Recursive subroutine for NN queries.
2043
2044          -- ALGLIB --
2045             Copyright 28.02.2010 by Bochkanov Sergey
2046        *************************************************************************/
2047        private static void kdtreequerynnrec(kdtree kdt,
2048            int offs)
2049        {
2050            double ptdist = 0;
2051            int i = 0;
2052            int j = 0;
2053            int nx = 0;
2054            int i1 = 0;
2055            int i2 = 0;
2056            int d = 0;
2057            double s = 0;
2058            double v = 0;
2059            double t1 = 0;
2060            int childbestoffs = 0;
2061            int childworstoffs = 0;
2062            int childoffs = 0;
2063            double prevdist = 0;
2064            bool todive = new bool();
2065            bool bestisleft = new bool();
2066            bool updatemin = new bool();
2067
2068           
2069            //
2070            // Leaf node.
2071            // Process points.
2072            //
2073            if( kdt.nodes[offs]>0 )
2074            {
2075                i1 = kdt.nodes[offs+1];
2076                i2 = i1+kdt.nodes[offs];
2077                for(i=i1; i<=i2-1; i++)
2078                {
2079                   
2080                    //
2081                    // Calculate distance
2082                    //
2083                    ptdist = 0;
2084                    nx = kdt.nx;
2085                    if( kdt.normtype==0 )
2086                    {
2087                        for(j=0; j<=nx-1; j++)
2088                        {
2089                            ptdist = Math.Max(ptdist, Math.Abs(kdt.xy[i,j]-kdt.x[j]));
2090                        }
2091                    }
2092                    if( kdt.normtype==1 )
2093                    {
2094                        for(j=0; j<=nx-1; j++)
2095                        {
2096                            ptdist = ptdist+Math.Abs(kdt.xy[i,j]-kdt.x[j]);
2097                        }
2098                    }
2099                    if( kdt.normtype==2 )
2100                    {
2101                        for(j=0; j<=nx-1; j++)
2102                        {
2103                            ptdist = ptdist+math.sqr(kdt.xy[i,j]-kdt.x[j]);
2104                        }
2105                    }
2106                   
2107                    //
2108                    // Skip points with zero distance if self-matches are turned off
2109                    //
2110                    if( (double)(ptdist)==(double)(0) & !kdt.selfmatch )
2111                    {
2112                        continue;
2113                    }
2114                   
2115                    //
2116                    // We CAN'T process point if R-criterion isn't satisfied,
2117                    // i.e. (RNeeded<>0) AND (PtDist>R).
2118                    //
2119                    if( (double)(kdt.rneeded)==(double)(0) | (double)(ptdist)<=(double)(kdt.rneeded) )
2120                    {
2121                       
2122                        //
2123                        // R-criterion is satisfied, we must either:
2124                        // * replace worst point, if (KNeeded<>0) AND (KCur=KNeeded)
2125                        //   (or skip, if worst point is better)
2126                        // * add point without replacement otherwise
2127                        //
2128                        if( kdt.kcur<kdt.kneeded | kdt.kneeded==0 )
2129                        {
2130                           
2131                            //
2132                            // add current point to heap without replacement
2133                            //
2134                            tsort.tagheappushi(ref kdt.r, ref kdt.idx, ref kdt.kcur, ptdist, i);
2135                        }
2136                        else
2137                        {
2138                           
2139                            //
2140                            // New points are added or not, depending on their distance.
2141                            // If added, they replace element at the top of the heap
2142                            //
2143                            if( (double)(ptdist)<(double)(kdt.r[0]) )
2144                            {
2145                                if( kdt.kneeded==1 )
2146                                {
2147                                    kdt.idx[0] = i;
2148                                    kdt.r[0] = ptdist;
2149                                }
2150                                else
2151                                {
2152                                    tsort.tagheapreplacetopi(ref kdt.r, ref kdt.idx, kdt.kneeded, ptdist, i);
2153                                }
2154                            }
2155                        }
2156                    }
2157                }
2158                return;
2159            }
2160           
2161            //
2162            // Simple split
2163            //
2164            if( kdt.nodes[offs]==0 )
2165            {
2166               
2167                //
2168                // Load:
2169                // * D  dimension to split
2170                // * S  split position
2171                //
2172                d = kdt.nodes[offs+1];
2173                s = kdt.splits[kdt.nodes[offs+2]];
2174               
2175                //
2176                // Calculate:
2177                // * ChildBestOffs      child box with best chances
2178                // * ChildWorstOffs     child box with worst chances
2179                //
2180                if( (double)(kdt.x[d])<=(double)(s) )
2181                {
2182                    childbestoffs = kdt.nodes[offs+3];
2183                    childworstoffs = kdt.nodes[offs+4];
2184                    bestisleft = true;
2185                }
2186                else
2187                {
2188                    childbestoffs = kdt.nodes[offs+4];
2189                    childworstoffs = kdt.nodes[offs+3];
2190                    bestisleft = false;
2191                }
2192               
2193                //
2194                // Navigate through childs
2195                //
2196                for(i=0; i<=1; i++)
2197                {
2198                   
2199                    //
2200                    // Select child to process:
2201                    // * ChildOffs      current child offset in Nodes[]
2202                    // * UpdateMin      whether minimum or maximum value
2203                    //                  of bounding box is changed on update
2204                    //
2205                    if( i==0 )
2206                    {
2207                        childoffs = childbestoffs;
2208                        updatemin = !bestisleft;
2209                    }
2210                    else
2211                    {
2212                        updatemin = bestisleft;
2213                        childoffs = childworstoffs;
2214                    }
2215                   
2216                    //
2217                    // Update bounding box and current distance
2218                    //
2219                    if( updatemin )
2220                    {
2221                        prevdist = kdt.curdist;
2222                        t1 = kdt.x[d];
2223                        v = kdt.curboxmin[d];
2224                        if( (double)(t1)<=(double)(s) )
2225                        {
2226                            if( kdt.normtype==0 )
2227                            {
2228                                kdt.curdist = Math.Max(kdt.curdist, s-t1);
2229                            }
2230                            if( kdt.normtype==1 )
2231                            {
2232                                kdt.curdist = kdt.curdist-Math.Max(v-t1, 0)+s-t1;
2233                            }
2234                            if( kdt.normtype==2 )
2235                            {
2236                                kdt.curdist = kdt.curdist-math.sqr(Math.Max(v-t1, 0))+math.sqr(s-t1);
2237                            }
2238                        }
2239                        kdt.curboxmin[d] = s;
2240                    }
2241                    else
2242                    {
2243                        prevdist = kdt.curdist;
2244                        t1 = kdt.x[d];
2245                        v = kdt.curboxmax[d];
2246                        if( (double)(t1)>=(double)(s) )
2247                        {
2248                            if( kdt.normtype==0 )
2249                            {
2250                                kdt.curdist = Math.Max(kdt.curdist, t1-s);
2251                            }
2252                            if( kdt.normtype==1 )
2253                            {
2254                                kdt.curdist = kdt.curdist-Math.Max(t1-v, 0)+t1-s;
2255                            }
2256                            if( kdt.normtype==2 )
2257                            {
2258                                kdt.curdist = kdt.curdist-math.sqr(Math.Max(t1-v, 0))+math.sqr(t1-s);
2259                            }
2260                        }
2261                        kdt.curboxmax[d] = s;
2262                    }
2263                   
2264                    //
2265                    // Decide: to dive into cell or not to dive
2266                    //
2267                    if( (double)(kdt.rneeded)!=(double)(0) & (double)(kdt.curdist)>(double)(kdt.rneeded) )
2268                    {
2269                        todive = false;
2270                    }
2271                    else
2272                    {
2273                        if( kdt.kcur<kdt.kneeded | kdt.kneeded==0 )
2274                        {
2275                           
2276                            //
2277                            // KCur<KNeeded (i.e. not all points are found)
2278                            //
2279                            todive = true;
2280                        }
2281                        else
2282                        {
2283                           
2284                            //
2285                            // KCur=KNeeded, decide to dive or not to dive
2286                            // using point position relative to bounding box.
2287                            //
2288                            todive = (double)(kdt.curdist)<=(double)(kdt.r[0]*kdt.approxf);
2289                        }
2290                    }
2291                    if( todive )
2292                    {
2293                        kdtreequerynnrec(kdt, childoffs);
2294                    }
2295                   
2296                    //
2297                    // Restore bounding box and distance
2298                    //
2299                    if( updatemin )
2300                    {
2301                        kdt.curboxmin[d] = v;
2302                    }
2303                    else
2304                    {
2305                        kdt.curboxmax[d] = v;
2306                    }
2307                    kdt.curdist = prevdist;
2308                }
2309                return;
2310            }
2311        }
2312
2313
2314        /*************************************************************************
2315        Copies X[] to KDT.X[]
2316        Loads distance from X[] to bounding box.
2317        Initializes CurBox[].
2318
2319          -- ALGLIB --
2320             Copyright 28.02.2010 by Bochkanov Sergey
2321        *************************************************************************/
2322        private static void kdtreeinitbox(kdtree kdt,
2323            double[] x)
2324        {
2325            int i = 0;
2326            double vx = 0;
2327            double vmin = 0;
2328            double vmax = 0;
2329
2330           
2331            //
2332            // calculate distance from point to current bounding box
2333            //
2334            kdt.curdist = 0;
2335            if( kdt.normtype==0 )
2336            {
2337                for(i=0; i<=kdt.nx-1; i++)
2338                {
2339                    vx = x[i];
2340                    vmin = kdt.boxmin[i];
2341                    vmax = kdt.boxmax[i];
2342                    kdt.x[i] = vx;
2343                    kdt.curboxmin[i] = vmin;
2344                    kdt.curboxmax[i] = vmax;
2345                    if( (double)(vx)<(double)(vmin) )
2346                    {
2347                        kdt.curdist = Math.Max(kdt.curdist, vmin-vx);
2348                    }
2349                    else
2350                    {
2351                        if( (double)(vx)>(double)(vmax) )
2352                        {
2353                            kdt.curdist = Math.Max(kdt.curdist, vx-vmax);
2354                        }
2355                    }
2356                }
2357            }
2358            if( kdt.normtype==1 )
2359            {
2360                for(i=0; i<=kdt.nx-1; i++)
2361                {
2362                    vx = x[i];
2363                    vmin = kdt.boxmin[i];
2364                    vmax = kdt.boxmax[i];
2365                    kdt.x[i] = vx;
2366                    kdt.curboxmin[i] = vmin;
2367                    kdt.curboxmax[i] = vmax;
2368                    if( (double)(vx)<(double)(vmin) )
2369                    {
2370                        kdt.curdist = kdt.curdist+vmin-vx;
2371                    }
2372                    else
2373                    {
2374                        if( (double)(vx)>(double)(vmax) )
2375                        {
2376                            kdt.curdist = kdt.curdist+vx-vmax;
2377                        }
2378                    }
2379                }
2380            }
2381            if( kdt.normtype==2 )
2382            {
2383                for(i=0; i<=kdt.nx-1; i++)
2384                {
2385                    vx = x[i];
2386                    vmin = kdt.boxmin[i];
2387                    vmax = kdt.boxmax[i];
2388                    kdt.x[i] = vx;
2389                    kdt.curboxmin[i] = vmin;
2390                    kdt.curboxmax[i] = vmax;
2391                    if( (double)(vx)<(double)(vmin) )
2392                    {
2393                        kdt.curdist = kdt.curdist+math.sqr(vmin-vx);
2394                    }
2395                    else
2396                    {
2397                        if( (double)(vx)>(double)(vmax) )
2398                        {
2399                            kdt.curdist = kdt.curdist+math.sqr(vx-vmax);
2400                        }
2401                    }
2402                }
2403            }
2404        }
2405
2406
2407    }
2408}
2409
Note: See TracBrowser for help on using the repository browser.