From 518f2373fa2093d45f24e7de19f9efd9f8f50483 Mon Sep 17 00:00:00 2001 From: Vlad Morariu Date: Thu, 22 Dec 2011 22:42:44 -0500 Subject: [PATCH] Added figtree-0.9.2 to git repository. Signed-off-by: Vlad Morariu --- Makefile | 2 +- external/Makefile | 22 + external/ann_1.1.1/Copyright.txt | 47 + external/ann_1.1.1/License.txt | 450 ++ external/ann_1.1.1/MS_Win32/Ann.sln | 46 + external/ann_1.1.1/MS_Win32/Ann.sln.old | 48 + external/ann_1.1.1/MS_Win32/Makefile | 53 + .../ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj | 75 +- .../MS_Win32/ann2fig/ann2fig.vcproj.7.10.old | 134 + external/ann_1.1.1/MS_Win32/dll/dll.vcproj | 592 ++ .../MS_Win32/dll/dll.vcproj.7.10.old | 452 ++ .../ann_1.1.1/MS_Win32/sample/sample.vcproj | 271 + .../MS_Win32/sample/sample.vcproj.7.10.old | 194 + external/ann_1.1.1/MS_Win32/test/test.vcproj | 302 + .../MS_Win32/test/test.vcproj.7.10.old | 220 + external/ann_1.1.1/Make-config | 208 + external/ann_1.1.1/Makefile | 114 + external/ann_1.1.1/ReadMe.txt | 75 + external/ann_1.1.1/ann2fig/Makefile | 87 + external/ann_1.1.1/ann2fig/ann2fig.cpp | 585 ++ external/ann_1.1.1/doc/ANNmanual.pdf | Bin 0 -> 357854 bytes external/ann_1.1.1/include/ANN/ANN.h | 855 +++ external/ann_1.1.1/include/ANN/ANNperf.h | 228 + external/ann_1.1.1/include/ANN/ANNx.h | 167 + external/ann_1.1.1/sample/Makefile | 90 + external/ann_1.1.1/sample/ann_sample.cpp | 198 + external/ann_1.1.1/sample/data.pts | 20 + external/ann_1.1.1/sample/query.pts | 10 + external/ann_1.1.1/sample/sample.save | 51 + external/ann_1.1.1/src/ANN.cpp | 198 + external/ann_1.1.1/src/Makefile | 121 + external/ann_1.1.1/src/bd_fix_rad_search.cpp | 90 + external/ann_1.1.1/src/bd_pr_search.cpp | 62 + external/ann_1.1.1/src/bd_search.cpp | 61 + external/ann_1.1.1/src/bd_tree.cpp | 417 ++ external/ann_1.1.1/src/bd_tree.h | 103 + external/ann_1.1.1/src/brute.cpp | 109 + external/ann_1.1.1/src/kd_dump.cpp | 444 ++ external/ann_1.1.1/src/kd_fix_rad_search.cpp | 465 ++ external/ann_1.1.1/src/kd_fix_rad_search.h | 44 + external/ann_1.1.1/src/kd_pr_search.cpp | 219 + external/ann_1.1.1/src/kd_pr_search.h | 49 + external/ann_1.1.1/src/kd_search.cpp | 210 + external/ann_1.1.1/src/kd_search.h | 48 + external/ann_1.1.1/src/kd_split.cpp | 428 ++ external/ann_1.1.1/src/kd_split.h | 85 + external/ann_1.1.1/src/kd_tree.cpp | 405 ++ external/ann_1.1.1/src/kd_tree.h | 206 + external/ann_1.1.1/src/kd_util.cpp | 471 ++ external/ann_1.1.1/src/kd_util.h | 133 + external/ann_1.1.1/src/perf.cpp | 134 + external/ann_1.1.1/src/pr_queue.h | 125 + external/ann_1.1.1/src/pr_queue_k.h | 138 + external/ann_1.1.1/test/Makefile | 96 + external/ann_1.1.1/test/ann_test.cpp | 1640 ++++++ external/ann_1.1.1/test/rand.cpp | 594 ++ external/ann_1.1.1/test/rand.h | 131 + external/ann_1.1.1/test/test1-data.pts | 20 + external/ann_1.1.1/test/test1-query.pts | 10 + external/ann_1.1.1/test/test1.in | 15 + external/ann_1.1.1/test/test1.save | 76 + external/ann_1.1.1/test/test2-data.pts | 5000 +++++++++++++++++ external/ann_1.1.1/test/test2-query.pts | 100 + external/ann_1.1.1/test/test2.in | 21 + external/ann_1.1.1/test/test2.save | 156 + include/figtree.h | 353 +- matlab/CompileMexFilesUsingMatlab.m | 74 +- matlab/figtree.m | 122 +- matlab/figtreeChooseEvaluationMethod.m | 46 + matlab/figtreeChooseParametersNonUniform.m | 42 - matlab/figtreeChooseParametersUniform.m | 39 - matlab/figtreeChooseTruncationNumber.m | 37 - matlab/figtreeEvaluateDirect.m | 30 - matlab/figtreeEvaluateDirectTree.m | 43 - matlab/figtreeEvaluateIfgt.m | 50 - matlab/figtreeEvaluateIfgtTree.m | 41 - matlab/figtreeKCenterClustering.m | 58 +- readme.txt | 304 +- samples/Makefile | 6 +- samples/matlab_sample1_shift_scale.m | 281 - samples/matlab_sample1_simple.m | 94 + samples/matlab_sample2.m | 173 - ...ample1.m => matlab_sample2_diff_methods.m} | 83 +- samples/matlab_sample3.m | 159 - samples/matlab_sample3_auto_selection.m | 180 + src/KCenterClustering.h | 1 - src/Makefile | 13 +- src/figtree.cpp | 2373 +++++++- src/figtree_internal.h | 341 ++ src/mex/mexFigtree.cpp | 102 +- ...p => mexFigtreeChooseEvaluationMethod.cpp} | 107 +- src/mex/mexFigtreeChooseEvaluationMethod.def | 2 + .../mexFigtreeChooseParametersNonUniform.cpp | 145 - .../mexFigtreeChooseParametersNonUniform.def | 2 - src/mex/mexFigtreeChooseParametersUniform.cpp | 127 - src/mex/mexFigtreeChooseParametersUniform.def | 2 - src/mex/mexFigtreeChooseTruncationNumber.cpp | 125 - src/mex/mexFigtreeChooseTruncationNumber.def | 2 - src/mex/mexFigtreeEvaluateDirect.cpp | 129 - src/mex/mexFigtreeEvaluateDirect.def | 2 - src/mex/mexFigtreeEvaluateDirectTree.def | 2 - src/mex/mexFigtreeEvaluateIfgt.cpp | 194 - src/mex/mexFigtreeEvaluateIfgt.def | 2 - src/mex/mexFigtreeEvaluateIfgtTree.cpp | 194 - src/mex/mexFigtreeEvaluateIfgtTree.def | 2 - test/Makefile | 6 +- test/test.cpp | 127 +- vs8/figtree.sln | 54 +- vs8/figtree.vcproj | 12 +- vs8/mexFigtree.vcproj | 136 +- ...> mexFigtreeChooseEvaluationMethod.vcproj} | 146 +- ...exFigtreeChooseParametersNonUniform.vcproj | 229 - vs8/mexFigtreeChooseTruncationNumber.vcproj | 229 - vs8/mexFigtreeEvaluateDirect.vcproj | 229 - vs8/mexFigtreeEvaluateDirectAnn.vcproj | 229 - vs8/mexFigtreeEvaluateTruncatedAnn.vcproj | 229 - vs8/mexFigtreeKCenterClustering.vcproj | 18 +- 117 files changed, 21834 insertions(+), 4112 deletions(-) create mode 100644 external/Makefile create mode 100644 external/ann_1.1.1/Copyright.txt create mode 100644 external/ann_1.1.1/License.txt create mode 100644 external/ann_1.1.1/MS_Win32/Ann.sln create mode 100644 external/ann_1.1.1/MS_Win32/Ann.sln.old create mode 100644 external/ann_1.1.1/MS_Win32/Makefile rename vs8/mexFigtreeEvaluateTruncated.vcproj => external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj (57%) create mode 100644 external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj.7.10.old create mode 100644 external/ann_1.1.1/MS_Win32/dll/dll.vcproj create mode 100644 external/ann_1.1.1/MS_Win32/dll/dll.vcproj.7.10.old create mode 100644 external/ann_1.1.1/MS_Win32/sample/sample.vcproj create mode 100644 external/ann_1.1.1/MS_Win32/sample/sample.vcproj.7.10.old create mode 100644 external/ann_1.1.1/MS_Win32/test/test.vcproj create mode 100644 external/ann_1.1.1/MS_Win32/test/test.vcproj.7.10.old create mode 100644 external/ann_1.1.1/Make-config create mode 100644 external/ann_1.1.1/Makefile create mode 100644 external/ann_1.1.1/ReadMe.txt create mode 100644 external/ann_1.1.1/ann2fig/Makefile create mode 100644 external/ann_1.1.1/ann2fig/ann2fig.cpp create mode 100644 external/ann_1.1.1/doc/ANNmanual.pdf create mode 100644 external/ann_1.1.1/include/ANN/ANN.h create mode 100644 external/ann_1.1.1/include/ANN/ANNperf.h create mode 100644 external/ann_1.1.1/include/ANN/ANNx.h create mode 100644 external/ann_1.1.1/sample/Makefile create mode 100644 external/ann_1.1.1/sample/ann_sample.cpp create mode 100644 external/ann_1.1.1/sample/data.pts create mode 100644 external/ann_1.1.1/sample/query.pts create mode 100644 external/ann_1.1.1/sample/sample.save create mode 100644 external/ann_1.1.1/src/ANN.cpp create mode 100644 external/ann_1.1.1/src/Makefile create mode 100644 external/ann_1.1.1/src/bd_fix_rad_search.cpp create mode 100644 external/ann_1.1.1/src/bd_pr_search.cpp create mode 100644 external/ann_1.1.1/src/bd_search.cpp create mode 100644 external/ann_1.1.1/src/bd_tree.cpp create mode 100644 external/ann_1.1.1/src/bd_tree.h create mode 100644 external/ann_1.1.1/src/brute.cpp create mode 100644 external/ann_1.1.1/src/kd_dump.cpp create mode 100644 external/ann_1.1.1/src/kd_fix_rad_search.cpp create mode 100644 external/ann_1.1.1/src/kd_fix_rad_search.h create mode 100644 external/ann_1.1.1/src/kd_pr_search.cpp create mode 100644 external/ann_1.1.1/src/kd_pr_search.h create mode 100644 external/ann_1.1.1/src/kd_search.cpp create mode 100644 external/ann_1.1.1/src/kd_search.h create mode 100644 external/ann_1.1.1/src/kd_split.cpp create mode 100644 external/ann_1.1.1/src/kd_split.h create mode 100644 external/ann_1.1.1/src/kd_tree.cpp create mode 100644 external/ann_1.1.1/src/kd_tree.h create mode 100644 external/ann_1.1.1/src/kd_util.cpp create mode 100644 external/ann_1.1.1/src/kd_util.h create mode 100644 external/ann_1.1.1/src/perf.cpp create mode 100644 external/ann_1.1.1/src/pr_queue.h create mode 100644 external/ann_1.1.1/src/pr_queue_k.h create mode 100644 external/ann_1.1.1/test/Makefile create mode 100644 external/ann_1.1.1/test/ann_test.cpp create mode 100644 external/ann_1.1.1/test/rand.cpp create mode 100644 external/ann_1.1.1/test/rand.h create mode 100644 external/ann_1.1.1/test/test1-data.pts create mode 100644 external/ann_1.1.1/test/test1-query.pts create mode 100644 external/ann_1.1.1/test/test1.in create mode 100644 external/ann_1.1.1/test/test1.save create mode 100644 external/ann_1.1.1/test/test2-data.pts create mode 100644 external/ann_1.1.1/test/test2-query.pts create mode 100644 external/ann_1.1.1/test/test2.in create mode 100644 external/ann_1.1.1/test/test2.save create mode 100644 matlab/figtreeChooseEvaluationMethod.m delete mode 100644 matlab/figtreeChooseParametersNonUniform.m delete mode 100644 matlab/figtreeChooseParametersUniform.m delete mode 100644 matlab/figtreeChooseTruncationNumber.m delete mode 100644 matlab/figtreeEvaluateDirect.m delete mode 100644 matlab/figtreeEvaluateDirectTree.m delete mode 100644 matlab/figtreeEvaluateIfgt.m delete mode 100644 matlab/figtreeEvaluateIfgtTree.m delete mode 100644 samples/matlab_sample1_shift_scale.m create mode 100644 samples/matlab_sample1_simple.m delete mode 100644 samples/matlab_sample2.m rename samples/{matlab_sample1.m => matlab_sample2_diff_methods.m} (72%) delete mode 100644 samples/matlab_sample3.m create mode 100644 samples/matlab_sample3_auto_selection.m create mode 100644 src/figtree_internal.h rename src/mex/{mexFigtreeEvaluateDirectTree.cpp => mexFigtreeChooseEvaluationMethod.cpp} (61%) create mode 100644 src/mex/mexFigtreeChooseEvaluationMethod.def delete mode 100644 src/mex/mexFigtreeChooseParametersNonUniform.cpp delete mode 100644 src/mex/mexFigtreeChooseParametersNonUniform.def delete mode 100644 src/mex/mexFigtreeChooseParametersUniform.cpp delete mode 100644 src/mex/mexFigtreeChooseParametersUniform.def delete mode 100644 src/mex/mexFigtreeChooseTruncationNumber.cpp delete mode 100644 src/mex/mexFigtreeChooseTruncationNumber.def delete mode 100644 src/mex/mexFigtreeEvaluateDirect.cpp delete mode 100644 src/mex/mexFigtreeEvaluateDirect.def delete mode 100644 src/mex/mexFigtreeEvaluateDirectTree.def delete mode 100644 src/mex/mexFigtreeEvaluateIfgt.cpp delete mode 100644 src/mex/mexFigtreeEvaluateIfgt.def delete mode 100644 src/mex/mexFigtreeEvaluateIfgtTree.cpp delete mode 100644 src/mex/mexFigtreeEvaluateIfgtTree.def rename vs8/{mexFigtreeChooseParametersUniform.vcproj => mexFigtreeChooseEvaluationMethod.vcproj} (53%) delete mode 100644 vs8/mexFigtreeChooseParametersNonUniform.vcproj delete mode 100644 vs8/mexFigtreeChooseTruncationNumber.vcproj delete mode 100644 vs8/mexFigtreeEvaluateDirect.vcproj delete mode 100644 vs8/mexFigtreeEvaluateDirectAnn.vcproj delete mode 100644 vs8/mexFigtreeEvaluateTruncatedAnn.vcproj diff --git a/Makefile b/Makefile index 9d62036..29bbc09 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all clean mostlyclean: + cd external; $(MAKE) $@ cd src; $(MAKE) $@ cd samples; $(MAKE) $@ cd test; $(MAKE) $@ - diff --git a/external/Makefile b/external/Makefile new file mode 100644 index 0000000..e8c382b --- /dev/null +++ b/external/Makefile @@ -0,0 +1,22 @@ +ifeq ($(FIGTREE_LIB_TYPE),static) +LIBSUFFIX=.a +MAKEOPT=linux-g++ +else +LIBSUFFIX=.so +MAKEOPT=linux-g++-sl +endif + +all: + cd ann_1.1.1 ; $(MAKE) $(MAKEOPT) + mv ann_1.1.1/lib/libann_figtree_version$(LIBSUFFIX) ../lib/libann_figtree_version$(LIBSUFFIX) + +clean: + cd ann_1.1.1 ; $(MAKE) realclean + rm -f ../lib/libann_figtree_version.so + rm -f ../lib/libann_figtree_version.a + +mostlyclean: + cd ann_1.1.1 ; $(MAKE) realclean + rm -f ../lib/libann_figtree_version.so + rm -f ../lib/libann_figtree_version.a + diff --git a/external/ann_1.1.1/Copyright.txt b/external/ann_1.1.1/Copyright.txt new file mode 100644 index 0000000..17d2c7c --- /dev/null +++ b/external/ann_1.1.1/Copyright.txt @@ -0,0 +1,47 @@ +ANN: Approximate Nearest Neighbors +Version: 1.1.1 +Release Date: Aug 4, 2006 +---------------------------------------------------------------------------- +Copyright (c) 1997-2005 University of Maryland and Sunil Arya and David +Mount All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser Public License as published by the +Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser Public License for more details. + +A copy of the terms and conditions of the license can be found in +License.txt or online at + + http://www.gnu.org/copyleft/lesser.html + +To obtain a copy, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Disclaimer +---------- +The University of Maryland and the authors make no representations about +the suitability or fitness of this software for any purpose. It is +provided "as is" without express or implied warranty. +--------------------------------------------------------------------- + +Authors +------- +David Mount +Dept of Computer Science +University of Maryland, +College Park, MD 20742 USA +mount@cs.umd.edu +http://www.cs.umd.edu/~mount/ + +Sunil Arya +Dept of Computer Science +Hong University of Science and Technology +Clearwater Bay, HONG KONG +arya@cs.ust.hk +http://www.cs.ust.hk/faculty/arya/ diff --git a/external/ann_1.1.1/License.txt b/external/ann_1.1.1/License.txt new file mode 100644 index 0000000..db06dbd --- /dev/null +++ b/external/ann_1.1.1/License.txt @@ -0,0 +1,450 @@ +---------------------------------------------------------------------- +The ANN Library (all versions) is provided under the terms and +conditions of the GNU Lesser General Public Library, which is stated +below. It can also be found at: + + http://www.gnu.org/copyleft/lesser.html + +---------------------------------------------------------------------- + +GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts +as the successor of the GNU Library Public License, version 2, hence the +version number 2.1.] + +Preamble + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public Licenses are +intended to guarantee your freedom to share and change free software--to +make sure the software is free for all its users. + +This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the Free +Software Foundation and other authors who decide to use it. You can use +it too, but we suggest you first think carefully about whether this +license or the ordinary General Public License is the better strategy to +use in any particular case, based on the explanations below. + +When we speak of free software, we are referring to freedom of use, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish); that you receive source code or can get it if +you want it; that you can change the software and use pieces of it in +new free programs; and that you are informed that you can do these +things. + +To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for you +if you distribute copies of the library or if you modify it. + +For example, if you distribute copies of the library, whether gratis or +for a fee, you must give the recipients all the rights that we gave you. +You must make sure that they, too, receive or can get the source code. +If you link other code with the library, you must provide complete +object files to the recipients, so that they can relink them with the +library after making changes to the library and recompiling it. And you +must show them these terms so they know their rights. + +We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + +To protect each distributor, we want to make it very clear that there is +no warranty for the free library. Also, if the library is modified by +someone else and passed on, the recipients should know that what they +have is not the original version, so that the original author's +reputation will not be affected by problems that might be introduced by +others. + +Finally, software patents pose a constant threat to the existence of any +free program. We wish to make sure that a company cannot effectively +restrict the users of a free program by obtaining a restrictive license +from a patent holder. Therefore, we insist that any patent license +obtained for a version of the library must be consistent with the full +freedom of use specified in this license. + +Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License. This license, the GNU Lesser General Public +License, applies to certain designated libraries, and is quite different +from the ordinary General Public License. We use this license for +certain libraries in order to permit linking those libraries into +non-free programs. + +When a program is linked with a library, whether statically or using a +shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the entire +combination fits its criteria of freedom. The Lesser General Public +License permits more lax criteria for linking other code with the +library. + +We call this license the "Lesser" General Public License because it does +Less to protect the user's freedom than the ordinary General Public +License. It also provides other free software developers Less of an +advantage over competing non-free programs. These disadvantages are the +reason we use the ordinary General Public License for many libraries. +However, the Lesser license provides advantages in certain special +circumstances. + +For example, on rare occasions, there may be a special need to encourage +the widest possible use of a certain library, so that it becomes a +de-facto standard. To achieve this, non-free programs must be allowed to +use the library. A more frequent case is that a free library does the +same job as widely used non-free libraries. In this case, there is +little to gain by limiting the free library to free software only, so we +use the Lesser General Public License. + +In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of free +software. For example, permission to use the GNU C Library in non-free +programs enables many more people to use the whole GNU operating system, +as well as its variant, the GNU/Linux operating system. + +Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is linked +with the Library has the freedom and the wherewithal to run that program +using a modified version of the Library. + +The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or other +authorized party saying it may be distributed under the terms of this +Lesser General Public License (also called "this License"). Each +licensee is addressed as "you". + +A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which +has been distributed under these terms. A "work based on the Library" +means either the Library or any derivative work under copyright law: +that is to say, a work containing the Library or a portion of it, either +verbatim or with modifications and/or translated straightforwardly into +another language. (Hereinafter, translation is included without +limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making +modifications to it. For a library, complete source code means all the +source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and +installation of the library. + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of running +a program using the Library is not restricted, and output from such a +program is covered only if its contents constitute a work based on the +Library (independent of the use of the Library in a tool for writing +it). Whether that is true depends on what the Library does and what the +program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the notices +that refer to this License and to the absence of any warranty; and +distribute a copy of this License along with the Library. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of +it, thus forming a work based on the Library, and copy and distribute +such modifications or work under the terms of Section 1 above, provided +that you also meet all of these conditions: + + a) The modified work must itself be a software library. + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has +a purpose that is entirely well-defined independent of the application. +Therefore, Subsection 2d requires that any application-supplied function +or table used by this function must be optional: if the application does +not supply it, the square root function must still compute square +roots.) + + These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, and +can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based on +the Library, the distribution of the whole must be on the terms of this +License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or +contest your rights to work written entirely by you; rather, the intent +is to exercise the right to control the distribution of derivative or +collective works based on the Library. + + In addition, mere aggregation of another work not based on the +Library with the Library (or with a work based on the Library) on a +volume of a storage or distribution medium does not bring the other work +under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so that +they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in these +notices. + +Once this change is made in a given copy, it is irreversible for that +copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the +Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative +of it, under Section 2) in object code or executable form under the +terms of Sections 1 and 2 above provided that you accompany it with the +complete corresponding machine-readable source code, which must be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a +designated place, then offering equivalent access to copy the source +code from the same place satisfies the requirement to distribute the +source code, even though third parties are not compelled to copy the +source along with the object code. + +5. A program that contains no derivative of any portion of the Library, +but is designed to work with the Library by being compiled or linked +with it, is called a "work that uses the Library". Such a work, in +isolation, is not a derivative work of the Library, and therefore falls +outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates +an executable that is a derivative of the Library (because it contains +portions of the Library), rather than a "work that uses the library". +The executable is therefore covered by this License. Section 6 states +terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be linked +without the Library, or if the work is itself a library. The threshold +for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure +layouts and accessors, and small macros and small inline functions (ten +lines or less in length), then the use of the object file is +unrestricted, regardless of whether it is legally a derivative work. +(Executables containing this object code plus portions of the Library +will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, whether +or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also combine or link a +"work that uses the Library" with the Library to produce a work +containing portions of the Library, and distribute that work under terms +of your choice, provided that the terms permit modification of the work +for the customer's own use and reverse engineering for debugging such +modifications. + +You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work during +execution displays copyright notices, you must include the copyright +notice for the Library among them, as well as a reference directing the +user to the copy of this License. Also, you must do one of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood that + the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" +must include any data and utility programs needed for reproducing the +executable from it. However, as a special exception, the materials to be +distributed need not include anything that is normally distributed (in +either source or binary form) with the major components (compiler, +kernel, and so on) of the operating system on which the executable runs, +unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions +of other proprietary libraries that do not normally accompany the +operating system. Such a contradiction means you cannot use both them +and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library +side-by-side in a single library together with other library facilities +not covered by this License, and distribute such a combined library, +provided that the separate distribution of the work based on the Library +and of the other library facilities is otherwise permitted, and provided +that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the +Library except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, link with, or distribute the +Library is void, and will automatically terminate your rights under this +License. However, parties who have received copies, or rights, from you +under this License will not have their licenses terminated so long as +such parties remain in full compliance. + +9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and all +its terms and conditions for copying, distributing or modifying the +Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + +11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot distribute +so as to satisfy simultaneously your obligations under this License and +any other pertinent obligations, then as a consequence you may not +distribute the Library at all. For example, if a patent license would +not permit royalty-free redistribution of the Library by all those who +receive copies directly or indirectly through you, then the only way you +could satisfy both it and this License would be to refrain entirely from +distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is implemented +by public license practices. Many people have made generous +contributions to the wide range of software distributed through that +system in reliance on consistent application of that system; it is up to +the author/donor to decide if he or she is willing to distribute +software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be +a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may +add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among countries +not thus excluded. In such case, this License incorporates the +limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions +of the Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a license +version number, you may choose any version ever published by the Free +Software Foundation. + +14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free Software +Foundation; we sometimes make exceptions for this. Our decision will be +guided by the two goals of preserving the free status of all derivatives +of our free software and of promoting the sharing and reuse of software +generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH +YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL +NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR +DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL +DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY +(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF +THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR +OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. diff --git a/external/ann_1.1.1/MS_Win32/Ann.sln b/external/ann_1.1.1/MS_Win32/Ann.sln new file mode 100644 index 0000000..c0a1969 --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/Ann.sln @@ -0,0 +1,46 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll\dll.vcproj", "{A7D00B21-CB9C-4BBB-8DEE-51025104F867}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample\sample.vcproj", "{C76F5A10-7A4A-4546-9414-296DB38BE825}" + ProjectSection(ProjectDependencies) = postProject + {A7D00B21-CB9C-4BBB-8DEE-51025104F867} = {A7D00B21-CB9C-4BBB-8DEE-51025104F867} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{6AC673C7-7B3F-4520-A761-647B212A4BEF}" + ProjectSection(ProjectDependencies) = postProject + {A7D00B21-CB9C-4BBB-8DEE-51025104F867} = {A7D00B21-CB9C-4BBB-8DEE-51025104F867} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ann2fig", "ann2fig\ann2fig.vcproj", "{622DD7D8-0C0A-4303-9176-C9A8AF467E70}" + ProjectSection(ProjectDependencies) = postProject + {A7D00B21-CB9C-4BBB-8DEE-51025104F867} = {A7D00B21-CB9C-4BBB-8DEE-51025104F867} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Debug|Win32.ActiveCfg = Debug|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Debug|Win32.Build.0 = Debug|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Release|Win32.ActiveCfg = Release|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Release|Win32.Build.0 = Release|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Debug|Win32.ActiveCfg = Debug|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Debug|Win32.Build.0 = Debug|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Release|Win32.ActiveCfg = Release|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Release|Win32.Build.0 = Release|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Debug|Win32.ActiveCfg = Debug|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Debug|Win32.Build.0 = Debug|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Release|Win32.ActiveCfg = Release|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Release|Win32.Build.0 = Release|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Debug|Win32.ActiveCfg = Debug|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Debug|Win32.Build.0 = Debug|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Release|Win32.ActiveCfg = Release|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/external/ann_1.1.1/MS_Win32/Ann.sln.old b/external/ann_1.1.1/MS_Win32/Ann.sln.old new file mode 100644 index 0000000..129df1b --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/Ann.sln.old @@ -0,0 +1,48 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll\dll.vcproj", "{A7D00B21-CB9C-4BBB-8DEE-51025104F867}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample\sample.vcproj", "{C76F5A10-7A4A-4546-9414-296DB38BE825}" + ProjectSection(ProjectDependencies) = postProject + {A7D00B21-CB9C-4BBB-8DEE-51025104F867} = {A7D00B21-CB9C-4BBB-8DEE-51025104F867} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{6AC673C7-7B3F-4520-A761-647B212A4BEF}" + ProjectSection(ProjectDependencies) = postProject + {A7D00B21-CB9C-4BBB-8DEE-51025104F867} = {A7D00B21-CB9C-4BBB-8DEE-51025104F867} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ann2fig", "ann2fig\ann2fig.vcproj", "{622DD7D8-0C0A-4303-9176-C9A8AF467E70}" + ProjectSection(ProjectDependencies) = postProject + {A7D00B21-CB9C-4BBB-8DEE-51025104F867} = {A7D00B21-CB9C-4BBB-8DEE-51025104F867} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Debug.ActiveCfg = Debug|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Debug.Build.0 = Debug|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Release.ActiveCfg = Release|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Release.Build.0 = Release|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Debug.ActiveCfg = Debug|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Debug.Build.0 = Debug|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Release.ActiveCfg = Release|Win32 + {C76F5A10-7A4A-4546-9414-296DB38BE825}.Release.Build.0 = Release|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Debug.ActiveCfg = Debug|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Debug.Build.0 = Debug|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Release.ActiveCfg = Release|Win32 + {6AC673C7-7B3F-4520-A761-647B212A4BEF}.Release.Build.0 = Release|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Debug.ActiveCfg = Debug|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Debug.Build.0 = Debug|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Release.ActiveCfg = Release|Win32 + {622DD7D8-0C0A-4303-9176-C9A8AF467E70}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/external/ann_1.1.1/MS_Win32/Makefile b/external/ann_1.1.1/MS_Win32/Makefile new file mode 100644 index 0000000..af3acae --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/Makefile @@ -0,0 +1,53 @@ +#----------------------------------------------------------------------------- +# Makefile for Windows Versions. +# +# ANN: Approximate Nearest Neighbors +# Version: 1.1.1 08/04/06 +#----------------------------------------------------------------------------- +# Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +# David Mount. All Rights Reserved. +# +# This software and related documentation is part of the Approximate +# Nearest Neighbor Library (ANN). This software is provided under +# the provisions of the Lesser GNU Public License (LGPL). See the +# file ../ReadMe.txt for further information. +# +# The University of Maryland (U.M.) and the authors make no +# representations about the suitability or fitness of this software for +# any purpose. It is provided "as is" without express or implied +# warranty. +#----------------------------------------------------------------------------- +# Revision 1.0 05/03/05 +# Initial release +# Revision 1.1.1 08/04/06 +# Added copyright/license +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# This is not used for compiling the dll. It is just used for cleaning +# things up for distribution. For compilcation, open the Ann.sln +# solution file in Microsoft Windows Visual Studio.NET. +#----------------------------------------------------------------------------- + +default: + @echo "Enter one of the following:" + @echo " make clean remove object files" + @echo " make realclean remove library and executable files" + @echo " " + @echo "See file Makefile for other compilation options." + +#----------------------------------------------------------------------------- +# Remove .o files and core files +#----------------------------------------------------------------------------- +clean: + -rm -f -r ann2fig/Debug ann2fig/Release + -rm -f -r dll/Debug dll/Release + -rm -f -r sample/Debug sample/Release + -rm -f -r test/Debug test/Release + -rm -f Ann.ncb Ann.suo + +#----------------------------------------------------------------------------- +# Remove everthing that can be remade +#----------------------------------------------------------------------------- +realclean: clean + -rm -f bin/* diff --git a/vs8/mexFigtreeEvaluateTruncated.vcproj b/external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj similarity index 57% rename from vs8/mexFigtreeEvaluateTruncated.vcproj rename to external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj index 7bc1835..977f639 100644 --- a/vs8/mexFigtreeEvaluateTruncated.vcproj +++ b/external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj @@ -2,9 +2,8 @@ @@ -17,10 +16,11 @@ @@ -183,23 +176,11 @@ - - - - - - @@ -208,18 +189,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > - - - - diff --git a/external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj.7.10.old b/external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj.7.10.old new file mode 100644 index 0000000..2a30e57 --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/ann2fig/ann2fig.vcproj.7.10.old @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/MS_Win32/dll/dll.vcproj b/external/ann_1.1.1/MS_Win32/dll/dll.vcproj new file mode 100644 index 0000000..4a1b4b3 --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/dll/dll.vcproj @@ -0,0 +1,592 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/MS_Win32/dll/dll.vcproj.7.10.old b/external/ann_1.1.1/MS_Win32/dll/dll.vcproj.7.10.old new file mode 100644 index 0000000..f2b9b99 --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/dll/dll.vcproj.7.10.old @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/MS_Win32/sample/sample.vcproj b/external/ann_1.1.1/MS_Win32/sample/sample.vcproj new file mode 100644 index 0000000..927027b --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/sample/sample.vcproj @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/MS_Win32/sample/sample.vcproj.7.10.old b/external/ann_1.1.1/MS_Win32/sample/sample.vcproj.7.10.old new file mode 100644 index 0000000..c723b12 --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/sample/sample.vcproj.7.10.old @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/MS_Win32/test/test.vcproj b/external/ann_1.1.1/MS_Win32/test/test.vcproj new file mode 100644 index 0000000..9dbd36c --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/test/test.vcproj @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/MS_Win32/test/test.vcproj.7.10.old b/external/ann_1.1.1/MS_Win32/test/test.vcproj.7.10.old new file mode 100644 index 0000000..b0fc3aa --- /dev/null +++ b/external/ann_1.1.1/MS_Win32/test/test.vcproj.7.10.old @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ann_1.1.1/Make-config b/external/ann_1.1.1/Make-config new file mode 100644 index 0000000..28c4203 --- /dev/null +++ b/external/ann_1.1.1/Make-config @@ -0,0 +1,208 @@ +#----------------------------------------------------------------------- +# Makefile variations depending on different configurations +# +# ANN: Approximate Nearest Neighbors +# Version: 1.1 05/03/05 +# +# (This Make-config structure is based on the one used by Mesa by Brian +# Paul. If you succeed in porting ANN to your favorite system, please +# send email to mount@cs.umd.edu, and I'll try to include it in this +# list.) +# +#---------------------------------------------------------------------- +# The following configuration-dependent variables are passed to each +# the Makefile in subdirectories: +# +# ANNLIB The name of the ANN library file (usually libANN.a) +# C++ The C compiler (usually CC or g++) +# MAKELIB The command and flags to make a library file (usually +# "ar ...") +# CFLAGS Flags to C++ compiler +# RANLIB For "ranlib" = use ranlib, "true" = don't use ranlib +#---------------------------------------------------------------------- +# Revision 0.1 09/06/97 +# Initial release +# Revision 0.2 06/24/98 +# Minor changes to fix compilation errors on SGI systems. +# Revision 1.0 04/01/05 +# Modifications for alpha with cxx +# Removed CFLAGS2 options (just write your own) +# Removed -DUSING... (Compilers are pretty consistent these days) +# Added linux-g++ target +# Revision 1.1 05/03/05 +# Added macosx-g++ target +# Changed by Vlad Morariu on 01/29/08 +# Added linux-g++-sl target for use with figtree library +# Changed by Vlad Morariu on 12/05/08 +# Changed name to 'libann_figtree_version' since it was changed for +# use with figtree. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Compilation options (add these, as desired, to the CFLAGS variable +# in the desired compilation target below). For example, +# +# "CFLAGS = -O3 -Wall -DANN_PERF" +# +# -g Debugging. +# -O? Run-time optimization. +# -Wall Be verbose about warnings. +# +# -DANN_PERF Enable performance evaluation. (This may slow execution +# slightly.) +# +# -DANN_NO_LIMITS_H +# Use this if limits.h or float.h does not exist on your +# system. (Also see include/ANN/ANN.h for other changes +# needed.) +# +# -DANN_NO_RANDOM +# Use this option if srandom()/random() are not available +# on your system. Pseudo-random number generation is used +# in the utility program test/ann_test. The combination +# srandom()/random() is considered the best pseudo-random +# number generator, but is not available on all systems. +# If they are not available on your system (for example, +# Visual C++) then srand()/rand() will be used instead by +# setting this parameter. +# +# -DWIN32 +# This is used only for compilation under windows systems +# (but instead of using this, use the various .vcproj +# files in the MS_WIN32 directory). +#----------------------------------------------------------------------------- + +# Linux using g++ +linux-g++: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -O3" \ + "MAKELIB = ar ruv" \ + "RANLIB = true" + +# Linux using g++, make shared library +linux-g++-sl: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.so" \ + "C++ = g++" \ + "CFLAGS = -fpic -O3" \ + "MAKELIB = g++ -shared -o" \ + "RANLIB = true" + +# Mac OS X using g++ +macosx-g++: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -O3" \ + "MAKELIB = libtool -static -o " \ + "RANLIB = true" + +# SunOS5 +sunos5: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = CC" \ + "CFLAGS = -O" \ + "MAKELIB = ar ruv" \ + "RANLIB = true" + +# SunOS5 with shared libraries +sunos5-sl: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = CC" \ + "CFLAGS = -Kpic -O" \ + "MAKELIB = ld -G -o" \ + "RANLIB = true" + +# SunOS5 with g++ +sunos5-g++: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -O3" \ + "MAKELIB = ar ruv" \ + "RANLIB = true" + +# SunOS5 with g++ and shared libraries +sunos5-g++-sl: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.so" \ + "C++ = g++" \ + "CFLAGS = -fpic -O3" \ + "MAKELIB = ld -G -o" \ + "RANLIB = true" + +#----------------------------------------------------------------------- +# Used for the author's testing and debugging only +#----------------------------------------------------------------------- + +# debugging version for authors +authors-debug: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -g -DANN_PERF -Wall" \ + "MAKELIB = ar ruv" \ + "RANLIB = true" + +# performance testing version for authors +authors-perf: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -O3 -DANN_PERF -Wall" \ + "MAKELIB = ar ruv" \ + "RANLIB = true" + +#----------------------------------------------------------------------- +# Some older ones that I have not tested with the latest version. +#----------------------------------------------------------------------- + +sgi: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = CC -ansi" \ + "CFLAGS = -O2" \ + "MAKELIB = ar ruv" \ + "RANLIB = true" + +# DEC Alpha with g++ +alpha-g++: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -O3" \ + "MAKELIB = ar ruv" \ + "RANLIB = ranlib" + +# SunOS4 +sunos4: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = CC" \ + "CFLAGS = -O" \ + "MAKELIB = ar ruv" \ + "RANLIB = ranlib" + +# SunOS4 with g++ +sunos4-g++: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.a" \ + "C++ = g++" \ + "CFLAGS = -O3" \ + "MAKELIB = ar ruv" \ + "RANLIB = ranlib" + +# SunOS4 with g++ and shared libraries +sunos4-g++-sl: + $(MAKE) targets \ + "ANNLIB = libann_figtree_version.so" \ + "C++ = g++" \ + "CC = g++" \ + "CFLAGS = -fPIC -O3" \ + "MAKELIB = ld -assert pure-text -o" \ + "RANLIB = true" + diff --git a/external/ann_1.1.1/Makefile b/external/ann_1.1.1/Makefile new file mode 100644 index 0000000..f923f26 --- /dev/null +++ b/external/ann_1.1.1/Makefile @@ -0,0 +1,114 @@ +#----------------------------------------------------------------------------- +# Top-level Makefile for ANN. +# +# ANN: Approximate Nearest Neighbors +# Version: 1.1 05/03/05 +#----------------------------------------------------------------------------- +# Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +# David Mount. All Rights Reserved. +# +# This software and related documentation is part of the Approximate +# Nearest Neighbor Library (ANN). This software is provided under +# the provisions of the Lesser GNU Public License (LGPL). See the +# file ../ReadMe.txt for further information. +# +# The University of Maryland (U.M.) and the authors make no +# representations about the suitability or fitness of this software for +# any purpose. It is provided "as is" without express or implied +# warranty. +#----------------------------------------------------------------------------- +# Revision 0.1 09/06/97 +# alpha release +# Revision 0.2 06/26/98 +# Minor changes to fix compilation errors on SGI systems. +# Revision 1.0 04/01/05 +# Initial release (finally!) +# Added linux-g++ target +# Revision 1.1 05/03/05 +# Added macosx-g++ target +# Changed by Vlad Morariu on 01/29/08 +# Added linux-g++-sl target for use with figtree library +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# default: list the options +# The following legacy targets are also available. +# make sunos4 for Sun with SunOS 4.x +# make sunos4-g++ for Sun with SunOS 4.x and g++ +# make alpha-g++ for DEC Alpha and g++ +# The following targets are used for internal development only +# make authors-debug author's debugging +# make authors-perf author's performance evaluations +# make distribution author's generation of distribution file +#----------------------------------------------------------------------------- +default: + @echo "Enter one of the following:" + @echo " make linux-g++ for Linux and g++" + @echo " make linux-g++-sl for Linux and g++, make shared libs" + @echo " make macosx-g++ for Mac OS X and g++" + @echo " make sunos5 for Sun with SunOS 5.x" + @echo " make sunos5-sl for Sun with SunOS 5.x, make shared libs" + @echo " make sunos5-g++ for Sun with SunOS 5.x and g++" + @echo " make sunos5-g++-sl for Sun with SunOS 5.x, g++, make shared libs" + @echo " make clean remove .o files" + @echo " make realclean remove .o, library and executable files" + @echo " " + @echo "See file Makefile for other compilation options, such as disabling" + @echo "performance measurement code." + +#----------------------------------------------------------------------------- +# main make entry point +#----------------------------------------------------------------------------- +alpha-g++ macosx-g++ linux-g++ linux-g++-sl sgi sunos4 sunos4-g++ sunos5 sunos5-g++ sunos5-g++-sl authors-debug authors-perf: + cd src ; $(MAKE) $@ + cd test ; $(MAKE) $@ + cd sample ; $(MAKE) $@ + cd ann2fig ; $(MAKE) $@ + +#----------------------------------------------------------------------------- +# Remove .o files and core files +#----------------------------------------------------------------------------- +clean: + cd src ; $(MAKE) clean + cd test ; $(MAKE) clean + cd sample ; $(MAKE) clean + cd ann2fig ; $(MAKE) clean + cd MS_Win32; $(MAKE) clean + +#----------------------------------------------------------------------------- +# Remove everthing that can be remade +#----------------------------------------------------------------------------- +realclean: + -rm -f lib/* + -rm -f bin/* + cd src ; $(MAKE) realclean + cd test ; $(MAKE) realclean + cd sample ; $(MAKE) realclean + cd ann2fig ; $(MAKE) realclean + cd MS_Win32; $(MAKE) realclean + +#----------------------------------------------------------------------------- +# Make distribution package (for use by authors only) +#----------------------------------------------------------------------------- +DISTR = ann_1.1.1 + +distribution: realclean + cd .. ; mv -f $(DISTR) $(DISTR)-old; mkdir $(DISTR) + cp Copyright.txt ../$(DISTR) + cp License.txt ../$(DISTR) + cp Make-config ../$(DISTR) + cp Makefile ../$(DISTR) + cp ReadMe.txt ../$(DISTR) + cp -r MS_Win32 ../$(DISTR) +# cd ..; mv -f $(DISTR)_MS_Win32_bin $(DISTR)_MS_Win32_bin-old + cp -r MS_Win32_bin ../$(DISTR)_MS_Win32_bin + cp -r bin ../$(DISTR) + cp -r include ../$(DISTR) + cp -r lib ../$(DISTR) + cp -r src ../$(DISTR) + cp -r test ../$(DISTR) + cp -r sample ../$(DISTR) + cp -r ann2fig ../$(DISTR) + cd ../$(DISTR); mkdir doc + cp doc/*.pdf ../$(DISTR)/doc +# cd .. ; tar -cfv $(DISTR).tar $(DISTR) ; gzip $(DISTR).tar diff --git a/external/ann_1.1.1/ReadMe.txt b/external/ann_1.1.1/ReadMe.txt new file mode 100644 index 0000000..d058123 --- /dev/null +++ b/external/ann_1.1.1/ReadMe.txt @@ -0,0 +1,75 @@ +---------------------------------------------------------------------------- + +This is a modified version of ANN version 1.1.1. It was modified for use with the figtree library. + +---------------------------------------------------------------------------- + + +ANN: Approximate Nearest Neighbors +Version: 1.1.1 +Release date: Aug 4, 2006 +---------------------------------------------------------------------------- +Copyright (c) 1997-2005 University of Maryland and Sunil Arya and David +Mount. All Rights Reserved. See Copyright.txt and License.txt for +complete information on terms and conditions of use and distribution of +this software. +---------------------------------------------------------------------------- + +Authors +------- +David Mount +Dept of Computer Science +University of Maryland, +College Park, MD 20742 USA +mount@cs.umd.edu +http://www.cs.umd.edu/~mount/ + +Sunil Arya +Dept of Computer Science +Hong University of Science and Technology +Clearwater Bay, HONG KONG +arya@cs.ust.hk +http://www.cs.ust.hk/faculty/arya/ + +Introduction +------------ +ANN is a library written in the C++ programming language to support both +exact and approximate nearest neighbor searching in spaces of various +dimensions. It was implemented by David M. Mount of the University of +Maryland, and Sunil Arya of the Hong Kong University of Science and +Technology. ANN (pronounced like the name ``Ann'') stands for +Approximate Nearest Neighbors. ANN is also a testbed containing +programs and procedures for generating data sets, collecting and +analyzing statistics on the performance of nearest neighbor algorithms +and data structures, and visualizing the geometric structure of these +data structures. + +The ANN source code and documentation is available from the following +web page: + + http://www.cs.umd.edu/~mount/ANN + +For more information on ANN and its use, see the ``ANN Programming +Manual,'' which is provided with the software distribution. + +---------------------------------------------------------------------------- +History + Version 0.1 03/04/98 + Preliminary release + Version 0.2 06/24/98 + Changes for SGI compiler. + Version 1.0 04/01/05 + Fixed a number of small bugs + Added dump/load operations + Added annClose to eliminate minor memory leak + Improved compatibility with current C++ compilers + Added compilation for Microsoft Visual Studio.NET + Added compilation for Linux 2.x + Version 1.1 05/03/05 + Added make target for Mac OS X + Added fixed-radius range searching and counting + Added instructions on compiling/using ANN on Windows platforms + Fixed minor output bug in ann2fig + Version 1.1.1 08/04/06 + Added "planted" distribution + Updated old source comments for GNU LPL. diff --git a/external/ann_1.1.1/ann2fig/Makefile b/external/ann_1.1.1/ann2fig/Makefile new file mode 100644 index 0000000..61b9275 --- /dev/null +++ b/external/ann_1.1.1/ann2fig/Makefile @@ -0,0 +1,87 @@ +#----------------------------------------------------------------------------- +# Makefile for ann2fig +# +# ANN: Approximate Nearest Neighbors +# Version: 1.1.1 08/04/06 +#----------------------------------------------------------------------------- +# Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +# David Mount. All Rights Reserved. +# +# This software and related documentation is part of the Approximate +# Nearest Neighbor Library (ANN). This software is provided under +# the provisions of the Lesser GNU Public License (LGPL). See the +# file ../ReadMe.txt for further information. +# +# The University of Maryland (U.M.) and the authors make no +# representations about the suitability or fitness of this software for +# any purpose. It is provided "as is" without express or implied +# warranty. +#----------------------------------------------------------------------------- +# Revision 0.1 03/04/98 +# Initial release +# Revision 1.1.1 08/04/06 +# Added copyright/license +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Basic definitions +# BASEDIR where include, src, lib, ... are +# INCDIR include directory +# LIBDIR library directory +# BINDIR bin directory +# LDFLAGS loader flags +# ANNLIB ANN library +# OTHERLIB other libraries +#----------------------------------------------------------------------------- + +BASEDIR = .. +INCDIR = $(BASEDIR)/include +LIBDIR = $(BASEDIR)/lib +BINDIR = $(BASEDIR)/bin +LDFLAGS = -L$(LIBDIR) +ANNLIBS = -lann_figtree_version +OTHERLIBS = -lm + +#----------------------------------------------------------------------------- +# Some more definitions +# ANN2FIG name of executable +#----------------------------------------------------------------------------- + +ANN2FIG = ann2fig +SOURCES = ann2fig.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +#----------------------------------------------------------------------------- +# Make the program +#----------------------------------------------------------------------------- + +default: + @echo "Specify a target configuration" + +targets: $(BINDIR)/$(ANN2FIG) + +$(BINDIR)/$(ANN2FIG): $(OBJECTS) + $(C++) $(OBJECTS) -o $(ANN2FIG) $(LDFLAGS) $(ANNLIBS) $(OTHERLIBS) + mv $(ANN2FIG) $(BINDIR) + +#----------------------------------------------------------------------------- +# configuration definitions +#----------------------------------------------------------------------------- + +include ../Make-config + +#----------------------------------------------------------------------------- +# Objects +#----------------------------------------------------------------------------- + +ann2fig.o: ann2fig.cpp + $(C++) -c -I$(INCDIR) ann2fig.cpp + +#----------------------------------------------------------------------------- +# Cleaning +#----------------------------------------------------------------------------- + +clean: + -rm -f *.o core + +realclean: clean diff --git a/external/ann_1.1.1/ann2fig/ann2fig.cpp b/external/ann_1.1.1/ann2fig/ann2fig.cpp new file mode 100644 index 0000000..e63663c --- /dev/null +++ b/external/ann_1.1.1/ann2fig/ann2fig.cpp @@ -0,0 +1,585 @@ +//---------------------------------------------------------------------- +// File: ann2fig.cpp +// Programmer: David Mount +// Last modified: 05/03/05 +// Description: convert ann dump file to fig file +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed dump file suffix from .ann to .dmp. +// Revision 1.1 05/03/05 +// Fixed usage output string. +//---------------------------------------------------------------------- +// This program inputs an ann dump file of a search structure +// perhaps along with point coordinates, and outputs a fig (Ver 3.1) +// file (see fig2dev (1)) displaying the tree. The fig file may +// then be displayed using xfig, or converted to any of a number of +// other formats using fig2dev. +// +// If the dimension is 2 then the entire tree is display. If the +// dimension is larger than 2 then the user has the option of +// selecting which two dimensions will be displayed, and the slice +// value for each of the remaining dimensions. All leaf cells +// intersecting the slice are shown along with the points in these +// cells. See the procedure getArgs() below for the command-line +// arguments. +//---------------------------------------------------------------------- + +#include // C standard I/O +#include // file I/O +#include // string manipulation +#include // all ANN includes + +using namespace std; // make std:: accessible + +//---------------------------------------------------------------------- +// Globals and their defaults +//---------------------------------------------------------------------- + +const int STRING_LEN = 500; // string lengths +const int MAX_DIM = 1000; // maximum dimension +const double DEF_SLICE_VAL = 0; // default slice value +const char FIG_HEAD[] = {"#FIG 3.1"}; // fig file header +const char DUMP_SUFFIX[] = {".dmp"}; // suffix for dump file +const char FIG_SUFFIX[] = {".fig"}; // suffix for fig file + +char file_name[STRING_LEN]; // (root) file name (say xxx) +char infile_name[STRING_LEN];// input file name (xxx.dmp) +char outfile_name[STRING_LEN];// output file name (xxx.fig) +char caption[STRING_LEN]; // caption line (= command line) +ofstream ofile; // output file stream +ifstream ifile; // input file stream +int dim_x = 0; // horizontal dimension +int dim_y = 1; // vertical dimension +double slice_val[MAX_DIM]; // array of slice values +double u_per_in = 1200; // fig units per inch (version 3.1) +double in_size = 5; // size of figure (in inches) +double in_low_x = 1; // fig upper left corner (in inches) +double in_low_y = 1; // fig upper left corner (in inches) +double u_size = 6000; // size of figure (in units) +double u_low_x = 1200; // fig upper left corner (in units) +double u_low_y = 1200; // fig upper left corner (in units) +int pt_size = 10; // point size (in fig units) + +int dim; // dimension +int n_pts; // number of points +ANNpointArray pts = NULL; // point array + +double scale; // scale factor for transformation +double offset_x; // offsets for transformation +double offset_y; + + // transformations +#define TRANS_X(p) (offset_x + scale*(p[dim_x])) +#define TRANS_Y(p) (offset_y - scale*(p[dim_y])) + +//---------------------------------------------------------------------- +// Error handler +//---------------------------------------------------------------------- + +void Error(char *msg, ANNerr level) +{ + if (level == ANNabort) { + cerr << "ann2fig: ERROR------->" << msg << "<-------------ERROR\n"; + exit(1); + } + else { + cerr << "ann2fig: WARNING----->" << msg << "<-------------WARNING\n"; + } +} + +//---------------------------------------------------------------------- +// set_slice_val - set all slice values to given value +//---------------------------------------------------------------------- + +void set_slice_val(double val) +{ + for (int i = 0; i < MAX_DIM; i++) { + slice_val[i] = val; + } +} + +//---------------------------------------------------------------------- +// getArgs - get input arguments +// +// Syntax: +// ann2fig [-upi scale] [-x low_x] [-y low_y] +// [-sz size] [-dx dim_x] [-dy dim_y] [-sl dim value]* +// [-ps pointsize] +// file +// +// where: +// -upi scale fig units per inch (default = 1200) +// -x low_x x and y offset of upper left corner (inches) +// -y low_y ...(default = 1) +// -sz size maximum side length of figure (in inches) +// ...(default = 5) +// -dx dim_x horizontal dimension (default = 0) +// -dy dim_y vertical dimension (default = 1) +// -sv value default slice value (default = 0) +// -sl dim value each such pair defines the value along the +// ...given dimension at which to slice. This +// ...may be supplied for all dimensions except +// ...dim_x and dim_y. +// -ps pointsize size of points in fig units (def = 10) +// file file (input=file.dmp, output=file.fig) +// +//---------------------------------------------------------------------- + +void getArgs(int argc, char **argv) +{ + int i; + int sl_dim; // temp slice dimension + double sl_val; // temp slice value + + set_slice_val(DEF_SLICE_VAL); // set initial slice-values + + if (argc <= 1) { + cerr << "Syntax:\n\ + ann2fig [-upi scale] [-x low_x] [-y low_y]\n\ + [-sz size] [-dx dim_x] [-dy dim_y] [-sl dim value]*\n\ + file\n\ + \n\ + where:\n\ + -upi scale fig units per inch (default = 1200)\n\ + -x low_x x and y offset of upper left corner (inches)\n\ + -y low_y ...(default = 1)\n\ + -sz size maximum side length of figure (in inches)\n\ + ...(default = 5)\n\ + -dx dim_x horizontal dimension (default = 0)\n\ + -dy dim_y vertical dimension (default = 1)\n\ + -sv value default slice value (default = 0)\n\ + -sl dim value each such pair defines the value along the\n\ + ...given dimension at which to slice. This\n\ + ...may be supplied for each dimension except\n\ + ...dim_x and dim_y.\n\ + -ps pointsize size of points in fig units (def = 10)\n\ + file file (input=file.dmp, output=file.fig)\n"; + exit(0); + } + + ANNbool fileSeen = ANNfalse; // file argument seen? + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-upi")) { // process -upi option + sscanf(argv[++i], "%lf", &u_per_in); + } + else if (!strcmp(argv[i], "-x")) { // process -x option + sscanf(argv[++i], "%lf", &in_low_x); + } + else if (!strcmp(argv[i], "-y")) { // process -y option + sscanf(argv[++i], "%lf", &in_low_y); + } + else if (!strcmp(argv[i], "-sz")) { // process -sz option + sscanf(argv[++i], "%lf", &in_size); + } + else if (!strcmp(argv[i], "-dx")) { // process -dx option + sscanf(argv[++i], "%d", &dim_x); + } + else if (!strcmp(argv[i], "-dy")) { // process -dy option + sscanf(argv[++i], "%d", &dim_y); + } + else if (!strcmp(argv[i], "-sv")) { // process -sv option + sscanf(argv[++i], "%lf", &sl_val); + set_slice_val(sl_val); // set slice values + } + else if (!strcmp(argv[i], "-sl")) { // process -sl option + sscanf(argv[++i], "%d", &sl_dim); + if (sl_dim < 0 || sl_dim >= MAX_DIM) { + Error("Slice dimension out of bounds", ANNabort); + } + sscanf(argv[++i], "%lf", &slice_val[sl_dim]); + } + if (!strcmp(argv[i], "-ps")) { // process -ps option + sscanf(argv[++i], "%i", &pt_size); + } + else { // must be file name + fileSeen = ANNtrue; + sscanf(argv[i], "%s", file_name); + strcpy(infile_name, file_name); // copy to input file name + strcat(infile_name, DUMP_SUFFIX); + strcpy(outfile_name, file_name); // copy to output file name + strcat(outfile_name, FIG_SUFFIX); + } + } + + if (!fileSeen) { // no file seen + Error("File argument is required", ANNabort); + } + + ifile.open(infile_name, ios::in); // open for reading + if (!ifile) { + Error("Cannot open input file", ANNabort); + } + ofile.open(outfile_name, ios::out); // open for writing + if (!ofile) { + Error("Cannot open output file", ANNabort); + } + + u_low_x = u_per_in * in_low_x; // convert inches to fig units + u_low_y = u_per_in * in_low_y; + u_size = u_per_in * in_size; + + strcpy(caption, argv[0]); // copy command line to caption + for (i = 1; i < argc; i++) { + strcat(caption, " "); + strcat(caption, argv[i]); + } +} + +//---------------------------------------------------------------------- +// Graphics utilities for fig output +// +// writeHeader write header for fig file +// writePoint write a point +// writeBox write a box +// writeLine write a line +//---------------------------------------------------------------------- + +void writeHeader() +{ + ofile << FIG_HEAD << "\n" // fig file header + << "Portrait\n" + << "Center\n" + << "Inches\n" + << (int) u_per_in << " 2\n"; +} + +void writePoint(ANNpoint p) // write a single point +{ + // filled black point object + ofile << "1 3 0 1 -1 7 0 0 0 0.000 1 0.0000 "; + int cent_x = (int) TRANS_X(p); // transform center coords + int cent_y = (int) TRANS_Y(p); + ofile << cent_x << " " << cent_y << " " // write center, radius, bounds + << pt_size << " " << pt_size << " " + << cent_x << " " << cent_y << " " + << cent_x + pt_size << " " << cent_y + pt_size << "\n"; +} + +void writeBox(const ANNorthRect &r) // write box +{ + // unfilled box object + ofile << "2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5\n"; + + int p0_x = (int) TRANS_X(r.lo); // transform endpoints + int p0_y = (int) TRANS_Y(r.lo); + int p1_x = (int) TRANS_X(r.hi); + int p1_y = (int) TRANS_Y(r.hi); + ofile << "\t" + << p0_x << " " << p0_y << " " // write vertices + << p1_x << " " << p0_y << " " + << p1_x << " " << p1_y << " " + << p0_x << " " << p1_y << " " + << p0_x << " " << p0_y << "\n"; +} + +void writeLine(ANNpoint p0, ANNpoint p1) // write line +{ + // unfilled line object + ofile << "2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2\n"; + + int p0_x = (int) TRANS_X(p0); // transform endpoints + int p0_y = (int) TRANS_Y(p0); + int p1_x = (int) TRANS_X(p1); + int p1_y = (int) TRANS_Y(p1); + ofile << "\t" + << p0_x << " " << p0_y << " " // write vertices + << p1_x << " " << p1_y << "\n"; +} + +void writeCaption( // write caption text + const ANNorthRect &bnd_box, // bounding box + char *caption) // caption +{ + if (!strcmp(caption, "\0")) return; // null string? + int px = (int) TRANS_X(bnd_box.lo); // put .5 in. lower left + int py = (int) (TRANS_Y(bnd_box.lo) + 0.50 * u_per_in); + ofile << "4 0 -1 0 0 0 20 0.0000 4 255 2000 "; + ofile << px << " " << py << " " << caption << "\\001\n"; +} + +//---------------------------------------------------------------------- +// overlap - test whether a box overlap slicing region +// +// The slicing region is a 2-dimensional plane in space +// which contains points (x1, x2, ..., xn) satisfying the +// n-2 linear equalities: +// +// xi == slice_val[i] for i != dim_x, dim_y +// +// This procedure returns true of the box defined by +// corner points box.lo and box.hi overlap this plane. +//---------------------------------------------------------------------- + +ANNbool overlap(const ANNorthRect &box) +{ + for (int i = 0; i < dim; i++) { + if (i != dim_x && i != dim_y && + (box.lo[i] > slice_val[i] || box.hi[i] < slice_val[i])) + return ANNfalse; + } + return ANNtrue; +} + +//---------------------------------------------------------------------- +// readTree, recReadTree - inputs tree and outputs figure +// +// readTree procedure initializes things and then calls recReadTree +// which does all the work. +// +// recReadTree reads in a node of the tree, makes any recursive +// calls as needed to input the children of this node (if internal) +// and maintains the bounding box. Note that the bounding box +// is modified within this procedure, but it is the responsibility +// of the procedure that it be restored to its original value +// on return. +// +// Recall that these are the formats. The tree is given in +// preorder. +// +// Leaf node: +// leaf ... +// Splitting nodes: +// split +// Shrinking nodes: +// shrink +// +// +// ... (repeated n_bnds times) +// +// On reading a leaf we determine whether we should output the +// cell's points (if dimension = 2 or this cell overlaps the +// slicing region). For splitting nodes we check whether the +// current cell overlaps the slicing plane and whether the +// cutting dimension coincides with either the x or y drawing +// dimensions. If so, we output the corresponding splitting +// segment. +//---------------------------------------------------------------------- + +void recReadTree(ANNorthRect &box) +{ + char tag[STRING_LEN]; // tag (leaf, split, shrink) + int n_pts; // number of points in leaf + int idx; // point index + int cd; // cut dimension + ANNcoord cv; // cut value + ANNcoord lb; // low bound + ANNcoord hb; // high bound + int n_bnds; // number of bounding sides + int sd; // which side + + ifile >> tag; // input node tag + if (strcmp(tag, "leaf") == 0) { // leaf node + + ifile >> n_pts; // input number of points + // check for overlap + if (dim == 2 || overlap(box)) { + for (int i = 0; i < n_pts; i++) { // yes, write the points + ifile >> idx; + writePoint(pts[idx]); + } + } + else { // input but ignore points + for (int i = 0; i < n_pts; i++) { + ifile >> idx; + } + } + } + else if (strcmp(tag, "split") == 0) { // splitting node + + ifile >> cd >> cv >> lb >> hb; + if (lb != box.lo[cd] || hb != box.hi[cd]) { + Error("Bounding box coordinates are fishy", ANNwarn); + } + + ANNcoord lv = box.lo[cd]; // save bounds for cutting dim + ANNcoord hv = box.hi[cd]; + + //-------------------------------------------------------------- + // The following code is rather fragile so modify at your + // own risk. We first decrease the high-end of the bounding + // box down to the cutting plane and then read the left subtree. + // Then we increase the low-end of the bounding box up to the + // cutting plane (thus collapsing the bounding box to a d-1 + // dimensional hyperrectangle). Then we draw the projection of + // its diagonal if it crosses the slicing plane. This will have + // the effect of drawing its intersection on the slicing plane. + // Then we restore the high-end of the bounding box and read + // the right subtree. Finally we restore the low-end of the + // bounding box, before returning. + //-------------------------------------------------------------- + box.hi[cd] = cv; // decrease high bounds + recReadTree(box); // read left subtree + // check for overlap + box.lo[cd] = cv; // increase low bounds + if (dim == 2 || overlap(box)) { // check for overlap + if (cd == dim_x || cd == dim_y) { // cut through slice plane + writeLine(box.lo, box.hi); // draw cutting line + } + } + box.hi[cd] = hv; // restore high bounds + + recReadTree(box); // read right subtree + box.lo[cd] = lv; // restore low bounds + } + else if (strcmp(tag, "shrink") == 0) { // splitting node + + ANNorthRect inner(dim, box); // copy bounding box + ifile >> n_bnds; // number of bounding sides + for (int i = 0; i < n_bnds; i++) { + ifile >> cd >> cv >> sd; // input bounding halfspace + ANNorthHalfSpace hs(cd, cv, sd); // create orthogonal halfspace + hs.project(inner.lo); // intersect by projecting + hs.project(inner.hi); + } + if (dim == 2 || overlap(inner)) { + writeBox(inner); // draw inner rectangle + } + recReadTree(inner); // read inner subtree + recReadTree(box); // read outer subtree + } + else { + Error("Illegal node type in dump file", ANNabort); + } +} + +void readTree(ANNorthRect &bnd_box) +{ + writeHeader(); // output header + writeBox(bnd_box); // draw bounding box + writeCaption(bnd_box, caption); // write caption + recReadTree(bnd_box); // do it +} + +//---------------------------------------------------------------------- +// readANN - read the ANN dump file +// +// This procedure reads in the dump file. See the format below. +// It first reads the header line with version number. If the +// points section is present it reads them (otherwise just leaves +// points = NULL), and then it reads the tree section. It inputs +// the bounding box and determines the parameters for transforming +// the image to figure units. It then invokes the procedure +// readTree to do all the real work. +// +// Dump File Format: = coordinate value (ANNcoord) +// +// #ANN [END_OF_LINE] +// points (point coordinates: this is optional) +// 0 ... (point indices and coordinates) +// 1 ... +// ... +// tree +// ... (lower end of bounding box) +// ... (upper end of bounding box) +// If the tree is null, then a single line "null" is +// output. Otherwise the nodes of the tree are printed +// one per line in preorder. Leaves and splitting nodes +// have the following formats: +// Leaf node: +// leaf ... +// Splitting nodes: +// split +// Shrinking nodes: +// shrink +// +// +// ... (repeated n_bnds times) +// +// Note: Infinite lo_ and hi_bounds are printed as the special +// values "-INF" and "+INF", respectively. We do not +// check for this, because the current version of ANN +// starts with a finite bounding box if the tree is +// nonempty. +//---------------------------------------------------------------------- + +void readANN() +{ + int j; + char str[STRING_LEN]; // storage for string + char version[STRING_LEN]; // storage for version + int bkt_size; // bucket size + + ifile >> str; // input header + if (strcmp(str, "#ANN") != 0) { // incorrect header + Error("Incorrect header for dump file", ANNabort); + } + ifile.getline(version, STRING_LEN); // get version (ignore) + ifile >> str; // get major heading + if (strcmp(str, "points") == 0) { // points section + ifile >> dim; // read dimension + ifile >> n_pts; // number of points + pts = annAllocPts(n_pts, dim); // allocate points + for (int i = 0; i < n_pts; i++) { // input point coordinates + int idx; // point index + ifile >> idx; // input point index + if (idx < 0 || idx >= n_pts) { + Error("Point index is out of range", ANNabort); + } + for (j = 0; j < dim; j++) { + ifile >> pts[idx][j]; // read point coordinates + } + } + ifile >> str; // get next major heading + } + if (strcmp(str, "tree") == 0) { // tree section + ifile >> dim; // read dimension + if (dim_x > dim || dim_y > dim) { + Error("Dimensions out of bounds", ANNabort); + } + ifile >> n_pts; // number of points + ifile >> bkt_size; // bucket size (ignored) + // read bounding box + ANNorthRect bnd_box(dim); // create bounding box + for (j = 0; j < dim; j++) { + ifile >> bnd_box.lo[j]; // read box low coordinates + } + for (j = 0; j < dim; j++) { + ifile >> bnd_box.hi[j]; // read box high coordinates + } + // compute scaling factors + double box_len_x = bnd_box.hi[dim_x] - bnd_box.lo[dim_x]; + double box_len_y = bnd_box.hi[dim_y] - bnd_box.lo[dim_y]; + // longer side determines scale + if (box_len_x > box_len_y) scale = u_size/box_len_x; + else scale = u_size/box_len_y; + // compute offsets + offset_x = u_low_x - scale*bnd_box.lo[dim_x]; + offset_y = u_low_y + scale*bnd_box.hi[dim_y]; + readTree(bnd_box); // read the tree and process + } + else if (strcmp(str, "null") == 0) return; // empty tree + else { + cerr << "Input string: " << str << "\n"; + Error("Illegal ann format. Expecting section heading", ANNabort); + } +} + +//---------------------------------------------------------------------- +// Main program +// +// Gets the command-line arguments and invokes the main scanning +// procedure. +//---------------------------------------------------------------------- + +main(int argc, char **argv) +{ + getArgs(argc, argv); // get input arguments + readANN(); // read the dump file +} diff --git a/external/ann_1.1.1/doc/ANNmanual.pdf b/external/ann_1.1.1/doc/ANNmanual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..00e9e909bb87561a9b7972d4aee6c11083939e82 GIT binary patch literal 357854 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𝔬Ty?=SK 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

3GiZusS9F=5L7LuGa-1{Z;XH`dB0k$Rd#mf61 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�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 literal 0 HcmV?d00001 diff --git a/external/ann_1.1.1/include/ANN/ANN.h b/external/ann_1.1.1/include/ANN/ANN.h new file mode 100644 index 0000000..152c297 --- /dev/null +++ b/external/ann_1.1.1/include/ANN/ANN.h @@ -0,0 +1,855 @@ +//---------------------------------------------------------------------- +// File: ANN.h +// Programmer: Sunil Arya and David Mount +// Last modified: 05/03/05 (Release 1.1) +// Description: Basic include file for approximate nearest +// neighbor searching. +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added copyright and revision information +// Added ANNcoordPrec for coordinate precision. +// Added methods theDim, nPoints, maxPoints, thePoints to ANNpointSet. +// Cleaned up C++ structure for modern compilers +// Revision 1.1 05/03/05 +// Added fixed-radius k-NN searching +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// ANN - approximate nearest neighbor searching +// ANN is a library for approximate nearest neighbor searching, +// based on the use of standard and priority search in kd-trees +// and balanced box-decomposition (bbd) trees. Here are some +// references to the main algorithmic techniques used here: +// +// kd-trees: +// Friedman, Bentley, and Finkel, ``An algorithm for finding +// best matches in logarithmic expected time,'' ACM +// Transactions on Mathematical Software, 3(3):209-226, 1977. +// +// Priority search in kd-trees: +// Arya and Mount, ``Algorithms for fast vector quantization,'' +// Proc. of DCC '93: Data Compression Conference, eds. J. A. +// Storer and M. Cohn, IEEE Press, 1993, 381-390. +// +// Approximate nearest neighbor search and bbd-trees: +// Arya, Mount, Netanyahu, Silverman, and Wu, ``An optimal +// algorithm for approximate nearest neighbor searching,'' +// 5th Ann. ACM-SIAM Symposium on Discrete Algorithms, +// 1994, 573-582. +//---------------------------------------------------------------------- + +#ifndef ANN_H +#define ANN_H + +#ifdef WIN32 + //---------------------------------------------------------------------- + // For Microsoft Visual C++, externally accessible symbols must be + // explicitly indicated with DLL_API, which is somewhat like "extern." + // + // The following ifdef block is the standard way of creating macros + // which make exporting from a DLL simpler. All files within this DLL + // are compiled with the DLL_EXPORTS preprocessor symbol defined on the + // command line. In contrast, projects that use (or import) the DLL + // objects do not define the DLL_EXPORTS symbol. This way any other + // project whose source files include this file see DLL_API functions as + // being imported from a DLL, wheras this DLL sees symbols defined with + // this macro as being exported. + //---------------------------------------------------------------------- + #ifdef DLL_EXPORTS + #define DLL_API __declspec(dllexport) + #else + #define DLL_API __declspec(dllimport) + #endif + //---------------------------------------------------------------------- + // DLL_API is ignored for all other systems + //---------------------------------------------------------------------- +#else + #define DLL_API +#endif + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- + +#include // math includes +#include // I/O streams + +//---------------------------------------------------------------------- +// Limits +// There are a number of places where we use the maximum double value as +// default initializers (and others may be used, depending on the +// data/distance representation). These can usually be found in limits.h +// (as LONG_MAX, INT_MAX) or in float.h (as DBL_MAX, FLT_MAX). +// +// Not all systems have these files. If you are using such a system, +// you should set the preprocessor symbol ANN_NO_LIMITS_H when +// compiling, and modify the statements below to generate the +// appropriate value. For practical purposes, this does not need to be +// the maximum double value. It is sufficient that it be at least as +// large than the maximum squared distance between between any two +// points. +//---------------------------------------------------------------------- +#ifdef ANN_NO_LIMITS_H // limits.h unavailable + #include // replacement for limits.h + const double ANN_DBL_MAX = MAXDOUBLE; // insert maximum double +#else + #include + #include + const double ANN_DBL_MAX = DBL_MAX; +#endif + +#define ANNversion "1.1.1" // ANN version and information +#define ANNversionCmt "" +#define ANNcopyright "David M. Mount and Sunil Arya" +#define ANNlatestRev "Aug 4, 2006" + +//---------------------------------------------------------------------- +// ANNbool +// This is a simple boolean type. Although ANSI C++ is supposed +// to support the type bool, some compilers do not have it. +//---------------------------------------------------------------------- + +enum ANNbool {ANNfalse = 0, ANNtrue = 1}; // ANN boolean type (non ANSI C++) + +//---------------------------------------------------------------------- +// ANNcoord, ANNdist +// ANNcoord and ANNdist are the types used for representing +// point coordinates and distances. They can be modified by the +// user, with some care. It is assumed that they are both numeric +// types, and that ANNdist is generally of an equal or higher type +// from ANNcoord. A variable of type ANNdist should be large +// enough to store the sum of squared components of a variable +// of type ANNcoord for the number of dimensions needed in the +// application. For example, the following combinations are +// legal: +// +// ANNcoord ANNdist +// --------- ------------------------------- +// short short, int, long, float, double +// int int, long, float, double +// long long, float, double +// float float, double +// double double +// +// It is the user's responsibility to make sure that overflow does +// not occur in distance calculation. +//---------------------------------------------------------------------- + +typedef double ANNcoord; // coordinate data type +typedef double ANNdist; // distance data type + +//---------------------------------------------------------------------- +// ANNidx +// ANNidx is a point index. When the data structure is built, the +// points are given as an array. Nearest neighbor results are +// returned as an integer index into this array. To make it +// clearer when this is happening, we define the integer type +// ANNidx. Indexing starts from 0. +// +// For fixed-radius near neighbor searching, it is possible that +// there are not k nearest neighbors within the search radius. To +// indicate this, the algorithm returns ANN_NULL_IDX as its result. +// It should be distinguishable from any valid array index. +//---------------------------------------------------------------------- + +typedef int ANNidx; // point index +const ANNidx ANN_NULL_IDX = -1; // a NULL point index + +//---------------------------------------------------------------------- +// Infinite distance: +// The code assumes that there is an "infinite distance" which it +// uses to initialize distances before performing nearest neighbor +// searches. It should be as larger or larger than any legitimate +// nearest neighbor distance. +// +// On most systems, these should be found in the standard include +// file or possibly . If you do not have these +// file, some suggested values are listed below, assuming 64-bit +// long, 32-bit int and 16-bit short. +// +// ANNdist ANN_DIST_INF Values (see or ) +// ------- ------------ ------------------------------------ +// double DBL_MAX 1.79769313486231570e+308 +// float FLT_MAX 3.40282346638528860e+38 +// long LONG_MAX 0x7fffffffffffffff +// int INT_MAX 0x7fffffff +// short SHRT_MAX 0x7fff +//---------------------------------------------------------------------- + +const ANNdist ANN_DIST_INF = ANN_DBL_MAX; + +//---------------------------------------------------------------------- +// Significant digits for tree dumps: +// When floating point coordinates are used, the routine that dumps +// a tree needs to know roughly how many significant digits there +// are in a ANNcoord, so it can output points to full precision. +// This is defined to be ANNcoordPrec. On most systems these +// values can be found in the standard include files or +// . For integer types, the value is essentially ignored. +// +// ANNcoord ANNcoordPrec Values (see or ) +// -------- ------------ ------------------------------------ +// double DBL_DIG 15 +// float FLT_DIG 6 +// long doesn't matter 19 +// int doesn't matter 10 +// short doesn't matter 5 +//---------------------------------------------------------------------- + +#ifdef DBL_DIG // number of sig. bits in ANNcoord + const int ANNcoordPrec = DBL_DIG; +#else + const int ANNcoordPrec = 15; // default precision +#endif + +//---------------------------------------------------------------------- +// Self match? +// In some applications, the nearest neighbor of a point is not +// allowed to be the point itself. This occurs, for example, when +// computing all nearest neighbors in a set. By setting the +// parameter ANN_ALLOW_SELF_MATCH to ANNfalse, the nearest neighbor +// is the closest point whose distance from the query point is +// strictly positive. +//---------------------------------------------------------------------- + +const ANNbool ANN_ALLOW_SELF_MATCH = ANNtrue; + +//---------------------------------------------------------------------- +// Norms and metrics: +// ANN supports any Minkowski norm for defining distance. In +// particular, for any p >= 1, the L_p Minkowski norm defines the +// length of a d-vector (v0, v1, ..., v(d-1)) to be +// +// (|v0|^p + |v1|^p + ... + |v(d-1)|^p)^(1/p), +// +// (where ^ denotes exponentiation, and |.| denotes absolute +// value). The distance between two points is defined to be the +// norm of the vector joining them. Some common distance metrics +// include +// +// Euclidean metric p = 2 +// Manhattan metric p = 1 +// Max metric p = infinity +// +// In the case of the max metric, the norm is computed by taking +// the maxima of the absolute values of the components. ANN is +// highly "coordinate-based" and does not support general distances +// functions (e.g. those obeying just the triangle inequality). It +// also does not support distance functions based on +// inner-products. +// +// For the purpose of computing nearest neighbors, it is not +// necessary to compute the final power (1/p). Thus the only +// component that is used by the program is |v(i)|^p. +// +// ANN parameterizes the distance computation through the following +// macros. (Macros are used rather than procedures for +// efficiency.) Recall that the distance between two points is +// given by the length of the vector joining them, and the length +// or norm of a vector v is given by formula: +// +// |v| = ROOT(POW(v0) # POW(v1) # ... # POW(v(d-1))) +// +// where ROOT, POW are unary functions and # is an associative and +// commutative binary operator mapping the following types: +// +// ** POW: ANNcoord --> ANNdist +// ** #: ANNdist x ANNdist --> ANNdist +// ** ROOT: ANNdist (>0) --> double +// +// For early termination in distance calculation (partial distance +// calculation) we assume that POW and # together are monotonically +// increasing on sequences of arguments, meaning that for all +// v0..vk and y: +// +// POW(v0) #...# POW(vk) <= (POW(v0) #...# POW(vk)) # POW(y). +// +// Incremental Distance Calculation: +// The program uses an optimized method of computing distances for +// kd-trees and bd-trees, called incremental distance calculation. +// It is used when distances are to be updated when only a single +// coordinate of a point has been changed. In order to use this, +// we assume that there is an incremental update function DIFF(x,y) +// for #, such that if: +// +// s = x0 # ... # xi # ... # xk +// +// then if s' is equal to s but with xi replaced by y, that is, +// +// s' = x0 # ... # y # ... # xk +// +// then the length of s' can be computed by: +// +// |s'| = |s| # DIFF(xi,y). +// +// Thus, if # is + then DIFF(xi,y) is (yi-x). For the L_infinity +// norm we make use of the fact that in the program this function +// is only invoked when y > xi, and hence DIFF(xi,y)=y. +// +// Finally, for approximate nearest neighbor queries we assume +// that POW and ROOT are related such that +// +// v*ROOT(x) = ROOT(POW(v)*x) +// +// Here are the values for the various Minkowski norms: +// +// L_p: p even: p odd: +// ------------------------- ------------------------ +// POW(v) = v^p POW(v) = |v|^p +// ROOT(x) = x^(1/p) ROOT(x) = x^(1/p) +// # = + # = + +// DIFF(x,y) = y - x DIFF(x,y) = y - x +// +// L_inf: +// POW(v) = |v| +// ROOT(x) = x +// # = max +// DIFF(x,y) = y +// +// By default the Euclidean norm is assumed. To change the norm, +// uncomment the appropriate set of macros below. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Use the following for the Euclidean norm +//---------------------------------------------------------------------- +#define ANN_POW(v) ((v)*(v)) +#define ANN_ROOT(x) sqrt(x) +#define ANN_SUM(x,y) ((x) + (y)) +#define ANN_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Use the following for the L_1 (Manhattan) norm +//---------------------------------------------------------------------- +// #define ANN_POW(v) fabs(v) +// #define ANN_ROOT(x) (x) +// #define ANN_SUM(x,y) ((x) + (y)) +// #define ANN_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Use the following for a general L_p norm +//---------------------------------------------------------------------- +// #define ANN_POW(v) pow(fabs(v),p) +// #define ANN_ROOT(x) pow(fabs(x),1/p) +// #define ANN_SUM(x,y) ((x) + (y)) +// #define ANN_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Use the following for the L_infinity (Max) norm +//---------------------------------------------------------------------- +// #define ANN_POW(v) fabs(v) +// #define ANN_ROOT(x) (x) +// #define ANN_SUM(x,y) ((x) > (y) ? (x) : (y)) +// #define ANN_DIFF(x,y) (y) + +//---------------------------------------------------------------------- +// Array types +// The following array types are of basic interest. A point is +// just a dimensionless array of coordinates, a point array is a +// dimensionless array of points. A distance array is a +// dimensionless array of distances and an index array is a +// dimensionless array of point indices. The latter two are used +// when returning the results of k-nearest neighbor queries. +//---------------------------------------------------------------------- + +typedef ANNcoord* ANNpoint; // a point +typedef ANNpoint* ANNpointArray; // an array of points +typedef ANNdist* ANNdistArray; // an array of distances +typedef ANNidx* ANNidxArray; // an array of point indices + +//---------------------------------------------------------------------- +// Basic point and array utilities: +// The following procedures are useful supplements to ANN's nearest +// neighbor capabilities. +// +// annDist(): +// Computes the (squared) distance between a pair of points. +// Note that this routine is not used internally by ANN for +// computing distance calculations. For reasons of efficiency +// this is done using incremental distance calculation. Thus, +// this routine cannot be modified as a method of changing the +// metric. +// +// Because points (somewhat like strings in C) are stored as +// pointers. Consequently, creating and destroying copies of +// points may require storage allocation. These procedures do +// this. +// +// annAllocPt() and annDeallocPt(): +// Allocate a deallocate storage for a single point, and +// return a pointer to it. The argument to AllocPt() is +// used to initialize all components. +// +// annAllocPts() and annDeallocPts(): +// Allocate and deallocate an array of points as well a +// place to store their coordinates, and initializes the +// points to point to their respective coordinates. It +// allocates point storage in a contiguous block large +// enough to store all the points. It performs no +// initialization. +// +// annCopyPt(): +// Creates a copy of a given point, allocating space for +// the new point. It returns a pointer to the newly +// allocated copy. +//---------------------------------------------------------------------- + +DLL_API ANNdist annDist( + int dim, // dimension of space + ANNpoint p, // points + ANNpoint q); + +DLL_API ANNpoint annAllocPt( + int dim, // dimension + ANNcoord c = 0); // coordinate value (all equal) + +DLL_API ANNpointArray annAllocPts( + int n, // number of points + int dim); // dimension + +DLL_API void annDeallocPt( + ANNpoint &p); // deallocate 1 point + +DLL_API void annDeallocPts( + ANNpointArray &pa); // point array + +DLL_API ANNpoint annCopyPt( + int dim, // dimension + ANNpoint source); // point to copy + +//---------------------------------------------------------------------- +//Overall structure: ANN supports a number of different data structures +//for approximate and exact nearest neighbor searching. These are: +// +// ANNbruteForce A simple brute-force search structure. +// ANNkd_tree A kd-tree tree search structure. ANNbd_tree +// A bd-tree tree search structure (a kd-tree with shrink +// capabilities). +// +// At a minimum, each of these data structures support k-nearest +// neighbor queries. The nearest neighbor query, annkSearch, +// returns an integer identifier and the distance to the nearest +// neighbor(s) and annRangeSearch returns the nearest points that +// lie within a given query ball. +// +// Each structure is built by invoking the appropriate constructor +// and passing it (at a minimum) the array of points, the total +// number of points and the dimension of the space. Each structure +// is also assumed to support a destructor and member functions +// that return basic information about the point set. +// +// Note that the array of points is not copied by the data +// structure (for reasons of space efficiency), and it is assumed +// to be constant throughout the lifetime of the search structure. +// +// The search algorithm, annkSearch, is given the query point (q), +// and the desired number of nearest neighbors to report (k), and +// the error bound (eps) (whose default value is 0, implying exact +// nearest neighbors). It returns two arrays which are assumed to +// contain at least k elements: one (nn_idx) contains the indices +// (within the point array) of the nearest neighbors and the other +// (dd) contains the squared distances to these nearest neighbors. +// +// The search algorithm, annkFRSearch, is a fixed-radius kNN +// search. In addition to a query point, it is given a (squared) +// radius bound. (This is done for consistency, because the search +// returns distances as squared quantities.) It does two things. +// First, it computes the k nearest neighbors within the radius +// bound, and second, it returns the total number of points lying +// within the radius bound. It is permitted to set k = 0, in which +// case it effectively answers a range counting query. If the +// error bound epsilon is positive, then the search is approximate +// in the sense that it is free to ignore any point that lies +// outside a ball of radius r/(1+epsilon), where r is the given +// (unsquared) radius bound. +// +// The generic object from which all the search structures are +// dervied is given below. It is a virtual object, and is useless +// by itself. +//---------------------------------------------------------------------- + +class DLL_API ANNpointSet { +public: + virtual ~ANNpointSet() {} // virtual distructor + + virtual void annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0 // error bound + ) = 0; // pure virtual (defined elsewhere) + + virtual int annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // query point + ANNdist sqRad, // squared radius + int k = 0, // number of near neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0 // error bound + ) = 0; // pure virtual (defined elsewhere) + + virtual int theDim() = 0; // return dimension of space + virtual int nPoints() = 0; // return number of points + // return pointer to points + virtual ANNpointArray thePoints() = 0; +}; + +//---------------------------------------------------------------------- +// Brute-force nearest neighbor search: +// The brute-force search structure is very simple but inefficient. +// It has been provided primarily for the sake of comparison with +// and validation of the more complex search structures. +// +// Query processing is the same as described above, but the value +// of epsilon is ignored, since all distance calculations are +// performed exactly. +// +// WARNING: This data structure is very slow, and should not be +// used unless the number of points is very small. +// +// Internal information: +// --------------------- +// This data structure bascially consists of the array of points +// (each a pointer to an array of coordinates). The search is +// performed by a simple linear scan of all the points. +//---------------------------------------------------------------------- + +class DLL_API ANNbruteForce: public ANNpointSet { + int dim; // dimension + int n_pts; // number of points + ANNpointArray pts; // point array +public: + ANNbruteForce( // constructor from point array + ANNpointArray pa, // point array + int n, // number of points + int dd); // dimension + + ~ANNbruteForce(); // destructor + + void annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // query point + ANNdist sqRad, // squared radius + int k = 0, // number of near neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int theDim() // return dimension of space + { return dim; } + + int nPoints() // return number of points + { return n_pts; } + + ANNpointArray thePoints() // return pointer to points + { return pts; } +}; + +//---------------------------------------------------------------------- +// kd- and bd-tree splitting and shrinking rules +// kd-trees supports a collection of different splitting rules. +// In addition to the standard kd-tree splitting rule proposed +// by Friedman, Bentley, and Finkel, we have introduced a +// number of other splitting rules, which seem to perform +// as well or better (for the distributions we have tested). +// +// The splitting methods given below allow the user to tailor +// the data structure to the particular data set. They are +// are described in greater details in the kd_split.cc source +// file. The method ANN_KD_SUGGEST is the method chosen (rather +// subjectively) by the implementors as the one giving the +// fastest performance, and is the default splitting method. +// +// As with splitting rules, there are a number of different +// shrinking rules. The shrinking rule ANN_BD_NONE does no +// shrinking (and hence produces a kd-tree tree). The rule +// ANN_BD_SUGGEST uses the implementors favorite rule. +//---------------------------------------------------------------------- + +enum ANNsplitRule { + ANN_KD_STD = 0, // the optimized kd-splitting rule + ANN_KD_MIDPT = 1, // midpoint split + ANN_KD_FAIR = 2, // fair split + ANN_KD_SL_MIDPT = 3, // sliding midpoint splitting method + ANN_KD_SL_FAIR = 4, // sliding fair split method + ANN_KD_SUGGEST = 5}; // the authors' suggestion for best +const int ANN_N_SPLIT_RULES = 6; // number of split rules + +enum ANNshrinkRule { + ANN_BD_NONE = 0, // no shrinking at all (just kd-tree) + ANN_BD_SIMPLE = 1, // simple splitting + ANN_BD_CENTROID = 2, // centroid splitting + ANN_BD_SUGGEST = 3}; // the authors' suggested choice +const int ANN_N_SHRINK_RULES = 4; // number of shrink rules + +//---------------------------------------------------------------------- +// kd-tree: +// The main search data structure supported by ANN is a kd-tree. +// The main constructor is given a set of points and a choice of +// splitting method to use in building the tree. +// +// Construction: +// ------------- +// The constructor is given the point array, number of points, +// dimension, bucket size (default = 1), and the splitting rule +// (default = ANN_KD_SUGGEST). The point array is not copied, and +// is assumed to be kept constant throughout the lifetime of the +// search structure. There is also a "load" constructor that +// builds a tree from a file description that was created by the +// Dump operation. +// +// Search: +// ------- +// There are two search methods: +// +// Standard search (annkSearch()): +// Searches nodes in tree-traversal order, always visiting +// the closer child first. +// Priority search (annkPriSearch()): +// Searches nodes in order of increasing distance of the +// associated cell from the query point. For many +// distributions the standard search seems to work just +// fine, but priority search is safer for worst-case +// performance. +// +// Printing: +// --------- +// There are two methods provided for printing the tree. Print() +// is used to produce a "human-readable" display of the tree, with +// indenation, which is handy for debugging. Dump() produces a +// format that is suitable reading by another program. There is a +// "load" constructor, which constructs a tree which is assumed to +// have been saved by the Dump() procedure. +// +// Performance and Structure Statistics: +// ------------------------------------- +// The procedure getStats() collects statistics information on the +// tree (its size, height, etc.) See ANNperf.h for information on +// the stats structure it returns. +// +// Internal information: +// --------------------- +// The data structure consists of three major chunks of storage. +// The first (implicit) storage are the points themselves (pts), +// which have been provided by the users as an argument to the +// constructor, or are allocated dynamically if the tree is built +// using the load constructor). These should not be changed during +// the lifetime of the search structure. It is the user's +// responsibility to delete these after the tree is destroyed. +// +// The second is the tree itself (which is dynamically allocated in +// the constructor) and is given as a pointer to its root node +// (root). These nodes are automatically deallocated when the tree +// is deleted. See the file src/kd_tree.h for further information +// on the structure of the tree nodes. +// +// Each leaf of the tree does not contain a pointer directly to a +// point, but rather contains a pointer to a "bucket", which is an +// array consisting of point indices. The third major chunk of +// storage is an array (pidx), which is a large array in which all +// these bucket subarrays reside. (The reason for storing them +// separately is the buckets are typically small, but of varying +// sizes. This was done to avoid fragmentation.) This array is +// also deallocated when the tree is deleted. +// +// In addition to this, the tree consists of a number of other +// pieces of information which are used in searching and for +// subsequent tree operations. These consist of the following: +// +// dim Dimension of space +// n_pts Number of points currently in the tree +// n_max Maximum number of points that are allowed +// in the tree +// bkt_size Maximum bucket size (no. of points per leaf) +// bnd_box_lo Bounding box low point +// bnd_box_hi Bounding box high point +// splitRule Splitting method used +// +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Some types and objects used by kd-tree functions +// See src/kd_tree.h and src/kd_tree.cpp for definitions +//---------------------------------------------------------------------- +class ANNkdStats; // stats on kd-tree +class ANNkd_node; // generic node in a kd-tree +typedef ANNkd_node* ANNkd_ptr; // pointer to a kd-tree node + +class DLL_API ANNkd_tree: public ANNpointSet { +protected: + int dim; // dimension of space + int n_pts; // number of points in tree + int bkt_size; // bucket size + ANNpointArray pts; // the points + ANNidxArray pidx; // point indices (to pts array) + ANNkd_ptr root; // root of kd-tree + ANNpoint bnd_box_lo; // bounding box low point + ANNpoint bnd_box_hi; // bounding box high point + + void SkeletonTree( // construct skeleton tree + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNpointArray pa = NULL, // point array (optional) + ANNidxArray pi = NULL); // point indices (optional) + +public: + ANNkd_tree( // build skeleton tree + int n = 0, // number of points + int dd = 0, // dimension + int bs = 1); // bucket size + + ANNkd_tree( // build from point array + ANNpointArray pa, // point array + int n, // number of points + int dd, // dimension + int bs = 1, // bucket size + ANNsplitRule split = ANN_KD_SUGGEST); // splitting method + + ANNkd_tree( // build from dump file + std::istream& in); // input stream for dump file + + ~ANNkd_tree(); // tree destructor + + void annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0); // error bound + + void annkPriSearch( // priority k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0); // error bound + + // added by vlad to allow user to update flops by calling this function + // even if ANN_PERF is not defined + int annkFRSearchFlops( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0, // error bound + int * flops=NULL); // returns the number of floating ops performed by this query + + int annkFRSearchUnordered( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int annkFRSearchUnorderedFlops( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0, // error bound + int * flops=NULL); // returns the number of floating ops performed by this query + + + int theDim() // return dimension of space + { return dim; } + + int nPoints() // return number of points + { return n_pts; } + + ANNpointArray thePoints() // return pointer to points + { return pts; } + + virtual void Print( // print the tree (for debugging) + ANNbool with_pts, // print points as well? + std::ostream& out); // output stream + + virtual void Dump( // dump entire tree + ANNbool with_pts, // print points as well? + std::ostream& out); // output stream + + virtual void getStats( // compute tree statistics + ANNkdStats& st); // the statistics (modified) +}; + +//---------------------------------------------------------------------- +// Box decomposition tree (bd-tree) +// The bd-tree is inherited from a kd-tree. The main difference +// in the bd-tree and the kd-tree is a new type of internal node +// called a shrinking node (in the kd-tree there is only one type +// of internal node, a splitting node). The shrinking node +// makes it possible to generate balanced trees in which the +// cells have bounded aspect ratio, by allowing the decomposition +// to zoom in on regions of dense point concentration. Although +// this is a nice idea in theory, few point distributions are so +// densely clustered that this is really needed. +//---------------------------------------------------------------------- + +class DLL_API ANNbd_tree: public ANNkd_tree { +public: + ANNbd_tree( // build skeleton tree + int n, // number of points + int dd, // dimension + int bs = 1) // bucket size + : ANNkd_tree(n, dd, bs) {} // build base kd-tree + + ANNbd_tree( // build from point array + ANNpointArray pa, // point array + int n, // number of points + int dd, // dimension + int bs = 1, // bucket size + ANNsplitRule split = ANN_KD_SUGGEST, // splitting rule + ANNshrinkRule shrink = ANN_BD_SUGGEST); // shrinking rule + + ANNbd_tree( // build from dump file + std::istream& in); // input stream for dump file +}; + +//---------------------------------------------------------------------- +// Other functions +// annMaxPtsVisit Sets a limit on the maximum number of points +// to visit in the search. +// annClose Can be called when all use of ANN is finished. +// It clears up a minor memory leak. +//---------------------------------------------------------------------- + +DLL_API void annMaxPtsVisit( // max. pts to visit in search + int maxPts); // the limit + +DLL_API void annClose(); // called to end use of ANN + +#endif diff --git a/external/ann_1.1.1/include/ANN/ANNperf.h b/external/ann_1.1.1/include/ANN/ANNperf.h new file mode 100644 index 0000000..e2eeea1 --- /dev/null +++ b/external/ann_1.1.1/include/ANN/ANNperf.h @@ -0,0 +1,228 @@ +//---------------------------------------------------------------------- +// File: ANNperf.h +// Programmer: Sunil Arya and David Mount +// Last modified: 03/04/98 (Release 0.1) +// Description: Include file for ANN performance stats +// +// Some of the code for statistics gathering has been adapted +// from the SmplStat.h package in the g++ library. +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added ANN_ prefix to avoid name conflicts. +//---------------------------------------------------------------------- + +#ifndef ANNperf_H +#define ANNperf_H + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- + +#include // basic ANN includes + +//---------------------------------------------------------------------- +// kd-tree stats object +// This object is used for collecting information about a kd-tree +// or bd-tree. +//---------------------------------------------------------------------- + +class ANNkdStats { // stats on kd-tree +public: + int dim; // dimension of space + int n_pts; // no. of points + int bkt_size; // bucket size + int n_lf; // no. of leaves (including trivial) + int n_tl; // no. of trivial leaves (no points) + int n_spl; // no. of splitting nodes + int n_shr; // no. of shrinking nodes (for bd-trees) + int depth; // depth of tree + float sum_ar; // sum of leaf aspect ratios + float avg_ar; // average leaf aspect ratio + // + // reset stats + void reset(int d=0, int n=0, int bs=0) + { + dim = d; n_pts = n; bkt_size = bs; + n_lf = n_tl = n_spl = n_shr = depth = 0; + sum_ar = avg_ar = 0.0; + } + + ANNkdStats() // basic constructor + { reset(); } + + void merge(const ANNkdStats &st); // merge stats from child +}; + +//---------------------------------------------------------------------- +// ANNsampStat +// A sample stat collects numeric (double) samples and returns some +// simple statistics. Its main functions are: +// +// reset() Reset to no samples. +// += x Include sample x. +// samples() Return number of samples. +// mean() Return mean of samples. +// stdDev() Return standard deviation +// min() Return minimum of samples. +// max() Return maximum of samples. +//---------------------------------------------------------------------- +class DLL_API ANNsampStat { + int n; // number of samples + double sum; // sum + double sum2; // sum of squares + double minVal, maxVal; // min and max +public : + void reset() // reset everything + { + n = 0; + sum = sum2 = 0; + minVal = ANN_DBL_MAX; + maxVal = -ANN_DBL_MAX; + } + + ANNsampStat() { reset(); } // constructor + + void operator+=(double x) // add sample + { + n++; sum += x; sum2 += x*x; + if (x < minVal) minVal = x; + if (x > maxVal) maxVal = x; + } + + int samples() { return n; } // number of samples + + double mean() { return sum/n; } // mean + + // standard deviation + double stdDev() { return sqrt((sum2 - (sum*sum)/n)/(n-1));} + + double min() { return minVal; } // minimum + double max() { return maxVal; } // maximum +}; + +//---------------------------------------------------------------------- +// Operation count updates +//---------------------------------------------------------------------- + +// defined by Vlad (05-01-2008) to get flop count even in Release version for some functions, +// while keeping the main functions fast +#define ANN_FLOP_ALWAYS(n) {ann_Nfloat_ops += (n);} +// end Vlad's modification + +#ifdef ANN_PERF + #define ANN_FLOP(n) {ann_Nfloat_ops += (n);} + #define ANN_LEAF(n) {ann_Nvisit_lfs += (n);} + #define ANN_SPL(n) {ann_Nvisit_spl += (n);} + #define ANN_SHR(n) {ann_Nvisit_shr += (n);} + #define ANN_PTS(n) {ann_Nvisit_pts += (n);} + #define ANN_COORD(n) {ann_Ncoord_hts += (n);} +#else + #define ANN_FLOP(n) + #define ANN_LEAF(n) + #define ANN_SPL(n) + #define ANN_SHR(n) + #define ANN_PTS(n) + #define ANN_COORD(n) +#endif + +//---------------------------------------------------------------------- +// Performance statistics +// The following data and routines are used for computing performance +// statistics for nearest neighbor searching. Because these routines +// can slow the code down, they can be activated and deactiviated by +// defining the ANN_PERF variable, by compiling with the option: +// -DANN_PERF +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Global counters for performance measurement +// +// visit_lfs The number of leaf nodes visited in the +// tree. +// +// visit_spl The number of splitting nodes visited in the +// tree. +// +// visit_shr The number of shrinking nodes visited in the +// tree. +// +// visit_pts The number of points visited in all the +// leaf nodes visited. Equivalently, this +// is the number of points for which distance +// calculations are performed. +// +// coord_hts The number of times a coordinate of a +// data point is accessed. This is generally +// less than visit_pts*d if partial distance +// calculation is used. This count is low +// in the sense that if a coordinate is hit +// many times in the same routine we may +// count it only once. +// +// float_ops The number of floating point operations. +// This includes all operations in the heap +// as well as distance calculations to boxes. +// +// average_err The average error of each query (the +// error of the reported point to the true +// nearest neighbor). For k nearest neighbors +// the error is computed k times. +// +// rank_err The rank error of each query (the difference +// in the rank of the reported point and its +// true rank). +// +// data_pts The number of data points. This is not +// a counter, but used in stats computation. +//---------------------------------------------------------------------- + +extern int ann_Ndata_pts; // number of data points +extern int ann_Nvisit_lfs; // number of leaf nodes visited +extern int ann_Nvisit_spl; // number of splitting nodes visited +extern int ann_Nvisit_shr; // number of shrinking nodes visited +extern int ann_Nvisit_pts; // visited points for one query +extern int ann_Ncoord_hts; // coordinate hits for one query +DLL_API extern int ann_Nfloat_ops; // floating ops for one query // DLL_API added by vlad 4/30/08 +extern ANNsampStat ann_visit_lfs; // stats on leaf nodes visits +extern ANNsampStat ann_visit_spl; // stats on splitting nodes visits +extern ANNsampStat ann_visit_shr; // stats on shrinking nodes visits +extern ANNsampStat ann_visit_nds; // stats on total nodes visits +extern ANNsampStat ann_visit_pts; // stats on points visited +extern ANNsampStat ann_coord_hts; // stats on coordinate hits +DLL_API extern ANNsampStat ann_float_ops; // stats on floating ops // DLL_API added by vlad 4/30/08 +//---------------------------------------------------------------------- +// The following need to be part of the public interface, because +// they are accessed outside the DLL in ann_test.cpp. +//---------------------------------------------------------------------- +DLL_API extern ANNsampStat ann_average_err; // average error +DLL_API extern ANNsampStat ann_rank_err; // rank error + +//---------------------------------------------------------------------- +// Declaration of externally accessible routines for statistics +//---------------------------------------------------------------------- + +DLL_API void annResetStats(int data_size); // reset stats for a set of queries + +DLL_API void annResetCounts(); // reset counts for one queries + +DLL_API void annUpdateStats(); // update stats with current counts + +DLL_API void annPrintStats(ANNbool validate); // print statistics for a run + +#endif diff --git a/external/ann_1.1.1/include/ANN/ANNx.h b/external/ann_1.1.1/include/ANN/ANNx.h new file mode 100644 index 0000000..34a4830 --- /dev/null +++ b/external/ann_1.1.1/include/ANN/ANNx.h @@ -0,0 +1,167 @@ +//---------------------------------------------------------------------- +// File: ANNx.h +// Programmer: Sunil Arya and David Mount +// Last modified: 03/04/98 (Release 0.1) +// Description: Internal include file for ANN +// +// These declarations are of use in manipulating some of +// the internal data objects appearing in ANN, but are not +// needed for applications just using the nearest neighbor +// search. +// +// Typical users of ANN should not need to access this file. +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed LO, HI, IN, OUT to ANN_LO, ANN_HI, etc. +//---------------------------------------------------------------------- + +#ifndef ANNx_H +#define ANNx_H + +#include // I/O manipulators +#include // ANN includes + +//---------------------------------------------------------------------- +// Global constants and types +//---------------------------------------------------------------------- +enum {ANN_LO=0, ANN_HI=1}; // splitting indices +enum {ANN_IN=0, ANN_OUT=1}; // shrinking indices + // what to do in case of error +enum ANNerr {ANNwarn = 0, ANNabort = 1}; + +//---------------------------------------------------------------------- +// Maximum number of points to visit +// We have an option for terminating the search early if the +// number of points visited exceeds some threshold. If the +// threshold is 0 (its default) this means there is no limit +// and the algorithm applies its normal termination condition. +//---------------------------------------------------------------------- + +extern int ANNmaxPtsVisited; // maximum number of pts visited +extern int ANNptsVisited; // number of pts visited in search + +//---------------------------------------------------------------------- +// Global function declarations +//---------------------------------------------------------------------- + +void annError( // ANN error routine + char *msg, // error message + ANNerr level); // level of error + +void annPrintPt( // print a point + ANNpoint pt, // the point + int dim, // the dimension + std::ostream &out); // output stream + +//---------------------------------------------------------------------- +// Orthogonal (axis aligned) rectangle +// Orthogonal rectangles are represented by two points, one +// for the lower left corner (min coordinates) and the other +// for the upper right corner (max coordinates). +// +// The constructor initializes from either a pair of coordinates, +// pair of points, or another rectangle. Note that all constructors +// allocate new point storage. The destructor deallocates this +// storage. +// +// BEWARE: Orthogonal rectangles should be passed ONLY BY REFERENCE. +// (C++'s default copy constructor will not allocate new point +// storage, then on return the destructor free's storage, and then +// you get into big trouble in the calling procedure.) +//---------------------------------------------------------------------- + +class ANNorthRect { +public: + ANNpoint lo; // rectangle lower bounds + ANNpoint hi; // rectangle upper bounds +// + ANNorthRect( // basic constructor + int dd, // dimension of space + ANNcoord l=0, // default is empty + ANNcoord h=0) + { lo = annAllocPt(dd, l); hi = annAllocPt(dd, h); } + + ANNorthRect( // (almost a) copy constructor + int dd, // dimension + const ANNorthRect &r) // rectangle to copy + { lo = annCopyPt(dd, r.lo); hi = annCopyPt(dd, r.hi); } + + ANNorthRect( // construct from points + int dd, // dimension + ANNpoint l, // low point + ANNpoint h) // hight point + { lo = annCopyPt(dd, l); hi = annCopyPt(dd, h); } + + ~ANNorthRect() // destructor + { annDeallocPt(lo); annDeallocPt(hi); } + + ANNbool inside(int dim, ANNpoint p);// is point p inside rectangle? +}; + +void annAssignRect( // assign one rect to another + int dim, // dimension (both must be same) + ANNorthRect &dest, // destination (modified) + const ANNorthRect &source); // source + +//---------------------------------------------------------------------- +// Orthogonal (axis aligned) halfspace +// An orthogonal halfspace is represented by an integer cutting +// dimension cd, coordinate cutting value, cv, and side, sd, which is +// either +1 or -1. Our convention is that point q lies in the (closed) +// halfspace if (q[cd] - cv)*sd >= 0. +//---------------------------------------------------------------------- + +class ANNorthHalfSpace { +public: + int cd; // cutting dimension + ANNcoord cv; // cutting value + int sd; // which side +// + ANNorthHalfSpace() // default constructor + { cd = 0; cv = 0; sd = 0; } + + ANNorthHalfSpace( // basic constructor + int cdd, // dimension of space + ANNcoord cvv, // cutting value + int sdd) // side + { cd = cdd; cv = cvv; sd = sdd; } + + ANNbool in(ANNpoint q) const // is q inside halfspace? + { return (ANNbool) ((q[cd] - cv)*sd >= 0); } + + ANNbool out(ANNpoint q) const // is q outside halfspace? + { return (ANNbool) ((q[cd] - cv)*sd < 0); } + + ANNdist dist(ANNpoint q) const // (squared) distance from q + { return (ANNdist) ANN_POW(q[cd] - cv); } + + void setLowerBound(int d, ANNpoint p)// set to lower bound at p[i] + { cd = d; cv = p[d]; sd = +1; } + + void setUpperBound(int d, ANNpoint p)// set to upper bound at p[i] + { cd = d; cv = p[d]; sd = -1; } + + void project(ANNpoint &q) // project q (modified) onto halfspace + { if (out(q)) q[cd] = cv; } +}; + + // array of halfspaces +typedef ANNorthHalfSpace *ANNorthHSArray; + +#endif diff --git a/external/ann_1.1.1/sample/Makefile b/external/ann_1.1.1/sample/Makefile new file mode 100644 index 0000000..4b742ff --- /dev/null +++ b/external/ann_1.1.1/sample/Makefile @@ -0,0 +1,90 @@ +#----------------------------------------------------------------------------- +# Makefile for the sample program +# +# ANN: Approximate Nearest Neighbors +# Version: 1.1.1 08/04/06 +#----------------------------------------------------------------------------- +# Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +# David Mount. All Rights Reserved. +# +# This software and related documentation is part of the Approximate +# Nearest Neighbor Library (ANN). This software is provided under +# the provisions of the Lesser GNU Public License (LGPL). See the +# file ../ReadMe.txt for further information. +# +# The University of Maryland (U.M.) and the authors make no +# representations about the suitability or fitness of this software for +# any purpose. It is provided "as is" without express or implied +# warranty. +#----------------------------------------------------------------------------- +# Revision 0.1 03/04/98 +# Initial release +# Revision 1.1.1 08/04/06 +# Added copyright/license +#----------------------------------------------------------------------------- +# Note: For full performance measurements, it is assumed that the library +# and this program have both been compiled with the -DPERF flag. See the +# Makefile in the ANN base directory for this flag. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Basic definitions +# BASEDIR where include, src, lib, ... are +# INCDIR include directory +# LIBDIR library directory +# BINDIR bin directory +# LDFLAGS loader flags +# ANNLIBS libraries +#----------------------------------------------------------------------------- + +BASEDIR = .. +INCDIR = $(BASEDIR)/include +LIBDIR = $(BASEDIR)/lib +BINDIR = $(BASEDIR)/bin +LDFLAGS = -L$(LIBDIR) +ANNLIBS = -lann_figtree_version -lm + +#----------------------------------------------------------------------------- +# Some more definitions +# ANNSAMP name of sample program +#----------------------------------------------------------------------------- + +ANNSAMP = ann_sample + +SAMPSOURCES = ann_sample.cpp +SAMPOBJECTS = $(SAMPSOURCES:.cpp=.o) + +#----------------------------------------------------------------------------- +# Make the program +#----------------------------------------------------------------------------- + +default: + @echo "Specify a target configuration" + +targets: $(BINDIR)/$(ANNSAMP) + +$(BINDIR)/$(ANNSAMP): $(SAMPOBJECTS) $(LIBDIR)/$(ANNLIB) + $(C++) $(SAMPOBJECTS) -o $(ANNSAMP) $(LDFLAGS) $(ANNLIBS) + mv $(ANNSAMP) $(BINDIR) + +#----------------------------------------------------------------------------- +# configuration definitions +#----------------------------------------------------------------------------- + +include ../Make-config + +#----------------------------------------------------------------------------- +# Objects +#----------------------------------------------------------------------------- + +ann_sample.o: ann_sample.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) ann_sample.cpp + +#----------------------------------------------------------------------------- +# Cleaning +#----------------------------------------------------------------------------- + +clean: + -rm -f *.o *.out core + +realclean: clean diff --git a/external/ann_1.1.1/sample/ann_sample.cpp b/external/ann_1.1.1/sample/ann_sample.cpp new file mode 100644 index 0000000..5d8647a --- /dev/null +++ b/external/ann_1.1.1/sample/ann_sample.cpp @@ -0,0 +1,198 @@ +//---------------------------------------------------------------------- +// File: ann_sample.cpp +// Programmer: Sunil Arya and David Mount +// Last modified: 03/04/98 (Release 0.1) +// Description: Sample program for ANN +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- + +#include // C standard library +#include // C I/O (for sscanf) +#include // string manipulation +#include // file I/O +#include // ANN declarations + +using namespace std; // make std:: accessible + +//---------------------------------------------------------------------- +// ann_sample +// +// This is a simple sample program for the ANN library. After compiling, +// it can be run as follows. +// +// ann_sample [-d dim] [-max mpts] [-nn k] [-e eps] [-df data] [-qf query] +// +// where +// dim is the dimension of the space (default = 2) +// mpts maximum number of data points (default = 1000) +// k number of nearest neighbors per query (default 1) +// eps is the error bound (default = 0.0) +// data file containing data points +// query file containing query points +// +// Results are sent to the standard output. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Parameters that are set in getArgs() +//---------------------------------------------------------------------- +void getArgs(int argc, char **argv); // get command-line arguments + +int k = 1; // number of nearest neighbors +int dim = 2; // dimension +double eps = 0; // error bound +int maxPts = 1000; // maximum number of data points + +istream* dataIn = NULL; // input for data points +istream* queryIn = NULL; // input for query points + +bool readPt(istream &in, ANNpoint p) // read point (false on EOF) +{ + for (int i = 0; i < dim; i++) { + if(!(in >> p[i])) return false; + } + return true; +} + +void printPt(ostream &out, ANNpoint p) // print point +{ + out << "(" << p[0]; + for (int i = 1; i < dim; i++) { + out << ", " << p[i]; + } + out << ")\n"; +} + +int main(int argc, char **argv) +{ + int nPts; // actual number of data points + ANNpointArray dataPts; // data points + ANNpoint queryPt; // query point + ANNidxArray nnIdx; // near neighbor indices + ANNdistArray dists; // near neighbor distances + ANNkd_tree* kdTree; // search structure + + getArgs(argc, argv); // read command-line arguments + + queryPt = annAllocPt(dim); // allocate query point + dataPts = annAllocPts(maxPts, dim); // allocate data points + nnIdx = new ANNidx[k]; // allocate near neigh indices + dists = new ANNdist[k]; // allocate near neighbor dists + + nPts = 0; // read data points + + cout << "Data Points:\n"; + while (nPts < maxPts && readPt(*dataIn, dataPts[nPts])) { + printPt(cout, dataPts[nPts]); + nPts++; + } + + kdTree = new ANNkd_tree( // build search structure + dataPts, // the data points + nPts, // number of points + dim); // dimension of space + + while (readPt(*queryIn, queryPt)) { // read query points + cout << "Query point: "; // echo query point + printPt(cout, queryPt); + + kdTree->annkSearch( // search + queryPt, // query point + k, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + eps); // error bound + + cout << "\tNN:\tIndex\tDistance\n"; + for (int i = 0; i < k; i++) { // print summary + dists[i] = sqrt(dists[i]); // unsquare distance + cout << "\t" << i << "\t" << nnIdx[i] << "\t" << dists[i] << "\n"; + } + } + delete [] nnIdx; // clean things up + delete [] dists; + delete kdTree; + annClose(); // done with ANN + + return EXIT_SUCCESS; +} + +//---------------------------------------------------------------------- +// getArgs - get command line arguments +//---------------------------------------------------------------------- + +void getArgs(int argc, char **argv) +{ + static ifstream dataStream; // data file stream + static ifstream queryStream; // query file stream + + if (argc <= 1) { // no arguments + cerr << "Usage:\n\n" + << " ann_sample [-d dim] [-max m] [-nn k] [-e eps] [-df data]" + " [-qf query]\n\n" + << " where:\n" + << " dim dimension of the space (default = 2)\n" + << " m maximum number of data points (default = 1000)\n" + << " k number of nearest neighbors per query (default 1)\n" + << " eps the error bound (default = 0.0)\n" + << " data name of file containing data points\n" + << " query name of file containing query points\n\n" + << " Results are sent to the standard output.\n" + << "\n" + << " To run this demo use:\n" + << " ann_sample -df data.pts -qf query.pts\n"; + exit(0); + } + int i = 1; + while (i < argc) { // read arguments + if (!strcmp(argv[i], "-d")) { // -d option + dim = atoi(argv[++i]); // get dimension to dump + } + else if (!strcmp(argv[i], "-max")) { // -max option + maxPts = atoi(argv[++i]); // get max number of points + } + else if (!strcmp(argv[i], "-nn")) { // -nn option + k = atoi(argv[++i]); // get number of near neighbors + } + else if (!strcmp(argv[i], "-e")) { // -e option + sscanf(argv[++i], "%lf", &eps); // get error bound + } + else if (!strcmp(argv[i], "-df")) { // -df option + dataStream.open(argv[++i], ios::in);// open data file + if (!dataStream) { + cerr << "Cannot open data file\n"; + exit(1); + } + dataIn = &dataStream; // make this the data stream + } + else if (!strcmp(argv[i], "-qf")) { // -qf option + queryStream.open(argv[++i], ios::in);// open query file + if (!queryStream) { + cerr << "Cannot open query file\n"; + exit(1); + } + queryIn = &queryStream; // make this query stream + } + else { // illegal syntax + cerr << "Unrecognized option.\n"; + exit(1); + } + i++; + } + if (dataIn == NULL || queryIn == NULL) { + cerr << "-df and -qf options must be specified\n"; + exit(1); + } +} diff --git a/external/ann_1.1.1/sample/data.pts b/external/ann_1.1.1/sample/data.pts new file mode 100644 index 0000000..b00c1d7 --- /dev/null +++ b/external/ann_1.1.1/sample/data.pts @@ -0,0 +1,20 @@ +-0.297462 0.176102 +0.565538 -0.361496 +0.909313 -0.182785 +0.920712 0.478408 +0.167682 0.0499836 +0.305223 -0.0805835 +0.114973 0.882453 +0.742916 0.16376 +0.0724605 -0.826775 +0.690960 -0.559284 +0.188485 -0.643934 +0.749427 -0.942415 +-0.970662 -0.223466 +0.916110 0.879597 +0.927417 -0.382593 +-0.711327 0.278713 +-0.519172 0.986146 +0.135338 0.924588 +-0.0837537 0.61687 +0.0520465 0.896306 diff --git a/external/ann_1.1.1/sample/query.pts b/external/ann_1.1.1/sample/query.pts new file mode 100644 index 0000000..a2b1f6d --- /dev/null +++ b/external/ann_1.1.1/sample/query.pts @@ -0,0 +1,10 @@ +0.0902484 -0.207129 +-0.419567 0.485743 +0.826225 -0.30962 +0.694758 0.987088 +-0.410807 -0.465182 +-0.836501 0.490184 +0.588289 0.656408 +0.325807 0.38721 +-0.532226 -0.727036 +-0.52506 -0.853508 diff --git a/external/ann_1.1.1/sample/sample.save b/external/ann_1.1.1/sample/sample.save new file mode 100644 index 0000000..4151e7d --- /dev/null +++ b/external/ann_1.1.1/sample/sample.save @@ -0,0 +1,51 @@ +Data Points: +(-0.297462, 0.176102) +(0.565538, -0.361496) +(0.909313, -0.182785) +(0.920712, 0.478408) +(0.167682, 0.0499836) +(0.305223, -0.0805835) +(0.114973, 0.882453) +(0.742916, 0.16376) +(0.0724605, -0.826775) +(0.69096, -0.559284) +(0.188485, -0.643934) +(0.749427, -0.942415) +(-0.970662, -0.223466) +(0.91611, 0.879597) +(0.927417, -0.382593) +(-0.711327, 0.278713) +(-0.519172, 0.986146) +(0.135338, 0.924588) +(-0.0837537, 0.61687) +(0.0520465, 0.896306) +Query point: (0.0902484, -0.207129) + NN: Index Distance + 0 5 0.249455 +Query point: (-0.419567, 0.485743) + NN: Index Distance + 0 0 0.332847 +Query point: (0.826225, -0.30962) + NN: Index Distance + 0 14 0.124759 +Query point: (0.694758, 0.987088) + NN: Index Distance + 0 13 0.246071 +Query point: (-0.410807, -0.465182) + NN: Index Distance + 0 8 0.60357 +Query point: (-0.836501, 0.490184) + NN: Index Distance + 0 15 0.245741 +Query point: (0.588289, 0.656408) + NN: Index Distance + 0 3 0.37708 +Query point: (0.325807, 0.38721) + NN: Index Distance + 0 4 0.372458 +Query point: (-0.532226, -0.727036) + NN: Index Distance + 0 8 0.612857 +Query point: (-0.52506, -0.853508) + NN: Index Distance + 0 8 0.598118 diff --git a/external/ann_1.1.1/src/ANN.cpp b/external/ann_1.1.1/src/ANN.cpp new file mode 100644 index 0000000..01ab8f1 --- /dev/null +++ b/external/ann_1.1.1/src/ANN.cpp @@ -0,0 +1,198 @@ +//---------------------------------------------------------------------- +// File: ANN.cpp +// Programmer: Sunil Arya and David Mount +// Description: Methods for ANN.h and ANNx.h +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added performance counting to annDist() +//---------------------------------------------------------------------- + +#include // all ANN includes +#include // ANN performance + +using namespace std; // make std:: accessible + +//---------------------------------------------------------------------- +// Point methods +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Distance utility. +// (Note: In the nearest neighbor search, most distances are +// computed using partial distance calculations, not this +// procedure.) +//---------------------------------------------------------------------- + +ANNdist annDist( // interpoint squared distance + int dim, + ANNpoint p, + ANNpoint q) +{ + register int d; + register ANNcoord diff; + register ANNcoord dist; + + dist = 0; + for (d = 0; d < dim; d++) { + diff = p[d] - q[d]; + dist = ANN_SUM(dist, ANN_POW(diff)); + } + ANN_FLOP(3*dim) // performance counts + ANN_PTS(1) + ANN_COORD(dim) + return dist; +} + +//---------------------------------------------------------------------- +// annPrintPoint() prints a point to a given output stream. +//---------------------------------------------------------------------- + +void annPrintPt( // print a point + ANNpoint pt, // the point + int dim, // the dimension + std::ostream &out) // output stream +{ + for (int j = 0; j < dim; j++) { + out << pt[j]; + if (j < dim-1) out << " "; + } +} + +//---------------------------------------------------------------------- +// Point allocation/deallocation: +// +// Because points (somewhat like strings in C) are stored +// as pointers. Consequently, creating and destroying +// copies of points may require storage allocation. These +// procedures do this. +// +// annAllocPt() and annDeallocPt() allocate a deallocate +// storage for a single point, and return a pointer to it. +// +// annAllocPts() allocates an array of points as well a place +// to store their coordinates, and initializes the points to +// point to their respective coordinates. It allocates point +// storage in a contiguous block large enough to store all the +// points. It performs no initialization. +// +// annDeallocPts() should only be used on point arrays allocated +// by annAllocPts since it assumes that points are allocated in +// a block. +// +// annCopyPt() copies a point taking care to allocate storage +// for the new point. +// +// annAssignRect() assigns the coordinates of one rectangle to +// another. The two rectangles must have the same dimension +// (and it is not possible to test this here). +//---------------------------------------------------------------------- + +ANNpoint annAllocPt(int dim, ANNcoord c) // allocate 1 point +{ + ANNpoint p = new ANNcoord[dim]; + for (int i = 0; i < dim; i++) p[i] = c; + return p; +} + +ANNpointArray annAllocPts(int n, int dim) // allocate n pts in dim +{ + ANNpointArray pa = new ANNpoint[n]; // allocate points + ANNpoint p = new ANNcoord[n*dim]; // allocate space for coords + for (int i = 0; i < n; i++) { + pa[i] = &(p[i*dim]); + } + return pa; +} + +void annDeallocPt(ANNpoint &p) // deallocate 1 point +{ + delete [] p; + p = NULL; +} + +void annDeallocPts(ANNpointArray &pa) // deallocate points +{ + delete [] pa[0]; // dealloc coordinate storage + delete [] pa; // dealloc points + pa = NULL; +} + +ANNpoint annCopyPt(int dim, ANNpoint source) // copy point +{ + ANNpoint p = new ANNcoord[dim]; + for (int i = 0; i < dim; i++) p[i] = source[i]; + return p; +} + + // assign one rect to another +void annAssignRect(int dim, ANNorthRect &dest, const ANNorthRect &source) +{ + for (int i = 0; i < dim; i++) { + dest.lo[i] = source.lo[i]; + dest.hi[i] = source.hi[i]; + } +} + + // is point inside rectangle? +ANNbool ANNorthRect::inside(int dim, ANNpoint p) +{ + for (int i = 0; i < dim; i++) { + if (p[i] < lo[i] || p[i] > hi[i]) return ANNfalse; + } + return ANNtrue; +} + +//---------------------------------------------------------------------- +// Error handler +//---------------------------------------------------------------------- + +void annError(char *msg, ANNerr level) +{ + if (level == ANNabort) { + cerr << "ANN: ERROR------->" << msg << "<-------------ERROR\n"; + exit(1); + } + else { + cerr << "ANN: WARNING----->" << msg << "<-------------WARNING\n"; + } +} + +//---------------------------------------------------------------------- +// Limit on number of points visited +// We have an option for terminating the search early if the +// number of points visited exceeds some threshold. If the +// threshold is 0 (its default) this means there is no limit +// and the algorithm applies its normal termination condition. +// This is for applications where there are real time constraints +// on the running time of the algorithm. +//---------------------------------------------------------------------- + +int ANNmaxPtsVisited = 0; // maximum number of pts visited +int ANNptsVisited; // number of pts visited in search + +//---------------------------------------------------------------------- +// Global function declarations +//---------------------------------------------------------------------- + +void annMaxPtsVisit( // set limit on max. pts to visit in search + int maxPts) // the limit +{ + ANNmaxPtsVisited = maxPts; +} diff --git a/external/ann_1.1.1/src/Makefile b/external/ann_1.1.1/src/Makefile new file mode 100644 index 0000000..4c9f155 --- /dev/null +++ b/external/ann_1.1.1/src/Makefile @@ -0,0 +1,121 @@ +#----------------------------------------------------------------------------- +# Makefile for ANN library +#---------------------------------------------------------------------- +# Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +# David Mount. All Rights Reserved. +# +# This software and related documentation is part of the Approximate +# Nearest Neighbor Library (ANN). This software is provided under +# the provisions of the Lesser GNU Public License (LGPL). See the +# file ../ReadMe.txt for further information. +# +# The University of Maryland (U.M.) and the authors make no +# representations about the suitability or fitness of this software for +# any purpose. It is provided "as is" without express or implied +# warranty. +#---------------------------------------------------------------------- +# History: +# Revision 0.1 03/04/98 +# Initial release +# Revision 1.0 04/01/05 +# Renamed files from .cc to .cpp for Microsoft Visual C++ +# Added kd_dump.cpp +# Revision 1.1 05/03/05 +# Added kd_fix_rad_search.cpp and bd_fix_rad_search.cpp +#---------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Some basic definitions: +# BASEDIR where include, src, lib, ... are +# INCLIB include directory +# LIBLIB library directory +#----------------------------------------------------------------------------- +BASEDIR = .. +INCDIR = $(BASEDIR)/include +LIBDIR = $(BASEDIR)/lib + +SOURCES = ANN.cpp brute.cpp kd_tree.cpp kd_util.cpp kd_split.cpp \ + kd_dump.cpp kd_search.cpp kd_pr_search.cpp kd_fix_rad_search.cpp \ + bd_tree.cpp bd_search.cpp bd_pr_search.cpp bd_fix_rad_search.cpp \ + perf.cpp + +HEADERS = kd_tree.h kd_split.h kd_util.h kd_search.h \ + kd_pr_search.h kd_fix_rad_search.h perf.h pr_queue.h pr_queue_k.h + +OBJECTS = $(SOURCES:.cpp=.o) + +#----------------------------------------------------------------------------- +# Make the library +#----------------------------------------------------------------------------- + +default: + @echo "Specify a target configuration" + +targets: $(LIBDIR)/$(ANNLIB) + +$(LIBDIR)/$(ANNLIB): $(OBJECTS) + $(MAKELIB) $(ANNLIB) $(OBJECTS) + $(RANLIB) $(ANNLIB) + mv $(ANNLIB) $(LIBDIR) + +#----------------------------------------------------------------------------- +# Make object files +#----------------------------------------------------------------------------- + +ANN.o: ANN.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) ANN.cpp + +brute.o: brute.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) brute.cpp + +kd_tree.o: kd_tree.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_tree.cpp + +kd_util.o: kd_util.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_util.cpp + +kd_split.o: kd_split.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_split.cpp + +kd_search.o: kd_search.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_search.cpp + +kd_pr_search.o: kd_pr_search.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_pr_search.cpp + +kd_fix_rad_search.o: kd_fix_rad_search.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_fix_rad_search.cpp + +kd_dump.o: kd_dump.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) kd_dump.cpp + +bd_tree.o: bd_tree.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) bd_tree.cpp + +bd_search.o: bd_search.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) bd_search.cpp + +bd_pr_search.o: bd_pr_search.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) bd_pr_search.cpp + +bd_fix_rad_search.o: bd_fix_rad_search.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) bd_fix_rad_search.cpp + +perf.o: perf.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) perf.cpp + +#----------------------------------------------------------------------------- +# Configuration definitions +#----------------------------------------------------------------------------- + +include ../Make-config + +#----------------------------------------------------------------------------- +# Cleaning +#----------------------------------------------------------------------------- + +clean: + -rm -f *.o core + +realclean: clean + diff --git a/external/ann_1.1.1/src/bd_fix_rad_search.cpp b/external/ann_1.1.1/src/bd_fix_rad_search.cpp new file mode 100644 index 0000000..4b2b432 --- /dev/null +++ b/external/ann_1.1.1/src/bd_fix_rad_search.cpp @@ -0,0 +1,90 @@ +//---------------------------------------------------------------------- +// File: bd_fix_rad_search.cpp +// Programmer: David Mount +// Description: Standard bd-tree search +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 1.1 05/03/05 +// Initial release +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_fix_rad_search.h" // kd-tree FR search declarations + +//---------------------------------------------------------------------- +// Approximate searching for bd-trees. +// See the file kd_FR_search.cpp for general information on the +// approximate nearest neighbor search algorithm. Here we +// include the extensions for shrinking nodes. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// bd_shrink::ann_FR_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_FR_search(ANNdist box_dist) +{ + // check dist calc term cond. + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNkdFRQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdFRQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + child[ANN_IN]->ann_FR_search(inner_dist);// search inner child first + child[ANN_OUT]->ann_FR_search(box_dist);// ...then outer child + } + else { // if outer box is closer + child[ANN_OUT]->ann_FR_search(box_dist);// search outer child first + child[ANN_IN]->ann_FR_search(inner_dist);// ...then outer child + } + ANN_FLOP(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} + + +//---------------------------------------------------------------------- +// bd_shrink::ann_FR_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_FR_searchFlops(ANNdist box_dist) +{ + // check dist calc term cond. + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNkdFRQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdFRQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + child[ANN_IN]->ann_FR_searchFlops(inner_dist);// search inner child first + child[ANN_OUT]->ann_FR_searchFlops(box_dist);// ...then outer child + } + else { // if outer box is closer + child[ANN_OUT]->ann_FR_searchFlops(box_dist);// search outer child first + child[ANN_IN]->ann_FR_searchFlops(inner_dist);// ...then outer child + } + ANN_FLOP_ALWAYS(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} diff --git a/external/ann_1.1.1/src/bd_pr_search.cpp b/external/ann_1.1.1/src/bd_pr_search.cpp new file mode 100644 index 0000000..ad980fb --- /dev/null +++ b/external/ann_1.1.1/src/bd_pr_search.cpp @@ -0,0 +1,62 @@ +//---------------------------------------------------------------------- +// File: bd_pr_search.cpp +// Programmer: David Mount +// Description: Priority search for bd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +//History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_pr_search.h" // kd priority search declarations + +//---------------------------------------------------------------------- +// Approximate priority searching for bd-trees. +// See the file kd_pr_search.cc for general information on the +// approximate nearest neighbor priority search algorithm. Here +// we include the extensions for shrinking nodes. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// bd_shrink::ann_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_pri_search(ANNdist box_dist) +{ + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNprQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNprQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + if (child[ANN_OUT] != KD_TRIVIAL) // enqueue outer if not trivial + ANNprBoxPQ->insert(box_dist,child[ANN_OUT]); + // continue with inner child + child[ANN_IN]->ann_pri_search(inner_dist); + } + else { // if outer box is closer + if (child[ANN_IN] != KD_TRIVIAL) // enqueue inner if not trivial + ANNprBoxPQ->insert(inner_dist,child[ANN_IN]); + // continue with outer child + child[ANN_OUT]->ann_pri_search(box_dist); + } + ANN_FLOP(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} diff --git a/external/ann_1.1.1/src/bd_search.cpp b/external/ann_1.1.1/src/bd_search.cpp new file mode 100644 index 0000000..1e49261 --- /dev/null +++ b/external/ann_1.1.1/src/bd_search.cpp @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------- +// File: bd_search.cpp +// Programmer: David Mount +// Description: Standard bd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_search.h" // kd-tree search declarations + +//---------------------------------------------------------------------- +// Approximate searching for bd-trees. +// See the file kd_search.cpp for general information on the +// approximate nearest neighbor search algorithm. Here we +// include the extensions for shrinking nodes. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// bd_shrink::ann_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_search(ANNdist box_dist) +{ + // check dist calc term cond. + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNkdQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + child[ANN_IN]->ann_search(inner_dist); // search inner child first + child[ANN_OUT]->ann_search(box_dist); // ...then outer child + } + else { // if outer box is closer + child[ANN_OUT]->ann_search(box_dist); // search outer child first + child[ANN_IN]->ann_search(inner_dist); // ...then outer child + } + ANN_FLOP(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} diff --git a/external/ann_1.1.1/src/bd_tree.cpp b/external/ann_1.1.1/src/bd_tree.cpp new file mode 100644 index 0000000..99425e4 --- /dev/null +++ b/external/ann_1.1.1/src/bd_tree.cpp @@ -0,0 +1,417 @@ +//---------------------------------------------------------------------- +// File: bd_tree.cpp +// Programmer: David Mount +// Description: Basic methods for bd-trees. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision l.0 04/01/05 +// Fixed centroid shrink threshold condition to depend on the +// dimension. +// Moved dump routine to kd_dump.cpp. +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "kd_split.h" // kd-tree splitting rules + +#include // performance evaluation + +//---------------------------------------------------------------------- +// Printing a bd-tree +// These routines print a bd-tree. See the analogous procedure +// in kd_tree.cpp for more information. +//---------------------------------------------------------------------- + +void ANNbd_shrink::print( // print shrinking node + int level, // depth of node in tree + ostream &out) // output stream +{ + child[ANN_OUT]->print(level+1, out); // print out-child + + out << " "; + for (int i = 0; i < level; i++) // print indentation + out << ".."; + out << "Shrink"; + for (int j = 0; j < n_bnds; j++) { // print sides, 2 per line + if (j % 2 == 0) { + out << "\n"; // newline and indentation + for (int i = 0; i < level+2; i++) out << " "; + } + out << " ([" << bnds[j].cd << "]" + << (bnds[j].sd > 0 ? ">=" : "< ") + << bnds[j].cv << ")"; + } + out << "\n"; + + child[ANN_IN]->print(level+1, out); // print in-child +} + +//---------------------------------------------------------------------- +// kd_tree statistics utility (for performance evaluation) +// This routine computes various statistics information for +// shrinking nodes. See file kd_tree.cpp for more information. +//---------------------------------------------------------------------- + +void ANNbd_shrink::getStats( // get subtree statistics + int dim, // dimension of space + ANNkdStats &st, // stats (modified) + ANNorthRect &bnd_box) // bounding box +{ + ANNkdStats ch_stats; // stats for children + ANNorthRect inner_box(dim); // inner box of shrink + + annBnds2Box(bnd_box, // enclosing box + dim, // dimension + n_bnds, // number of bounds + bnds, // bounds array + inner_box); // inner box (modified) + // get stats for inner child + ch_stats.reset(); // reset + child[ANN_IN]->getStats(dim, ch_stats, inner_box); + st.merge(ch_stats); // merge them + // get stats for outer child + ch_stats.reset(); // reset + child[ANN_OUT]->getStats(dim, ch_stats, bnd_box); + st.merge(ch_stats); // merge them + + st.depth++; // increment depth + st.n_shr++; // increment number of shrinks +} + +//---------------------------------------------------------------------- +// bd-tree constructor +// This is the main constructor for bd-trees given a set of points. +// It first builds a skeleton kd-tree as a basis, then computes the +// bounding box of the data points, and then invokes rbd_tree() to +// actually build the tree, passing it the appropriate splitting +// and shrinking information. +//---------------------------------------------------------------------- + +ANNkd_ptr rbd_tree( // recursive construction of bd-tree + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter, // splitting routine + ANNshrinkRule shrink); // shrinking rule + +ANNbd_tree::ANNbd_tree( // construct from point array + ANNpointArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNsplitRule split, // splitting rule + ANNshrinkRule shrink) // shrinking rule + : ANNkd_tree(n, dd, bs) // build skeleton base tree +{ + pts = pa; // where the points are + if (n == 0) return; // no points--no sweat + + ANNorthRect bnd_box(dd); // bounding box for points + // construct bounding rectangle + annEnclRect(pa, pidx, n, dd, bnd_box); + // copy to tree structure + bnd_box_lo = annCopyPt(dd, bnd_box.lo); + bnd_box_hi = annCopyPt(dd, bnd_box.hi); + + switch (split) { // build by rule + case ANN_KD_STD: // standard kd-splitting rule + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split, shrink); + break; + case ANN_KD_MIDPT: // midpoint split + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split, shrink); + break; + case ANN_KD_SUGGEST: // best (in our opinion) + case ANN_KD_SL_MIDPT: // sliding midpoint split + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split, shrink); + break; + case ANN_KD_FAIR: // fair split + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split, shrink); + break; + case ANN_KD_SL_FAIR: // sliding fair split + root = rbd_tree(pa, pidx, n, dd, bs, + bnd_box, sl_fair_split, shrink); + break; + default: + annError("Illegal splitting method", ANNabort); + } +} + +//---------------------------------------------------------------------- +// Shrinking rules +//---------------------------------------------------------------------- + +enum ANNdecomp {SPLIT, SHRINK}; // decomposition methods + +//---------------------------------------------------------------------- +// trySimpleShrink - Attempt a simple shrink +// +// We compute the tight bounding box of the points, and compute +// the 2*dim ``gaps'' between the sides of the tight box and the +// bounding box. If any of the gaps is large enough relative to +// the longest side of the tight bounding box, then we shrink +// all sides whose gaps are large enough. (The reason for +// comparing against the tight bounding box, is that after +// shrinking the longest box size will decrease, and if we use +// the standard bounding box, we may decide to shrink twice in +// a row. Since the tight box is fixed, we cannot shrink twice +// consecutively.) +//---------------------------------------------------------------------- +const float BD_GAP_THRESH = 0.5; // gap threshold (must be < 1) +const int BD_CT_THRESH = 2; // min number of shrink sides + +ANNdecomp trySimpleShrink( // try a simple shrink + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + const ANNorthRect &bnd_box, // current bounding box + ANNorthRect &inner_box) // inner box if shrinking (returned) +{ + int i; + // compute tight bounding box + annEnclRect(pa, pidx, n, dim, inner_box); + + ANNcoord max_length = 0; // find longest box side + for (i = 0; i < dim; i++) { + ANNcoord length = inner_box.hi[i] - inner_box.lo[i]; + if (length > max_length) { + max_length = length; + } + } + + int shrink_ct = 0; // number of sides we shrunk + for (i = 0; i < dim; i++) { // select which sides to shrink + // gap between boxes + ANNcoord gap_hi = bnd_box.hi[i] - inner_box.hi[i]; + // big enough gap to shrink? + if (gap_hi < max_length*BD_GAP_THRESH) + inner_box.hi[i] = bnd_box.hi[i]; // no - expand + else shrink_ct++; // yes - shrink this side + + // repeat for high side + ANNcoord gap_lo = inner_box.lo[i] - bnd_box.lo[i]; + if (gap_lo < max_length*BD_GAP_THRESH) + inner_box.lo[i] = bnd_box.lo[i]; // no - expand + else shrink_ct++; // yes - shrink this side + } + + if (shrink_ct >= BD_CT_THRESH) // did we shrink enough sides? + return SHRINK; + else return SPLIT; +} + +//---------------------------------------------------------------------- +// tryCentroidShrink - Attempt a centroid shrink +// +// We repeatedly apply the splitting rule, always to the larger subset +// of points, until the number of points decreases by the constant +// fraction BD_FRACTION. If this takes more than dim*BD_MAX_SPLIT_FAC +// splits for this to happen, then we shrink to the final inner box +// Otherwise we split. +//---------------------------------------------------------------------- + +const float BD_MAX_SPLIT_FAC = 0.5; // maximum number of splits allowed +const float BD_FRACTION = 0.5; // ...to reduce points by this fraction + // ...This must be < 1. + +ANNdecomp tryCentroidShrink( // try a centroid shrink + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + const ANNorthRect &bnd_box, // current bounding box + ANNkd_splitter splitter, // splitting procedure + ANNorthRect &inner_box) // inner box if shrinking (returned) +{ + int n_sub = n; // number of points in subset + int n_goal = (int) (n*BD_FRACTION); // number of point in goal + int n_splits = 0; // number of splits needed + // initialize inner box to bounding box + annAssignRect(dim, inner_box, bnd_box); + + while (n_sub > n_goal) { // keep splitting until goal reached + int cd; // cut dim from splitter (ignored) + ANNcoord cv; // cut value from splitter (ignored) + int n_lo; // number of points on low side + // invoke splitting procedure + (*splitter)(pa, pidx, inner_box, n_sub, dim, cd, cv, n_lo); + n_splits++; // increment split count + + if (n_lo >= n_sub/2) { // most points on low side + inner_box.hi[cd] = cv; // collapse high side + n_sub = n_lo; // recurse on lower points + } + else { // most points on high side + inner_box.lo[cd] = cv; // collapse low side + pidx += n_lo; // recurse on higher points + n_sub -= n_lo; + } + } + if (n_splits > dim*BD_MAX_SPLIT_FAC)// took too many splits + return SHRINK; // shrink to final subset + else + return SPLIT; +} + +//---------------------------------------------------------------------- +// selectDecomp - select which decomposition to use +//---------------------------------------------------------------------- + +ANNdecomp selectDecomp( // select decomposition method + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + const ANNorthRect &bnd_box, // current bounding box + ANNkd_splitter splitter, // splitting procedure + ANNshrinkRule shrink, // shrinking rule + ANNorthRect &inner_box) // inner box if shrinking (returned) +{ + ANNdecomp decomp = SPLIT; // decomposition + + switch (shrink) { // check shrinking rule + case ANN_BD_NONE: // no shrinking allowed + decomp = SPLIT; + break; + case ANN_BD_SUGGEST: // author's suggestion + case ANN_BD_SIMPLE: // simple shrink + decomp = trySimpleShrink( + pa, pidx, // points and indices + n, dim, // number of points and dimension + bnd_box, // current bounding box + inner_box); // inner box if shrinking (returned) + break; + case ANN_BD_CENTROID: // centroid shrink + decomp = tryCentroidShrink( + pa, pidx, // points and indices + n, dim, // number of points and dimension + bnd_box, // current bounding box + splitter, // splitting procedure + inner_box); // inner box if shrinking (returned) + break; + default: + annError("Illegal shrinking rule", ANNabort); + } + return decomp; +} + +//---------------------------------------------------------------------- +// rbd_tree - recursive procedure to build a bd-tree +// +// This is analogous to rkd_tree, but for bd-trees. See the +// procedure rkd_tree() in kd_split.cpp for more information. +// +// If the number of points falls below the bucket size, then a +// leaf node is created for the points. Otherwise we invoke the +// procedure selectDecomp() which determines whether we are to +// split or shrink. If splitting is chosen, then we essentially +// do exactly as rkd_tree() would, and invoke the specified +// splitting procedure to the points. Otherwise, the selection +// procedure returns a bounding box, from which we extract the +// appropriate shrinking bounds, and create a shrinking node. +// Finally the points are subdivided, and the procedure is +// invoked recursively on the two subsets to form the children. +//---------------------------------------------------------------------- + +ANNkd_ptr rbd_tree( // recursive construction of bd-tree + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter, // splitting routine + ANNshrinkRule shrink) // shrinking rule +{ + ANNdecomp decomp; // decomposition method + + ANNorthRect inner_box(dim); // inner box (if shrinking) + + if (n <= bsp) { // n small, make a leaf node + if (n == 0) // empty leaf node + return KD_TRIVIAL; // return (canonical) empty leaf + else // construct the node and return + return new ANNkd_leaf(n, pidx); + } + + decomp = selectDecomp( // select decomposition method + pa, pidx, // points and indices + n, dim, // number of points and dimension + bnd_box, // current bounding box + splitter, shrink, // splitting/shrinking methods + inner_box); // inner box if shrinking (returned) + + if (decomp == SPLIT) { // split selected + int cd; // cutting dimension + ANNcoord cv; // cutting value + int n_lo; // number on low side of cut + // invoke splitting procedure + (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); + + ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension + ANNcoord hv = bnd_box.hi[cd]; + + bnd_box.hi[cd] = cv; // modify bounds for left subtree + ANNkd_ptr lo = rbd_tree( // build left subtree + pa, pidx, n_lo, // ...from pidx[0..n_lo-1] + dim, bsp, bnd_box, splitter, shrink); + bnd_box.hi[cd] = hv; // restore bounds + + bnd_box.lo[cd] = cv; // modify bounds for right subtree + ANNkd_ptr hi = rbd_tree( // build right subtree + pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] + dim, bsp, bnd_box, splitter, shrink); + bnd_box.lo[cd] = lv; // restore bounds + // create the splitting node + return new ANNkd_split(cd, cv, lv, hv, lo, hi); + } + else { // shrink selected + int n_in; // number of points in box + int n_bnds; // number of bounding sides + + annBoxSplit( // split points around inner box + pa, // points to split + pidx, // point indices + n, // number of points + dim, // dimension + inner_box, // inner box + n_in); // number of points inside (returned) + + ANNkd_ptr in = rbd_tree( // build inner subtree pidx[0..n_in-1] + pa, pidx, n_in, dim, bsp, inner_box, splitter, shrink); + ANNkd_ptr out = rbd_tree( // build outer subtree pidx[n_in..n] + pa, pidx+n_in, n - n_in, dim, bsp, bnd_box, splitter, shrink); + + ANNorthHSArray bnds = NULL; // bounds (alloc in Box2Bnds and + // ...freed in bd_shrink destroyer) + + annBox2Bnds( // convert inner box to bounds + inner_box, // inner box + bnd_box, // enclosing box + dim, // dimension + n_bnds, // number of bounds (returned) + bnds); // bounds array (modified) + + // return shrinking node + return new ANNbd_shrink(n_bnds, bnds, in, out); + } +} diff --git a/external/ann_1.1.1/src/bd_tree.h b/external/ann_1.1.1/src/bd_tree.h new file mode 100644 index 0000000..45b8c3c --- /dev/null +++ b/external/ann_1.1.1/src/bd_tree.h @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------- +// File: bd_tree.h +// Programmer: David Mount +// Description: Declarations for standard bd-tree routines +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed IN, OUT to ANN_IN, ANN_OUT +//---------------------------------------------------------------------- + +#ifndef ANN_bd_tree_H +#define ANN_bd_tree_H + +#include // all ANN includes +#include "kd_tree.h" // kd-tree includes + +//---------------------------------------------------------------------- +// bd-tree shrinking node. +// The main addition in the bd-tree is the shrinking node, which +// is declared here. +// +// Shrinking nodes are defined by list of orthogonal halfspaces. +// These halfspaces define a (possibly unbounded) orthogonal +// rectangle. There are two children, in and out. Points that +// lie within this rectangle are stored in the in-child, and the +// other points are stored in the out-child. +// +// We use a list of orthogonal halfspaces rather than an +// orthogonal rectangle object because typically the number of +// sides of the shrinking box will be much smaller than the +// worst case bound of 2*dim. +// +// BEWARE: Note that constructor just copies the pointer to the +// bounding array, but the destructor deallocates it. This is +// rather poor practice, but happens to be convenient. The list +// is allocated in the bd-tree building procedure rbd_tree() just +// prior to construction, and is used for no other purposes. +// +// WARNING: In the near neighbor searching code it is assumed that +// the list of bounding halfspaces is irredundant, meaning that there +// are no two distinct halfspaces in the list with the same outward +// pointing normals. +//---------------------------------------------------------------------- + +class ANNbd_shrink : public ANNkd_node // splitting node of a kd-tree +{ + int n_bnds; // number of bounding halfspaces + ANNorthHSArray bnds; // list of bounding halfspaces + ANNkd_ptr child[2]; // in and out children +public: + ANNbd_shrink( // constructor + int nb, // number of bounding halfspaces + ANNorthHSArray bds, // list of bounding halfspaces + ANNkd_ptr ic=NULL, ANNkd_ptr oc=NULL) // children + { + n_bnds = nb; // cutting dimension + bnds = bds; // assign bounds + child[ANN_IN] = ic; // set children + child[ANN_OUT] = oc; + } + + ~ANNbd_shrink() // destructor + { + if (child[ANN_IN]!= NULL && child[ANN_IN]!= KD_TRIVIAL) + delete child[ANN_IN]; + if (child[ANN_OUT]!= NULL&& child[ANN_OUT]!= KD_TRIVIAL) + delete child[ANN_OUT]; + if (bnds != NULL) + delete [] bnds; // delete bounds + } + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box); // bounding box + virtual void print(int level, ostream &out);// print node + virtual void dump(ostream &out); // dump node + + virtual void ann_search(ANNdist); // standard search + virtual void ann_pri_search(ANNdist); // priority search + virtual void ann_FR_search(ANNdist); // fixed-radius search + + // added by Vlad 5-1-08 to update flops even when ANN_PERF is not defined + virtual void ann_FR_searchFlops(ANNdist); // fixed-radius search +}; + +#endif diff --git a/external/ann_1.1.1/src/brute.cpp b/external/ann_1.1.1/src/brute.cpp new file mode 100644 index 0000000..f930adf --- /dev/null +++ b/external/ann_1.1.1/src/brute.cpp @@ -0,0 +1,109 @@ +//---------------------------------------------------------------------- +// File: brute.cpp +// Programmer: Sunil Arya and David Mount +// Description: Brute-force nearest neighbors +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.1 05/03/05 +// Added fixed-radius kNN search +//---------------------------------------------------------------------- + +#include // all ANN includes +#include "pr_queue_k.h" // k element priority queue + +//---------------------------------------------------------------------- +// Brute-force search simply stores a pointer to the list of +// data points and searches linearly for the nearest neighbor. +// The k nearest neighbors are stored in a k-element priority +// queue (which is implemented in a pretty dumb way as well). +// +// If ANN_ALLOW_SELF_MATCH is ANNfalse then data points at distance +// zero are not considered. +// +// Note that the error bound eps is passed in, but it is ignored. +// These routines compute exact nearest neighbors (which is needed +// for validation purposes in ann_test.cpp). +//---------------------------------------------------------------------- + +ANNbruteForce::ANNbruteForce( // constructor from point array + ANNpointArray pa, // point array + int n, // number of points + int dd) // dimension +{ + dim = dd; n_pts = n; pts = pa; +} + +ANNbruteForce::~ANNbruteForce() { } // destructor (empty) + +void ANNbruteForce::annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // dist to near neighbors (returned) + double eps) // error bound (ignored) +{ + ANNmin_k mk(k); // construct a k-limited priority queue + int i; + + if (k > n_pts) { // too many near neighbors? + annError("Requesting more near neighbors than data points", ANNabort); + } + // run every point through queue + for (i = 0; i < n_pts; i++) { + // compute distance to point + ANNdist sqDist = annDist(dim, pts[i], q); + if (ANN_ALLOW_SELF_MATCH || sqDist != 0) + mk.insert(sqDist, i); + } + for (i = 0; i < k; i++) { // extract the k closest points + dd[i] = mk.ith_smallest_key(i); + nn_idx[i] = mk.ith_smallest_info(i); + } +} + +int ANNbruteForce::annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // query point + ANNdist sqRad, // squared radius + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (returned) + ANNdistArray dd, // dist to near neighbors (returned) + double eps) // error bound +{ + ANNmin_k mk(k); // construct a k-limited priority queue + int i; + int pts_in_range = 0; // number of points in query range + // run every point through queue + for (i = 0; i < n_pts; i++) { + // compute distance to point + ANNdist sqDist = annDist(dim, pts[i], q); + if (sqDist <= sqRad && // within radius bound + (ANN_ALLOW_SELF_MATCH || sqDist != 0)) { // ...and no self match + mk.insert(sqDist, i); + pts_in_range++; + } + } + for (i = 0; i < k; i++) { // extract the k closest points + if (dd != NULL) + dd[i] = mk.ith_smallest_key(i); + if (nn_idx != NULL) + nn_idx[i] = mk.ith_smallest_info(i); + } + + return pts_in_range; +} diff --git a/external/ann_1.1.1/src/kd_dump.cpp b/external/ann_1.1.1/src/kd_dump.cpp new file mode 100644 index 0000000..82cf559 --- /dev/null +++ b/external/ann_1.1.1/src/kd_dump.cpp @@ -0,0 +1,444 @@ +//---------------------------------------------------------------------- +// File: kd_dump.cc +// Programmer: David Mount +// Description: Dump and Load for kd- and bd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Moved dump out of kd_tree.cc into this file. +// Added kd-tree load constructor. +//---------------------------------------------------------------------- +// This file contains routines for dumping kd-trees and bd-trees and +// reloading them. (It is an abuse of policy to include both kd- and +// bd-tree routines in the same file, sorry. There should be no problem +// in deleting the bd- versions of the routines if they are not +// desired.) +//---------------------------------------------------------------------- + +#include "kd_tree.h" // kd-tree declarations +#include "bd_tree.h" // bd-tree declarations + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------- + +const int STRING_LEN = 500; // maximum string length +const double EPSILON = 1E-5; // small number for float comparison + +enum ANNtreeType {KD_TREE, BD_TREE}; // tree types (used in loading) + +//---------------------------------------------------------------------- +// Procedure declarations +//---------------------------------------------------------------------- + +static ANNkd_ptr annReadDump( // read dump file + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNpointArray &the_pts, // new points (if applic) + ANNidxArray &the_pidx, // point indices (returned) + int &the_dim, // dimension (returned) + int &the_n_pts, // number of points (returned) + int &the_bkt_size, // bucket size (returned) + ANNpoint &the_bnd_box_lo, // low bounding point + ANNpoint &the_bnd_box_hi); // high bounding point + +static ANNkd_ptr annReadTree( // read tree-part of dump file + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNidxArray the_pidx, // point indices (modified) + int &next_idx); // next index (modified) + +//---------------------------------------------------------------------- +// ANN kd- and bd-tree Dump Format +// The dump file begins with a header containing the version of +// ANN, an optional section containing the points, followed by +// a description of the tree. The tree is printed in preorder. +// +// Format: +// #ANN [END_OF_LINE] +// points (point coordinates: this is optional) +// 0 ... (point indices and coordinates) +// 1 ... +// ... +// tree +// ... (lower end of bounding box) +// ... (upper end of bounding box) +// If the tree is null, then a single line "null" is +// output. Otherwise the nodes of the tree are printed +// one per line in preorder. Leaves and splitting nodes +// have the following formats: +// Leaf node: +// leaf ... +// Splitting nodes: +// split +// +// For bd-trees: +// +// Shrinking nodes: +// shrink +// +// +// ... (repeated n_bnds times) +//---------------------------------------------------------------------- + +void ANNkd_tree::Dump( // dump entire tree + ANNbool with_pts, // print points as well? + ostream &out) // output stream +{ + out << "#ANN " << ANNversion << "\n"; + out.precision(ANNcoordPrec); // use full precision in dumping + if (with_pts) { // print point coordinates + out << "points " << dim << " " << n_pts << "\n"; + for (int i = 0; i < n_pts; i++) { + out << i << " "; + annPrintPt(pts[i], dim, out); + out << "\n"; + } + } + out << "tree " // print tree elements + << dim << " " + << n_pts << " " + << bkt_size << "\n"; + + annPrintPt(bnd_box_lo, dim, out); // print lower bound + out << "\n"; + annPrintPt(bnd_box_hi, dim, out); // print upper bound + out << "\n"; + + if (root == NULL) // empty tree? + out << "null\n"; + else { + root->dump(out); // invoke printing at root + } + out.precision(0); // restore default precision +} + +void ANNkd_split::dump( // dump a splitting node + ostream &out) // output stream +{ + out << "split " << cut_dim << " " << cut_val << " "; + out << cd_bnds[ANN_LO] << " " << cd_bnds[ANN_HI] << "\n"; + + child[ANN_LO]->dump(out); // print low child + child[ANN_HI]->dump(out); // print high child +} + +void ANNkd_leaf::dump( // dump a leaf node + ostream &out) // output stream +{ + if (this == KD_TRIVIAL) { // canonical trivial leaf node + out << "leaf 0\n"; // leaf no points + } + else{ + out << "leaf " << n_pts; + for (int j = 0; j < n_pts; j++) { + out << " " << bkt[j]; + } + out << "\n"; + } +} + +void ANNbd_shrink::dump( // dump a shrinking node + ostream &out) // output stream +{ + out << "shrink " << n_bnds << "\n"; + for (int j = 0; j < n_bnds; j++) { + out << bnds[j].cd << " " << bnds[j].cv << " " << bnds[j].sd << "\n"; + } + child[ANN_IN]->dump(out); // print in-child + child[ANN_OUT]->dump(out); // print out-child +} + +//---------------------------------------------------------------------- +// Load kd-tree from dump file +// This rebuilds a kd-tree which was dumped to a file. The dump +// file contains all the basic tree information according to a +// preorder traversal. We assume that the dump file also contains +// point data. (This is to guarantee the consistency of the tree.) +// If not, then an error is generated. +// +// Indirectly, this procedure allocates space for points, point +// indices, all nodes in the tree, and the bounding box for the +// tree. When the tree is destroyed, all but the points are +// deallocated. +// +// This routine calls annReadDump to do all the work. +//---------------------------------------------------------------------- + +ANNkd_tree::ANNkd_tree( // build from dump file + istream &in) // input stream for dump file +{ + int the_dim; // local dimension + int the_n_pts; // local number of points + int the_bkt_size; // local number of points + ANNpoint the_bnd_box_lo; // low bounding point + ANNpoint the_bnd_box_hi; // high bounding point + ANNpointArray the_pts; // point storage + ANNidxArray the_pidx; // point index storage + ANNkd_ptr the_root; // root of the tree + + the_root = annReadDump( // read the dump file + in, // input stream + KD_TREE, // expecting a kd-tree + the_pts, // point array (returned) + the_pidx, // point indices (returned) + the_dim, the_n_pts, the_bkt_size, // basic tree info (returned) + the_bnd_box_lo, the_bnd_box_hi); // bounding box info (returned) + + // create a skeletal tree + SkeletonTree(the_n_pts, the_dim, the_bkt_size, the_pts, the_pidx); + + bnd_box_lo = the_bnd_box_lo; + bnd_box_hi = the_bnd_box_hi; + + root = the_root; // set the root +} + +ANNbd_tree::ANNbd_tree( // build bd-tree from dump file + istream &in) : ANNkd_tree() // input stream for dump file +{ + int the_dim; // local dimension + int the_n_pts; // local number of points + int the_bkt_size; // local number of points + ANNpoint the_bnd_box_lo; // low bounding point + ANNpoint the_bnd_box_hi; // high bounding point + ANNpointArray the_pts; // point storage + ANNidxArray the_pidx; // point index storage + ANNkd_ptr the_root; // root of the tree + + the_root = annReadDump( // read the dump file + in, // input stream + BD_TREE, // expecting a bd-tree + the_pts, // point array (returned) + the_pidx, // point indices (returned) + the_dim, the_n_pts, the_bkt_size, // basic tree info (returned) + the_bnd_box_lo, the_bnd_box_hi); // bounding box info (returned) + + // create a skeletal tree + SkeletonTree(the_n_pts, the_dim, the_bkt_size, the_pts, the_pidx); + bnd_box_lo = the_bnd_box_lo; + bnd_box_hi = the_bnd_box_hi; + + root = the_root; // set the root +} + +//---------------------------------------------------------------------- +// annReadDump - read a dump file +// +// This procedure reads a dump file, constructs a kd-tree +// and returns all the essential information needed to actually +// construct the tree. Because this procedure is used for +// constructing both kd-trees and bd-trees, the second argument +// is used to indicate which type of tree we are expecting. +//---------------------------------------------------------------------- + +static ANNkd_ptr annReadDump( + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNpointArray &the_pts, // new points (returned) + ANNidxArray &the_pidx, // point indices (returned) + int &the_dim, // dimension (returned) + int &the_n_pts, // number of points (returned) + int &the_bkt_size, // bucket size (returned) + ANNpoint &the_bnd_box_lo, // low bounding point (ret'd) + ANNpoint &the_bnd_box_hi) // high bounding point (ret'd) +{ + int j; + char str[STRING_LEN]; // storage for string + char version[STRING_LEN]; // ANN version number + ANNkd_ptr the_root = NULL; + + //------------------------------------------------------------------ + // Input file header + //------------------------------------------------------------------ + in >> str; // input header + if (strcmp(str, "#ANN") != 0) { // incorrect header + annError("Incorrect header for dump file", ANNabort); + } + in.getline(version, STRING_LEN); // get version (ignore) + + //------------------------------------------------------------------ + // Input the points + // An array the_pts is allocated and points are read from + // the dump file. + //------------------------------------------------------------------ + in >> str; // get major heading + if (strcmp(str, "points") == 0) { // points section + in >> the_dim; // input dimension + in >> the_n_pts; // number of points + // allocate point storage + the_pts = annAllocPts(the_n_pts, the_dim); + for (int i = 0; i < the_n_pts; i++) { // input point coordinates + ANNidx idx; // point index + in >> idx; // input point index + if (idx < 0 || idx >= the_n_pts) { + annError("Point index is out of range", ANNabort); + } + for (j = 0; j < the_dim; j++) { + in >> the_pts[idx][j]; // read point coordinates + } + } + in >> str; // get next major heading + } + else { // no points were input + annError("Points must be supplied in the dump file", ANNabort); + } + + //------------------------------------------------------------------ + // Input the tree + // After the basic header information, we invoke annReadTree + // to do all the heavy work. We create our own array of + // point indices (so we can pass them to annReadTree()) + // but we do not deallocate them. They will be deallocated + // when the tree is destroyed. + //------------------------------------------------------------------ + if (strcmp(str, "tree") == 0) { // tree section + in >> the_dim; // read dimension + in >> the_n_pts; // number of points + in >> the_bkt_size; // bucket size + the_bnd_box_lo = annAllocPt(the_dim); // allocate bounding box pts + the_bnd_box_hi = annAllocPt(the_dim); + + for (j = 0; j < the_dim; j++) { // read bounding box low + in >> the_bnd_box_lo[j]; + } + for (j = 0; j < the_dim; j++) { // read bounding box low + in >> the_bnd_box_hi[j]; + } + the_pidx = new ANNidx[the_n_pts]; // allocate point index array + int next_idx = 0; // number of indices filled + // read the tree and indices + the_root = annReadTree(in, tree_type, the_pidx, next_idx); + if (next_idx != the_n_pts) { // didn't see all the points? + annError("Didn't see as many points as expected", ANNwarn); + } + } + else { + annError("Illegal dump format. Expecting section heading", ANNabort); + } + return the_root; +} + +//---------------------------------------------------------------------- +// annReadTree - input tree and return pointer +// +// annReadTree reads in a node of the tree, makes any recursive +// calls as needed to input the children of this node (if internal). +// It returns a pointer to the node that was created. An array +// of point indices is given along with a pointer to the next +// available location in the array. As leaves are read, their +// point indices are stored here, and the point buckets point +// to the first entry in the array. +// +// Recall that these are the formats. The tree is given in +// preorder. +// +// Leaf node: +// leaf ... +// Splitting nodes: +// split +// +// For bd-trees: +// +// Shrinking nodes: +// shrink +// +// +// ... (repeated n_bnds times) +//---------------------------------------------------------------------- + +static ANNkd_ptr annReadTree( + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNidxArray the_pidx, // point indices (modified) + int &next_idx) // next index (modified) +{ + char tag[STRING_LEN]; // tag (leaf, split, shrink) + int n_pts; // number of points in leaf + int cd; // cut dimension + ANNcoord cv; // cut value + ANNcoord lb; // low bound + ANNcoord hb; // high bound + int n_bnds; // number of bounding sides + int sd; // which side + + in >> tag; // input node tag + + if (strcmp(tag, "null") == 0) { // null tree + return NULL; + } + //------------------------------------------------------------------ + // Read a leaf + //------------------------------------------------------------------ + if (strcmp(tag, "leaf") == 0) { // leaf node + + in >> n_pts; // input number of points + int old_idx = next_idx; // save next_idx + if (n_pts == 0) { // trivial leaf + return KD_TRIVIAL; + } + else { + for (int i = 0; i < n_pts; i++) { // input point indices + in >> the_pidx[next_idx++]; // store in array of indices + } + } + return new ANNkd_leaf(n_pts, &the_pidx[old_idx]); + } + //------------------------------------------------------------------ + // Read a splitting node + //------------------------------------------------------------------ + else if (strcmp(tag, "split") == 0) { // splitting node + + in >> cd >> cv >> lb >> hb; + + // read low and high subtrees + ANNkd_ptr lc = annReadTree(in, tree_type, the_pidx, next_idx); + ANNkd_ptr hc = annReadTree(in, tree_type, the_pidx, next_idx); + // create new node and return + return new ANNkd_split(cd, cv, lb, hb, lc, hc); + } + //------------------------------------------------------------------ + // Read a shrinking node (bd-tree only) + //------------------------------------------------------------------ + else if (strcmp(tag, "shrink") == 0) { // shrinking node + if (tree_type != BD_TREE) { + annError("Shrinking node not allowed in kd-tree", ANNabort); + } + + in >> n_bnds; // number of bounding sides + // allocate bounds array + ANNorthHSArray bds = new ANNorthHalfSpace[n_bnds]; + for (int i = 0; i < n_bnds; i++) { + in >> cd >> cv >> sd; // input bounding halfspace + // copy to array + bds[i] = ANNorthHalfSpace(cd, cv, sd); + } + // read inner and outer subtrees + ANNkd_ptr ic = annReadTree(in, tree_type, the_pidx, next_idx); + ANNkd_ptr oc = annReadTree(in, tree_type, the_pidx, next_idx); + // create new node and return + return new ANNbd_shrink(n_bnds, bds, ic, oc); + } + else { + annError("Illegal node type in dump file", ANNabort); + exit(0); // to keep the compiler happy + } +} diff --git a/external/ann_1.1.1/src/kd_fix_rad_search.cpp b/external/ann_1.1.1/src/kd_fix_rad_search.cpp new file mode 100644 index 0000000..c41ed1b --- /dev/null +++ b/external/ann_1.1.1/src/kd_fix_rad_search.cpp @@ -0,0 +1,465 @@ +//---------------------------------------------------------------------- +// File: kd_fix_rad_search.cpp +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree fixed-radius kNN search +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 1.1 05/03/05 +// Initial release +//---------------------------------------------------------------------- + +#include "kd_fix_rad_search.h" // kd fixed-radius search decls + +//---------------------------------------------------------------------- +// Approximate fixed-radius k nearest neighbor search +// The squared radius is provided, and this procedure finds the +// k nearest neighbors within the radius, and returns the total +// number of points lying within the radius. +// +// The method used for searching the kd-tree is a variation of the +// nearest neighbor search used in kd_search.cpp, except that the +// radius of the search ball is known. We refer the reader to that +// file for the explanation of the recursive search procedure. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + +int ANNkdFRDim; // dimension of space +ANNpoint ANNkdFRQ; // query point +ANNdist ANNkdFRSqRad; // squared radius search bound +double ANNkdFRMaxErr; // max tolerable squared error +ANNpointArray ANNkdFRPts; // the points +ANNmin_k* ANNkdFRPointMK; // set of k closest points +int ANNkdFRPtsVisited; // total points visited +int ANNkdFRPtsInRange; // number of points in the range + +// these are added by Vlad to report nn's found during range search +// with out spending any time sorting them +ANNidxArray fr_search_indexes; +ANNdistArray fr_search_dists; +int fr_search_unordered; +int fr_search_k; // this his here so we know the length of the arrays above + + +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearch( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps) // the error bound +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating op count + + fr_search_unordered = 0; // added by Vlad so that the leaf nodes know where + // to put pts (either in priority queue or in array; this case pq) + ANNkdFRPointMK = new ANNmin_k(k); // create set for closest k points + // search starting at the root + root->ann_FR_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + for (int i = 0; i < k; i++) { // extract the k-th closest points + if (dd != NULL) + dd[i] = ANNkdFRPointMK->ith_smallest_key(i); + if (nn_idx != NULL) + nn_idx[i] = ANNkdFRPointMK->ith_smallest_info(i); + } + + delete ANNkdFRPointMK; // deallocate closest point set + return ANNkdFRPtsInRange; // return final point count +} + +// Added by Vlad to update flops even when ANN_PERF is not defined +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearchFlops( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps, // the error bound + int * flops ) // the number of floating ops performed by this query +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + if( flops != NULL ) + *flops = ann_Nfloat_ops; + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP_ALWAYS(2) // increment floating op count + + fr_search_unordered = 0; // added by Vlad so that the leaf nodes know where + // to put pts (either in priority queue or in array; this case pq) + ANNkdFRPointMK = new ANNmin_k(k); // create set for closest k points + // search starting at the root + root->ann_FR_searchFlops(annBoxDistanceFlops(q, bnd_box_lo, bnd_box_hi, dim)); + + for (int i = 0; i < k; i++) { // extract the k-th closest points + if (dd != NULL) + dd[i] = ANNkdFRPointMK->ith_smallest_key(i); + if (nn_idx != NULL) + nn_idx[i] = ANNkdFRPointMK->ith_smallest_info(i); + } + + if( flops != NULL ) + *flops = ann_Nfloat_ops - *flops; + + delete ANNkdFRPointMK; // deallocate closest point set + return ANNkdFRPtsInRange; // return final point count +} + +//---------------------------------------------------------------------- +// kd_split::ann_FR_search - search a splitting node +// Note: This routine is similar in structure to the standard kNN +// search. It visits the subtree that is closer to the query point +// first. For fixed-radius search, there is no benefit in visiting +// one subtree before the other, but we maintain the same basic +// code structure for the sake of uniformity. +//---------------------------------------------------------------------- + +void ANNkd_split::ann_FR_search(ANNdist box_dist) +{ + // check dist calc term condition + if (ANNmaxPtsVisited != 0 && ANNkdFRPtsVisited > ANNmaxPtsVisited) return; + + // distance to cutting plane + ANNcoord cut_diff = ANNkdFRQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + child[ANN_LO]->ann_FR_search(box_dist);// visit closer child first + + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdFRQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if in range + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_HI]->ann_FR_search(box_dist); + + } + else { // right of cutting plane + child[ANN_HI]->ann_FR_search(box_dist);// visit closer child first + + ANNcoord box_diff = ANNkdFRQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_LO]->ann_FR_search(box_dist); + + } + ANN_FLOP(13) // increment floating ops + ANN_SPL(1) // one more splitting node visited +} + +// Added by Vlad 5-1-08 to update flops even when ANN_PERF is not defined +//---------------------------------------------------------------------- +// kd_split::ann_FR_search - search a splitting node +// Note: This routine is similar in structure to the standard kNN +// search. It visits the subtree that is closer to the query point +// first. For fixed-radius search, there is no benefit in visiting +// one subtree before the other, but we maintain the same basic +// code structure for the sake of uniformity. +//---------------------------------------------------------------------- + +void ANNkd_split::ann_FR_searchFlops(ANNdist box_dist) +{ + // check dist calc term condition + if (ANNmaxPtsVisited != 0 && ANNkdFRPtsVisited > ANNmaxPtsVisited) return; + + // distance to cutting plane + ANNcoord cut_diff = ANNkdFRQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + child[ANN_LO]->ann_FR_searchFlops(box_dist);// visit closer child first + + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdFRQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if in range + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_HI]->ann_FR_searchFlops(box_dist); + + } + else { // right of cutting plane + child[ANN_HI]->ann_FR_searchFlops(box_dist);// visit closer child first + + ANNcoord box_diff = ANNkdFRQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_LO]->ann_FR_searchFlops(box_dist); + + } + ANN_FLOP_ALWAYS(13) // increment floating ops + ANN_SPL(1) // one more splitting node visited +} + +//---------------------------------------------------------------------- +// kd_leaf::ann_FR_search - search points in a leaf node +// Note: The unreadability of this code is the result of +// some fine tuning to replace indexing by pointer operations. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_FR_search(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNcoord t; + register int d; + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNkdFRPts[bkt[i]]; // first coord of next data point + qq = ANNkdFRQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNkdFRDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP(5) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > ANNkdFRSqRad) { + break; + } + } + + if (d >= ANNkdFRDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + if( fr_search_unordered == 0 ) + { + // add new neighbor and its distance to priority queue + ANNkdFRPointMK->insert(dist, bkt[i]); + } + else + { + // add new neighbor index and its distance to the unordered arrays + if( fr_search_indexes != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_indexes[ANNkdFRPtsInRange] = bkt[i]; + if( fr_search_dists != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_dists[ANNkdFRPtsInRange] = dist; + } + ANNkdFRPtsInRange++; // increment point count + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNkdFRPtsVisited += n_pts; // increment number of points visited +} + +// Added by Vlad to allow update of flops even when ANN_PERF is not +// defined, at the same time keeping the fast version of the fcn above +//---------------------------------------------------------------------- +// kd_leaf::ann_FR_search - search points in a leaf node +// Note: The unreadability of this code is the result of +// some fine tuning to replace indexing by pointer operations. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_FR_searchFlops(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNcoord t; + register int d; + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNkdFRPts[bkt[i]]; // first coord of next data point + qq = ANNkdFRQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNkdFRDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP_ALWAYS(5) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > ANNkdFRSqRad) { + break; + } + } + + if (d >= ANNkdFRDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + if( fr_search_unordered == 0 ) + { + // add new neighbor and its distance to priority queue + ANNkdFRPointMK->insertFlops(dist, bkt[i]); + } + else + { + // add new neighbor index and its distance to the unordered arrays + if( fr_search_indexes != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_indexes[ANNkdFRPtsInRange] = bkt[i]; + if( fr_search_dists != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_dists[ANNkdFRPtsInRange] = dist; + } + ANNkdFRPtsInRange++; // increment point count + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNkdFRPtsVisited += n_pts; // increment number of points visited +} + + +/////////////////////////////////////////////////////////////////////////////////////// +// +// +// +// +// Functions, added by Vlad to allow for unordered fixed radius search where all neighbors within +// radius are reported. This reduces the cost since we do not need to keep neighbors sorted. +// +// 6/10/08 +// +// +// +// +// +// +// +// +// +////////////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + + +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearchUnordered( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps) // the error bound +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating op count + + // set the flag that we are doing unordered search + fr_search_unordered = 1; + fr_search_indexes = nn_idx; + fr_search_dists = dd; + fr_search_k = k; + + // search starting at the root + root->ann_FR_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + return ANNkdFRPtsInRange; // return final point count +} + +// Added by Vlad to update flops even when ANN_PERF is not defined +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearchUnorderedFlops( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps, // the error bound + int * flops ) // the number of floating ops performed by this query +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + if( flops != NULL ) + *flops = ann_Nfloat_ops; + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP_ALWAYS(2) // increment floating op count + + // set the flag that we are doing unordered search + fr_search_unordered = 1; + fr_search_indexes = nn_idx; + fr_search_dists = dd; + fr_search_k = k; + + // search starting at the root + root->ann_FR_searchFlops(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + if( flops != NULL ) + *flops = ann_Nfloat_ops - *flops; + + return ANNkdFRPtsInRange; // return final point count +} diff --git a/external/ann_1.1.1/src/kd_fix_rad_search.h b/external/ann_1.1.1/src/kd_fix_rad_search.h new file mode 100644 index 0000000..7567327 --- /dev/null +++ b/external/ann_1.1.1/src/kd_fix_rad_search.h @@ -0,0 +1,44 @@ +//---------------------------------------------------------------------- +// File: kd_fix_rad_search.h +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree fixed-radius kNN search +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 1.1 05/03/05 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_fix_rad_search_H +#define ANN_kd_fix_rad_search_H + +#include "kd_tree.h" // kd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "pr_queue_k.h" // k-element priority queue + +#include // performance evaluation + +//---------------------------------------------------------------------- +// Global variables +// These are active for the life of each call to +// annRangeSearch(). They are set to save the number of +// variables that need to be passed among the various search +// procedures. +//---------------------------------------------------------------------- + +extern ANNpoint ANNkdFRQ; // query point (static copy) + +#endif diff --git a/external/ann_1.1.1/src/kd_pr_search.cpp b/external/ann_1.1.1/src/kd_pr_search.cpp new file mode 100644 index 0000000..0d16060 --- /dev/null +++ b/external/ann_1.1.1/src/kd_pr_search.cpp @@ -0,0 +1,219 @@ +//---------------------------------------------------------------------- +// File: kd_pr_search.cpp +// Programmer: Sunil Arya and David Mount +// Description: Priority search for kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "kd_pr_search.h" // kd priority search declarations + +//---------------------------------------------------------------------- +// Approximate nearest neighbor searching by priority search. +// The kd-tree is searched for an approximate nearest neighbor. +// The point is returned through one of the arguments, and the +// distance returned is the SQUARED distance to this point. +// +// The method used for searching the kd-tree is called priority +// search. (It is described in Arya and Mount, ``Algorithms for +// fast vector quantization,'' Proc. of DCC '93: Data Compression +// Conference}, eds. J. A. Storer and M. Cohn, IEEE Press, 1993, +// 381--390.) +// +// The cell of the kd-tree containing the query point is located, +// and cells are visited in increasing order of distance from the +// query point. This is done by placing each subtree which has +// NOT been visited in a priority queue, according to the closest +// distance of the corresponding enclosing rectangle from the +// query point. The search stops when the distance to the nearest +// remaining rectangle exceeds the distance to the nearest point +// seen by a factor of more than 1/(1+eps). (Implying that any +// point found subsequently in the search cannot be closer by more +// than this factor.) +// +// The main entry point is annkPriSearch() which sets things up and +// then call the recursive routine ann_pri_search(). This is a +// recursive routine which performs the processing for one node in +// the kd-tree. There are two versions of this virtual procedure, +// one for splitting nodes and one for leaves. When a splitting node +// is visited, we determine which child to continue the search on +// (the closer one), and insert the other child into the priority +// queue. When a leaf is visited, we compute the distances to the +// points in the buckets, and update information on the closest +// points. +// +// Some trickery is used to incrementally update the distance from +// a kd-tree rectangle to the query point. This comes about from +// the fact that which each successive split, only one component +// (along the dimension that is split) of the squared distance to +// the child rectangle is different from the squared distance to +// the parent rectangle. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + +double ANNprEps; // the error bound +int ANNprDim; // dimension of space +ANNpoint ANNprQ; // query point +double ANNprMaxErr; // max tolerable squared error +ANNpointArray ANNprPts; // the points +ANNpr_queue *ANNprBoxPQ; // priority queue for boxes +ANNmin_k *ANNprPointMK; // set of k closest points + +//---------------------------------------------------------------------- +// annkPriSearch - priority search for k nearest neighbors +//---------------------------------------------------------------------- + +void ANNkd_tree::annkPriSearch( + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // dist to near neighbors (returned) + double eps) // error bound (ignored) +{ + // max tolerable squared error + ANNprMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating ops + + ANNprDim = dim; // copy arguments to static equivs + ANNprQ = q; + ANNprPts = pts; + ANNptsVisited = 0; // initialize count of points visited + + ANNprPointMK = new ANNmin_k(k); // create set for closest k points + + // distance to root box + ANNdist box_dist = annBoxDistance(q, + bnd_box_lo, bnd_box_hi, dim); + + ANNprBoxPQ = new ANNpr_queue(n_pts);// create priority queue for boxes + ANNprBoxPQ->insert(box_dist, root); // insert root in priority queue + + while (ANNprBoxPQ->non_empty() && + (!(ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited))) { + ANNkd_ptr np; // next box from prior queue + + // extract closest box from queue + ANNprBoxPQ->extr_min(box_dist, (void *&) np); + + ANN_FLOP(2) // increment floating ops + if (box_dist*ANNprMaxErr >= ANNprPointMK->max_key()) + break; + + np->ann_pri_search(box_dist); // search this subtree. + } + + for (int i = 0; i < k; i++) { // extract the k-th closest points + dd[i] = ANNprPointMK->ith_smallest_key(i); + nn_idx[i] = ANNprPointMK->ith_smallest_info(i); + } + + delete ANNprPointMK; // deallocate closest point set + delete ANNprBoxPQ; // deallocate priority queue +} + +//---------------------------------------------------------------------- +// kd_split::ann_pri_search - search a splitting node +//---------------------------------------------------------------------- + +void ANNkd_split::ann_pri_search(ANNdist box_dist) +{ + ANNdist new_dist; // distance to child visited later + // distance to cutting plane + ANNcoord cut_diff = ANNprQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNprQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + new_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + if (child[ANN_HI] != KD_TRIVIAL)// enqueue if not trivial + ANNprBoxPQ->insert(new_dist, child[ANN_HI]); + // continue with closer child + child[ANN_LO]->ann_pri_search(box_dist); + } + else { // right of cutting plane + ANNcoord box_diff = ANNprQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + new_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + if (child[ANN_LO] != KD_TRIVIAL)// enqueue if not trivial + ANNprBoxPQ->insert(new_dist, child[ANN_LO]); + // continue with closer child + child[ANN_HI]->ann_pri_search(box_dist); + } + ANN_SPL(1) // one more splitting node visited + ANN_FLOP(8) // increment floating ops +} + +//---------------------------------------------------------------------- +// kd_leaf::ann_pri_search - search points in a leaf node +// +// This is virtually identical to the ann_search for standard search. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_pri_search(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNdist min_dist; // distance to k-th closest point + register ANNcoord t; + register int d; + + min_dist = ANNprPointMK->max_key(); // k-th smallest distance so far + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNprPts[bkt[i]]; // first coord of next data point + qq = ANNprQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNprDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP(4) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > min_dist) { + break; + } + } + + if (d >= ANNprDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + ANNprPointMK->insert(dist, bkt[i]); + min_dist = ANNprPointMK->max_key(); + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNptsVisited += n_pts; // increment number of points visited +} diff --git a/external/ann_1.1.1/src/kd_pr_search.h b/external/ann_1.1.1/src/kd_pr_search.h new file mode 100644 index 0000000..a55efe2 --- /dev/null +++ b/external/ann_1.1.1/src/kd_pr_search.h @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------- +// File: kd_pr_search.h +// Programmer: Sunil Arya and David Mount +// Description: Priority kd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_pr_search_H +#define ANN_kd_pr_search_H + +#include "kd_tree.h" // kd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "pr_queue.h" // priority queue declarations +#include "pr_queue_k.h" // k-element priority queue + +#include // performance evaluation + +//---------------------------------------------------------------------- +// Global variables +// Active for the life of each call to Appx_Near_Neigh() or +// Appx_k_Near_Neigh(). +//---------------------------------------------------------------------- + +extern double ANNprEps; // the error bound +extern int ANNprDim; // dimension of space +extern ANNpoint ANNprQ; // query point +extern double ANNprMaxErr; // max tolerable squared error +extern ANNpointArray ANNprPts; // the points +extern ANNpr_queue *ANNprBoxPQ; // priority queue for boxes +extern ANNmin_k *ANNprPointMK; // set of k closest points + +#endif diff --git a/external/ann_1.1.1/src/kd_search.cpp b/external/ann_1.1.1/src/kd_search.cpp new file mode 100644 index 0000000..745e0e3 --- /dev/null +++ b/external/ann_1.1.1/src/kd_search.cpp @@ -0,0 +1,210 @@ +//---------------------------------------------------------------------- +// File: kd_search.cpp +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed names LO, HI to ANN_LO, ANN_HI +//---------------------------------------------------------------------- + +#include "kd_search.h" // kd-search declarations + +//---------------------------------------------------------------------- +// Approximate nearest neighbor searching by kd-tree search +// The kd-tree is searched for an approximate nearest neighbor. +// The point is returned through one of the arguments, and the +// distance returned is the squared distance to this point. +// +// The method used for searching the kd-tree is an approximate +// adaptation of the search algorithm described by Friedman, +// Bentley, and Finkel, ``An algorithm for finding best matches +// in logarithmic expected time,'' ACM Transactions on Mathematical +// Software, 3(3):209-226, 1977). +// +// The algorithm operates recursively. When first encountering a +// node of the kd-tree we first visit the child which is closest to +// the query point. On return, we decide whether we want to visit +// the other child. If the box containing the other child exceeds +// 1/(1+eps) times the current best distance, then we skip it (since +// any point found in this child cannot be closer to the query point +// by more than this factor.) Otherwise, we visit it recursively. +// The distance between a box and the query point is computed exactly +// (not approximated as is often done in kd-tree), using incremental +// distance updates, as described by Arya and Mount in ``Algorithms +// for fast vector quantization,'' Proc. of DCC '93: Data Compression +// Conference, eds. J. A. Storer and M. Cohn, IEEE Press, 1993, +// 381-390. +// +// The main entry points is annkSearch() which sets things up and +// then call the recursive routine ann_search(). This is a recursive +// routine which performs the processing for one node in the kd-tree. +// There are two versions of this virtual procedure, one for splitting +// nodes and one for leaves. When a splitting node is visited, we +// determine which child to visit first (the closer one), and visit +// the other child on return. When a leaf is visited, we compute +// the distances to the points in the buckets, and update information +// on the closest points. +// +// Some trickery is used to incrementally update the distance from +// a kd-tree rectangle to the query point. This comes about from +// the fact that which each successive split, only one component +// (along the dimension that is split) of the squared distance to +// the child rectangle is different from the squared distance to +// the parent rectangle. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + +int ANNkdDim; // dimension of space +ANNpoint ANNkdQ; // query point +double ANNkdMaxErr; // max tolerable squared error +ANNpointArray ANNkdPts; // the points +ANNmin_k *ANNkdPointMK; // set of k closest points + +//---------------------------------------------------------------------- +// annkSearch - search for the k nearest neighbors +//---------------------------------------------------------------------- + +void ANNkd_tree::annkSearch( + ANNpoint q, // the query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps) // the error bound +{ + + ANNkdDim = dim; // copy arguments to static equivs + ANNkdQ = q; + ANNkdPts = pts; + ANNptsVisited = 0; // initialize count of points visited + + if (k > n_pts) { // too many near neighbors? + annError("Requesting more near neighbors than data points", ANNabort); + } + + ANNkdMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating op count + + ANNkdPointMK = new ANNmin_k(k); // create set for closest k points + // search starting at the root + root->ann_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + for (int i = 0; i < k; i++) { // extract the k-th closest points + dd[i] = ANNkdPointMK->ith_smallest_key(i); + nn_idx[i] = ANNkdPointMK->ith_smallest_info(i); + } + delete ANNkdPointMK; // deallocate closest point set +} + +//---------------------------------------------------------------------- +// kd_split::ann_search - search a splitting node +//---------------------------------------------------------------------- + +void ANNkd_split::ann_search(ANNdist box_dist) +{ + // check dist calc term condition + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + // distance to cutting plane + ANNcoord cut_diff = ANNkdQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + child[ANN_LO]->ann_search(box_dist);// visit closer child first + + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdMaxErr < ANNkdPointMK->max_key()) + child[ANN_HI]->ann_search(box_dist); + + } + else { // right of cutting plane + child[ANN_HI]->ann_search(box_dist);// visit closer child first + + ANNcoord box_diff = ANNkdQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdMaxErr < ANNkdPointMK->max_key()) + child[ANN_LO]->ann_search(box_dist); + + } + ANN_FLOP(10) // increment floating ops + ANN_SPL(1) // one more splitting node visited +} + +//---------------------------------------------------------------------- +// kd_leaf::ann_search - search points in a leaf node +// Note: The unreadability of this code is the result of +// some fine tuning to replace indexing by pointer operations. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_search(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNdist min_dist; // distance to k-th closest point + register ANNcoord t; + register int d; + + min_dist = ANNkdPointMK->max_key(); // k-th smallest distance so far + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNkdPts[bkt[i]]; // first coord of next data point + qq = ANNkdQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNkdDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP(4) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > min_dist) { + break; + } + } + + if (d >= ANNkdDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + ANNkdPointMK->insert(dist, bkt[i]); + min_dist = ANNkdPointMK->max_key(); + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNptsVisited += n_pts; // increment number of points visited +} diff --git a/external/ann_1.1.1/src/kd_search.h b/external/ann_1.1.1/src/kd_search.h new file mode 100644 index 0000000..aaafc1e --- /dev/null +++ b/external/ann_1.1.1/src/kd_search.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------- +// File: kd_search.h +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_search_H +#define ANN_kd_search_H + +#include "kd_tree.h" // kd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "pr_queue_k.h" // k-element priority queue + +#include // performance evaluation + +//---------------------------------------------------------------------- +// More global variables +// These are active for the life of each call to annkSearch(). They +// are set to save the number of variables that need to be passed +// among the various search procedures. +//---------------------------------------------------------------------- + +extern int ANNkdDim; // dimension of space (static copy) +extern ANNpoint ANNkdQ; // query point (static copy) +extern double ANNkdMaxErr; // max tolerable squared error +extern ANNpointArray ANNkdPts; // the points (static copy) +extern ANNmin_k *ANNkdPointMK; // set of k closest points +extern int ANNptsVisited; // number of points visited + +#endif diff --git a/external/ann_1.1.1/src/kd_split.cpp b/external/ann_1.1.1/src/kd_split.cpp new file mode 100644 index 0000000..f5fb620 --- /dev/null +++ b/external/ann_1.1.1/src/kd_split.cpp @@ -0,0 +1,428 @@ +//---------------------------------------------------------------------- +// File: kd_split.cpp +// Programmer: Sunil Arya and David Mount +// Description: Methods for splitting kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +//---------------------------------------------------------------------- + +#include "kd_tree.h" // kd-tree definitions +#include "kd_util.h" // kd-tree utilities +#include "kd_split.h" // splitting functions + +//---------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------- + +const double ERR = 0.001; // a small value +const double FS_ASPECT_RATIO = 3.0; // maximum allowed aspect ratio + // in fair split. Must be >= 2. + +//---------------------------------------------------------------------- +// kd_split - Bentley's standard splitting routine for kd-trees +// Find the dimension of the greatest spread, and split +// just before the median point along this dimension. +//---------------------------------------------------------------------- + +void kd_split( + ANNpointArray pa, // point array (permuted on return) + ANNidxArray pidx, // point indices + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + // find dimension of maximum spread + cut_dim = annMaxSpread(pa, pidx, n, dim); + n_lo = n/2; // median rank + // split about median + annMedianSplit(pa, pidx, n, cut_dim, cut_val, n_lo); +} + +//---------------------------------------------------------------------- +// midpt_split - midpoint splitting rule for box-decomposition trees +// +// This is the simplest splitting rule that guarantees boxes +// of bounded aspect ratio. It simply cuts the box with the +// longest side through its midpoint. If there are ties, it +// selects the dimension with the maximum point spread. +// +// WARNING: This routine (while simple) doesn't seem to work +// well in practice in high dimensions, because it tends to +// generate a large number of trivial and/or unbalanced splits. +// Either kd_split(), sl_midpt_split(), or fair_split() are +// recommended, instead. +//---------------------------------------------------------------------- + +void midpt_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + } + } + ANNcoord max_spread = -1; // find long side with most spread + for (d = 0; d < dim; d++) { + // is it among longest? + if (double(bnds.hi[d] - bnds.lo[d]) >= (1-ERR)*max_length) { + // compute its spread + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // is it max so far? + max_spread = spr; + cut_dim = d; + } + } + } + // split along cut_dim at midpoint + cut_val = (bnds.lo[cut_dim] + bnds.hi[cut_dim]) / 2; + // permute points accordingly + int br1, br2; + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + //------------------------------------------------------------------ + // On return: pa[0..br1-1] < cut_val + // pa[br1..br2-1] == cut_val + // pa[br2..n-1] > cut_val + // + // We can set n_lo to any value in the range [br1..br2]. + // We choose split so that points are most evenly divided. + //------------------------------------------------------------------ + if (br1 > n/2) n_lo = br1; + else if (br2 < n/2) n_lo = br2; + else n_lo = n/2; +} + +//---------------------------------------------------------------------- +// sl_midpt_split - sliding midpoint splitting rule +// +// This is a modification of midpt_split, which has the nonsensical +// name "sliding midpoint". The idea is that we try to use the +// midpoint rule, by bisecting the longest side. If there are +// ties, the dimension with the maximum spread is selected. If, +// however, the midpoint split produces a trivial split (no points +// on one side of the splitting plane) then we slide the splitting +// (maintaining its orientation) until it produces a nontrivial +// split. For example, if the splitting plane is along the x-axis, +// and all the data points have x-coordinate less than the x-bisector, +// then the split is taken along the maximum x-coordinate of the +// data points. +// +// Intuitively, this rule cannot generate trivial splits, and +// hence avoids midpt_split's tendency to produce trees with +// a very large number of nodes. +// +//---------------------------------------------------------------------- + +void sl_midpt_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + } + } + ANNcoord max_spread = -1; // find long side with most spread + for (d = 0; d < dim; d++) { + // is it among longest? + if ((bnds.hi[d] - bnds.lo[d]) >= (1-ERR)*max_length) { + // compute its spread + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // is it max so far? + max_spread = spr; + cut_dim = d; + } + } + } + // ideal split at midpoint + ANNcoord ideal_cut_val = (bnds.lo[cut_dim] + bnds.hi[cut_dim])/2; + + ANNcoord min, max; + annMinMax(pa, pidx, n, cut_dim, min, max); // find min/max coordinates + + if (ideal_cut_val < min) // slide to min or max as needed + cut_val = min; + else if (ideal_cut_val > max) + cut_val = max; + else + cut_val = ideal_cut_val; + + // permute points accordingly + int br1, br2; + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + //------------------------------------------------------------------ + // On return: pa[0..br1-1] < cut_val + // pa[br1..br2-1] == cut_val + // pa[br2..n-1] > cut_val + // + // We can set n_lo to any value in the range [br1..br2] to satisfy + // the exit conditions of the procedure. + // + // if ideal_cut_val < min (implying br2 >= 1), + // then we select n_lo = 1 (so there is one point on left) and + // if ideal_cut_val > max (implying br1 <= n-1), + // then we select n_lo = n-1 (so there is one point on right). + // Otherwise, we select n_lo as close to n/2 as possible within + // [br1..br2]. + //------------------------------------------------------------------ + if (ideal_cut_val < min) n_lo = 1; + else if (ideal_cut_val > max) n_lo = n-1; + else if (br1 > n/2) n_lo = br1; + else if (br2 < n/2) n_lo = br2; + else n_lo = n/2; +} + +//---------------------------------------------------------------------- +// fair_split - fair-split splitting rule +// +// This is a compromise between the kd-tree splitting rule (which +// always splits data points at their median) and the midpoint +// splitting rule (which always splits a box through its center. +// The goal of this procedure is to achieve both nicely balanced +// splits, and boxes of bounded aspect ratio. +// +// A constant FS_ASPECT_RATIO is defined. Given a box, those sides +// which can be split so that the ratio of the longest to shortest +// side does not exceed ASPECT_RATIO are identified. Among these +// sides, we select the one in which the points have the largest +// spread. We then split the points in a manner which most evenly +// distributes the points on either side of the splitting plane, +// subject to maintaining the bound on the ratio of long to short +// sides. To determine that the aspect ratio will be preserved, +// we determine the longest side (other than this side), and +// determine how narrowly we can cut this side, without causing the +// aspect ratio bound to be exceeded (small_piece). +// +// This procedure is more robust than either kd_split or midpt_split, +// but is more complicated as well. When point distribution is +// extremely skewed, this degenerates to midpt_split (actually +// 1/3 point split), and when the points are most evenly distributed, +// this degenerates to kd-split. +//---------------------------------------------------------------------- + +void fair_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + cut_dim = 0; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + cut_dim = d; + } + } + + ANNcoord max_spread = 0; // find legal cut with max spread + cut_dim = 0; + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + // is this side midpoint splitable + // without violating aspect ratio? + if (((double) max_length)*2.0/((double) length) <= FS_ASPECT_RATIO) { + // compute spread along this dim + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // best spread so far + max_spread = spr; + cut_dim = d; // this is dimension to cut + } + } + } + + max_length = 0; // find longest side other than cut_dim + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (d != cut_dim && length > max_length) + max_length = length; + } + // consider most extreme splits + ANNcoord small_piece = max_length / FS_ASPECT_RATIO; + ANNcoord lo_cut = bnds.lo[cut_dim] + small_piece;// lowest legal cut + ANNcoord hi_cut = bnds.hi[cut_dim] - small_piece;// highest legal cut + + int br1, br2; + // is median below lo_cut ? + if (annSplitBalance(pa, pidx, n, cut_dim, lo_cut) >= 0) { + cut_val = lo_cut; // cut at lo_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br1; + } + // is median above hi_cut? + else if (annSplitBalance(pa, pidx, n, cut_dim, hi_cut) <= 0) { + cut_val = hi_cut; // cut at hi_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br2; + } + else { // median cut preserves asp ratio + n_lo = n/2; // split about median + annMedianSplit(pa, pidx, n, cut_dim, cut_val, n_lo); + } +} + +//---------------------------------------------------------------------- +// sl_fair_split - sliding fair split splitting rule +// +// Sliding fair split is a splitting rule that combines the +// strengths of both fair split with sliding midpoint split. +// Fair split tends to produce balanced splits when the points +// are roughly uniformly distributed, but it can produce many +// trivial splits when points are highly clustered. Sliding +// midpoint never produces trivial splits, and shrinks boxes +// nicely if points are highly clustered, but it may produce +// rather unbalanced splits when points are unclustered but not +// quite uniform. +// +// Sliding fair split is based on the theory that there are two +// types of splits that are "good": balanced splits that produce +// fat boxes, and unbalanced splits provided the cell with fewer +// points is fat. +// +// This splitting rule operates by first computing the longest +// side of the current bounding box. Then it asks which sides +// could be split (at the midpoint) and still satisfy the aspect +// ratio bound with respect to this side. Among these, it selects +// the side with the largest spread (as fair split would). It +// then considers the most extreme cuts that would be allowed by +// the aspect ratio bound. This is done by dividing the longest +// side of the box by the aspect ratio bound. If the median cut +// lies between these extreme cuts, then we use the median cut. +// If not, then consider the extreme cut that is closer to the +// median. If all the points lie to one side of this cut, then +// we slide the cut until it hits the first point. This may +// violate the aspect ratio bound, but will never generate empty +// cells. However the sibling of every such skinny cell is fat, +// and hence packing arguments still apply. +// +//---------------------------------------------------------------------- + +void sl_fair_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + ANNcoord min, max; // min/max coordinates + int br1, br2; // split break points + + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + cut_dim = 0; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + cut_dim = d; + } + } + + ANNcoord max_spread = 0; // find legal cut with max spread + cut_dim = 0; + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + // is this side midpoint splitable + // without violating aspect ratio? + if (((double) max_length)*2.0/((double) length) <= FS_ASPECT_RATIO) { + // compute spread along this dim + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // best spread so far + max_spread = spr; + cut_dim = d; // this is dimension to cut + } + } + } + + max_length = 0; // find longest side other than cut_dim + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (d != cut_dim && length > max_length) + max_length = length; + } + // consider most extreme splits + ANNcoord small_piece = max_length / FS_ASPECT_RATIO; + ANNcoord lo_cut = bnds.lo[cut_dim] + small_piece;// lowest legal cut + ANNcoord hi_cut = bnds.hi[cut_dim] - small_piece;// highest legal cut + // find min and max along cut_dim + annMinMax(pa, pidx, n, cut_dim, min, max); + // is median below lo_cut? + if (annSplitBalance(pa, pidx, n, cut_dim, lo_cut) >= 0) { + if (max > lo_cut) { // are any points above lo_cut? + cut_val = lo_cut; // cut at lo_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br1; // balance if there are ties + } + else { // all points below lo_cut + cut_val = max; // cut at max value + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = n-1; + } + } + // is median above hi_cut? + else if (annSplitBalance(pa, pidx, n, cut_dim, hi_cut) <= 0) { + if (min < hi_cut) { // are any points below hi_cut? + cut_val = hi_cut; // cut at hi_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br2; // balance if there are ties + } + else { // all points above hi_cut + cut_val = min; // cut at min value + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = 1; + } + } + else { // median cut is good enough + n_lo = n/2; // split about median + annMedianSplit(pa, pidx, n, cut_dim, cut_val, n_lo); + } +} diff --git a/external/ann_1.1.1/src/kd_split.h b/external/ann_1.1.1/src/kd_split.h new file mode 100644 index 0000000..130e188 --- /dev/null +++ b/external/ann_1.1.1/src/kd_split.h @@ -0,0 +1,85 @@ +//---------------------------------------------------------------------- +// File: kd_split.h +// Programmer: Sunil Arya and David Mount +// Description: Methods for splitting kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_KD_SPLIT_H +#define ANN_KD_SPLIT_H + +#include "kd_tree.h" // kd-tree definitions + +//---------------------------------------------------------------------- +// External entry points +// These are all splitting procedures for kd-trees. +//---------------------------------------------------------------------- + +void kd_split( // standard (optimized) kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void midpt_split( // midpoint kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void sl_midpt_split( // sliding midpoint kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void fair_split( // fair-split kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void sl_fair_split( // sliding fair-split kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +#endif diff --git a/external/ann_1.1.1/src/kd_tree.cpp b/external/ann_1.1.1/src/kd_tree.cpp new file mode 100644 index 0000000..6fc68cc --- /dev/null +++ b/external/ann_1.1.1/src/kd_tree.cpp @@ -0,0 +1,405 @@ +//---------------------------------------------------------------------- +// File: kd_tree.cpp +// Programmer: Sunil Arya and David Mount +// Description: Basic methods for kd-trees. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Increased aspect ratio bound (ANN_AR_TOOBIG) from 100 to 1000. +// Fixed leaf counts to count trivial leaves. +// Added optional pa, pi arguments to Skeleton kd_tree constructor +// for use in load constructor. +// Added annClose() to eliminate KD_TRIVIAL memory leak. +//---------------------------------------------------------------------- + +#include "kd_tree.h" // kd-tree declarations +#include "kd_split.h" // kd-tree splitting rules +#include "kd_util.h" // kd-tree utilities +#include // performance evaluation + +//---------------------------------------------------------------------- +// Global data +// +// For some splitting rules, especially with small bucket sizes, +// it is possible to generate a large number of empty leaf nodes. +// To save storage we allocate a single trivial leaf node which +// contains no points. For messy coding reasons it is convenient +// to have it reference a trivial point index. +// +// KD_TRIVIAL is allocated when the first kd-tree is created. It +// must *never* deallocated (since it may be shared by more than +// one tree). +//---------------------------------------------------------------------- +static int IDX_TRIVIAL[] = {0}; // trivial point index +ANNkd_leaf *KD_TRIVIAL = NULL; // trivial leaf node + +//---------------------------------------------------------------------- +// Printing the kd-tree +// These routines print a kd-tree in reverse inorder (high then +// root then low). (This is so that if you look at the output +// from the right side it appear from left to right in standard +// inorder.) When outputting leaves we output only the point +// indices rather than the point coordinates. There is an option +// to print the point coordinates separately. +// +// The tree printing routine calls the printing routines on the +// individual nodes of the tree, passing in the level or depth +// in the tree. The level in the tree is used to print indentation +// for readability. +//---------------------------------------------------------------------- + +void ANNkd_split::print( // print splitting node + int level, // depth of node in tree + ostream &out) // output stream +{ + child[ANN_HI]->print(level+1, out); // print high child + out << " "; + for (int i = 0; i < level; i++) // print indentation + out << ".."; + out << "Split cd=" << cut_dim << " cv=" << cut_val; + out << " lbnd=" << cd_bnds[ANN_LO]; + out << " hbnd=" << cd_bnds[ANN_HI]; + out << "\n"; + child[ANN_LO]->print(level+1, out); // print low child +} + +void ANNkd_leaf::print( // print leaf node + int level, // depth of node in tree + ostream &out) // output stream +{ + + out << " "; + for (int i = 0; i < level; i++) // print indentation + out << ".."; + + if (this == KD_TRIVIAL) { // canonical trivial leaf node + out << "Leaf (trivial)\n"; + } + else{ + out << "Leaf n=" << n_pts << " <"; + for (int j = 0; j < n_pts; j++) { + out << bkt[j]; + if (j < n_pts-1) out << ","; + } + out << ">\n"; + } +} + +void ANNkd_tree::Print( // print entire tree + ANNbool with_pts, // print points as well? + ostream &out) // output stream +{ + out << "ANN Version " << ANNversion << "\n"; + if (with_pts) { // print point coordinates + out << " Points:\n"; + for (int i = 0; i < n_pts; i++) { + out << "\t" << i << ": "; + annPrintPt(pts[i], dim, out); + out << "\n"; + } + } + if (root == NULL) // empty tree? + out << " Null tree.\n"; + else { + root->print(0, out); // invoke printing at root + } +} + +//---------------------------------------------------------------------- +// kd_tree statistics (for performance evaluation) +// This routine compute various statistics information for +// a kd-tree. It is used by the implementors for performance +// evaluation of the data structure. +//---------------------------------------------------------------------- + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +void ANNkdStats::merge(const ANNkdStats &st) // merge stats from child +{ + n_lf += st.n_lf; n_tl += st.n_tl; + n_spl += st.n_spl; n_shr += st.n_shr; + depth = MAX(depth, st.depth); + sum_ar += st.sum_ar; +} + +//---------------------------------------------------------------------- +// Update statistics for nodes +//---------------------------------------------------------------------- + +const double ANN_AR_TOOBIG = 1000; // too big an aspect ratio + +void ANNkd_leaf::getStats( // get subtree statistics + int dim, // dimension of space + ANNkdStats &st, // stats (modified) + ANNorthRect &bnd_box) // bounding box +{ + st.reset(); + st.n_lf = 1; // count this leaf + if (this == KD_TRIVIAL) st.n_tl = 1; // count trivial leaf + double ar = annAspectRatio(dim, bnd_box); // aspect ratio of leaf + // incr sum (ignore outliers) + st.sum_ar += float(ar < ANN_AR_TOOBIG ? ar : ANN_AR_TOOBIG); +} + +void ANNkd_split::getStats( // get subtree statistics + int dim, // dimension of space + ANNkdStats &st, // stats (modified) + ANNorthRect &bnd_box) // bounding box +{ + ANNkdStats ch_stats; // stats for children + // get stats for low child + ANNcoord hv = bnd_box.hi[cut_dim]; // save box bounds + bnd_box.hi[cut_dim] = cut_val; // upper bound for low child + ch_stats.reset(); // reset + child[ANN_LO]->getStats(dim, ch_stats, bnd_box); + st.merge(ch_stats); // merge them + bnd_box.hi[cut_dim] = hv; // restore bound + // get stats for high child + ANNcoord lv = bnd_box.lo[cut_dim]; // save box bounds + bnd_box.lo[cut_dim] = cut_val; // lower bound for high child + ch_stats.reset(); // reset + child[ANN_HI]->getStats(dim, ch_stats, bnd_box); + st.merge(ch_stats); // merge them + bnd_box.lo[cut_dim] = lv; // restore bound + + st.depth++; // increment depth + st.n_spl++; // increment number of splits +} + +//---------------------------------------------------------------------- +// getStats +// Collects a number of statistics related to kd_tree or +// bd_tree. +//---------------------------------------------------------------------- + +void ANNkd_tree::getStats( // get tree statistics + ANNkdStats &st) // stats (modified) +{ + st.reset(dim, n_pts, bkt_size); // reset stats + // create bounding box + ANNorthRect bnd_box(dim, bnd_box_lo, bnd_box_hi); + if (root != NULL) { // if nonempty tree + root->getStats(dim, st, bnd_box); // get statistics + st.avg_ar = st.sum_ar / st.n_lf; // average leaf asp ratio + } +} + +//---------------------------------------------------------------------- +// kd_tree destructor +// The destructor just frees the various elements that were +// allocated in the construction process. +//---------------------------------------------------------------------- + +ANNkd_tree::~ANNkd_tree() // tree destructor +{ + if (root != NULL) delete root; + if (pidx != NULL) delete [] pidx; + if (bnd_box_lo != NULL) annDeallocPt(bnd_box_lo); + if (bnd_box_hi != NULL) annDeallocPt(bnd_box_hi); +} + +//---------------------------------------------------------------------- +// This is called with all use of ANN is finished. It eliminates the +// minor memory leak caused by the allocation of KD_TRIVIAL. +//---------------------------------------------------------------------- +void annClose() // close use of ANN +{ + if (KD_TRIVIAL != NULL) { + delete KD_TRIVIAL; + KD_TRIVIAL = NULL; + } +} + +//---------------------------------------------------------------------- +// kd_tree constructors +// There is a skeleton kd-tree constructor which sets up a +// trivial empty tree. The last optional argument allows +// the routine to be passed a point index array which is +// assumed to be of the proper size (n). Otherwise, one is +// allocated and initialized to the identity. Warning: In +// either case the destructor will deallocate this array. +// +// As a kludge, we need to allocate KD_TRIVIAL if one has not +// already been allocated. (This is because I'm too dumb to +// figure out how to cause a pointer to be allocated at load +// time.) +//---------------------------------------------------------------------- + +void ANNkd_tree::SkeletonTree( // construct skeleton tree + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNpointArray pa, // point array + ANNidxArray pi) // point indices +{ + dim = dd; // initialize basic elements + n_pts = n; + bkt_size = bs; + pts = pa; // initialize points array + + root = NULL; // no associated tree yet + + if (pi == NULL) { // point indices provided? + pidx = new ANNidx[n]; // no, allocate space for point indices + for (int i = 0; i < n; i++) { + pidx[i] = i; // initially identity + } + } + else { + pidx = pi; // yes, use them + } + + bnd_box_lo = bnd_box_hi = NULL; // bounding box is nonexistent + if (KD_TRIVIAL == NULL) // no trivial leaf node yet? + KD_TRIVIAL = new ANNkd_leaf(0, IDX_TRIVIAL); // allocate it +} + +ANNkd_tree::ANNkd_tree( // basic constructor + int n, // number of points + int dd, // dimension + int bs) // bucket size +{ SkeletonTree(n, dd, bs); } // construct skeleton tree + +//---------------------------------------------------------------------- +// rkd_tree - recursive procedure to build a kd-tree +// +// Builds a kd-tree for points in pa as indexed through the +// array pidx[0..n-1] (typically a subarray of the array used in +// the top-level call). This routine permutes the array pidx, +// but does not alter pa[]. +// +// The construction is based on a standard algorithm for constructing +// the kd-tree (see Friedman, Bentley, and Finkel, ``An algorithm for +// finding best matches in logarithmic expected time,'' ACM Transactions +// on Mathematical Software, 3(3):209-226, 1977). The procedure +// operates by a simple divide-and-conquer strategy, which determines +// an appropriate orthogonal cutting plane (see below), and splits +// the points. When the number of points falls below the bucket size, +// we simply store the points in a leaf node's bucket. +// +// One of the arguments is a pointer to a splitting routine, +// whose prototype is: +// +// void split( +// ANNpointArray pa, // complete point array +// ANNidxArray pidx, // point array (permuted on return) +// ANNorthRect &bnds, // bounds of current cell +// int n, // number of points +// int dim, // dimension of space +// int &cut_dim, // cutting dimension +// ANNcoord &cut_val, // cutting value +// int &n_lo) // no. of points on low side of cut +// +// This procedure selects a cutting dimension and cutting value, +// partitions pa about these values, and returns the number of +// points on the low side of the cut. +//---------------------------------------------------------------------- + +ANNkd_ptr rkd_tree( // recursive construction of kd-tree + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter) // splitting routine +{ + if (n <= bsp) { // n small, make a leaf node + if (n == 0) // empty leaf node + return KD_TRIVIAL; // return (canonical) empty leaf + else // construct the node and return + return new ANNkd_leaf(n, pidx); + } + else { // n large, make a splitting node + int cd; // cutting dimension + ANNcoord cv; // cutting value + int n_lo; // number on low side of cut + ANNkd_node *lo, *hi; // low and high children + + // invoke splitting procedure + (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); + + ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension + ANNcoord hv = bnd_box.hi[cd]; + + bnd_box.hi[cd] = cv; // modify bounds for left subtree + lo = rkd_tree( // build left subtree + pa, pidx, n_lo, // ...from pidx[0..n_lo-1] + dim, bsp, bnd_box, splitter); + bnd_box.hi[cd] = hv; // restore bounds + + bnd_box.lo[cd] = cv; // modify bounds for right subtree + hi = rkd_tree( // build right subtree + pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] + dim, bsp, bnd_box, splitter); + bnd_box.lo[cd] = lv; // restore bounds + + // create the splitting node + ANNkd_split *ptr = new ANNkd_split(cd, cv, lv, hv, lo, hi); + + return ptr; // return pointer to this node + } +} + +//---------------------------------------------------------------------- +// kd-tree constructor +// This is the main constructor for kd-trees given a set of points. +// It first builds a skeleton tree, then computes the bounding box +// of the data points, and then invokes rkd_tree() to actually +// build the tree, passing it the appropriate splitting routine. +//---------------------------------------------------------------------- + +ANNkd_tree::ANNkd_tree( // construct from point array + ANNpointArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNsplitRule split) // splitting method +{ + SkeletonTree(n, dd, bs); // set up the basic stuff + pts = pa; // where the points are + if (n == 0) return; // no points--no sweat + + ANNorthRect bnd_box(dd); // bounding box for points + annEnclRect(pa, pidx, n, dd, bnd_box);// construct bounding rectangle + // copy to tree structure + bnd_box_lo = annCopyPt(dd, bnd_box.lo); + bnd_box_hi = annCopyPt(dd, bnd_box.hi); + + switch (split) { // build by rule + case ANN_KD_STD: // standard kd-splitting rule + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split); + break; + case ANN_KD_MIDPT: // midpoint split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split); + break; + case ANN_KD_FAIR: // fair split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split); + break; + case ANN_KD_SUGGEST: // best (in our opinion) + case ANN_KD_SL_MIDPT: // sliding midpoint split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split); + break; + case ANN_KD_SL_FAIR: // sliding fair split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_fair_split); + break; + default: + annError("Illegal splitting method", ANNabort); + } +} diff --git a/external/ann_1.1.1/src/kd_tree.h b/external/ann_1.1.1/src/kd_tree.h new file mode 100644 index 0000000..7604c40 --- /dev/null +++ b/external/ann_1.1.1/src/kd_tree.h @@ -0,0 +1,206 @@ +//---------------------------------------------------------------------- +// File: kd_tree.h +// Programmer: Sunil Arya and David Mount +// Description: Declarations for standard kd-tree routines +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.1 05/03/05 +// Added fixed radius kNN search +//---------------------------------------------------------------------- + +#ifndef ANN_kd_tree_H +#define ANN_kd_tree_H + +#include // all ANN includes + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// Generic kd-tree node +// +// Nodes in kd-trees are of two types, splitting nodes which contain +// splitting information (a splitting hyperplane orthogonal to one +// of the coordinate axes) and leaf nodes which contain point +// information (an array of points stored in a bucket). This is +// handled by making a generic class kd_node, which is essentially an +// empty shell, and then deriving the leaf and splitting nodes from +// this. +//---------------------------------------------------------------------- + +class ANNkd_node{ // generic kd-tree node (empty shell) +public: + virtual ~ANNkd_node() {} // virtual distroyer + + virtual void ann_search(ANNdist) = 0; // tree search + virtual void ann_pri_search(ANNdist) = 0; // priority search + virtual void ann_FR_search(ANNdist) = 0; // fixed-radius search + + // added by vlad to allow update of flops even when ANN_PERF is not defined + // this gives user choice between speed and stats at runtime + virtual void ann_FR_searchFlops(ANNdist)=0; // fixed-radius search + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box) = 0; // bounding box + // print node + virtual void print(int level, ostream &out) = 0; + virtual void dump(ostream &out) = 0; // dump node + + friend class ANNkd_tree; // allow kd-tree to access us +}; + +//---------------------------------------------------------------------- +// kd-splitting function: +// kd_splitter is a pointer to a splitting routine for preprocessing. +// Different splitting procedures result in different strategies +// for building the tree. +//---------------------------------------------------------------------- + +typedef void (*ANNkd_splitter)( // splitting routine for kd-trees + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +//---------------------------------------------------------------------- +// Leaf kd-tree node +// Leaf nodes of the kd-tree store the set of points associated +// with this bucket, stored as an array of point indices. These +// are indices in the array points, which resides with the +// root of the kd-tree. We also store the number of points +// that reside in this bucket. +//---------------------------------------------------------------------- + +class ANNkd_leaf: public ANNkd_node // leaf node for kd-tree +{ + int n_pts; // no. points in bucket + ANNidxArray bkt; // bucket of points +public: + ANNkd_leaf( // constructor + int n, // number of points + ANNidxArray b) // bucket + { + n_pts = n; // number of points in bucket + bkt = b; // the bucket + } + + ~ANNkd_leaf() { } // destructor (none) + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box); // bounding box + virtual void print(int level, ostream &out);// print node + virtual void dump(ostream &out); // dump node + + virtual void ann_search(ANNdist); // standard search + virtual void ann_pri_search(ANNdist); // priority search + virtual void ann_FR_search(ANNdist); // fixed-radius search + // added by Vlad to always update flops, even if ANN_PERF is not defined + virtual void ann_FR_searchFlops(ANNdist); // fixed-radius search +}; + +//---------------------------------------------------------------------- +// KD_TRIVIAL is a special pointer to an empty leaf node. Since +// some splitting rules generate many (more than 50%) trivial +// leaves, we use this one shared node to save space. +// +// The pointer is initialized to NULL, but whenever a kd-tree is +// created, we allocate this node, if it has not already been +// allocated. This node is *never* deallocated, so it produces +// a small memory leak. +//---------------------------------------------------------------------- + +extern ANNkd_leaf *KD_TRIVIAL; // trivial (empty) leaf node + +//---------------------------------------------------------------------- +// kd-tree splitting node. +// Splitting nodes contain a cutting dimension and a cutting value. +// These indicate the axis-parellel plane which subdivide the +// box for this node. The extent of the bounding box along the +// cutting dimension is maintained (this is used to speed up point +// to box distance calculations) [we do not store the entire bounding +// box since this may be wasteful of space in high dimensions]. +// We also store pointers to the 2 children. +//---------------------------------------------------------------------- + +class ANNkd_split : public ANNkd_node // splitting node of a kd-tree +{ + int cut_dim; // dim orthogonal to cutting plane + ANNcoord cut_val; // location of cutting plane + ANNcoord cd_bnds[2]; // lower and upper bounds of + // rectangle along cut_dim + ANNkd_ptr child[2]; // left and right children +public: + ANNkd_split( // constructor + int cd, // cutting dimension + ANNcoord cv, // cutting value + ANNcoord lv, ANNcoord hv, // low and high values + ANNkd_ptr lc=NULL, ANNkd_ptr hc=NULL) // children + { + cut_dim = cd; // cutting dimension + cut_val = cv; // cutting value + cd_bnds[ANN_LO] = lv; // lower bound for rectangle + cd_bnds[ANN_HI] = hv; // upper bound for rectangle + child[ANN_LO] = lc; // left child + child[ANN_HI] = hc; // right child + } + + ~ANNkd_split() // destructor + { + if (child[ANN_LO]!= NULL && child[ANN_LO]!= KD_TRIVIAL) + delete child[ANN_LO]; + if (child[ANN_HI]!= NULL && child[ANN_HI]!= KD_TRIVIAL) + delete child[ANN_HI]; + } + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box); // bounding box + virtual void print(int level, ostream &out);// print node + virtual void dump(ostream &out); // dump node + + virtual void ann_search(ANNdist); // standard search + virtual void ann_pri_search(ANNdist); // priority search + virtual void ann_FR_search(ANNdist); // fixed-radius search + + // added by Vlad on 5-1-08 so that flops are updated even when ANN_PERF is not defined + virtual void ann_FR_searchFlops(ANNdist); // fixed-radius search +}; + +//---------------------------------------------------------------------- +// External entry points +//---------------------------------------------------------------------- + +ANNkd_ptr rkd_tree( // recursive construction of kd-tree + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter); // splitting routine + +#endif diff --git a/external/ann_1.1.1/src/kd_util.cpp b/external/ann_1.1.1/src/kd_util.cpp new file mode 100644 index 0000000..621ce8a --- /dev/null +++ b/external/ann_1.1.1/src/kd_util.cpp @@ -0,0 +1,471 @@ +//---------------------------------------------------------------------- +// File: kd_util.cpp +// Programmer: Sunil Arya and David Mount +// Description: Common utilities for kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "kd_util.h" // kd-utility declarations + +#include // performance evaluation + +//---------------------------------------------------------------------- +// The following routines are utility functions for manipulating +// points sets, used in determining splitting planes for kd-tree +// construction. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// NOTE: Virtually all point indexing is done through an index (i.e. +// permutation) array pidx. Consequently, a reference to the d-th +// coordinate of the i-th point is pa[pidx[i]][d]. The macro PA(i,d) +// is a shorthand for this. +//---------------------------------------------------------------------- + // standard 2-d indirect indexing +#define PA(i,d) (pa[pidx[(i)]][(d)]) + // accessing a single point +#define PP(i) (pa[pidx[(i)]]) + +//---------------------------------------------------------------------- +// annAspectRatio +// Compute the aspect ratio (ratio of longest to shortest side) +// of a rectangle. +//---------------------------------------------------------------------- + +double annAspectRatio( + int dim, // dimension + const ANNorthRect &bnd_box) // bounding cube +{ + ANNcoord length = bnd_box.hi[0] - bnd_box.lo[0]; + ANNcoord min_length = length; // min side length + ANNcoord max_length = length; // max side length + for (int d = 0; d < dim; d++) { + length = bnd_box.hi[d] - bnd_box.lo[d]; + if (length < min_length) min_length = length; + if (length > max_length) max_length = length; + } + return max_length/min_length; +} + +//---------------------------------------------------------------------- +// annEnclRect, annEnclCube +// These utilities compute the smallest rectangle and cube enclosing +// a set of points, respectively. +//---------------------------------------------------------------------- + +void annEnclRect( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds) // bounding cube (returned) +{ + for (int d = 0; d < dim; d++) { // find smallest enclosing rectangle + ANNcoord lo_bnd = PA(0,d); // lower bound on dimension d + ANNcoord hi_bnd = PA(0,d); // upper bound on dimension d + for (int i = 0; i < n; i++) { + if (PA(i,d) < lo_bnd) lo_bnd = PA(i,d); + else if (PA(i,d) > hi_bnd) hi_bnd = PA(i,d); + } + bnds.lo[d] = lo_bnd; + bnds.hi[d] = hi_bnd; + } +} + +void annEnclCube( // compute smallest enclosing cube + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds) // bounding cube (returned) +{ + int d; + // compute smallest enclosing rect + annEnclRect(pa, pidx, n, dim, bnds); + + ANNcoord max_len = 0; // max length of any side + for (d = 0; d < dim; d++) { // determine max side length + ANNcoord len = bnds.hi[d] - bnds.lo[d]; + if (len > max_len) { // update max_len if longest + max_len = len; + } + } + for (d = 0; d < dim; d++) { // grow sides to match max + ANNcoord len = bnds.hi[d] - bnds.lo[d]; + ANNcoord half_diff = (max_len - len) / 2; + bnds.lo[d] -= half_diff; + bnds.hi[d] += half_diff; + } +} + +//---------------------------------------------------------------------- +// annBoxDistance - utility routine which computes distance from point to +// box (Note: most distances to boxes are computed using incremental +// distance updates, not this function.) +//---------------------------------------------------------------------- + +ANNdist annBoxDistance( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim) // dimension of space +{ + register ANNdist dist = 0.0; // sum of squared distances + register ANNdist t; + + for (register int d = 0; d < dim; d++) { + if (q[d] < lo[d]) { // q is left of box + t = ANNdist(lo[d]) - ANNdist(q[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + else if (q[d] > hi[d]) { // q is right of box + t = ANNdist(q[d]) - ANNdist(hi[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + } + ANN_FLOP(4*dim) // increment floating op count + + return dist; +} + +//---------------------------------------------------------------------- +// annBoxDistanceFlops - utility routine which computes distance from point to +// box (Note: most distances to boxes are computed using incremental +// distance updates, not this function.) +// Added by Vlad 5-1-08 to allow computation of flops if user desires it +// at runtime (while still keeping the fast version that does not compute flops). +//---------------------------------------------------------------------- + +ANNdist annBoxDistanceFlops( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim) // dimension of space +{ + register ANNdist dist = 0.0; // sum of squared distances + register ANNdist t; + + for (register int d = 0; d < dim; d++) { + if (q[d] < lo[d]) { // q is left of box + t = ANNdist(lo[d]) - ANNdist(q[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + else if (q[d] > hi[d]) { // q is right of box + t = ANNdist(q[d]) - ANNdist(hi[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + } + ANN_FLOP_ALWAYS(4*dim) // increment floating op count + + return dist; +} + +//---------------------------------------------------------------------- +// annSpread - find spread along given dimension +// annMinMax - find min and max coordinates along given dimension +// annMaxSpread - find dimension of max spread +//---------------------------------------------------------------------- + +ANNcoord annSpread( // compute point spread along dimension + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d) // dimension to check +{ + ANNcoord min = PA(0,d); // compute max and min coords + ANNcoord max = PA(0,d); + for (int i = 1; i < n; i++) { + ANNcoord c = PA(i,d); + if (c < min) min = c; + else if (c > max) max = c; + } + return (max - min); // total spread is difference +} + +void annMinMax( // compute min and max coordinates along dim + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension to check + ANNcoord &min, // minimum value (returned) + ANNcoord &max) // maximum value (returned) +{ + min = PA(0,d); // compute max and min coords + max = PA(0,d); + for (int i = 1; i < n; i++) { + ANNcoord c = PA(i,d); + if (c < min) min = c; + else if (c > max) max = c; + } +} + +int annMaxSpread( // compute dimension of max spread + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim) // dimension of space +{ + int max_dim = 0; // dimension of max spread + ANNcoord max_spr = 0; // amount of max spread + + if (n == 0) return max_dim; // no points, who cares? + + for (int d = 0; d < dim; d++) { // compute spread along each dim + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spr) { // bigger than current max + max_spr = spr; + max_dim = d; + } + } + return max_dim; +} + +//---------------------------------------------------------------------- +// annMedianSplit - split point array about its median +// Splits a subarray of points pa[0..n] about an element of given +// rank (median: n_lo = n/2) with respect to dimension d. It places +// the element of rank n_lo-1 correctly (because our splitting rule +// takes the mean of these two). On exit, the array is permuted so +// that: +// +// pa[0..n_lo-2][d] <= pa[n_lo-1][d] <= pa[n_lo][d] <= pa[n_lo+1..n-1][d]. +// +// The mean of pa[n_lo-1][d] and pa[n_lo][d] is returned as the +// splitting value. +// +// All indexing is done indirectly through the index array pidx. +// +// This function uses the well known selection algorithm due to +// C.A.R. Hoare. +//---------------------------------------------------------------------- + + // swap two points in pa array +#define PASWAP(a,b) { int tmp = pidx[a]; pidx[a] = pidx[b]; pidx[b] = tmp; } + +void annMedianSplit( + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord &cv, // cutting value + int n_lo) // split into n_lo and n-n_lo +{ + int l = 0; // left end of current subarray + int r = n-1; // right end of current subarray + while (l < r) { + register int i = (r+l)/2; // select middle as pivot + register int k; + + if (PA(i,d) > PA(r,d)) // make sure last > pivot + PASWAP(i,r) + PASWAP(l,i); // move pivot to first position + + ANNcoord c = PA(l,d); // pivot value + i = l; + k = r; + for(;;) { // pivot about c + while (PA(++i,d) < c) ; + while (PA(--k,d) > c) ; + if (i < k) PASWAP(i,k) else break; + } + PASWAP(l,k); // pivot winds up in location k + + if (k > n_lo) r = k-1; // recurse on proper subarray + else if (k < n_lo) l = k+1; + else break; // got the median exactly + } + if (n_lo > 0) { // search for next smaller item + ANNcoord c = PA(0,d); // candidate for max + int k = 0; // candidate's index + for (int i = 1; i < n_lo; i++) { + if (PA(i,d) > c) { + c = PA(i,d); + k = i; + } + } + PASWAP(n_lo-1, k); // max among pa[0..n_lo-1] to pa[n_lo-1] + } + // cut value is midpoint value + cv = (PA(n_lo-1,d) + PA(n_lo,d))/2.0; +} + +//---------------------------------------------------------------------- +// annPlaneSplit - split point array about a cutting plane +// Split the points in an array about a given plane along a +// given cutting dimension. On exit, br1 and br2 are set so +// that: +// +// pa[ 0 ..br1-1] < cv +// pa[br1..br2-1] == cv +// pa[br2.. n -1] > cv +// +// All indexing is done indirectly through the index array pidx. +// +//---------------------------------------------------------------------- + +void annPlaneSplit( // split points by a plane + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv, // cutting value + int &br1, // first break (values < cv) + int &br2) // second break (values == cv) +{ + int l = 0; + int r = n-1; + for(;;) { // partition pa[0..n-1] about cv + while (l < n && PA(l,d) < cv) l++; + while (r >= 0 && PA(r,d) >= cv) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + br1 = l; // now: pa[0..br1-1] < cv <= pa[br1..n-1] + r = n-1; + for(;;) { // partition pa[br1..n-1] about cv + while (l < n && PA(l,d) <= cv) l++; + while (r >= br1 && PA(r,d) > cv) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + br2 = l; // now: pa[br1..br2-1] == cv < pa[br2..n-1] +} + + +//---------------------------------------------------------------------- +// annBoxSplit - split point array about a orthogonal rectangle +// Split the points in an array about a given orthogonal +// rectangle. On exit, n_in is set to the number of points +// that are inside (or on the boundary of) the rectangle. +// +// All indexing is done indirectly through the index array pidx. +// +//---------------------------------------------------------------------- + +void annBoxSplit( // split points by a box + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension of space + ANNorthRect &box, // the box + int &n_in) // number of points inside (returned) +{ + int l = 0; + int r = n-1; + for(;;) { // partition pa[0..n-1] about box + while (l < n && box.inside(dim, PP(l))) l++; + while (r >= 0 && !box.inside(dim, PP(r))) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + n_in = l; // now: pa[0..n_in-1] inside and rest outside +} + +//---------------------------------------------------------------------- +// annSplitBalance - compute balance factor for a given plane split +// Balance factor is defined as the number of points lying +// below the splitting value minus n/2 (median). Thus, a +// median split has balance 0, left of this is negative and +// right of this is positive. (The points are unchanged.) +//---------------------------------------------------------------------- + +int annSplitBalance( // determine balance factor of a split + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv) // cutting value +{ + int n_lo = 0; + for(int i = 0; i < n; i++) { // count number less than cv + if (PA(i,d) < cv) n_lo++; + } + return n_lo - n/2; +} + +//---------------------------------------------------------------------- +// annBox2Bnds - convert bounding box to list of bounds +// Given two boxes, an inner box enclosed within a bounding +// box, this routine determines all the sides for which the +// inner box is strictly contained with the bounding box, +// and adds an appropriate entry to a list of bounds. Then +// we allocate storage for the final list of bounds, and return +// the resulting list and its size. +//---------------------------------------------------------------------- + +void annBox2Bnds( // convert inner box to bounds + const ANNorthRect &inner_box, // inner box + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int &n_bnds, // number of bounds (returned) + ANNorthHSArray &bnds) // bounds array (returned) +{ + int i; + n_bnds = 0; // count number of bounds + for (i = 0; i < dim; i++) { + if (inner_box.lo[i] > bnd_box.lo[i]) // low bound is inside + n_bnds++; + if (inner_box.hi[i] < bnd_box.hi[i]) // high bound is inside + n_bnds++; + } + + bnds = new ANNorthHalfSpace[n_bnds]; // allocate appropriate size + + int j = 0; + for (i = 0; i < dim; i++) { // fill the array + if (inner_box.lo[i] > bnd_box.lo[i]) { + bnds[j].cd = i; + bnds[j].cv = inner_box.lo[i]; + bnds[j].sd = +1; + j++; + } + if (inner_box.hi[i] < bnd_box.hi[i]) { + bnds[j].cd = i; + bnds[j].cv = inner_box.hi[i]; + bnds[j].sd = -1; + j++; + } + } +} + +//---------------------------------------------------------------------- +// annBnds2Box - convert list of bounds to bounding box +// Given an enclosing box and a list of bounds, this routine +// computes the corresponding inner box. It is assumed that +// the box points have been allocated already. +//---------------------------------------------------------------------- + +void annBnds2Box( + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int n_bnds, // number of bounds + ANNorthHSArray bnds, // bounds array + ANNorthRect &inner_box) // inner box (returned) +{ + annAssignRect(dim, inner_box, bnd_box); // copy bounding box to inner + + for (int i = 0; i < n_bnds; i++) { + bnds[i].project(inner_box.lo); // project each endpoint + bnds[i].project(inner_box.hi); + } +} diff --git a/external/ann_1.1.1/src/kd_util.h b/external/ann_1.1.1/src/kd_util.h new file mode 100644 index 0000000..18d7efb --- /dev/null +++ b/external/ann_1.1.1/src/kd_util.h @@ -0,0 +1,133 @@ +//---------------------------------------------------------------------- +// File: kd_util.h +// Programmer: Sunil Arya and David Mount +// Description: Common utilities for kd- trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_util_H +#define ANN_kd_util_H + +#include "kd_tree.h" // kd-tree declarations + +//---------------------------------------------------------------------- +// externally accessible functions +//---------------------------------------------------------------------- + +double annAspectRatio( // compute aspect ratio of box + int dim, // dimension + const ANNorthRect &bnd_box); // bounding cube + +void annEnclRect( // compute smallest enclosing rectangle + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds); // bounding cube (returned) + +void annEnclCube( // compute smallest enclosing cube + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds); // bounding cube (returned) + +ANNdist annBoxDistance( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim); // dimension of space + +// added by vlad 5-1-2008 to allow user to compute flops at runtime in release version +// while keeping the version above fast +ANNdist annBoxDistanceFlops( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim); // dimension of space + + +ANNcoord annSpread( // compute point spread along dimension + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d); // dimension to check + +void annMinMax( // compute min and max coordinates along dim + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension to check + ANNcoord& min, // minimum value (returned) + ANNcoord& max); // maximum value (returned) + +int annMaxSpread( // compute dimension of max spread + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim); // dimension of space + +void annMedianSplit( // split points along median value + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord &cv, // cutting value + int n_lo); // split into n_lo and n-n_lo + +void annPlaneSplit( // split points by a plane + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv, // cutting value + int &br1, // first break (values < cv) + int &br2); // second break (values == cv) + +void annBoxSplit( // split points by a box + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension of space + ANNorthRect &box, // the box + int &n_in); // number of points inside (returned) + +int annSplitBalance( // determine balance factor of a split + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv); // cutting value + +void annBox2Bnds( // convert inner box to bounds + const ANNorthRect &inner_box, // inner box + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int &n_bnds, // number of bounds (returned) + ANNorthHSArray &bnds); // bounds array (returned) + +void annBnds2Box( // convert bounds to inner box + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int n_bnds, // number of bounds + ANNorthHSArray bnds, // bounds array + ANNorthRect &inner_box); // inner box (returned) + +#endif diff --git a/external/ann_1.1.1/src/perf.cpp b/external/ann_1.1.1/src/perf.cpp new file mode 100644 index 0000000..83b22c7 --- /dev/null +++ b/external/ann_1.1.1/src/perf.cpp @@ -0,0 +1,134 @@ +//---------------------------------------------------------------------- +// File: perf.cpp +// Programmer: Sunil Arya and David Mount +// Description: Methods for performance stats +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed names to avoid namespace conflicts. +// Added flush after printing performance stats to fix bug +// in Microsoft Windows version. +//---------------------------------------------------------------------- + +#include // basic ANN includes +#include // performance includes + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// Performance statistics +// The following data and routines are used for computing +// performance statistics for nearest neighbor searching. +// Because these routines can slow the code down, they can be +// activated and deactiviated by defining the PERF variable, +// by compiling with the option: -DPERF +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Global counters for performance measurement +//---------------------------------------------------------------------- + +int ann_Ndata_pts = 0; // number of data points +int ann_Nvisit_lfs = 0; // number of leaf nodes visited +int ann_Nvisit_spl = 0; // number of splitting nodes visited +int ann_Nvisit_shr = 0; // number of shrinking nodes visited +int ann_Nvisit_pts = 0; // visited points for one query +int ann_Ncoord_hts = 0; // coordinate hits for one query +int ann_Nfloat_ops = 0; // floating ops for one query +ANNsampStat ann_visit_lfs; // stats on leaf nodes visits +ANNsampStat ann_visit_spl; // stats on splitting nodes visits +ANNsampStat ann_visit_shr; // stats on shrinking nodes visits +ANNsampStat ann_visit_nds; // stats on total nodes visits +ANNsampStat ann_visit_pts; // stats on points visited +ANNsampStat ann_coord_hts; // stats on coordinate hits +ANNsampStat ann_float_ops; // stats on floating ops +// +ANNsampStat ann_average_err; // average error +ANNsampStat ann_rank_err; // rank error + +//---------------------------------------------------------------------- +// Routines for statistics. +//---------------------------------------------------------------------- + +DLL_API void annResetStats(int data_size) // reset stats for a set of queries +{ + ann_Ndata_pts = data_size; + ann_visit_lfs.reset(); + ann_visit_spl.reset(); + ann_visit_shr.reset(); + ann_visit_nds.reset(); + ann_visit_pts.reset(); + ann_coord_hts.reset(); + ann_float_ops.reset(); + ann_average_err.reset(); + ann_rank_err.reset(); +} + +DLL_API void annResetCounts() // reset counts for one query +{ + ann_Nvisit_lfs = 0; + ann_Nvisit_spl = 0; + ann_Nvisit_shr = 0; + ann_Nvisit_pts = 0; + ann_Ncoord_hts = 0; + ann_Nfloat_ops = 0; +} + +DLL_API void annUpdateStats() // update stats with current counts +{ + ann_visit_lfs += ann_Nvisit_lfs; + ann_visit_nds += ann_Nvisit_spl + ann_Nvisit_lfs; + ann_visit_spl += ann_Nvisit_spl; + ann_visit_shr += ann_Nvisit_shr; + ann_visit_pts += ann_Nvisit_pts; + ann_coord_hts += ann_Ncoord_hts; + ann_float_ops += ann_Nfloat_ops; +} + + // print a single statistic +void print_one_stat(char *title, ANNsampStat s, double div) +{ + cout << title << "= [ "; + cout.width(9); cout << s.mean()/div << " : "; + cout.width(9); cout << s.stdDev()/div << " ]<"; + cout.width(9); cout << s.min()/div << " , "; + cout.width(9); cout << s.max()/div << " >\n"; +} + +DLL_API void annPrintStats( // print statistics for a run + ANNbool validate) // true if average errors desired +{ + cout.precision(4); // set floating precision + cout << " (Performance stats: " + << " [ mean : stddev ]< min , max >\n"; + print_one_stat(" leaf_nodes ", ann_visit_lfs, 1); + print_one_stat(" splitting_nodes ", ann_visit_spl, 1); + print_one_stat(" shrinking_nodes ", ann_visit_shr, 1); + print_one_stat(" total_nodes ", ann_visit_nds, 1); + print_one_stat(" points_visited ", ann_visit_pts, 1); + print_one_stat(" coord_hits/pt ", ann_coord_hts, ann_Ndata_pts); + print_one_stat(" floating_ops_(K) ", ann_float_ops, 1000); + if (validate) { + print_one_stat(" average_error ", ann_average_err, 1); + print_one_stat(" rank_error ", ann_rank_err, 1); + } + cout.precision(0); // restore the default + cout << " )\n"; + cout.flush(); +} diff --git a/external/ann_1.1.1/src/pr_queue.h b/external/ann_1.1.1/src/pr_queue.h new file mode 100644 index 0000000..3eb9a61 --- /dev/null +++ b/external/ann_1.1.1/src/pr_queue.h @@ -0,0 +1,125 @@ +//---------------------------------------------------------------------- +// File: pr_queue.h +// Programmer: Sunil Arya and David Mount +// Description: Include file for priority queue and related +// structures. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef PR_QUEUE_H +#define PR_QUEUE_H + +#include // all ANN includes +#include // performance evaluation + +//---------------------------------------------------------------------- +// Basic types. +//---------------------------------------------------------------------- +typedef void *PQinfo; // info field is generic pointer +typedef ANNdist PQkey; // key field is distance + +//---------------------------------------------------------------------- +// Priority queue +// A priority queue is a list of items, along with associated +// priorities. The basic operations are insert and extract_minimum. +// +// The priority queue is maintained using a standard binary heap. +// (Implementation note: Indexing is performed from [1..max] rather +// than the C standard of [0..max-1]. This simplifies parent/child +// computations.) User information consists of a void pointer, +// and the user is responsible for casting this quantity into whatever +// useful form is desired. +// +// Because the priority queue is so central to the efficiency of +// query processing, all the code is inline. +//---------------------------------------------------------------------- + +class ANNpr_queue { + + struct pq_node { // node in priority queue + PQkey key; // key value + PQinfo info; // info field + }; + int n; // number of items in queue + int max_size; // maximum queue size + pq_node *pq; // the priority queue (array of nodes) + +public: + ANNpr_queue(int max) // constructor (given max size) + { + n = 0; // initially empty + max_size = max; // maximum number of items + pq = new pq_node[max+1]; // queue is array [1..max] of nodes + } + + ~ANNpr_queue() // destructor + { delete [] pq; } + + ANNbool empty() // is queue empty? + { if (n==0) return ANNtrue; else return ANNfalse; } + + ANNbool non_empty() // is queue nonempty? + { if (n==0) return ANNfalse; else return ANNtrue; } + + void reset() // make existing queue empty + { n = 0; } + + inline void insert( // insert item (inlined for speed) + PQkey kv, // key value + PQinfo inf) // item info + { + if (++n > max_size) annError("Priority queue overflow.", ANNabort); + register int r = n; + while (r > 1) { // sift up new item + register int p = r/2; + ANN_FLOP(1) // increment floating ops + if (pq[p].key <= kv) // in proper order + break; + pq[r] = pq[p]; // else swap with parent + r = p; + } + pq[r].key = kv; // insert new item at final location + pq[r].info = inf; + } + + inline void extr_min( // extract minimum (inlined for speed) + PQkey &kv, // key (returned) + PQinfo &inf) // item info (returned) + { + kv = pq[1].key; // key of min item + inf = pq[1].info; // information of min item + register PQkey kn = pq[n--].key;// last item in queue + register int p = 1; // p points to item out of position + register int r = p<<1; // left child of p + while (r <= n) { // while r is still within the heap + ANN_FLOP(2) // increment floating ops + // set r to smaller child of p + if (r < n && pq[r].key > pq[r+1].key) r++; + if (kn <= pq[r].key) // in proper order + break; + pq[p] = pq[r]; // else swap with child + p = r; // advance pointers + r = p<<1; + } + pq[p] = pq[n+1]; // insert last item in proper place + } +}; + +#endif diff --git a/external/ann_1.1.1/src/pr_queue_k.h b/external/ann_1.1.1/src/pr_queue_k.h new file mode 100644 index 0000000..5447085 --- /dev/null +++ b/external/ann_1.1.1/src/pr_queue_k.h @@ -0,0 +1,138 @@ +//---------------------------------------------------------------------- +// File: pr_queue_k.h +// Programmer: Sunil Arya and David Mount +// Description: Include file for priority queue with k items. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef PR_QUEUE_K_H +#define PR_QUEUE_K_H + +#include // all ANN includes +#include // performance evaluation + +//---------------------------------------------------------------------- +// Basic types +//---------------------------------------------------------------------- +typedef ANNdist PQKkey; // key field is distance +typedef int PQKinfo; // info field is int + +//---------------------------------------------------------------------- +// Constants +// The NULL key value is used to initialize the priority queue, and +// so it should be larger than any valid distance, so that it will +// be replaced as legal distance values are inserted. The NULL +// info value must be a nonvalid array index, we use ANN_NULL_IDX, +// which is guaranteed to be negative. +//---------------------------------------------------------------------- + +const PQKkey PQ_NULL_KEY = ANN_DIST_INF; // nonexistent key value +const PQKinfo PQ_NULL_INFO = ANN_NULL_IDX; // nonexistent info value + +//---------------------------------------------------------------------- +// ANNmin_k +// An ANNmin_k structure is one which maintains the smallest +// k values (of type PQKkey) and associated information (of type +// PQKinfo). The special info and key values PQ_NULL_INFO and +// PQ_NULL_KEY means that thise entry is empty. +// +// It is currently implemented using an array with k items. +// Items are stored in increasing sorted order, and insertions +// are made through standard insertion sort. (This is quite +// inefficient, but current applications call for small values +// of k and relatively few insertions.) +// +// Note that the list contains k+1 entries, but the last entry +// is used as a simple placeholder and is otherwise ignored. +//---------------------------------------------------------------------- + +class ANNmin_k { + struct mk_node { // node in min_k structure + PQKkey key; // key value + PQKinfo info; // info field (user defined) + }; + + int k; // max number of keys to store + int n; // number of keys currently active + mk_node *mk; // the list itself + +public: + ANNmin_k(int max) // constructor (given max size) + { + n = 0; // initially no items + k = max; // maximum number of items + mk = new mk_node[max+1]; // sorted array of keys + } + + ~ANNmin_k() // destructor + { delete [] mk; } + + PQKkey ANNmin_key() // return minimum key + { return (n > 0 ? mk[0].key : PQ_NULL_KEY); } + + PQKkey max_key() // return maximum key + { return (n == k ? mk[k-1].key : PQ_NULL_KEY); } + + PQKkey ith_smallest_key(int i) // ith smallest key (i in [0..n-1]) + { return (i < n ? mk[i].key : PQ_NULL_KEY); } + + PQKinfo ith_smallest_info(int i) // info for ith smallest (i in [0..n-1]) + { return (i < n ? mk[i].info : PQ_NULL_INFO); } + + inline void insert( // insert item (inlined for speed) + PQKkey kv, // key value + PQKinfo inf) // item info + { + register int i; + // slide larger values up + for (i = n; i > 0; i--) { + if (mk[i-1].key > kv) + mk[i] = mk[i-1]; + else + break; + } + mk[i].key = kv; // store element here + mk[i].info = inf; + if (n < k) n++; // increment number of items + ANN_FLOP(k-i+1) // increment floating ops + } + + // added by Vlad 5-1-08 to allow user to update flops by calling this + // function even when ANN_PERF is not defined + inline void insertFlops( // insert item (inlined for speed) + PQKkey kv, // key value + PQKinfo inf) // item info + { + register int i; + // slide larger values up + for (i = n; i > 0; i--) { + if (mk[i-1].key > kv) + mk[i] = mk[i-1]; + else + break; + } + mk[i].key = kv; // store element here + mk[i].info = inf; + if (n < k) n++; // increment number of items + ANN_FLOP_ALWAYS(k-i+1) // increment floating ops + } +}; + +#endif diff --git a/external/ann_1.1.1/test/Makefile b/external/ann_1.1.1/test/Makefile new file mode 100644 index 0000000..63bec2a --- /dev/null +++ b/external/ann_1.1.1/test/Makefile @@ -0,0 +1,96 @@ +#----------------------------------------------------------------------------- +# Makefile for the test and evaluation program +# +# ANN: Approximate Nearest Neighbors +# Version: 1.1.1 08/04/06 +#----------------------------------------------------------------------------- +# Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +# David Mount. All Rights Reserved. +# +# This software and related documentation is part of the Approximate +# Nearest Neighbor Library (ANN). This software is provided under +# the provisions of the Lesser GNU Public License (LGPL). See the +# file ../ReadMe.txt for further information. +# +# The University of Maryland (U.M.) and the authors make no +# representations about the suitability or fitness of this software for +# any purpose. It is provided "as is" without express or implied +# warranty. +#----------------------------------------------------------------------------- +# Revision 0.1 03/04/98 +# Initial release +# Revision 1.1.1 08/04/06 +# Added copyright/license +#----------------------------------------------------------------------------- +# Note: For full performance measurements, it is assumed that the library +# and this program have both been compiled with the -DANN_PERF flag. See +# the Makefile in the ANN base directory for this flag. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Basic definitions +# BASEDIR where include, src, lib, ... are +# INCDIR include directory +# LIBDIR library directory +# BINDIR bin directory +# LDFLAGS loader flags +# ANNLIBS ANN library +# OTHERLIBS other libraries +#----------------------------------------------------------------------------- + +BASEDIR = .. +INCDIR = $(BASEDIR)/include +LIBDIR = $(BASEDIR)/lib +BINDIR = $(BASEDIR)/bin +LDFLAGS = -L$(LIBDIR) +ANNLIBS = -lann_figtree_version +OTHERLIBS = -lm + +#----------------------------------------------------------------------------- +# Some more definitions +# ANNTEST name of test program +#----------------------------------------------------------------------------- + +ANNTEST = ann_test + +HEADERS = rand.h +TESTSOURCES = ann_test.cpp rand.cpp +TESTOBJECTS = $(TESTSOURCES:.cpp=.o) + +#----------------------------------------------------------------------------- +# Make the program +#----------------------------------------------------------------------------- + +default: + @echo "Specify a target configuration" + +targets: $(BINDIR)/$(ANNTEST) + +$(BINDIR)/$(ANNTEST): $(TESTOBJECTS) $(LIBDIR)/$(ANNLIB) + $(C++) $(TESTOBJECTS) -o $(ANNTEST) $(LDFLAGS) $(ANNLIBS) $(OTHERLIBS) + mv $(ANNTEST) $(BINDIR) + +#----------------------------------------------------------------------------- +# configuration definitions +#----------------------------------------------------------------------------- + +include ../Make-config + +#----------------------------------------------------------------------------- +# Objects +#----------------------------------------------------------------------------- + +ann_test.o: ann_test.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) ann_test.cpp + +rand.o: rand.cpp + $(C++) -c -I$(INCDIR) $(CFLAGS) rand.cpp + +#----------------------------------------------------------------------------- +# Cleaning +#----------------------------------------------------------------------------- + +clean: + -rm -f *.o *.out core + +realclean: clean diff --git a/external/ann_1.1.1/test/ann_test.cpp b/external/ann_1.1.1/test/ann_test.cpp new file mode 100644 index 0000000..aa4125d --- /dev/null +++ b/external/ann_1.1.1/test/ann_test.cpp @@ -0,0 +1,1640 @@ +//---------------------------------------------------------------------- +// File: ann_test.cpp +// Programmer: Sunil Arya and David Mount +// Description: test program for ANN (approximate nearest neighbors) +// Last modified: 08/04/06 (Version 1.1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 0.2 06/26/98 +// Added CLOCKS_PER_SEC definition if needed +// Revision 1.0 04/01/05 +// Added comments (from "#" to eol) +// Added clus_orth_flats and clus_ellipsoids distributions +// Fixed order of fair and midpt in split_table +// Added dump/load operations +// Cleaned up C++ for modern compilers +// Revision 1.1 05/03/05 +// Added fixed radius kNN search +// Revision 1.1.1 08/04/06 +// Added planted distribution +//---------------------------------------------------------------------- + +#include // clock +#include // math routines +#include // C string ops +#include // file I/O + +#include // ANN declarations +#include // more ANN declarations +#include // performance evaluation + +#include "rand.h" // random point generation + +#ifndef CLOCKS_PER_SEC // define clocks-per-second if needed + #define CLOCKS_PER_SEC 1000000 +#endif + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// ann_test +// +// This program is a driver for testing and evaluating the ANN library +// for computing approximate nearest neighbors. It allows the user to +// generate data and query sets of various sizes, dimensions, and +// distributions, to build kd- and bbd-trees of various types, and then +// run queries and outputting various performance statistics. +// +// Overview: +// --------- +// The test program is run as follows: +// +// ann_test < test_input > test_output +// +// where the test_input file contains a list of directives as described +// below. Directives consist of a directive name, followed by list of +// arguments (depending on the directive). Arguments and directives are +// separated by white space (blank, tab, and newline). String arguments +// are not quoted, and consist of a string of nonwhite chacters. A +// character "#" denotes a comment. The following characters up to +// the end of line are ignored. Comments may only be inserted between +// directives (not within the argument list of a directive). +// +// Basic operations: +// ----------------- +// The test program can perform the following operations. How these +// operations are performed depends on the options which are described +// later. +// +// Data Generation: +// ---------------- +// read_data_pts Create a set of data points whose +// coordinates are input from file . +// gen_data_pts Create a set of data points whose +// coordinates are generated from the +// current point distribution. +// +// Building the tree: +// ------------------ +// build_ann Generate an approximate nearest neighbor +// structure for the current data set, using +// the selected splitting rules. Any existing +// tree will be destroyed. +// +// Query Generation/Searching: +// --------------------------- +// read_query_pts Create a set of query points whose +// coordinates are input from file . +// gen_query_pts Create a set of query points whose +// coordinates are generated from the +// current point distribution. +// run_queries Apply nearest neighbor searching to the +// query points using the approximate nearest +// neighbor structure and the given search +// strategy. Possible strategies are: +// standard = standard kd-tree search +// priority = priority search +// +// Miscellaneous: +// -------------- +// output_label Output a label to the output file. +// dump Dump the current structure to given file. +// (The dump format is explained further in +// the source file kd_tree.cc.) +// load Load a tree from a data file which was +// created by the dump operation. Any +// existing tree will be destroyed. +// +// Options: +// -------- +// How these operations are performed depends on a set of options. +// If an option is not specified, a default value is used. An option +// retains its value until it is set again. String inputs are not +// enclosed in quotes, and must contain no embedded white space (sorry, +// this is C++'s convention). +// +// Options affecting search tree structure: +// ---------------------------------------- +// split_rule Type of splitting rule to use in building +// the search tree. Choices are: +// kd = optimized kd-tree +// midpt = midpoint split +// fair = fair split +// sl_midpt = sliding midpt split +// sl_fair = sliding fair split +// suggest = authors' choice for best +// The default is "suggest". See the file +// kd_split.cc for more detailed information. +// +// shrink_rule Type of shrinking rule to use in building +// a bd-tree data structure. If "none" is +// given, then no shrinking is performed and +// the result is a kd-tree. Choices are: +// none = perform no shrinking +// simple = simple shrinking +// centroid = centroid shrinking +// suggest = authors' choice for best +// The default is "none". See the file +// bd_tree.cc for more information. +// bucket_size Bucket size, that is, the maximum number of +// points stored in each leaf node. +// +// Options affecting data and query point generation: +// -------------------------------------------------- +// dim Dimension of space. +// seed Seed for random number generation. +// data_size Number of data points. When reading data +// points from a file, this indicates the +// maximum number of points for storage +// allocation. Default = 100. +// query_size Same as data_size for query points. +// std_dev Standard deviation (used in gauss, +// planted, and clustered distributions). +// This is the "small" distribution for +// clus_ellipsoids. Default = 1. +// std_dev_lo Low and high standard deviations (used in +// std_dev_hi clus_ellipsoids). Default = 1. +// corr_coef Correlation coefficient (used in co-gauss +// and co_lapace distributions). Default = 0.05. +// colors Number of color classes (clusters) (used +// in the clustered distributions). Default = 5. +// new_clust Once generated, cluster centers are not +// normally regenerated. This is so that both +// query points and data points can be generated +// using the same set of clusters. This option +// forces new cluster centers to be generated +// with the next generation of either data or +// query points. +// max_clus_dim Maximum dimension of clusters (used in +// clus_orth_flats and clus_ellipsoids). +// Default = 1. +// distribution Type of input distribution +// uniform = uniform over cube [-1,1]^d. +// gauss = Gaussian with mean 0 +// laplace = Laplacian, mean 0 and var 1 +// co_gauss = correlated Gaussian +// co_laplace = correlated Laplacian +// clus_gauss = clustered Gaussian +// clus_orth_flats = clusters of orth flats +// clus_ellipsoids = clusters of ellipsoids +// planted = planted distribution +// See the file rand.cpp for further information. +// +// Options affecting nearest neighbor search: +// ------------------------------------------ +// epsilon Error bound for approx. near neigh. search. +// near_neigh Number of nearest neighbors to compute. +// max_pts_visit Maximum number of points to visit before +// terminating. (Used in applications where +// real-time performance is important.) +// (Default = 0, which means no limit.) +// radius_bound Sets an upper bound on the nearest +// neighbor search radius. If the bound is +// positive, then fixed-radius nearest +// neighbor searching is performed, and the +// count of the number of points in the +// range is returned. If the bound is +// zero, then standard search is used. +// This can only be used with standard, not +// priority, search. (Default = 0, which +// means standard search.) +// +// Options affection general program behavior: +// ------------------------------------------- +// stats Level of statistics output +// silent = no output, +// exec_time += execution time only +// prep_stats += preprocessing statistics +// query_stats += query performance stats +// query_res += results of queries +// show_pts += show the data points +// show_struct += print search structure +// validate Validate experiment and compute average +// error. Since validation causes exact +// nearest neighbors to be computed by the +// brute force method, this can take a long +// time. Valid arguments are: +// on = turn validation on +// off = turn validation off +// true_near_neigh Number of true nearest neighbors to compute. +// When validating, we compute the difference +// in rank between each reported nearest neighbor +// and the true nearest neighbor of the same +// rank. Thus it is necessary to compute a +// few more true nearest neighbors. By default +// we compute 10 more than near_neigh. With +// this option the exact number can be set. +// (Used only when validating.) +// +// Example: +// -------- +// output_label test_run_0 # output label for this run +// validate off # do not perform validation +// dim 16 # points in dimension 16 +// stats query_stats # output performance statistics for queries +// seed 121212 # random number seed +// data_size 1000 +// distribution uniform +// gen_data_pts # 1000 uniform data points in dim 16 +// query_size 100 +// std_dev 0.05 +// distribution clus_gauss +// gen_query_pts # 100 points in 10 clusters with std_dev 0.05 +// bucket_size 2 +// split_rule kd +// shrink_rule none +// build_ann # kd-tree, bucket size 2 +// epsilon 0.1 +// near_neigh 5 +// max_pts_visit 100 # stop search if more than 100 points seen +// run_queries standard # run queries; 5 nearest neighbors, 10% error +// data_size 500 +// read_data_pts data.in # read up to 500 points from file data.in +// split_rule sl_midpt +// shrink_rule simple +// build_ann # bd-tree; simple shrink, sliding midpoint split +// epsilon 0 +// run_queries priority # run same queries; 0 allowable error +// +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------ + +const int STRING_LEN = 500; // max string length +const double ERR = 0.00001; // epsilon (for float compares) + +//------------------------------------------------------------------------ +// Enumerated values and conversions +//------------------------------------------------------------------------ + +typedef enum {DATA, QUERY} PtType; // point types + +//------------------------------------------------------------------------ +// Statistics output levels +//------------------------------------------------------------------------ + +typedef enum { // stat levels + SILENT, // no output + EXEC_TIME, // just execution time + PREP_STATS, // preprocessing info + QUERY_STATS, // query performance + QUERY_RES, // query results + SHOW_PTS, // show data points + SHOW_STRUCT, // show tree structure + N_STAT_LEVELS} // number of levels + StatLev; + +const char stat_table[N_STAT_LEVELS][STRING_LEN] = { + "silent", // SILENT + "exec_time", // EXEC_TIME + "prep_stats", // PREP_STATS + "query_stats", // QUERY_STATS + "query_res", // QUERY_RES + "show_pts", // SHOW_PTS + "show_struct"}; // SHOW_STRUCT + +//------------------------------------------------------------------------ +// Distributions +//------------------------------------------------------------------------ + +typedef enum { // distributions + UNIFORM, // uniform over cube [-1,1]^d. + GAUSS, // Gaussian with mean 0 + LAPLACE, // Laplacian, mean 0 and var 1 + CO_GAUSS, // correlated Gaussian + CO_LAPLACE, // correlated Laplacian + CLUS_GAUSS, // clustered Gaussian + CLUS_ORTH_FLATS, // clustered on orthog flats + CLUS_ELLIPSOIDS, // clustered on ellipsoids + PLANTED, // planted distribution + N_DISTRIBS} + Distrib; + +const char distr_table[N_DISTRIBS][STRING_LEN] = { + "uniform", // UNIFORM + "gauss", // GAUSS + "laplace", // LAPLACE + "co_gauss", // CO_GAUSS + "co_laplace", // CO_LAPLACE + "clus_gauss", // CLUS_GAUSS + "clus_orth_flats", // CLUS_ORTH_FLATS + "clus_ellipsoids", // CLUS_ELLIPSOIS + "planted"}; // PLANTED + +//------------------------------------------------------------------------ +// Splitting rules for kd-trees (see ANN.h for types) +//------------------------------------------------------------------------ + +const int N_SPLIT_RULES = 6; +const char split_table[N_SPLIT_RULES][STRING_LEN] = { + "standard", // standard optimized kd-tree + "midpt", // midpoint split + "fair", // fair split + "sl_midpt", // sliding midpt split + "sl_fair", // sliding fair split + "suggest"}; // authors' choice for best + +//------------------------------------------------------------------------ +// Shrinking rules for bd-trees (see ANN.h for types) +//------------------------------------------------------------------------ + +const int N_SHRINK_RULES = 4; +const char shrink_table[N_SHRINK_RULES][STRING_LEN] = { + "none", // perform no shrinking (kd-tree) + "simple", // simple shrinking + "centroid", // centroid shrinking + "suggest"}; // authors' choice for best + +//---------------------------------------------------------------------- +// Short utility functions +// Error - general error routine +// printPoint - print a point to standard output +// lookUp - look up a name in table and return index +//---------------------------------------------------------------------- + +void Error( // error routine + char *msg, // error message + ANNerr level) // abort afterwards +{ + if (level == ANNabort) { + cerr << "ann_test: ERROR------->" << msg << "<-------------ERROR\n"; + exit(1); + } + else { + cerr << "ann_test: WARNING----->" << msg << "<-------------WARNING\n"; + } +} + +void printPoint( // print point + ANNpoint p, // the point + int dim) // the dimension +{ + cout << "["; + for (int i = 0; i < dim; i++) { + cout << p[i]; + if (i < dim-1) cout << ","; + } + cout << "]"; +} + +int lookUp( // look up name in table + const char *arg, // name to look up + const char (*table)[STRING_LEN], // name table + int size) // table size +{ + int i; + for (i = 0; i < size; i++) { + if (!strcmp(arg, table[i])) return i; + } + return i; +} + +//------------------------------------------------------------------------ +// Function declarations +//------------------------------------------------------------------------ + +void generatePts( // generate data/query points + ANNpointArray &pa, // point array (returned) + int n, // number of points + PtType type, // point type + ANNbool new_clust, // new cluster centers desired? + ANNpointArray src = NULL, // source array (for PLANTED) + int n_src = 0); // source size (for PLANTED) + +void readPts( // read data/query points from file + ANNpointArray &pa, // point array (returned) + int &n, // number of points + char *file_nm, // file name + PtType type); // point type (DATA, QUERY) + +void doValidation(); // perform validation +void getTrueNN(); // compute true nearest neighbors + +void treeStats( // print statistics on kd- or bd-tree + ostream &out, // output stream + ANNbool verbose); // print stats + +//------------------------------------------------------------------------ +// Default execution parameters +//------------------------------------------------------------------------ +const int extra_nn = 10; // how many extra true nn's? + +const int def_dim = 2; // def dimension +const int def_data_size = 100; // def data size +const int def_query_size = 100; // def number of queries +const int def_n_color = 5; // def number of colors +const ANNbool def_new_clust = ANNfalse; // def new clusters flag +const int def_max_dim = 1; // def max flat dimension +const Distrib def_distr = UNIFORM; // def distribution +const double def_std_dev = 1.00; // def standard deviation +const double def_corr_coef = 0.05; // def correlation coef +const int def_bucket_size = 1; // def bucket size +const double def_epsilon = 0.0; // def error bound +const int def_near_neigh = 1; // def number of near neighbors +const int def_max_visit = 0; // def number of points visited +const int def_rad_bound = 0; // def radius bound + // def number of true nn's +const int def_true_nn = def_near_neigh + extra_nn; +const int def_seed = 0; // def seed for random numbers +const ANNbool def_validate = ANNfalse; // def validation flag + // def statistics output level +const StatLev def_stats = QUERY_STATS; +const ANNsplitRule // def splitting rule + def_split = ANN_KD_SUGGEST; +const ANNshrinkRule // def shrinking rule + def_shrink = ANN_BD_NONE; + +//------------------------------------------------------------------------ +// Global variables - Execution options +//------------------------------------------------------------------------ + +int dim; // dimension +int data_size; // data size +int query_size; // number of queries +int n_color; // number of colors +ANNbool new_clust; // generate new clusters? +int max_dim; // maximum flat dimension +Distrib distr; // distribution +double corr_coef; // correlation coef +double std_dev; // standard deviation +double std_dev_lo; // low standard deviation +double std_dev_hi; // high standard deviation +int bucket_size; // bucket size +double epsilon; // error bound +int near_neigh; // number of near neighbors +int max_pts_visit; // max number of points to visit +double radius_bound; // maximum radius search bound +int true_nn; // number of true nn's +ANNbool validate; // validation flag +StatLev stats; // statistics output level +ANNsplitRule split; // splitting rule +ANNshrinkRule shrink; // shrinking rule + +//------------------------------------------------------------------------ +// More globals - pointers to dynamically allocated arrays and structures +// +// It is assumed that all these values are set to NULL when nothing +// is allocated. +// +// data_pts, query_pts The data and query points +// the_tree Points to the kd- or bd-tree for +// nearest neighbor searching. +// apx_nn_idx, apx_dists Record approximate near neighbor +// indices and distances +// apx_pts_in_range Counts of the number of points in +// the in approx range, for fixed- +// radius NN searching. +// true_nn_idx, true_dists Record true near neighbor +// indices and distances +// min_pts_in_range, max_... Min and max counts of the number +// of points in the in approximate +// range. +// valid_dirty To avoid repeated validation, +// we only validate query results +// once. This validation becomes +// invalid, if a new tree, new data +// points or new query points have +// been generated. +// tree_data_size The number of points in the +// current tree. (This will be the +// same a data_size unless points have +// been added since the tree was +// built.) +// +// The approximate and true nearest neighbor results are stored +// in: apx_nn_idx, apx_dists, and true_nn_idx, true_dists. +// They are really flattened 2-dimensional arrays. Each of these +// arrays consists of query_size blocks, each of which contains +// near_neigh (or true_nn) entries, one for each of the nearest +// neighbors for a given query point. +//------------------------------------------------------------------------ + +ANNpointArray data_pts; // data points +ANNpointArray query_pts; // query points +ANNbd_tree* the_tree; // kd- or bd-tree search structure +ANNidxArray apx_nn_idx; // storage for near neighbor indices +ANNdistArray apx_dists; // storage for near neighbor distances +int* apx_pts_in_range; // storage for no. of points in range +ANNidxArray true_nn_idx; // true near neighbor indices +ANNdistArray true_dists; // true near neighbor distances +int* min_pts_in_range; // min points in approx range +int* max_pts_in_range; // max points in approx range + +ANNbool valid_dirty; // validation is no longer valid + +//------------------------------------------------------------------------ +// Initialize global parameters +//------------------------------------------------------------------------ + +void initGlobals() +{ + dim = def_dim; // init execution parameters + data_size = def_data_size; + query_size = def_query_size; + distr = def_distr; + corr_coef = def_corr_coef; + std_dev = def_std_dev; + std_dev_lo = def_std_dev; + std_dev_hi = def_std_dev; + new_clust = def_new_clust; + max_dim = def_max_dim; + n_color = def_n_color; + bucket_size = def_bucket_size; + epsilon = def_epsilon; + near_neigh = def_near_neigh; + max_pts_visit = def_max_visit; + radius_bound = def_rad_bound; + true_nn = def_true_nn; + validate = def_validate; + stats = def_stats; + split = def_split; + shrink = def_shrink; + annIdum = -def_seed; // init. global seed for ran0() + + data_pts = NULL; // initialize storage pointers + query_pts = NULL; + the_tree = NULL; + apx_nn_idx = NULL; + apx_dists = NULL; + apx_pts_in_range = NULL; + true_nn_idx = NULL; + true_dists = NULL; + min_pts_in_range = NULL; + max_pts_in_range = NULL; + + valid_dirty = ANNtrue; // (validation must be done) +} + +//------------------------------------------------------------------------ +// getDirective - skip comments and read next directive +// Returns ANNtrue if directive read, and ANNfalse if eof seen. +//------------------------------------------------------------------------ + +ANNbool skipComment( // skip any comments + istream &in) // input stream +{ + char ch = 0; + // skip whitespace + do { in.get(ch); } while (isspace(ch) && !in.eof()); + while (ch == '#' && !in.eof()) { // comment? + // skip to end of line + do { in.get(ch); } while(ch != '\n' && !in.eof()); + // skip whitespace + do { in.get(ch); } while(isspace(ch) && !in.eof()); + } + if (in.eof()) return ANNfalse; // end of file + in.putback(ch); // put character back + return ANNtrue; +} + +ANNbool getDirective( + istream &in, // input stream + char *directive) // directive storage +{ + if (!skipComment(in)) // skip comments + return ANNfalse; // found eof along the way? + in >> directive; // read directive + return ANNtrue; +} + + +//------------------------------------------------------------------------ +// main program - driver +// The main program reads input options, invokes the necessary +// routines to process them. +//------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + long clock0; // clock time + char directive[STRING_LEN]; // input directive + char arg[STRING_LEN]; // all-purpose argument + + cout << "------------------------------------------------------------\n" + << "ann_test: Version " << ANNversion << " " << ANNversionCmt << "\n" + << " Copyright: " << ANNcopyright << ".\n" + << " Latest Revision: " << ANNlatestRev << ".\n" + << "------------------------------------------------------------\n\n"; + + initGlobals(); // initialize global values + + //-------------------------------------------------------------------- + // Main input loop + //-------------------------------------------------------------------- + // read input directive + while (getDirective(cin, directive)) { + //---------------------------------------------------------------- + // Read options + //---------------------------------------------------------------- + if (!strcmp(directive,"dim")) { + cin >> dim; + } + else if (!strcmp(directive,"colors")) { + cin >> n_color; + } + else if (!strcmp(directive,"new_clust")) { + new_clust = ANNtrue; + } + else if (!strcmp(directive,"max_clus_dim")) { + cin >> max_dim; + } + else if (!strcmp(directive,"std_dev")) { + cin >> std_dev; + } + else if (!strcmp(directive,"std_dev_lo")) { + cin >> std_dev_lo; + } + else if (!strcmp(directive,"std_dev_hi")) { + cin >> std_dev_hi; + } + else if (!strcmp(directive,"corr_coef")) { + cin >> corr_coef; + } + else if (!strcmp(directive, "data_size")) { + cin >> data_size; + } + else if (!strcmp(directive,"query_size")) { + cin >> query_size; + } + else if (!strcmp(directive,"bucket_size")) { + cin >> bucket_size; + } + else if (!strcmp(directive,"epsilon")) { + cin >> epsilon; + } + else if (!strcmp(directive,"max_pts_visit")) { + cin >> max_pts_visit; + valid_dirty = ANNtrue; // validation must be redone + } + else if (!strcmp(directive,"radius_bound")) { + cin >> radius_bound; + valid_dirty = ANNtrue; // validation must be redone + } + else if (!strcmp(directive,"near_neigh")) { + cin >> near_neigh; + true_nn = near_neigh + extra_nn; // also reset true near neighs + valid_dirty = ANNtrue; // validation must be redone + } + else if (!strcmp(directive,"true_near_neigh")) { + cin >> true_nn; + valid_dirty = ANNtrue; // validation must be redone + } + //---------------------------------------------------------------- + // seed option + // The seed is reset by setting the global annIdum to the + // negation of the seed value. See rand.cpp. + //---------------------------------------------------------------- + else if (!strcmp(directive,"seed")) { + cin >> annIdum; + annIdum = -annIdum; + } + //---------------------------------------------------------------- + // validate option + //---------------------------------------------------------------- + else if (!strcmp(directive,"validate")) { + cin >> arg; // input argument + if (!strcmp(arg, "on")) { + validate = ANNtrue; + cout << "validate = on " + << "(Warning: this may slow execution time.)\n"; + } + else if (!strcmp(arg, "off")) { + validate = ANNfalse; + } + else { + cerr << "Argument: " << arg << "\n"; + Error("validate argument must be \"on\" or \"off\"", ANNabort); + } + } + //---------------------------------------------------------------- + // distribution option + //---------------------------------------------------------------- + else if (!strcmp(directive,"distribution")) { + cin >> arg; // input name and translate + distr = (Distrib) lookUp(arg, distr_table, N_DISTRIBS); + if (distr >= N_DISTRIBS) { // not something we recognize + cerr << "Distribution: " << arg << "\n"; + Error("Unknown distribution", ANNabort); + } + } + //---------------------------------------------------------------- + // stats option + //---------------------------------------------------------------- + else if (!strcmp(directive,"stats")) { + cin >> arg; // input name and translate + stats = (StatLev) lookUp(arg, stat_table, N_STAT_LEVELS); + if (stats >= N_STAT_LEVELS) { // not something we recognize + cerr << "Stats level: " << arg << "\n"; + Error("Unknown statistics level", ANNabort); + } + if (stats > SILENT) + cout << "stats = " << arg << "\n"; + } + //---------------------------------------------------------------- + // split_rule option + //---------------------------------------------------------------- + else if (!strcmp(directive,"split_rule")) { + cin >> arg; // input split_rule name + split = (ANNsplitRule) lookUp(arg, split_table, N_SPLIT_RULES); + if (split >= N_SPLIT_RULES) { // not something we recognize + cerr << "Splitting rule: " << arg << "\n"; + Error("Unknown splitting rule", ANNabort); + } + } + //---------------------------------------------------------------- + // shrink_rule option + //---------------------------------------------------------------- + else if (!strcmp(directive,"shrink_rule")) { + cin >> arg; // input split_rule name + shrink = (ANNshrinkRule) lookUp(arg, shrink_table, N_SHRINK_RULES); + if (shrink >= N_SHRINK_RULES) { // not something we recognize + cerr << "Shrinking rule: " << arg << "\n"; + Error("Unknown shrinking rule", ANNabort); + } + } + //---------------------------------------------------------------- + // label operation + //---------------------------------------------------------------- + else if (!strcmp(directive,"output_label")) { + cin >> arg; + if (stats > SILENT) + cout << "<" << arg << ">\n"; + } + //---------------------------------------------------------------- + // gen_data_pts operation + //---------------------------------------------------------------- + else if (!strcmp(directive,"gen_data_pts")) { + if (distr == PLANTED) { // planted distribution + Error("Cannot use planted distribution for data points", ANNabort); + } + generatePts( // generate data points + data_pts, // data points + data_size, // data size + DATA, // data points + new_clust); // new clusters flag + valid_dirty = ANNtrue; // validation must be redone + new_clust = ANNfalse; // reset flag + } + //---------------------------------------------------------------- + // gen_query_pts operation + // If the distribution is PLANTED, then the query points + // are planted near the data points (which must already be + // generated). + //---------------------------------------------------------------- + else if (!strcmp(directive,"gen_query_pts")) { + if (distr == PLANTED) { // planted distribution + if (data_pts == NULL) { + Error("Must generate data points before query points for planted distribution", ANNabort); + } + generatePts( // generate query points + query_pts, // point array + query_size, // number of query points + QUERY, // query points + new_clust, // new clusters flag + data_pts, // plant around data pts + data_size); + } + else { // all other distributions + generatePts( // generate query points + query_pts, // point array + query_size, // number of query points + QUERY, // query points + new_clust); // new clusters flag + } + valid_dirty = ANNtrue; // validation must be redone + new_clust = ANNfalse; // reset flag + } + //---------------------------------------------------------------- + // read_data_pts operation + //---------------------------------------------------------------- + else if (!strcmp(directive,"read_data_pts")) { + cin >> arg; // input file name + readPts( + data_pts, // point array + data_size, // number of points + arg, // file name + DATA); // data points + valid_dirty = ANNtrue; // validation must be redone + } + //---------------------------------------------------------------- + // read_query_pts operation + //---------------------------------------------------------------- + else if (!strcmp(directive,"read_query_pts")) { + cin >> arg; // input file name + readPts( + query_pts, // point array + query_size, // number of points + arg, // file name + QUERY); // query points + valid_dirty = ANNtrue; // validation must be redone + } + //---------------------------------------------------------------- + // build_ann operation + // We always invoke the constructor for bd-trees. Note + // that when the shrinking rule is NONE (which is true by + // default), then this constructs a kd-tree. + //---------------------------------------------------------------- + else if (!strcmp(directive,"build_ann")) { + //------------------------------------------------------------ + // Build the tree + //------------------------------------------------------------ + if (the_tree != NULL) { // tree exists already + delete the_tree; // get rid of it + } + clock0 = clock(); // start time + + the_tree = new ANNbd_tree( // build it + data_pts, // the data points + data_size, // number of points + dim, // dimension of space + bucket_size, // maximum bucket size + split, // splitting rule + shrink); // shrinking rule + + //------------------------------------------------------------ + // Print summary + //------------------------------------------------------------ + long prep_time = clock() - clock0; // end of prep time + + if (stats > SILENT) { + cout << "[Build ann-structure:\n"; + cout << " split_rule = " << split_table[split] << "\n"; + cout << " shrink_rule = " << shrink_table[shrink] << "\n"; + cout << " data_size = " << data_size << "\n"; + cout << " dim = " << dim << "\n"; + cout << " bucket_size = " << bucket_size << "\n"; + + if (stats >= EXEC_TIME) { // output processing time + cout << " process_time = " + << double(prep_time)/CLOCKS_PER_SEC << " sec\n"; + } + + if (stats >= PREP_STATS) // output or check tree stats + treeStats(cout, ANNtrue); // print tree stats + else + treeStats(cout, ANNfalse); // check stats + + if (stats >= SHOW_STRUCT) { // print the whole tree + cout << " (Structure Contents:\n"; + the_tree->Print(ANNfalse, cout); + cout << " )\n"; + } + cout << "]\n"; + } + } + //---------------------------------------------------------------- + // dump operation + //---------------------------------------------------------------- + else if (!strcmp(directive,"dump")) { + cin >> arg; // input file name + if (the_tree == NULL) { // no tree + Error("Cannot dump. No tree has been built yet", ANNwarn); + } + else { // there is a tree + // try to open file + ofstream out_dump_file(arg); + if (!out_dump_file) { + cerr << "File name: " << arg << "\n"; + Error("Cannot open dump file", ANNabort); + } + // dump the tree and points + the_tree->Dump(ANNtrue, out_dump_file); + if (stats > SILENT) { + cout << "(Tree has been dumped to file " << arg << ")\n"; + } + } + } + //---------------------------------------------------------------- + // load operation + // Since this not only loads a tree, but loads a new set + // of data points. + //---------------------------------------------------------------- + else if (!strcmp(directive,"load")) { + cin >> arg; // input file name + if (the_tree != NULL) { // tree exists already + delete the_tree; // get rid of it + } + if (data_pts != NULL) { // data points exist already + delete data_pts; // get rid of them + } + + ifstream in_dump_file(arg); // try to open file + if (!in_dump_file) { + cerr << "File name: " << arg << "\n"; + Error("Cannot open file for loading", ANNabort); + } + // build tree by loading + the_tree = new ANNbd_tree(in_dump_file); + + dim = the_tree->theDim(); // new dimension + data_size = the_tree->nPoints(); // number of points + data_pts = the_tree->thePoints(); // new points + + valid_dirty = ANNtrue; // validation must be redone + + if (stats > SILENT) { + cout << "(Tree has been loaded from file " << arg << ")\n"; + } + if (stats >= SHOW_STRUCT) { // print the tree + cout << " (Structure Contents:\n"; + the_tree->Print(ANNfalse, cout); + cout << " )\n"; + } + } + //---------------------------------------------------------------- + // run_queries operation + // This section does all the query processing. It consists + // of the following subsections: + // + // ** input the argument (standard or priority) and output + // the header describing the essential information. + // ** allocate space for the results to be stored. + // ** run the queries by invoking the appropriate search + // procedure on the query points. Print nearest neighbor + // if requested. + // ** print final summaries + // + // The approach for processing multiple nearest neighbors is + // pretty crude. We allocate an array whose size is the + // product of the total number of queries times the number of + // nearest neighbors (k), and then use each k consecutive + // entries to store the results of each query. + //---------------------------------------------------------------- + else if (!strcmp(directive,"run_queries")) { + + //------------------------------------------------------------ + // Input arguments and print summary + //------------------------------------------------------------ + enum {STANDARD, PRIORITY} method; + + cin >> arg; // input argument + if (!strcmp(arg, "standard")) { + method = STANDARD; + } + else if (!strcmp(arg, "priority")) { + method = PRIORITY; + } + else { + cerr << "Search type: " << arg << "\n"; + Error("Search type must be \"standard\" or \"priority\"", + ANNabort); + } + if (data_pts == NULL || query_pts == NULL) { + Error("Either data set and query set not constructed", ANNabort); + } + if (the_tree == NULL) { + Error("No search tree built.", ANNabort); + } + + //------------------------------------------------------------ + // Set up everything + //------------------------------------------------------------ + + #ifdef ANN_PERF // performance only + annResetStats(data_size); // reset statistics + #endif + + clock0 = clock(); // start time + // deallocate existing storage + if (apx_nn_idx != NULL) delete [] apx_nn_idx; + if (apx_dists != NULL) delete [] apx_dists; + if (apx_pts_in_range != NULL) delete [] apx_pts_in_range; + // allocate apx answer storage + apx_nn_idx = new ANNidx[near_neigh*query_size]; + apx_dists = new ANNdist[near_neigh*query_size]; + apx_pts_in_range = new int[query_size]; + + annMaxPtsVisit(max_pts_visit); // set max points to visit + + //------------------------------------------------------------ + // Run the queries + //------------------------------------------------------------ + // pointers for current query + ANNidxArray curr_nn_idx = apx_nn_idx; + ANNdistArray curr_dists = apx_dists; + + for (int i = 0; i < query_size; i++) { + #ifdef ANN_PERF + annResetCounts(); // reset counters + #endif + apx_pts_in_range[i] = 0; + + if (radius_bound == 0) { // no radius bound + if (method == STANDARD) { + the_tree->annkSearch( + query_pts[i], // query point + near_neigh, // number of near neighbors + curr_nn_idx, // nearest neighbors (returned) + curr_dists, // distance (returned) + epsilon); // error bound + } + else if (method == PRIORITY) { + the_tree->annkPriSearch( + query_pts[i], // query point + near_neigh, // number of near neighbors + curr_nn_idx, // nearest neighbors (returned) + curr_dists, // distance (returned) + epsilon); // error bound + } + else { + Error("Internal error - invalid method", ANNabort); + } + } + else { // use radius bound + if (method != STANDARD) { + Error("A nonzero radius bound assumes standard search", + ANNwarn); + } + apx_pts_in_range[i] = the_tree->annkFRSearch( + query_pts[i], // query point + ANN_POW(radius_bound), // squared radius search bound + near_neigh, // number of near neighbors + curr_nn_idx, // nearest neighbors (returned) + curr_dists, // distance (returned) + epsilon); // error bound + } + curr_nn_idx += near_neigh; // increment current pointers + curr_dists += near_neigh; + + #ifdef ANN_PERF + annUpdateStats(); // update stats + #endif + } + + long query_time = clock() - clock0; // end of query time + + if (validate) { // validation requested + if (valid_dirty) getTrueNN(); // get true near neighbors + doValidation(); // validate + } + + //------------------------------------------------------------ + // Print summaries + //------------------------------------------------------------ + + if (stats > SILENT) { + cout << "[Run Queries:\n"; + cout << " query_size = " << query_size << "\n"; + cout << " dim = " << dim << "\n"; + cout << " search_method = " << arg << "\n"; + cout << " epsilon = " << epsilon << "\n"; + cout << " near_neigh = " << near_neigh << "\n"; + if (max_pts_visit != 0) + cout << " max_pts_visit = " << max_pts_visit << "\n"; + if (radius_bound != 0) + cout << " radius_bound = " << radius_bound << "\n"; + if (validate) + cout << " true_nn = " << true_nn << "\n"; + + if (stats >= EXEC_TIME) { // print exec time summary + cout << " query_time = " << + double(query_time)/(query_size*CLOCKS_PER_SEC) + << " sec/query"; + #ifdef ANN_PERF + cout << " (biased by perf measurements)"; + #endif + cout << "\n"; + } + + if (stats >= QUERY_STATS) { // output performance stats + #ifdef ANN_PERF + cout.flush(); + annPrintStats(validate); + #else + cout << " (Performance statistics unavailable.)\n"; + #endif + } + + if (stats >= QUERY_RES) { // output results + cout << " (Query Results:\n"; + cout << " Pt\tANN\tDist\n"; + curr_nn_idx = apx_nn_idx; // subarray pointers + curr_dists = apx_dists; + // output nearest neighbors + for (int i = 0; i < query_size; i++) { + cout << " " << setw(4) << i; + for (int j = 0; j < near_neigh; j++) { + // exit if no more neighbors + if (curr_nn_idx[j] == ANN_NULL_IDX) { + cout << "\t[no other pts in radius bound]\n"; + break; + } + else { // output point info + cout << "\t" << curr_nn_idx[j] + << "\t" << ANN_ROOT(curr_dists[j]) + << "\n"; + } + } + // output range count + if (radius_bound != 0) { + cout << " pts_in_radius_bound = " + << apx_pts_in_range[i] << "\n"; + } + // increment subarray pointers + curr_nn_idx += near_neigh; + curr_dists += near_neigh; + } + cout << " )\n"; + } + cout << "]\n"; + } + } + //---------------------------------------------------------------- + // Unknown directive + //---------------------------------------------------------------- + else { + cerr << "Directive: " << directive << "\n"; + Error("Unknown directive", ANNabort); + } + } + //-------------------------------------------------------------------- + // End of input loop (deallocate stuff that was allocated) + //-------------------------------------------------------------------- + if (the_tree != NULL) delete the_tree; + if (data_pts != NULL) annDeallocPts(data_pts); + if (query_pts != NULL) annDeallocPts(query_pts); + if (apx_nn_idx != NULL) delete [] apx_nn_idx; + if (apx_dists != NULL) delete [] apx_dists; + if (apx_pts_in_range != NULL) delete [] apx_pts_in_range; + + annClose(); // close ANN + + return EXIT_SUCCESS; +} + +//------------------------------------------------------------------------ +// generatePts - call appropriate routine to generate points of a +// given distribution. +//------------------------------------------------------------------------ + +void generatePts( + ANNpointArray &pa, // point array (returned) + int n, // number of points to generate + PtType type, // point type + ANNbool new_clust, // new cluster centers desired? + ANNpointArray src, // source array (if distr=PLANTED) + int n_src) // source size (if distr=PLANTED) +{ + if (pa != NULL) annDeallocPts(pa); // get rid of any old points + pa = annAllocPts(n, dim); // allocate point storage + + switch (distr) { + case UNIFORM: // uniform over cube [-1,1]^d. + annUniformPts(pa, n, dim); + break; + case GAUSS: // Gaussian with mean 0 + annGaussPts(pa, n, dim, std_dev); + break; + case LAPLACE: // Laplacian, mean 0 and var 1 + annLaplacePts(pa, n, dim); + break; + case CO_GAUSS: // correlated Gaussian + annCoGaussPts(pa, n, dim, corr_coef); + break; + case CO_LAPLACE: // correlated Laplacian + annCoLaplacePts(pa, n, dim, corr_coef); + break; + case CLUS_GAUSS: // clustered Gaussian + annClusGaussPts(pa, n, dim, n_color, new_clust, std_dev); + break; + case CLUS_ORTH_FLATS: // clustered on orthog flats + annClusOrthFlats(pa, n, dim, n_color, new_clust, std_dev, max_dim); + break; + case CLUS_ELLIPSOIDS: // clustered ellipsoids + annClusEllipsoids(pa, n, dim, n_color, new_clust, std_dev, + std_dev_lo, std_dev_hi, max_dim); + break; + case PLANTED: // planted distribution + annPlanted(pa, n, dim, src, n_src, std_dev); + break; + default: + Error("INTERNAL ERROR: Unknown distribution", ANNabort); + break; + } + + if (stats > SILENT) { + if(type == DATA) cout << "[Generating Data Points:\n"; + else cout << "[Generating Query Points:\n"; + cout << " number = " << n << "\n"; + cout << " dim = " << dim << "\n"; + cout << " distribution = " << distr_table[distr] << "\n"; + if (annIdum < 0) + cout << " seed = " << annIdum << "\n"; + if (distr == GAUSS || distr == CLUS_GAUSS + || distr == CLUS_ORTH_FLATS) + cout << " std_dev = " << std_dev << "\n"; + if (distr == CLUS_ELLIPSOIDS) { + cout << " std_dev = " << std_dev << " (small) \n"; + cout << " std_dev_lo = " << std_dev_lo << "\n"; + cout << " std_dev_hi = " << std_dev_hi << "\n"; + } + if (distr == CO_GAUSS || distr == CO_LAPLACE) + cout << " corr_coef = " << corr_coef << "\n"; + if (distr == CLUS_GAUSS || distr == CLUS_ORTH_FLATS + || distr == CLUS_ELLIPSOIDS) { + cout << " colors = " << n_color << "\n"; + if (new_clust) + cout << " (cluster centers regenerated)\n"; + } + if (distr == CLUS_ORTH_FLATS || distr == CLUS_ELLIPSOIDS) { + cout << " max_dim = " << max_dim << "\n"; + } + } + // want to see points? + if ((type == DATA && stats >= SHOW_PTS) || + (type == QUERY && stats >= QUERY_RES)) { + if(type == DATA) cout << "(Data Points:\n"; + else cout << "(Query Points:\n"; + for (int i = 0; i < n; i++) { + cout << " " << setw(4) << i << "\t"; + printPoint(pa[i], dim); + cout << "\n"; + } + cout << " )\n"; + } + cout << "]\n"; +} + +//------------------------------------------------------------------------ +// readPts - read a collection of data or query points. +//------------------------------------------------------------------------ + +void readPts( + ANNpointArray &pa, // point array (returned) + int &n, // number of points + char *file_nm, // file name + PtType type) // point type (DATA, QUERY) +{ + int i; + //-------------------------------------------------------------------- + // Open input file and read points + //-------------------------------------------------------------------- + ifstream in_file(file_nm); // try to open data file + if (!in_file) { + cerr << "File name: " << file_nm << "\n"; + Error("Cannot open input data/query file", ANNabort); + } + // allocate storage for points + if (pa != NULL) annDeallocPts(pa); // get rid of old points + pa = annAllocPts(n, dim); + + for (i = 0; i < n; i++) { // read the data + if (!(in_file >> pa[i][0])) break; + for (int d = 1; d < dim; d++) { + in_file >> pa[i][d]; + } + } + + char ignore_me; // character for EOF test + in_file >> ignore_me; // try to get one more character + if (!in_file.eof()) { // exhausted space before eof + if (type == DATA) + Error("`data_size' too small. Input file truncated.", ANNwarn); + else + Error("`query_size' too small. Input file truncated.", ANNwarn); + } + n = i; // number of points read + + //-------------------------------------------------------------------- + // Print summary + //-------------------------------------------------------------------- + if (stats > SILENT) { + if (type == DATA) { + cout << "[Read Data Points:\n"; + cout << " data_size = " << n << "\n"; + } + else { + cout << "[Read Query Points:\n"; + cout << " query_size = " << n << "\n"; + } + cout << " file_name = " << file_nm << "\n"; + cout << " dim = " << dim << "\n"; + // print if results requested + if ((type == DATA && stats >= SHOW_PTS) || + (type == QUERY && stats >= QUERY_RES)) { + cout << " (Points:\n"; + for (i = 0; i < n; i++) { + cout << " " << i << "\t"; + printPoint(pa[i], dim); + cout << "\n"; + } + cout << " )\n"; + } + cout << "]\n"; + } +} + +//------------------------------------------------------------------------ +// getTrueNN +// Computes the true nearest neighbors. For purposes of validation, +// this intentionally done in a rather dumb (but safe way), by +// invoking the brute-force search. +// +// The number of true nearest neighbors is somewhat larger than +// the number of nearest neighbors. This is so that the validation +// can determine the expected difference in element ranks. +// +// This procedure is invoked just prior to running queries. Since +// the operation takes a long time, it is performed only if needed. +// In particular, once generated, it will be regenerated only if +// new query or data points are generated, or if the requested number +// of true near neighbors or approximate near neighbors has changed. +// +// To validate fixed-radius searching, we compute two counts, one +// with the original query radius (trueSqRadius) and the other with +// a radius shrunken by the error factor (minSqradius). We then +// check that the count of points inside the approximate range is +// between these two bounds. Because fixed-radius search is +// allowed to ignore points within the shrunken radius, we only +// compute exact neighbors within this smaller distance (for we +// cannot guarantee that we will even visit the other points). +//------------------------------------------------------------------------ + +void getTrueNN() // compute true nearest neighbors +{ + if (stats > SILENT) { + cout << "(Computing true nearest neighbors for validation. This may take time.)\n"; + } + // deallocate existing storage + if (true_nn_idx != NULL) delete [] true_nn_idx; + if (true_dists != NULL) delete [] true_dists; + if (min_pts_in_range != NULL) delete [] min_pts_in_range; + if (max_pts_in_range != NULL) delete [] max_pts_in_range; + + if (true_nn > data_size) { // can't get more nn than points + true_nn = data_size; + } + + // allocate true answer storage + true_nn_idx = new ANNidx[true_nn*query_size]; + true_dists = new ANNdist[true_nn*query_size]; + min_pts_in_range = new int[query_size]; + max_pts_in_range = new int[query_size]; + + ANNidxArray curr_nn_idx = true_nn_idx; // current locations in arrays + ANNdistArray curr_dists = true_dists; + + // allocate search structure + ANNbruteForce *the_brute = new ANNbruteForce(data_pts, data_size, dim); + // compute nearest neighbors + for (int i = 0; i < query_size; i++) { + if (radius_bound == 0) { // standard kNN search + the_brute->annkSearch( // compute true near neighbors + query_pts[i], // query point + true_nn, // number of nearest neighbors + curr_nn_idx, // where to put indices + curr_dists); // where to put distances + } + else { // fixed radius kNN search + // search radii limits + ANNdist trueSqRadius = ANN_POW(radius_bound); + ANNdist minSqRadius = ANN_POW(radius_bound / (1+epsilon)); + min_pts_in_range[i] = the_brute->annkFRSearch( + query_pts[i], // query point + minSqRadius, // shrunken search radius + true_nn, // number of near neighbors + curr_nn_idx, // nearest neighbors (returned) + curr_dists); // distance (returned) + max_pts_in_range[i] = the_brute->annkFRSearch( + query_pts[i], // query point + trueSqRadius, // true search radius + 0, NULL, NULL); // (ignore kNN info) + } + curr_nn_idx += true_nn; // increment nn index pointer + curr_dists += true_nn; // increment nn dist pointer + } + delete the_brute; // delete brute-force struct + valid_dirty = ANNfalse; // validation good for now +} + +//------------------------------------------------------------------------ +// doValidation +// Compares the approximate answers to the k-nearest neighbors +// against the true nearest neighbors (computed earlier). It is +// assumed that the true nearest neighbors and indices have been +// computed earlier. +// +// First, we check that all the results are within their allowed +// limits, and generate an internal error, if not. For the sake of +// performance evaluation, we also compute the following two +// quantities for nearest neighbors: +// +// Average Error +// ------------- +// The relative error between the distance to a reported nearest +// neighbor and the true nearest neighbor (of the same rank), +// +// Rank Error +// ---------- +// The difference in rank between the reported nearest neighbor and +// its position (if any) among the true nearest neighbors. If we +// cannot find this point among the true nearest neighbors, then +// it assumed that the rank of the true nearest neighbor is true_nn+1. +// +// Because of the possibility of duplicate distances, this is computed +// as follows. For the j-th reported nearest neighbor, we count the +// number of true nearest neighbors that are at least this close. Let +// this be rnk. Then the rank error is max(0, j-rnk). (In the code +// below, j is an array index and so the first item is 0, not 1. Thus +// we take max(0, j+1-rnk) instead.) +// +// For the results of fixed-radious range count, we verify that the +// reported number of points in the range lies between the actual +// number of points in the shrunken and the true search radius. +//------------------------------------------------------------------------ + +void doValidation() // perform validation +{ + int* curr_apx_idx = apx_nn_idx; // approx index pointer + ANNdistArray curr_apx_dst = apx_dists; // approx distance pointer + int* curr_tru_idx = true_nn_idx; // true index pointer + ANNdistArray curr_tru_dst = true_dists; // true distance pointer + int i, j; + + if (true_nn < near_neigh) { + Error("Cannot validate with fewer true near neighbors than actual", ANNabort); + } + + for (i = 0; i < query_size; i++) { // validate each query + //---------------------------------------------------------------- + // Compute result errors + // In fixed radius search it is possible that not all k + // nearest neighbors were computed. Because the true + // results are computed over the shrunken radius, we should + // have at least as many true nearest neighbors as + // approximate nearest neighbors. (If not, an infinite + // error will be generated, and so an internal error will + // will be generated. + // + // Because nearest neighbors are sorted in increasing order + // of distance, as soon as we see a null index, we can + // terminate the distance checking. The error in the + // result should not exceed epsilon. However, if + // max_pts_visit is nonzero (meaning that the search is + // terminated early) this might happen. + //---------------------------------------------------------------- + for (j = 0; j < near_neigh; j++) { + if (curr_tru_idx[j] == ANN_NULL_IDX)// no more true neighbors? + break; + // true i-th smallest distance + double true_dist = ANN_ROOT(curr_tru_dst[j]); + // reported i-th smallest + double rept_dist = ANN_ROOT(curr_apx_dst[j]); + // better than optimum? + if (rept_dist < true_dist*(1-ERR)) { + Error("INTERNAL ERROR: True nearest neighbor incorrect", + ANNabort); + } + + double resultErr; // result error + if (true_dist == 0.0) { // let's not divide by zero + if (rept_dist != 0.0) resultErr = ANN_DBL_MAX; + else resultErr = 0.0; + } + else { + resultErr = (rept_dist - true_dist) / ((double) true_dist); + } + + if (resultErr > epsilon && max_pts_visit == 0) { + Error("INTERNAL ERROR: Actual error exceeds epsilon", + ANNabort); + } + #ifdef ANN_PERF + ann_average_err += resultErr; // update statistics error + #endif + } + //-------------------------------------------------------------------- + // Compute rank errors (only needed for perf measurements) + //-------------------------------------------------------------------- + #ifdef ANN_PERF + for (j = 0; j < near_neigh; j++) { + if (curr_tru_idx[i] == ANN_NULL_IDX) // no more true neighbors? + break; + + double rnkErr = 0.0; // rank error + // reported j-th distance + ANNdist rept_dist = curr_apx_dst[j]; + int rnk = 0; // compute rank of this item + while (rnk < true_nn && curr_tru_dst[rnk] <= rept_dist) + rnk++; + if (j+1-rnk > 0) rnkErr = (double) (j+1-rnk); + ann_rank_err += rnkErr; // update average rank error + } + #endif + //---------------------------------------------------------------- + // Check range counts from fixed-radius query + //---------------------------------------------------------------- + if (radius_bound != 0) { // fixed-radius search + if (apx_pts_in_range[i] < min_pts_in_range[i] || + apx_pts_in_range[i] > max_pts_in_range[i]) + Error("INTERNAL ERROR: Invalid fixed-radius range count", + ANNabort); + } + + curr_apx_idx += near_neigh; + curr_apx_dst += near_neigh; + curr_tru_idx += true_nn; // increment current pointers + curr_tru_dst += true_nn; + } +} + +//---------------------------------------------------------------------- +// treeStats +// Computes a number of statistics related to kd_trees and +// bd_trees. These statistics are printed if in verbose mode, +// and otherwise they are only printed if they are deemed to +// be outside of reasonable operating bounds. +//---------------------------------------------------------------------- + +#define log2(x) (log(x)/log(2.0)) // log base 2 + +void treeStats( + ostream &out, // output stream + ANNbool verbose) // print stats +{ + const int MIN_PTS = 20; // min no. pts for checking + const float MAX_FRAC_TL = 0.50; // max frac of triv leaves + const float MAX_AVG_AR = 20; // max average aspect ratio + + ANNkdStats st; // statistics structure + + the_tree->getStats(st); // get statistics + // total number of nodes + int n_nodes = st.n_lf + st.n_spl + st.n_shr; + // should be O(n/bs) + int opt_n_nodes = (int) (2*(float(st.n_pts)/st.bkt_size)); + int too_many_nodes = 10*opt_n_nodes; + if (st.n_pts >= MIN_PTS && n_nodes > too_many_nodes) { + out << "-----------------------------------------------------------\n"; + out << "Warning: The tree has more than 10x as many nodes as points.\n"; + out << "You may want to consider a different split or shrink method.\n"; + out << "-----------------------------------------------------------\n"; + verbose = ANNtrue; + } + // fraction of trivial leaves + float frac_tl = (st.n_lf == 0 ? 0 : ((float) st.n_tl)/ st.n_lf); + if (st.n_pts >= MIN_PTS && frac_tl > MAX_FRAC_TL) { + out << "-----------------------------------------------------------\n"; + out << "Warning: A significant fraction of leaves contain no points.\n"; + out << "You may want to consider a different split or shrink method.\n"; + out << "-----------------------------------------------------------\n"; + verbose = ANNtrue; + } + // depth should be O(dim*log n) + int too_many_levels = (int) (2.0 * st.dim * log2((double) st.n_pts)); + int opt_levels = (int) log2(double(st.n_pts)/st.bkt_size); + if (st.n_pts >= MIN_PTS && st.depth > too_many_levels) { + out << "-----------------------------------------------------------\n"; + out << "Warning: The tree is more than 2x as deep as (dim*log n).\n"; + out << "You may want to consider a different split or shrink method.\n"; + out << "-----------------------------------------------------------\n"; + verbose = ANNtrue; + } + // average leaf aspect ratio + if (st.n_pts >= MIN_PTS && st.avg_ar > MAX_AVG_AR) { + out << "-----------------------------------------------------------\n"; + out << "Warning: Average aspect ratio of cells is quite large.\n"; + out << "This may slow queries depending on the point distribution.\n"; + out << "-----------------------------------------------------------\n"; + verbose = ANNtrue; + } + + //------------------------------------------------------------------ + // Print summaries if requested + //------------------------------------------------------------------ + if (verbose) { // output statistics + out << " (Structure Statistics:\n"; + out << " n_nodes = " << n_nodes + << " (opt = " << opt_n_nodes + << ", best if < " << too_many_nodes << ")\n" + << " n_leaves = " << st.n_lf + << " (" << st.n_tl << " contain no points)\n" + << " n_splits = " << st.n_spl << "\n" + << " n_shrinks = " << st.n_shr << "\n"; + out << " empty_leaves = " << frac_tl*100 + << " percent (best if < " << MAX_FRAC_TL*100 << " percent)\n"; + out << " depth = " << st.depth + << " (opt = " << opt_levels + << ", best if < " << too_many_levels << ")\n"; + out << " avg_aspect_ratio = " << st.avg_ar + << " (best if < " << MAX_AVG_AR << ")\n"; + out << " )\n"; + } +} diff --git a/external/ann_1.1.1/test/rand.cpp b/external/ann_1.1.1/test/rand.cpp new file mode 100644 index 0000000..eca981e --- /dev/null +++ b/external/ann_1.1.1/test/rand.cpp @@ -0,0 +1,594 @@ +//---------------------------------------------------------------------- +// File: rand.cpp +// Programmer: Sunil Arya and David Mount +// Description: Routines for random point generation +// Last modified: 08/04/06 (Version 1.1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 0.2 03/26/98 +// Changed random/srandom declarations for SGI's. +// Revision 1.0 04/01/05 +// annClusGauss centers distributed over [-1,1] rather than [0,1] +// Added annClusOrthFlats distribution +// Changed procedure names to avoid namespace conflicts +// Added annClusFlats distribution +// Added rand/srand option and fixed annRan0() initialization. +// Revision 1.1.1 08/04/06 +// Added planted distribution +//---------------------------------------------------------------------- + +#include "rand.h" // random generator declarations + +using namespace std; // make std:: accessible + +//---------------------------------------------------------------------- +// Globals +//---------------------------------------------------------------------- +int annIdum = 0; // used for random number generation + +//------------------------------------------------------------------------ +// annRan0 - (safer) uniform random number generator +// +// The code given here is taken from "Numerical Recipes in C" by +// William Press, Brian Flannery, Saul Teukolsky, and William +// Vetterling. The task of the code is to do an additional randomizing +// shuffle on the system-supplied random number generator to make it +// safer to use. +// +// Returns a uniform deviate between 0.0 and 1.0 using the +// system-supplied routine random() or rand(). Set the global +// annIdum to any negative value to initialise or reinitialise +// the sequence. +//------------------------------------------------------------------------ + +double annRan0() +{ + const int TAB_SIZE = 97; // table size: any large number + int j; + + static double y, v[TAB_SIZE]; + static int iff = 0; + const double RAN_DIVISOR = double(ANN_RAND_MAX + 1UL); + if (RAN_DIVISOR < 0) { + cout << "RAN_DIVISOR " << RAN_DIVISOR << endl; + exit(0); + } + + //-------------------------------------------------------------------- + // As a precaution against misuse, we will always initialize on the + // first call, even if "annIdum" is not set negative. Determine + // "maxran", the next integer after the largest representable value + // of type int. We assume this is a factor of 2 smaller than the + // corresponding value of type unsigned int. + //-------------------------------------------------------------------- + + if (annIdum < 0 || iff == 0) { // initialize + iff = 1; + ANN_SRAND(annIdum); // (re)seed the generator + annIdum = 1; + + for (j = 0; j < TAB_SIZE; j++) // exercise the system routine + ANN_RAND(); // (values intentionally ignored) + + for (j = 0; j < TAB_SIZE; j++) // then save TAB_SIZE-1 values + v[j] = ANN_RAND(); + y = ANN_RAND(); // generate starting value + } + + //-------------------------------------------------------------------- + // This is where we start if not initializing. Use the previously + // saved random number y to get an index j between 1 and TAB_SIZE-1. + // Then use the corresponding v[j] for both the next j and as the + // output number. + //-------------------------------------------------------------------- + + j = int(TAB_SIZE * (y / RAN_DIVISOR)); + y = v[j]; + v[j] = ANN_RAND(); // refill the table entry + return y / RAN_DIVISOR; +} + +//------------------------------------------------------------------------ +// annRanInt - generate a random integer from {0,1,...,n-1} +// +// If n == 0, then -1 is returned. +//------------------------------------------------------------------------ + +static int annRanInt( + int n) +{ + int r = (int) (annRan0()*n); + if (r == n) r--; // (in case annRan0() == 1 or n == 0) + return r; +} + +//------------------------------------------------------------------------ +// annRanUnif - generate a random uniform in [lo,hi] +//------------------------------------------------------------------------ + +static double annRanUnif( + double lo, + double hi) +{ + return annRan0()*(hi-lo) + lo; +} + +//------------------------------------------------------------------------ +// annRanGauss - Gaussian random number generator +// Returns a normally distributed deviate with zero mean and unit +// variance, using annRan0() as the source of uniform deviates. +//------------------------------------------------------------------------ + +static double annRanGauss() +{ + static int iset=0; + static double gset; + + if (iset == 0) { // we don't have a deviate handy + double v1, v2; + double r = 2.0; + while (r >= 1.0) { + //------------------------------------------------------------ + // Pick two uniform numbers in the square extending from -1 to + // +1 in each direction, see if they are in the circle of radius + // 1. If not, try again + //------------------------------------------------------------ + v1 = annRanUnif(-1, 1); + v2 = annRanUnif(-1, 1); + r = v1 * v1 + v2 * v2; + } + double fac = sqrt(-2.0 * log(r) / r); + //----------------------------------------------------------------- + // Now make the Box-Muller transformation to get two normal + // deviates. Return one and save the other for next time. + //----------------------------------------------------------------- + gset = v1 * fac; + iset = 1; // set flag + return v2 * fac; + } + else { // we have an extra deviate handy + iset = 0; // so unset the flag + return gset; // and return it + } +} + +//------------------------------------------------------------------------ +// annRanLaplace - Laplacian random number generator +// Returns a Laplacian distributed deviate with zero mean and +// unit variance, using annRan0() as the source of uniform deviates. +// +// prob(x) = b/2 * exp(-b * |x|). +// +// b is chosen to be sqrt(2.0) so that the variance of the Laplacian +// distribution [2/(b^2)] becomes 1. +//------------------------------------------------------------------------ + +static double annRanLaplace() +{ + const double b = 1.4142136; + + double laprand = -log(annRan0()) / b; + double sign = annRan0(); + if (sign < 0.5) laprand = -laprand; + return(laprand); +} + +//---------------------------------------------------------------------- +// annUniformPts - Generate uniformly distributed points +// A uniform distribution over [-1,1]. +//---------------------------------------------------------------------- + +void annUniformPts( // uniform distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim) // dimension +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (ANNcoord) (annRanUnif(-1,1)); + } + } +} + +//---------------------------------------------------------------------- +// annGaussPts - Generate Gaussian distributed points +// A Gaussian distribution with zero mean and the given standard +// deviation. +//---------------------------------------------------------------------- + +void annGaussPts( // Gaussian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double std_dev) // standard deviation +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (ANNcoord) (annRanGauss() * std_dev); + } + } +} + +//---------------------------------------------------------------------- +// annLaplacePts - Generate Laplacian distributed points +// Generates a Laplacian distribution (zero mean and unit variance). +//---------------------------------------------------------------------- + +void annLaplacePts( // Laplacian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim) // dimension +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (ANNcoord) annRanLaplace(); + } + } +} + +//---------------------------------------------------------------------- +// annCoGaussPts - Generate correlated Gaussian distributed points +// Generates a Gauss-Markov distribution of zero mean and unit +// variance. +//---------------------------------------------------------------------- + +void annCoGaussPts( // correlated-Gaussian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation) // correlation +{ + double std_dev_w = sqrt(1.0 - correlation * correlation); + for (int i = 0; i < n; i++) { + double previous = annRanGauss(); + pa[i][0] = (ANNcoord) previous; + for (int d = 1; d < dim; d++) { + previous = correlation*previous + std_dev_w*annRanGauss(); + pa[i][d] = (ANNcoord) previous; + } + } +} + +//---------------------------------------------------------------------- +// annCoLaplacePts - Generate correlated Laplacian distributed points +// Generates a Laplacian-Markov distribution of zero mean and unit +// variance. +//---------------------------------------------------------------------- + +void annCoLaplacePts( // correlated-Laplacian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation) // correlation +{ + double wn; + double corr_sq = correlation * correlation; + + for (int i = 0; i < n; i++) { + double previous = annRanLaplace(); + pa[i][0] = (ANNcoord) previous; + for (int d = 1; d < dim; d++) { + double temp = annRan0(); + if (temp < corr_sq) + wn = 0.0; + else + wn = annRanLaplace(); + previous = correlation * previous + wn; + pa[i][d] = (ANNcoord) previous; + } + } +} + +//---------------------------------------------------------------------- +// annClusGaussPts - Generate clusters of Gaussian distributed points +// Cluster centers are uniformly distributed over [-1,1], and the +// standard deviation within each cluster is fixed. +// +// Note: Once cluster centers have been set, they are not changed, +// unless new_clust = true. This is so that subsequent calls generate +// points from the same distribution. It follows, of course, that any +// attempt to change the dimension or number of clusters without +// generating new clusters is asking for trouble. +// +// Note: Cluster centers are not generated by a call to uniformPts(). +// Although this could be done, it has been omitted for +// compatibility with annClusGaussPts() in the colored version, +// rand_c.cc. +//---------------------------------------------------------------------- + +void annClusGaussPts( // clustered-Gaussian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_clus, // number of colors + ANNbool new_clust, // generate new clusters. + double std_dev) // standard deviation within clusters +{ + static ANNpointArray clusters = NULL;// cluster storage + + if (clusters == NULL || new_clust) {// need new cluster centers + if (clusters != NULL) // clusters already exist + annDeallocPts(clusters); // get rid of them + clusters = annAllocPts(n_clus, dim); + // generate cluster center coords + for (int i = 0; i < n_clus; i++) { + for (int d = 0; d < dim; d++) { + clusters[i][d] = (ANNcoord) annRanUnif(-1,1); + } + } + } + + for (int i = 0; i < n; i++) { + int c = annRanInt(n_clus); // generate cluster index + for (int d = 0; d < dim; d++) { + pa[i][d] = (ANNcoord) (std_dev*annRanGauss() + clusters[c][d]); + } + } +} + +//---------------------------------------------------------------------- +// annClusOrthFlats - points clustered along orthogonal flats +// +// This distribution consists of a collection points clustered +// among a collection of axis-aligned low dimensional flats in +// the hypercube [-1,1]^d. A set of n_clus orthogonal flats are +// generated, each whose dimension is a random number between 1 +// and max_dim. The points are evenly distributed among the clusters. +// For each cluster, we generate points uniformly distributed along +// the flat within the hypercube. +// +// This is done as follows. Each cluster is defined by a d-element +// control vector whose components are either: +// +// CO_FLAG indicating that this component is to be generated +// uniformly in [-1,1], +// x a value other than CO_FLAG in the range [-1,1], +// which indicates that this coordinate is to be +// generated as x plus a Gaussian random deviation +// with the given standard deviation. +// +// The number of zero components is the dimension of the flat, which +// is a random integer in the range from 1 to max_dim. The points +// are disributed between clusters in nearly equal sized groups. +// +// Note: Once cluster centers have been set, they are not changed, +// unless new_clust = true. This is so that subsequent calls generate +// points from the same distribution. It follows, of course, that any +// attempt to change the dimension or number of clusters without +// generating new clusters is asking for trouble. +// +// To make this a bad scenario at query time, query points should be +// selected from a different distribution, e.g. uniform or Gaussian. +// +// We use a little programming trick to generate groups of roughly +// equal size. If n is the total number of points, and n_clus is +// the number of clusters, then the c-th cluster (0 <= c < n_clus) +// is given floor((n+c)/n_clus) points. It can be shown that this +// will exactly consume all n points. +// +// This procedure makes use of the utility procedure, genOrthFlat +// which generates points in one orthogonal flat, according to +// the given control vector. +// +//---------------------------------------------------------------------- +const double CO_FLAG = 999; // special flag value + +static void genOrthFlat( // generate points on an orthog flat + ANNpointArray pa, // point array + int n, // number of points + int dim, // dimension + double *control, // control vector + double std_dev) // standard deviation +{ + for (int i = 0; i < n; i++) { // generate each point + for (int d = 0; d < dim; d++) { // generate each coord + if (control[d] == CO_FLAG) // dimension on flat + pa[i][d] = (ANNcoord) annRanUnif(-1,1); + else // dimension off flat + pa[i][d] = (ANNcoord) (std_dev*annRanGauss() + control[d]); + } + } +} + +void annClusOrthFlats( // clustered along orthogonal flats + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_clus, // number of colors + ANNbool new_clust, // generate new clusters. + double std_dev, // standard deviation within clusters + int max_dim) // maximum dimension of the flats +{ + static ANNpointArray control = NULL; // control vectors + + if (control == NULL || new_clust) { // need new cluster centers + if (control != NULL) { // clusters already exist + annDeallocPts(control); // get rid of them + } + control = annAllocPts(n_clus, dim); + + for (int c = 0; c < n_clus; c++) { // generate clusters + int n_dim = 1 + annRanInt(max_dim); // number of dimensions in flat + for (int d = 0; d < dim; d++) { // generate side locations + // prob. of picking next dim + double Prob = ((double) n_dim)/((double) (dim-d)); + if (annRan0() < Prob) { // add this one to flat + control[c][d] = CO_FLAG; // flag this entry + n_dim--; // one fewer dim to fill + } + else { // don't take this one + control[c][d] = annRanUnif(-1,1);// random value in [-1,1] + } + } + } + } + int offset = 0; // offset in pa array + for (int c = 0; c < n_clus; c++) { // generate clusters + int pick = (n+c)/n_clus; // number of points to pick + // generate the points + genOrthFlat(pa+offset, pick, dim, control[c], std_dev); + offset += pick; // increment offset + } +} + +//---------------------------------------------------------------------- +// annClusEllipsoids - points clustered around axis-aligned ellipsoids +// +// This distribution consists of a collection points clustered +// among a collection of low dimensional ellipsoids whose axes +// are alligned with the coordinate axes in the hypercube [-1,1]^d. +// The objective is to model distributions in which the points are +// distributed in lower dimensional subspaces, and within this +// lower dimensional space the points are distributed with a +// Gaussian distribution (with no correlation between the +// dimensions). +// +// The distribution is given the number of clusters or "colors" +// (n_clus), maximum number of dimensions (max_dim) of the lower +// dimensional subspace, a "small" standard deviation +// (std_dev_small), and a "large" standard deviation range +// (std_dev_lo, std_dev_hi). +// +// The algorithm generates n_clus cluster centers uniformly from +// the hypercube [-1,1]^d. For each cluster, it selects the +// dimension of the subspace as a random number r between 1 and +// max_dim. These are the dimensions of the ellipsoid. Then it +// generates a d-element std dev vector whose entries are the +// standard deviation for the coordinates of each cluster in the +// distribution. Among the d-element control vector, r randomly +// chosen values are chosen uniformly from the range [std_dev_lo, +// std_dev_hi]. The remaining values are set to std_dev_small. +// +// Note that annClusGaussPts is a special case of this in which +// max_dim = 0, and std_dev = std_dev_small. +// +// If the flag new_clust is set, then new cluster centers are +// generated. +// +// This procedure makes use of the utility procedure genGauss +// which generates points distributed according to a Gaussian +// distribution. +// +//---------------------------------------------------------------------- + +static void genGauss( // generate points on a general Gaussian + ANNpointArray pa, // point array + int n, // number of points + int dim, // dimension + double *center, // center vector + double *std_dev) // standard deviation vector +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (ANNcoord) (std_dev[d]*annRanGauss() + center[d]); + } + } +} + +void annClusEllipsoids( // clustered around ellipsoids + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_clus, // number of colors + ANNbool new_clust, // generate new clusters. + double std_dev_small, // small standard deviation + double std_dev_lo, // low standard deviation for ellipses + double std_dev_hi, // high standard deviation for ellipses + int max_dim) // maximum dimension of the flats +{ + static ANNpointArray centers = NULL; // cluster centers + static ANNpointArray std_dev = NULL; // standard deviations + + if (centers == NULL || new_clust) { // need new cluster centers + if (centers != NULL) // clusters already exist + annDeallocPts(centers); // get rid of them + if (std_dev != NULL) // std deviations already exist + annDeallocPts(std_dev); // get rid of them + + centers = annAllocPts(n_clus, dim); // alloc new clusters and devs + std_dev = annAllocPts(n_clus, dim); + + for (int i = 0; i < n_clus; i++) { // gen cluster center coords + for (int d = 0; d < dim; d++) { + centers[i][d] = (ANNcoord) annRanUnif(-1,1); + } + } + for (int c = 0; c < n_clus; c++) { // generate cluster std dev + int n_dim = 1 + annRanInt(max_dim); // number of dimensions in flat + for (int d = 0; d < dim; d++) { // generate std dev's + // prob. of picking next dim + double Prob = ((double) n_dim)/((double) (dim-d)); + if (annRan0() < Prob) { // add this one to ellipse + // generate random std dev + std_dev[c][d] = annRanUnif(std_dev_lo, std_dev_hi); + n_dim--; // one fewer dim to fill + } + else { // don't take this one + std_dev[c][d] = std_dev_small;// use small std dev + } + } + } + } + + int offset = 0; // next slot to fill + for (int c = 0; c < n_clus; c++) { // generate clusters + int pick = (n+c)/n_clus; // number of points to pick + // generate the points + genGauss(pa+offset, pick, dim, centers[c], std_dev[c]); + offset += pick; // increment offset in array + } +} + +//---------------------------------------------------------------------- +// annPlanted - Generates points from a "planted" distribution +// In high dimensional spaces, interpoint distances tend to be +// highly clustered around the mean value. Approximate nearest +// neighbor searching makes little sense in this context, unless it +// is the case that each query point is significantly closer to its +// nearest neighbor than to other points. Thus, the query points +// should be planted close to the data points. Given a source data +// set, this procedure generates a set of query points having this +// property. +// +// We are given a source data array and a standard deviation. We +// generate points as follows. We select a random point from the +// source data set, and we generate a Gaussian point centered about +// this random point and perturbed by a normal distributed random +// variable with mean zero and the given standard deviation along +// each coordinate. +// +// Note that this essentially the same a clustered Gaussian +// distribution, but where the cluster centers are given by the +// source data set. +//---------------------------------------------------------------------- + +void annPlanted( // planted nearest neighbors + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + ANNpointArray src, // source point array + int n_src, // source size + double std_dev) // standard deviation about source +{ + for (int i = 0; i < n; i++) { + int c = annRanInt(n_src); // generate source index + for (int d = 0; d < dim; d++) { + pa[i][d] = (ANNcoord) (std_dev*annRanGauss() + src[c][d]); + } + } +} diff --git a/external/ann_1.1.1/test/rand.h b/external/ann_1.1.1/test/rand.h new file mode 100644 index 0000000..575044a --- /dev/null +++ b/external/ann_1.1.1/test/rand.h @@ -0,0 +1,131 @@ +//---------------------------------------------------------------------- +// File: rand.h +// Programmer: Sunil Arya and David Mount +// Description: Basic include file for random point generators +// Last modified: 08/04/06 (Version 1.1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added annClusOrthFlats distribution +// Changed procedure names to avoid namespace conflicts +// Added annClusFlats distribution +// Revision 1.1.1 08/04/06 +// Added planted distribution +//---------------------------------------------------------------------- + +#ifndef rand_H +#define rand_H + +//---------------------------------------------------------------------- +// Basic includes +//---------------------------------------------------------------------- +#include // standard includes (rand/random) +#include // math routines +#include // basic ANN includes + +//---------------------------------------------------------------------- +// Although random/srandom is a more reliable random number generator, +// many systems do not have it. If it is not available, set the +// preprocessor symbol ANN_NO_RANDOM, and this will substitute the use +// of rand/srand for them. +//---------------------------------------------------------------------- +#ifdef ANN_NO_RANDOM // for systems not having random() + #define ANN_RAND rand + #define ANN_SRAND srand + #define ANN_RAND_MAX RAND_MAX +#else // otherwise use rand() + #define ANN_RAND random + #define ANN_SRAND srandom + #define ANN_RAND_MAX 2147483647UL // 2**{31} - 1 + // #define ANN_RAND_MAX 1073741824UL // 2**{30} +#endif + +//---------------------------------------------------------------------- +// Globals +//---------------------------------------------------------------------- +extern int annIdum; // random number seed + +//---------------------------------------------------------------------- +// External entry points +//---------------------------------------------------------------------- + +void annUniformPts( // uniform distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim); // dimension + +void annGaussPts( // Gaussian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double std_dev); // standard deviation + +void annCoGaussPts( // correlated-Gaussian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation); // correlation + +void annLaplacePts( // Laplacian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim); // dimension + +void annCoLaplacePts( // correlated-Laplacian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation); // correlation + +void annClusGaussPts( // clustered-Gaussian distribution + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_clus, // number of colors (clusters) + ANNbool new_clust, // generate new cluster centers + double std_dev); // standard deviation within clusters + +void annClusOrthFlats( // clustered along orthogonal flats + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_clus, // number of colors + ANNbool new_clust, // generate new clusters. + double std_dev, // standard deviation within clusters + int max_dim); // maximum dimension of the flats + +void annClusEllipsoids( // clustered around ellipsoids + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_clus, // number of colors + ANNbool new_clust, // generate new clusters. + double std_dev_small, // small standard deviation + double std_dev_lo, // low standard deviation for ellipses + double std_dev_hi, // high standard deviation for ellipses + int max_dim); // maximum dimension of the flats + +void annPlanted( // planted nearest neighbors + ANNpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + ANNpointArray src, // source point array + int n_src, // source size + double std_dev); // standard deviation about source + +#endif diff --git a/external/ann_1.1.1/test/test1-data.pts b/external/ann_1.1.1/test/test1-data.pts new file mode 100644 index 0000000..b00c1d7 --- /dev/null +++ b/external/ann_1.1.1/test/test1-data.pts @@ -0,0 +1,20 @@ +-0.297462 0.176102 +0.565538 -0.361496 +0.909313 -0.182785 +0.920712 0.478408 +0.167682 0.0499836 +0.305223 -0.0805835 +0.114973 0.882453 +0.742916 0.16376 +0.0724605 -0.826775 +0.690960 -0.559284 +0.188485 -0.643934 +0.749427 -0.942415 +-0.970662 -0.223466 +0.916110 0.879597 +0.927417 -0.382593 +-0.711327 0.278713 +-0.519172 0.986146 +0.135338 0.924588 +-0.0837537 0.61687 +0.0520465 0.896306 diff --git a/external/ann_1.1.1/test/test1-query.pts b/external/ann_1.1.1/test/test1-query.pts new file mode 100644 index 0000000..a2b1f6d --- /dev/null +++ b/external/ann_1.1.1/test/test1-query.pts @@ -0,0 +1,10 @@ +0.0902484 -0.207129 +-0.419567 0.485743 +0.826225 -0.30962 +0.694758 0.987088 +-0.410807 -0.465182 +-0.836501 0.490184 +0.588289 0.656408 +0.325807 0.38721 +-0.532226 -0.727036 +-0.52506 -0.853508 diff --git a/external/ann_1.1.1/test/test1.in b/external/ann_1.1.1/test/test1.in new file mode 100644 index 0000000..1158924 --- /dev/null +++ b/external/ann_1.1.1/test/test1.in @@ -0,0 +1,15 @@ + validate on + stats query_stats + dim 2 + data_size 20 + query_size 10 +read_data_pts test1-data.pts +read_query_pts test1-query.pts + bucket_size 1 + near_neigh 3 + split_rule suggest + shrink_rule none +build_ann + epsilon 0.0 +run_queries standard +run_queries priority diff --git a/external/ann_1.1.1/test/test1.save b/external/ann_1.1.1/test/test1.save new file mode 100644 index 0000000..6088352 --- /dev/null +++ b/external/ann_1.1.1/test/test1.save @@ -0,0 +1,76 @@ +------------------------------------------------------------ +ann_test: Version 1.0 + Copyright: David M. Mount and Sunil Arya. + Latest Revision: Mar 1, 2005. +------------------------------------------------------------ + +validate = on (Warning: this may slow execution time.) +stats = query_stats +[Read Data Points: + data_size = 20 + file_name = test1-data.pts + dim = 2 +] +[Read Query Points: + query_size = 10 + file_name = test1-query.pts + dim = 2 +] +[Build ann-structure: + split_rule = suggest + shrink_rule = none + data_size = 20 + dim = 2 + bucket_size = 1 + process_time = 0 sec + (Structure Statistics: + n_nodes = 39 (opt = 40, best if < 400) + n_leaves = 20 (0 contain no points) + n_splits = 19 + n_shrinks = 0 + empty_leaves = 0 percent (best if < 50 percent) + depth = 6 (opt = 4, best if < 17) + avg_aspect_ratio = 1.48847 (best if < 20) + ) +] +(Computing true nearest neighbors for validation. This may take time.) +[Run Queries: + query_size = 10 + dim = 2 + search_method = standard + epsilon = 0 + near_neigh = 3 + true_nn = 13 + query_time = 0 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 6.3 : 2.751 ]< 4 , 11 > + splitting_nodes = [ 8.8 : 3.676 ]< 5 , 15 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 15.1 : 6.35 ]< 9 , 26 > + points_visited = [ 6.3 : 2.751 ]< 4 , 11 > + coord_hits/pt = [ 0.57 : 0.2201 ]< 0.35 , 0.95 > + floating_ops_(K) = [ 0.156 : 0.0563 ]< 0.101 , 0.254 > + average_error = [ 0 : 0 ]< 0 , 0 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] +[Run Queries: + query_size = 10 + dim = 2 + search_method = priority + epsilon = 0 + near_neigh = 3 + true_nn = 13 + query_time = 0 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 5.9 : 2.025 ]< 4 , 9 > + splitting_nodes = [ 8.7 : 3.498 ]< 5 , 15 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 14.6 : 5.42 ]< 9 , 24 > + points_visited = [ 5.9 : 2.025 ]< 4 , 9 > + coord_hits/pt = [ 0.535 : 0.1667 ]< 0.35 , 0.8 > + floating_ops_(K) = [ 0.1719 : 0.05861 ]< 0.114 , 0.267 > + average_error = [ 0 : 0 ]< 0 , 0 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] diff --git a/external/ann_1.1.1/test/test2-data.pts b/external/ann_1.1.1/test/test2-data.pts new file mode 100644 index 0000000..2fba4f0 --- /dev/null +++ b/external/ann_1.1.1/test/test2-data.pts @@ -0,0 +1,5000 @@ +-0.297462 0.176102 0.565538 -0.361496 0.909313 -0.182785 0.920712 0.478408 +0.167682 0.0499836 0.305223 -0.0805835 0.114973 0.882453 0.742916 0.16376 +0.0724605 -0.826775 0.69096 -0.559284 0.188485 -0.643934 0.749427 -0.942415 +-0.970662 -0.223466 0.91611 0.879597 0.927417 -0.382593 -0.711327 0.278713 +-0.519172 0.986146 0.135338 0.924588 -0.0837537 0.61687 0.0520465 0.896306 +0.901473 -0.325291 0.0652063 -0.120574 -0.488327 0.751363 -0.697499 -0.947413 +-0.987624 0.963139 0.369289 -0.211379 -0.883509 -0.708899 0.600525 -0.582872 +-0.643506 0.71497 0.575093 0.00459678 0.539812 -0.258652 0.869204 -0.00241996 +0.772744 -0.676832 -0.897886 -0.196002 -0.628767 0.30896 0.570148 0.26033 +-0.386577 -0.874337 -0.259992 0.312917 -0.0935399 0.573666 0.239825 0.85421 +-0.796208 0.678532 -0.642731 -0.143502 -0.381581 0.356034 0.65693 0.401868 +-0.218174 0.780909 0.499682 0.523531 0.214211 -0.29589 -0.291622 0.0764825 +0.091177 0.447957 -0.848885 -0.752714 -0.40904 0.733853 0.721019 0.0583175 +0.663434 -0.344447 0.696992 0.511178 0.723191 0.159443 -0.988504 -0.898227 +-0.972966 -0.467816 -0.756507 -0.00932436 0.665708 -0.215697 0.193261 -0.73054 +-0.503446 -0.623009 0.0161417 -0.0152601 -0.586458 0.358857 0.480893 -0.481899 +0.231917 -0.216164 -0.302167 0.938651 -0.337667 -0.550426 0.304921 0.733026 +0.881044 -0.953436 0.468168 0.290473 0.624624 -0.88191 -0.173327 0.594642 +-0.616391 0.222285 0.780042 0.915883 0.152626 0.500683 0.679114 0.974283 +0.111703 -0.193509 -0.932136 0.47911 -0.99438 -0.865367 -0.0967407 -0.375721 +0.876059 0.397368 0.90637 -0.91502 -0.254416 -0.770248 -0.95772 0.192315 +0.543171 0.18398 -0.605726 -0.108319 0.366217 -0.226911 -0.46079 0.683085 +0.337 -0.447926 0.728826 -0.72444 0.25202 0.201194 0.2288 -0.595918 +-0.989507 -0.323679 0.812735 -0.786256 -0.498072 -0.386284 0.049872 0.0345352 +0.575 0.358321 -0.63589 0.0972841 -0.205853 0.931691 -0.638675 0.374053 +0.335957 -0.223622 -0.627704 0.37217 -0.994567 -0.557683 -0.57658 -0.701232 +0.0755894 0.974534 0.715631 -0.206894 -0.526541 0.501268 0.571862 0.212854 +-0.869894 -0.151379 0.296696 0.616219 0.804961 0.216442 0.169456 -0.387354 +-0.417341 -0.677607 -0.101949 0.336936 0.759843 -0.780843 0.118637 -0.563597 +0.0711953 0.678427 -0.291873 0.388899 -0.369805 -0.543637 -0.272861 0.757796 +0.164091 0.2259 0.593925 -0.60811 -0.876473 -0.859748 -0.555799 -0.0760664 +-0.0258962 0.842516 -0.273949 0.755465 0.718062 0.698204 0.411453 0.57304 +-0.718382 0.878294 0.340659 -0.866202 -0.842228 -0.358782 -0.0827611 0.19 +0.195705 0.702977 -0.139206 0.49806 0.292129 -0.711906 0.460747 0.415933 +0.0301255 -0.0247891 0.655832 -0.28719 -0.980266 0.0435323 -0.218995 -0.328763 +0.152072 0.101915 -0.733531 0.979024 -0.402967 0.996893 -0.0937599 0.560043 +-0.146347 0.638532 -0.455591 0.757517 0.736552 -0.402962 0.279153 0.392166 +0.935555 -0.435862 -0.220478 -0.216536 -0.486893 -0.999307 0.870995 -0.219688 +0.874182 0.687041 0.818154 0.888706 -0.409832 -0.0864898 0.548772 -0.2601 +0.634894 0.752933 0.694626 0.568505 -0.53463 0.823661 -0.128738 0.589029 +0.876153 -0.936599 0.558147 0.461222 0.83707 -0.394617 0.293574 0.397603 +-0.605902 0.147833 0.883365 0.934395 -0.517984 -0.518272 0.15289 -0.197287 +-0.841908 -0.189046 -0.687789 -0.400047 -0.0059939 0.636801 -0.926915 0.456876 +0.895508 -0.273416 0.809081 -0.91928 -0.203844 0.216291 0.863094 -0.268931 +-0.0429209 0.67578 -0.352266 0.411506 0.81286 0.68938 0.852793 -0.629614 +-0.339257 0.526827 0.531975 0.187766 0.22966 0.453669 -0.662857 0.298569 +-0.710394 0.81991 -0.0218645 0.713223 -0.531523 0.0181046 -0.152334 -0.116328 +-0.907862 -0.406953 0.925716 -0.539728 0.785887 -0.971309 -0.413071 0.975195 +-0.648158 -0.12306 0.122396 -0.524215 -0.586375 0.803927 -0.1532 -0.714185 +0.393997 -0.147598 0.309933 0.780862 0.756713 -0.275399 -0.333717 0.65411 +-0.0393073 0.238394 0.329379 -0.529649 0.338274 0.355714 -0.0642789 0.790386 +0.854227 -0.538818 -0.137987 -0.352855 -0.438209 0.0361346 0.277982 -0.831233 +-0.619246 0.342369 0.641529 -0.388092 -0.0129252 0.649824 0.407042 0.60878 +-0.555105 -0.682711 0.150686 0.73807 0.164439 -0.579306 0.417745 -0.585381 +-0.338461 -0.483024 -0.726698 0.0718554 -0.107977 -0.182788 -0.390668 0.342764 +-0.0275691 -0.962499 0.7334 -0.106491 0.297794 -0.33725 -0.17166 -0.638197 +0.586193 0.352238 -0.0854822 0.654726 -0.476064 0.656265 0.66643 0.852146 +0.616724 -0.709663 0.684614 -0.148603 0.354114 -0.230582 0.277798 -0.631456 +-0.905237 0.403059 -0.699449 -0.898671 0.31476 0.878856 0.336509 -0.387219 +0.45696 0.0752823 -0.171288 0.555415 0.596403 0.901777 -0.441202 0.194817 +-0.192999 -0.88183 -0.254202 0.053615 0.441121 -0.094888 -0.225595 0.658495 +0.956766 -0.897565 -0.387446 0.444515 0.300364 0.864927 -0.74361 0.263379 +0.612994 -0.854378 0.0613588 0.837108 -0.535565 0.461418 -0.412153 -0.995443 +-0.649823 -0.976708 -0.188926 -0.456246 0.364738 0.0958001 -0.581642 0.271749 +-0.367256 -0.110651 0.723649 0.948672 0.824979 0.173978 -0.804377 -0.529976 +0.700675 -0.839077 0.211385 0.781518 -0.98416 0.0010383 -0.735942 -0.820944 +-0.21899 -0.698457 0.0323291 0.358671 -0.237131 0.766883 0.722428 -0.615278 +0.925019 0.477009 0.0929154 -0.963981 -0.770475 -0.66034 -0.412604 -0.989395 +0.188951 -0.899547 0.659488 0.000167491 0.241788 -0.833199 0.890115 -0.51071 +-0.567007 0.171081 -0.313735 0.263977 -0.452386 0.058921 0.245298 -0.681204 +-0.706525 0.541778 0.337212 0.527072 0.25638 -0.199825 0.935215 -0.303665 +-0.671715 0.928582 0.382235 -0.747164 -0.70352 -0.833457 0.486566 -0.880991 +0.00239932 -0.303997 -0.580476 0.159374 -0.766379 0.662052 -0.406566 0.247808 +0.72319 0.154886 -0.681147 -0.136651 -0.658755 0.119839 -0.396113 0.341413 +-0.846152 -0.765456 0.305871 0.317983 -0.416314 -0.0165978 0.579588 0.628929 +0.214003 0.0627324 -0.375235 0.0384183 -0.543795 -0.525115 -0.335451 -0.343502 +0.373437 -0.99614 -0.29953 0.819305 -0.350093 0.623615 -0.298837 0.593464 +-0.528475 0.623557 -0.0741295 0.437527 -0.145454 -0.915441 0.63253 -0.803763 +-0.106869 -0.0737426 -0.446327 0.475409 0.626033 -0.963294 -0.299805 0.942468 +0.892964 0.170889 0.311687 0.716786 -0.39085 -0.986859 0.484436 0.995274 +-0.706496 -0.537461 -0.762442 -0.904428 -0.433185 0.564872 0.470109 0.123817 +-0.262784 0.902148 0.774335 0.663736 -0.624472 -0.0984558 -0.337614 -0.720203 +-0.866238 -0.375162 -0.278362 -0.900335 0.530593 -0.519309 0.947509 -0.864766 +0.541422 -0.517111 0.969367 -0.00489309 -0.999942 -0.813808 -0.232481 -0.546827 +0.72111 0.500202 0.225871 0.601391 -0.530886 0.0662849 0.25603 0.0269803 +-0.55402 -0.733515 -0.474599 0.293354 -0.830255 -0.632472 0.591209 -0.958008 +0.190085 -0.953903 -0.102418 -0.31927 -0.808489 -0.0164479 0.965921 0.859736 +-0.045593 0.0761261 0.815027 0.0726849 -0.739992 -0.324571 0.37797 0.766814 +-0.53319 0.870626 0.882681 0.876645 0.335389 -0.91757 -0.645386 0.695575 +-0.654247 0.936453 0.3427 -0.897004 -0.631964 0.645085 -0.722994 0.782582 +-0.596276 -0.969859 -0.379385 0.862274 -0.162028 -0.78108 -0.779214 0.657125 +-0.389549 -0.139342 -0.226078 -0.629354 0.658266 0.749323 -0.712046 -0.463735 +-0.515695 -0.590335 -0.260976 0.836529 -0.43391 0.992155 -0.372528 0.256853 +-0.728294 -0.545911 -0.932695 0.607095 0.252943 0.679097 0.357944 -0.544717 +-0.522439 -0.597402 0.789478 0.216115 0.308621 0.906395 -0.446619 0.311532 +-0.354402 0.859965 0.73919 0.564627 0.799822 0.0650698 0.796785 0.0643813 +-0.822488 0.356159 0.73162 -0.950163 0.0307983 0.707154 -0.0150776 0.768888 +0.293397 0.470361 0.999707 -0.105452 0.265617 -0.0899393 -0.139308 0.247726 +-0.814213 0.000165209 0.743174 0.723423 -0.495665 -0.569869 0.20464 0.226699 +0.797078 -0.910643 0.638684 0.708226 -0.473388 -0.682395 0.937041 0.962691 +-0.599728 -0.0115274 0.0426607 0.77116 0.0906074 -0.225591 -0.476268 0.435468 +-0.825989 0.96699 0.402459 0.746756 0.0971159 0.960465 0.734328 -0.616388 +0.120195 -0.770287 0.700157 -0.362726 -0.977723 0.801883 0.572893 -0.86369 +-0.640466 0.160692 -0.0868509 0.337732 -0.365243 0.287518 0.00417294 -0.221229 +0.808683 0.9046 -0.714129 -0.142761 -0.885229 -0.491364 0.0646426 0.46698 +-0.639558 0.162556 0.261822 -0.785512 0.621871 -0.173387 0.57077 0.885758 +0.937931 -0.895746 -0.424813 0.396573 0.119719 -0.777125 0.503697 -0.929197 +0.317781 -0.437269 0.905695 -0.233495 0.531483 -0.117484 -0.433652 -0.210996 +0.237316 0.870417 0.499755 0.154555 -0.855437 0.993596 0.606112 -0.484495 +-0.871784 -0.00282462 -0.999517 -0.404143 0.332888 -0.401976 0.917133 -0.062792 +0.984408 0.979356 0.444104 -0.22763 0.780517 -0.335999 0.996501 -0.312278 +-0.959262 0.424283 -0.860627 -0.0694463 -0.733332 0.24356 0.704195 -0.629933 +-0.568364 -0.926862 -0.660816 -0.717476 -0.430908 0.312 0.0532743 0.621865 +-0.604698 -0.195759 -0.528853 -0.0751889 0.634449 0.376064 0.0408941 -0.233978 +0.86435 0.881091 -0.381823 0.415693 0.329333 0.533571 -0.472293 0.0100355 +-0.848382 -0.421601 0.325856 0.0402104 0.0375616 0.160701 -0.0488019 -0.821447 +-0.830876 -0.577031 0.668062 0.244227 0.786971 0.641181 0.185922 0.557849 +-0.222176 0.873644 -0.842672 0.0822688 0.1352 -0.720617 -0.753538 0.351144 +0.33882 -0.69687 0.670628 0.854046 0.0373551 -0.245094 -0.685852 0.465421 +-0.255688 -0.533918 -0.636433 0.782628 -0.908956 0.257956 0.127924 0.176628 +0.346114 -0.825391 -0.798756 -0.673796 0.0464586 -0.564756 -0.649834 -0.93799 +-0.872198 -0.525028 0.655929 -0.33057 0.578602 -0.0980388 0.18996 0.624275 +0.0377116 0.20725 0.534533 0.941527 -0.49673 -0.302692 -0.305545 -0.434091 +-0.892842 0.272028 0.621542 0.880808 0.461609 -0.575953 0.00533898 0.407816 +0.798509 -0.652709 -0.953708 0.363563 -0.6924 -0.506284 -0.854446 -0.900739 +0.42303 0.140742 -0.982719 -0.486268 0.619562 0.242502 -0.691598 -0.82573 +0.281322 0.738703 -0.745971 -0.921568 -0.0965933 -0.458791 -0.0239777 -0.391412 +0.737994 0.506724 0.408581 0.914318 0.944033 0.470169 0.517512 -0.582022 +0.854393 0.638642 0.925928 -0.266903 0.249463 0.348856 -0.373119 -0.272758 +0.359209 -0.00257437 -0.0371977 -0.0566714 -0.104687 -0.927367 -0.878102 0.915497 +-0.980826 -0.831506 -0.392008 0.98813 -0.796466 0.932677 0.751053 -0.268263 +-0.931643 -0.837905 0.246372 0.244269 -0.894743 -0.789657 0.791453 -0.811077 +0.354346 -0.970716 -0.632394 -0.321787 0.00575287 -0.309555 -0.0123187 0.175477 +0.180362 -0.284787 0.777856 0.93745 0.839013 0.184939 0.102242 0.0720602 +0.256497 -0.470638 -0.507036 -0.321465 0.848751 -0.745974 -0.921839 -0.743009 +0.393878 -0.842621 0.0562395 0.922845 0.141543 0.0318582 0.0349252 -0.0904675 +-0.229106 0.696157 0.770312 0.0376088 -0.673544 -0.282075 -0.90807 0.162741 +-0.926558 -0.74316 -0.55728 0.278791 -0.497663 -0.893535 0.3457 -0.395518 +-0.336464 -0.829243 -0.711496 0.136823 -0.599154 0.237323 -0.18359 0.770229 +-0.145921 0.482492 -0.71054 0.987273 0.741452 0.729582 -0.0281977 0.917108 +-0.458362 0.0658424 -0.0279174 0.856926 0.709681 -0.783696 -0.961252 0.688503 +0.973118 0.849728 -0.814271 -0.469361 -0.653283 -0.104521 -0.960699 0.245302 +-0.911346 0.999177 -0.148402 -0.549248 -0.128112 -0.0623094 0.602351 0.0236946 +-0.766632 -0.244277 0.434017 -0.175912 0.530235 0.51945 0.933491 0.795817 +0.135716 0.0875148 -0.117921 -0.964061 -0.884529 -0.444931 -0.113143 -0.49756 +-0.155353 0.381952 -0.549882 0.304886 0.085705 0.409697 0.326658 -0.401568 +0.661057 0.785486 -0.682437 -0.371898 -0.47805 -0.545586 0.349588 0.0399875 +0.283964 0.117143 -0.388108 -0.0946642 0.73372 0.41185 -0.117624 0.269631 +0.665895 -0.170339 -0.367877 -0.134399 -0.338441 -0.0982146 0.128465 -0.30942 +-0.588202 -0.901838 0.206724 0.15348 0.906219 -0.990114 0.668819 -0.942605 +-0.367757 0.180424 -0.472094 0.731779 -0.329447 -0.332298 -0.0121267 0.29385 +-0.739351 -0.68326 -0.789779 0.293027 0.248523 0.574044 0.282377 -0.654182 +-0.327741 0.769444 -0.45172 -0.485067 -0.687509 0.712137 -0.245604 -0.802737 +0.462452 0.287437 -0.862168 -0.0115283 0.180286 -0.0755134 0.00532817 -0.314071 +0.299825 0.304382 0.790399 0.539985 -0.132184 -0.116863 -0.450487 0.177349 +0.46726 -0.497682 -0.919405 -0.136883 -0.239881 0.38042 -0.657034 -0.58277 +0.408087 -0.352302 0.533597 -0.221728 -0.401964 -0.468149 -0.582847 0.0768009 +0.698612 0.482192 -0.863302 -0.848353 -0.637903 0.889848 0.338528 -0.121574 +-0.57544 0.386562 0.196173 -0.395793 -0.658929 -0.0862365 -0.134087 -0.503467 +-0.596217 -0.889683 -0.297276 -0.228813 0.0438439 -0.57411 -0.615104 0.398265 +0.723855 -0.750041 -0.539976 -0.936613 0.355356 0.352291 0.839291 -0.88281 +0.299302 -0.219931 0.0672785 -0.288995 -0.218354 0.800048 0.754672 0.318256 +0.572547 0.260125 0.792013 0.244274 -0.640165 -0.595878 0.403371 -0.188557 +-0.894039 -0.638266 -0.856429 0.24191 -0.296712 0.976669 0.609767 0.573067 +-0.445127 -0.973205 0.388411 0.603933 0.853165 -0.441861 0.0535785 -0.648563 +0.770047 -0.82881 -0.295716 0.465457 0.538209 0.157396 0.730344 0.786522 +-0.275821 -0.913917 0.839515 0.0459649 -0.20751 -0.125001 -0.805479 -0.657282 +-0.851585 0.989703 0.947285 -0.727628 0.831814 0.625855 -0.63615 -0.381488 +-0.0655911 -0.808206 0.600867 0.899066 -0.278109 0.910354 0.473494 0.142634 +0.808929 -0.168982 -0.847232 0.459863 -0.910526 0.656583 -0.285735 -0.404819 +-0.0320648 -0.825178 -0.387763 0.0331624 -0.946075 0.551552 0.328367 -0.520419 +0.664296 0.307382 0.78977 0.998128 -0.784913 -0.623012 -0.855921 -0.38578 +0.417838 -0.0115991 -0.188635 0.546942 0.0187048 -0.513309 0.0977445 0.683181 +-0.654691 -0.707864 -0.655903 -0.27102 0.494584 -0.64251 -0.822701 0.948065 +0.0520526 -0.7392 0.301475 -0.367139 0.0226178 0.3656 0.493187 -0.833477 +0.546452 0.25182 -0.240083 0.663908 0.233792 -0.40176 -0.523707 -0.958207 +0.637881 -0.434266 0.937711 -0.884153 0.967427 -0.2417 0.423966 0.338289 +0.580809 0.251979 -0.627208 -0.799636 0.556872 -0.367169 0.251983 0.792732 +-0.976935 0.0116265 0.982995 -0.792821 -0.951236 -0.669607 -0.580612 0.69541 +-0.477557 -0.462184 -0.940225 -0.358341 -0.908887 0.453559 0.248522 -0.777471 +-0.445277 0.195476 0.00953749 -0.637083 0.666037 -0.318406 -0.510122 0.157887 +-0.233629 0.404874 0.757236 0.73776 0.885794 0.604826 -0.0677713 -0.572471 +0.77151 0.61707 0.415902 0.310543 -0.580839 0.489709 -0.650273 -0.325419 +0.412893 -0.955568 0.956084 0.130488 0.0726098 -0.569455 0.596294 0.839599 +-0.298585 0.246649 0.950922 -0.735803 -0.0357101 -0.0360352 -0.260508 -0.817461 +0.216787 -0.426844 0.107673 -0.515836 0.249557 -0.532994 -0.352223 0.62053 +-0.0782868 -0.00041177 -0.100859 -0.0858553 0.847271 0.689137 0.170866 -0.47497 +0.0473733 0.288673 0.984627 -0.675146 -0.767599 -0.305889 -0.727514 -0.0746797 +0.443565 0.113971 -0.128798 0.689816 0.331141 0.878447 -0.0820185 -0.685195 +0.152155 0.232343 0.620349 0.810755 0.805267 -0.645301 0.371111 0.999969 +0.771033 -0.518711 -0.46167 -0.778356 -0.303337 0.338897 -0.788653 -0.641049 +-0.601934 -0.331875 -0.356332 -0.97196 -0.428272 0.489866 0.815942 -0.0266128 +-0.827429 -0.195289 0.949786 0.0602482 0.614102 -0.629974 -0.88504 -0.797522 +0.092041 0.467493 -0.907994 0.859784 0.514958 0.195214 0.533135 0.443255 +0.373345 -0.834546 -0.990051 0.482633 -0.576983 -0.78488 0.258782 0.143983 +0.0252336 -0.35831 0.267115 0.602956 0.567865 -0.0744821 0.350106 -0.965662 +-0.0995878 -0.0662973 -0.403141 0.363913 0.0576992 -0.778704 -0.0906451 0.132037 +0.901541 0.193029 0.958542 -0.279989 0.748255 0.523988 -0.178916 -0.122212 +0.662571 0.599512 -0.692118 -0.140859 0.943946 0.374829 -0.577019 -0.317454 +-0.569703 -0.421185 0.209724 -0.0272069 -0.825385 -0.299885 -0.702465 -0.841303 +-0.625022 -0.939014 -0.646478 -0.929883 -0.872406 0.240342 0.329466 0.982431 +-0.548367 -0.233095 -0.934782 0.563045 0.458769 0.805903 -0.395638 -0.335692 +0.0298147 0.93917 -0.641635 -0.93952 0.808355 0.0620558 0.272624 0.91682 +0.685732 -0.454605 0.895198 0.535367 -0.195084 0.798437 0.78036 0.0728712 +0.748921 0.613001 -0.586845 -0.368276 0.607438 0.44901 -0.860836 0.0710699 +0.160246 -0.912767 0.793088 -0.0789475 0.86137 -0.646717 -0.418569 -0.504365 +-0.714887 -0.158707 -0.312812 0.0879129 0.150715 0.0164083 -0.488934 0.0938861 +-0.671302 0.831696 0.215217 -0.394584 0.86001 -0.41718 -0.584042 -0.28624 +-0.493184 0.740163 -0.570726 -0.0863252 0.396933 0.379573 0.761653 -0.529462 +-0.0744424 0.903038 -0.587916 -0.666138 -0.602562 0.580486 -0.0215209 0.610203 +-0.0184679 0.767602 -0.617271 -0.70958 -0.401369 0.76296 0.730919 -0.0675959 +0.202507 0.0970708 0.813517 -0.379081 0.500343 -0.891592 -0.947009 -0.130569 +-0.3293 0.0190248 0.130283 0.0215455 0.468149 0.487996 -0.91982 0.263618 +0.166966 0.257769 -0.870823 -0.742854 0.347766 -0.517503 0.0991567 -0.937943 +0.177273 0.654459 -0.12014 0.0798352 0.328079 -0.41541 -0.981877 0.650573 +-0.416929 0.864492 -0.616631 -0.543461 -0.816447 0.627673 0.12846 -0.0171272 +-0.00616636 -0.927528 0.748037 0.627434 -0.763391 -0.43345 -0.631288 0.529012 +0.283554 -0.648569 0.872216 -0.546691 0.576309 0.996444 -0.243198 -0.933623 +-0.930564 0.547018 0.18931 -0.698586 0.151469 -0.842365 0.637498 -0.163121 +-0.00261068 0.704759 0.27449 -0.242241 -0.607262 0.580741 0.245604 0.92185 +0.582213 -0.823424 -0.10619 -0.990174 -0.0735172 -0.909104 0.520764 -0.820255 +0.900447 -0.94827 0.155163 0.417331 0.0114175 -0.00628024 -0.910574 -0.283187 +-0.187358 -0.139705 0.562407 0.292244 0.890497 -0.977713 -0.0115719 -0.0382545 +-0.690194 -0.0973353 -0.155404 0.0832844 0.162616 0.568383 -0.753987 0.435038 +0.291621 -0.5899 0.396798 -0.0742157 0.0331849 0.684662 0.655881 -0.261075 +0.872796 0.850441 0.888413 -0.469705 -0.100169 -0.416602 0.926549 0.101557 +-0.873468 -0.197107 -0.675292 0.49963 0.365601 -0.429868 0.132738 0.0865636 +-0.103572 -0.0652441 0.763867 -0.803298 0.438389 0.0059869 0.961121 0.149466 +0.156736 -0.240026 -0.016764 0.493385 0.197859 0.959152 -0.559036 -0.355299 +-0.129929 -0.100494 -0.324997 -0.932065 -0.439955 -0.908395 -0.815456 -0.0763179 +-0.51843 -0.429505 -0.404266 0.773386 0.669001 0.405253 -0.362474 -0.657479 +-0.326284 0.91793 -0.113967 0.27732 0.0900128 -0.0141997 -0.101568 -0.177652 +0.253364 0.944982 -0.981293 0.681051 0.220457 0.678805 0.117425 0.81758 +0.76245 0.882228 0.588842 -0.0966178 0.0846132 -0.814894 -0.599803 -0.157418 +0.602957 0.776127 0.436864 -0.0315237 -0.380279 -0.577336 -0.687014 -0.40178 +-0.138798 -0.105822 0.841678 -0.0263646 0.640965 -0.921257 -0.787924 0.262715 +-0.332249 0.699275 0.160189 -0.277205 -0.0486838 -0.735237 -0.00192763 0.880213 +-0.0118682 -0.907686 -0.196037 0.14673 -0.583138 0.602316 0.174741 -0.242854 +0.128001 0.0702017 -0.520309 0.950693 0.983046 0.976974 -0.696315 0.339818 +-0.220227 0.959419 -0.447921 0.772382 0.245944 -0.231034 0.781869 0.566132 +-0.739302 0.827347 0.564051 -0.450396 0.131851 -0.627369 0.0814461 0.792095 +-0.707655 0.761645 -0.347376 0.952777 -0.782499 0.000215353 0.130336 -0.123162 +0.200002 -0.651541 0.765025 -0.502356 -0.000344623 -0.349748 -0.700109 -0.847312 +0.636117 -0.129245 0.676774 -0.576404 0.0827873 -0.203879 0.701524 -0.809694 +0.434977 0.179651 -0.290366 -0.0791204 0.263298 0.639721 0.629461 0.670814 +0.00186741 -0.432625 -0.00158293 -0.831541 -0.823676 0.472602 -0.961719 -0.66056 +-0.984705 0.190091 0.565003 -0.884111 -0.559499 0.233506 -0.713269 0.547719 +0.355859 -0.245797 -0.742472 -0.677628 -0.970212 0.149376 -0.392426 0.544144 +-0.147631 0.907208 0.391922 -0.312962 0.963317 0.973541 0.291944 0.448386 +0.29835 -0.982196 0.707691 0.449114 0.460402 -0.526763 -0.993272 -0.782804 +0.304143 0.122948 0.493004 -0.717811 -0.37569 0.844869 -0.788104 0.617283 +0.743039 0.955465 0.235476 0.707989 -0.066996 0.420538 -0.721263 0.825603 +0.0494904 0.559394 -0.670968 -0.191983 -0.0920988 0.22054 0.580336 0.547939 +-0.188052 0.239844 0.27005 -0.188772 0.592379 -0.193501 0.501971 0.892349 +0.859846 0.604318 0.715631 -0.0350142 -0.386098 -0.253564 0.626177 -0.227681 +-0.867934 -0.332436 0.279554 -0.389763 0.528261 0.264091 0.292911 -0.265678 +0.566285 -0.180326 0.809413 0.526826 0.941549 0.383176 -0.515368 -0.477709 +0.965153 0.397489 0.82954 -0.696508 -0.64787 -0.324891 0.614777 -0.965558 +-0.0796109 -0.790563 -0.845366 -0.650756 -0.956735 -0.616139 0.246225 0.633251 +-0.0871428 -0.472832 -0.105659 0.22979 0.375183 0.486171 0.119254 0.872361 +0.681773 -0.0360835 0.262123 0.0616381 0.530013 -0.916977 -0.0935366 0.980232 +0.132328 -0.570867 -0.10049 -0.327286 0.515566 -0.46658 -0.539151 -0.91762 +0.296509 -0.4306 0.212748 -0.819735 0.863 0.396073 -0.804393 0.938419 +0.301962 0.126031 -0.422601 -0.538843 -0.730788 -0.672684 0.357379 0.19197 +0.0436512 0.947901 -0.200379 0.294212 -0.263388 0.889449 -0.158338 0.742788 +-0.857164 -0.794924 0.960183 0.462791 0.909592 0.621129 -0.979916 -0.483498 +-0.950737 0.509248 -0.415408 0.339305 0.0395366 0.326865 -0.0173424 -0.184521 +0.926779 -0.695107 0.178422 -0.0335427 0.558427 0.873586 -0.798514 0.59477 +0.0116028 -0.639165 -0.99498 -0.817078 -0.75414 0.997985 -0.149242 -0.757341 +-0.854019 -0.0510839 0.0171485 -0.499207 0.312593 0.354565 -0.726875 -0.509954 +-0.0973036 -0.97082 0.686793 -0.523589 -0.0157376 0.782279 0.692317 0.0632247 +0.778373 0.749199 -0.288588 -0.125306 0.483981 0.692396 0.0789724 0.616047 +0.563043 -0.109978 0.236749 -0.460316 -0.0637256 -0.939167 -0.218829 0.671097 +0.96692 0.293831 -0.285168 -0.125799 0.760805 0.894275 0.417545 -0.673229 +0.768438 0.955127 0.752221 0.554419 0.586243 -0.299753 0.0538873 0.857052 +-0.251428 -0.178101 0.598394 -0.783113 -0.312652 0.751426 -0.327546 -0.417581 +-0.373495 0.580349 -0.671673 0.191876 -0.524553 0.480578 -0.697009 0.121584 +0.940414 -0.420872 -0.399819 -0.734092 0.228542 0.438589 -0.656298 -0.94457 +-0.215194 -0.255169 0.305846 -0.796909 0.983606 -0.502691 0.736112 -0.0623938 +0.40672 -0.387792 0.688816 0.498798 -0.450368 0.732224 -0.592412 0.104975 +-0.81188 0.208479 0.16719 -0.649639 0.912674 0.644033 0.714323 -0.332735 +-0.58738 0.069026 0.281932 -0.93151 0.11176 -0.847874 -0.907921 -0.618208 +-0.0166421 0.32995 -0.413312 0.987446 -0.663446 -0.848917 -0.660166 0.918778 +-0.472898 -0.619355 0.081946 0.977692 0.424855 -0.698976 -0.247465 -0.414872 +-0.709575 0.437799 0.819009 -0.603688 0.911107 -0.0593075 0.6424 -0.841602 +-0.301987 0.0139387 0.703714 -0.142194 0.346217 0.886637 0.351668 0.0953612 +-0.798206 0.515067 0.350112 -0.118378 0.627946 -0.196216 -0.119848 -0.666486 +-0.0960841 -0.0905893 -0.401865 0.367503 0.522487 0.172046 0.405863 -0.703013 +0.681311 0.251237 0.726527 -0.788047 0.608837 0.87006 0.19911 -0.756488 +-0.367448 0.847017 -0.483341 -0.934484 0.484957 0.310926 -0.141077 0.799676 +0.129294 -0.939129 0.434043 0.928614 -0.784234 -0.155421 0.56559 0.42488 +-0.81969 -0.365195 -0.0990222 -0.659092 0.935576 0.997549 0.261516 0.479096 +-0.30282 0.597882 -0.0400856 -0.359952 0.65592 0.0900222 0.526692 0.387967 +-0.106283 0.985081 0.479074 0.825846 0.485159 0.432059 0.825164 0.975166 +-0.629375 -0.271564 -0.865987 -0.513429 -0.363984 -0.760674 -0.725854 -0.883243 +-0.724934 -0.00115233 -0.800608 -0.585264 -0.854157 -0.767145 -0.503937 -0.859145 +-0.437062 0.218128 0.339113 0.777923 -0.129217 -0.45072 -0.694891 0.195081 +0.253737 -0.0208482 -0.0750381 -0.924029 0.996339 0.482457 -0.625736 -0.844848 +-0.536997 -0.122948 -0.952199 0.298501 -0.572839 0.803669 0.846795 -0.204753 +-0.814245 0.856752 -0.854549 0.0121502 -0.244473 -0.477249 -0.926179 0.38471 +-0.622075 0.950099 -0.234329 -0.635224 0.689427 -0.242433 0.887506 -0.363187 +-0.268139 -0.997729 -0.0682811 0.697112 0.717812 0.817084 0.821962 0.354532 +0.281839 0.122168 -0.872511 -0.0787717 -0.433926 -0.297339 0.234911 -0.700059 +-0.442467 0.964492 -0.434611 0.75884 -0.90507 -0.0809998 -0.123331 -0.486963 +0.629516 -0.671634 -0.667595 -0.680669 0.00628531 -0.0160714 -0.0682033 0.404433 +0.493993 -0.5621 -0.300429 -0.541774 -0.609693 0.477616 -0.611964 0.777714 +-0.820392 -0.194439 -0.843868 0.548159 0.933125 0.0682794 0.90077 -0.912988 +0.346994 0.460742 0.0711625 0.143112 -0.322344 0.706363 0.581826 0.85121 +-0.340411 0.13449 -0.340575 -0.846684 -0.478047 0.177675 -0.409092 0.334076 +-0.944282 -0.814166 -0.83139 0.548307 0.512799 0.51377 -0.977379 -0.256738 +0.327306 0.449161 -0.589384 -0.377997 -0.980277 -0.317601 -0.825479 0.668345 +0.476947 -0.231503 -0.230226 0.291133 0.867569 -0.483659 -0.699588 -0.866898 +-0.417091 0.0796027 0.74786 0.663857 0.495741 0.14875 0.834061 -0.406024 +0.473261 0.140245 -0.84201 -0.513092 0.173684 -0.171047 -0.270411 -0.740897 +-0.279202 0.242499 -0.0531898 0.01875 -0.368387 0.11644 -0.22019 -0.844834 +-0.183708 -0.737165 0.850556 -0.345713 0.653315 0.773672 0.645283 0.926115 +0.505334 0.348271 0.312431 -0.0445571 -0.329575 -0.271828 0.0056622 -0.666408 +-0.649974 -0.683124 -0.000972694 0.317819 0.0950826 -0.979677 -0.816691 -0.619386 +0.679926 0.0729124 -0.823981 0.2991 0.448544 0.0401972 -0.756171 0.371164 +-0.840083 0.959263 -0.830681 -0.598575 0.0837273 -0.733904 -0.79105 0.484256 +0.412114 -0.407305 0.943331 0.608559 -0.323736 -0.0952373 -0.456893 0.464353 +-0.670586 -0.865889 -0.40852 -0.0711989 -0.0330043 0.374488 -0.747553 -0.00226158 +0.751611 0.0783874 0.80301 0.184682 -0.327936 0.246717 -0.910611 0.264174 +0.514412 -0.473595 0.6392 0.668385 0.84815 0.827681 0.222833 -0.37884 +-0.180982 -0.361258 0.407307 0.744511 0.469552 -0.544188 -0.780816 0.833719 +-0.665318 0.209095 0.0774345 -0.130712 -0.763488 0.624944 -0.350726 0.0769057 +0.703306 0.147031 -0.108821 0.0217217 -0.441957 -0.235285 -0.946216 0.0952471 +0.468648 0.922992 0.32141 0.611106 -0.828832 0.329353 0.0698133 -0.0894808 +-0.682444 0.155833 -0.76055 -0.926175 0.552841 -0.127039 0.215525 -0.129632 +0.928951 -0.145428 -0.983338 -0.242727 0.570928 0.484034 -0.372604 -0.0987295 +-0.373366 -0.583479 0.00910048 -0.678305 0.168452 0.754081 0.646345 -0.499036 +-0.17539 0.263483 0.988656 0.322723 -0.732819 -0.532137 0.0227312 -0.635047 +0.525417 0.0649438 0.6975 0.0404561 -0.544791 0.620582 -0.709808 -0.477295 +-0.334942 0.324497 0.847588 0.662796 -0.132046 -0.482696 0.991537 0.923082 +-0.20068 0.74449 -0.489799 0.63289 -0.866579 -0.282239 -0.625266 0.843382 +-0.135319 0.873575 -0.561836 -0.576817 0.0431551 -0.848525 -0.335841 0.774156 +-0.649615 0.740492 -0.645749 -0.361132 -0.205354 -0.675642 0.931562 -0.533698 +0.192217 0.0832572 0.543377 0.408635 -0.943419 -0.646391 -0.967457 -0.481755 +0.281202 0.868417 -0.114176 0.671657 -0.153338 0.73452 0.574116 -0.955257 +0.557163 -0.223188 0.962339 0.452624 0.613705 0.900581 0.645901 0.329851 +-0.598393 -0.487692 -0.602136 -0.472586 0.881521 -0.883675 0.537421 0.0677523 +0.263266 0.203235 -0.829731 0.189255 0.102929 -0.79814 0.254124 0.612319 +-0.0713455 -0.375519 0.419743 -0.225415 0.964394 0.109494 -0.709433 -0.331222 +0.843804 -0.183654 -0.341667 0.537221 0.250964 0.701849 0.730312 0.0704345 +0.284205 -0.673898 -0.298678 -0.468715 -0.997889 0.732829 -0.825887 -0.94121 +0.904557 -0.0467022 0.475033 0.270049 -0.736836 0.470416 0.0970923 -0.598756 +-0.424076 0.136916 0.524596 0.374663 0.203456 -0.681284 0.0263966 -0.699673 +0.0130246 -0.0532326 -0.0615701 -0.339619 -0.852729 -0.0357394 -0.83475 -0.89354 +0.987203 -0.0959013 0.0851994 -0.724039 -0.26461 -0.682084 -0.47515 -0.177745 +-0.877482 -0.537615 0.248853 0.0758161 0.28464 -0.359021 0.713614 -0.549527 +-0.336066 0.723184 0.424637 -0.609074 -0.0372588 0.694688 0.161025 0.00549367 +0.450152 0.566343 0.0599369 0.60323 0.331496 0.156181 0.228176 0.197368 +0.584285 0.30046 0.66568 0.818899 0.0788251 0.0212786 -0.352632 -0.489074 +0.479954 -0.201059 0.474697 0.74284 -0.143695 -0.829963 0.326414 -0.832921 +0.988085 -0.278915 0.605341 -0.152305 0.78077 0.881069 -0.818724 0.474738 +-0.436552 0.712162 -0.0635374 0.244215 -0.571331 0.204936 -0.111836 -0.0682449 +-0.0709972 0.574723 -0.909965 0.335705 0.269968 0.465588 -0.918693 0.091444 +0.98582 -0.0754521 -0.547262 -0.380355 -0.0867791 -0.0747597 -0.0866743 0.42908 +0.419141 0.100784 -0.917742 -0.638208 0.971851 0.0873342 0.508788 0.511826 +0.254514 -0.379363 0.344608 -0.253227 -0.126856 0.211372 -0.760917 -0.0370611 +0.461313 0.0262896 0.634298 0.447411 -0.731852 0.734685 -0.349677 -0.158824 +0.334537 -0.180378 -0.0369194 0.256403 0.0446841 -0.493594 0.54217 0.294292 +-0.0925171 -0.180654 0.701996 -0.634091 0.173207 0.15828 0.0562676 0.831866 +0.878095 0.981166 0.563838 -0.527609 -0.891458 0.55635 -0.369676 -0.816483 +-0.505458 0.434734 0.837874 -0.634362 -0.295461 -0.310891 -0.270371 0.78806 +0.0550179 -0.2884 -0.946651 0.276765 0.765948 0.803761 0.987376 0.339298 +0.363058 -0.200504 0.269844 -0.846002 0.821406 -0.899048 0.452818 -0.965904 +0.240888 -0.723617 0.850907 0.77804 0.416406 -0.881811 0.475796 -0.706006 +0.949923 0.703903 -0.577528 0.484688 -0.151916 -0.614139 0.278253 0.750611 +-0.562183 -0.840888 0.201305 -0.863502 -0.841988 0.963908 0.553503 -0.265581 +0.556983 0.914997 0.175021 0.676986 -0.515886 -0.708668 -0.0416682 -0.240647 +-0.470628 0.0114494 0.556913 -0.473869 -0.647865 -0.857761 -0.131074 -0.5774 +0.100571 0.572337 -0.86835 -0.772119 -0.895905 0.185833 0.820328 0.50272 +-0.145288 -0.879785 0.735591 0.143136 0.183041 -0.848571 0.770955 0.895035 +0.860503 0.638752 -0.923975 -0.776266 -0.0339876 0.392074 -0.409834 0.904356 +0.665608 -0.377151 0.539506 -0.885743 0.587655 -0.247009 0.929327 0.41128 +-0.333 0.693968 -0.200711 0.825734 -0.709479 -0.580446 0.0255974 0.0384008 +0.131076 0.347609 -0.372302 -0.57721 0.115747 -0.296598 -0.683664 0.3911 +-0.764893 0.147385 0.886291 -0.185818 -0.662009 -0.772474 0.27857 0.249265 +0.801509 0.807046 0.367588 -0.854962 0.493405 -0.290518 -0.641011 -0.775767 +0.286831 -0.691024 -0.444923 -0.0338499 0.339135 0.0460713 -0.329586 0.76591 +0.802283 0.0193814 -0.789017 0.473164 0.0212489 -0.635791 0.6961 -0.596351 +-0.596642 -0.998232 0.0136001 -0.276802 0.915992 0.691271 -0.300357 0.320925 +0.637074 -0.0804191 0.151036 -0.351331 0.542885 -0.289594 -0.821636 0.743944 +0.578408 0.0780374 -0.281724 -0.544973 -0.716897 0.932581 -0.476661 0.019135 +-0.380527 -0.443295 -0.546443 -0.0261096 -0.533649 -0.386573 -0.693799 -0.478674 +-0.046097 0.13709 -0.241074 -0.312128 -0.172706 0.414745 0.677841 -0.971149 +0.363223 0.655025 0.273508 -0.728881 0.288561 -0.417987 0.216158 0.297134 +-0.0229396 0.274697 -0.572701 -0.00854633 -0.891319 0.497741 0.707254 -0.0715516 +-0.166197 -0.175614 -0.382295 0.221078 0.31008 -0.40528 0.555547 0.206632 +0.0926327 -0.897087 -0.537789 0.423398 0.615531 -0.383331 0.485904 0.520743 +-0.992939 -0.571718 -0.43316 -0.714167 0.849937 0.646327 0.94783 -0.198636 +-0.174774 0.806576 -0.0249607 0.65846 -0.477966 0.209632 -0.397504 0.388044 +-0.558192 -0.478565 -0.071865 -0.788793 0.33193 -0.259333 -0.32999 0.807504 +0.407392 -0.293065 -0.620214 -0.342446 0.655084 -0.709866 0.276465 0.472418 +-0.742165 0.464929 -0.735399 0.827727 0.501501 -0.745092 0.151738 0.895937 +0.728639 -0.673592 0.805636 0.407921 -0.27646 -0.595708 0.786234 0.277305 +0.965162 -0.299604 0.0224402 -0.736399 0.99229 0.403263 -0.672184 -0.195072 +0.732057 0.242696 -0.842716 -0.981741 0.910077 0.37308 0.189254 -0.711949 +-0.112862 0.508801 -0.784562 -0.260952 -0.141216 -0.884663 0.659708 -0.645477 +0.137565 0.961694 -0.402307 -0.237631 0.879642 0.818971 -0.934519 -0.156967 +-0.369574 -0.448501 -0.0253348 -0.156766 -0.774773 -0.315431 0.0272124 0.383744 +-0.265289 0.0890106 -0.341694 0.749724 0.691768 0.210621 -0.946144 0.692789 +-0.366599 0.272157 -0.355304 -0.198237 0.896213 0.627534 0.0261838 -0.141295 +0.45492 0.302257 -0.0468647 0.649361 0.158008 0.117297 0.282796 0.953413 +-0.159449 -0.296339 -0.0335203 -0.523948 -0.872181 0.88031 -0.285115 -0.0267583 +0.572534 -0.0236469 0.274608 -0.931378 -0.0453279 -0.712016 -0.380912 -0.424716 +-0.934625 -0.456438 -0.661584 -0.116224 0.977467 0.0170871 -0.115195 -0.792868 +0.0637042 0.0229216 -0.00697457 -0.0529792 0.964685 0.231166 0.229974 0.3553 +0.789391 0.0625273 0.0602473 0.244722 0.645841 0.17548 -0.689109 -0.244772 +-0.690024 -0.095846 0.900466 -0.208639 -0.969796 -0.227784 0.108467 0.0271702 +-0.15074 -0.833923 0.128248 0.430724 0.482692 -0.969463 -0.632649 -0.145399 +-0.37713 0.0774293 -0.236528 0.922563 -0.81271 0.299678 -0.932778 0.492247 +0.188545 -0.529713 0.624936 -0.469141 0.987246 0.431504 0.854037 -0.762246 +-0.0552025 0.372414 0.869929 0.159012 -0.687834 -0.139634 -0.39739 -0.498658 +0.578699 0.910161 -0.154866 0.769141 -0.659524 -0.891779 -0.353737 0.622878 +0.901131 -0.957311 0.384053 -0.244528 -0.698428 0.14552 0.451192 0.547946 +-0.560394 0.785912 -0.671458 0.637162 -0.608589 -0.109387 -0.0562739 0.749011 +-0.235035 0.975024 -0.720015 0.423625 -0.194715 -0.844956 0.904767 0.334961 +-0.250385 0.278003 -0.960428 -0.560063 0.459592 0.549588 -0.587277 -0.317793 +-0.672238 -0.0193841 -0.609921 -0.743995 0.347307 -0.950875 0.304479 -0.0682391 +-0.738912 0.871768 -0.80597 0.943043 0.584323 0.184483 -0.823518 -0.450663 +-0.299693 0.658124 -0.0920184 -0.517681 -0.167155 -0.885931 -0.252782 -0.859972 +0.301004 -0.715509 -0.878621 0.343585 -0.305201 0.300754 -0.0804703 0.88171 +0.146689 -0.0406856 0.502733 -0.728415 0.667357 -0.681166 0.635528 -0.569843 +-0.605522 -0.389553 0.97596 -0.544883 -0.499722 -0.739967 0.936435 0.569182 +0.115188 -0.933271 0.618308 0.771824 -0.273154 0.973603 -0.548468 -0.377346 +0.289198 0.400707 0.341007 0.242693 0.629546 -0.841992 -0.902661 -0.680752 +0.790193 0.450719 -0.676837 -0.998801 -0.953709 -0.514285 -0.608983 -0.063873 +-0.845608 0.13869 0.308817 0.573333 -0.111053 0.850081 -0.130535 -0.626792 +0.557385 -0.668952 -0.517374 -0.837176 -0.0946193 -0.342095 0.329456 -0.725253 +-0.996383 0.298292 0.613085 0.279964 -0.341768 -0.0500832 0.836943 -0.382539 +-0.257443 -0.334236 0.341544 -0.762126 0.830931 -0.755055 -0.629344 -0.366851 +-0.00481919 0.954593 -0.807561 -0.415451 0.182417 -0.154364 -0.364854 0.835567 +-0.237453 0.829338 -0.0698139 0.596618 -0.349329 0.796922 -0.890895 0.178854 +-0.64816 0.967274 0.945728 0.734379 -0.994984 -0.931034 -0.267934 -0.924349 +0.473281 0.542363 -0.339317 -0.232638 0.56468 0.349527 -0.929153 0.944001 +-0.289266 0.588317 -0.0176391 0.735485 -0.997942 -0.885337 0.20366 0.112654 +-0.558884 0.940195 -0.889159 -0.673324 -0.995184 0.0471987 0.185648 0.949386 +0.196061 -0.930484 0.00639625 0.637149 -0.307618 0.998405 -0.0294353 -0.594105 +0.0552998 -0.11803 0.382521 0.119049 -0.0321779 0.0782131 -0.412258 -0.704946 +-0.76376 0.628232 0.832789 -0.0694965 0.126545 0.0439213 0.607367 0.335537 +-0.579641 -0.740907 -0.351012 0.88042 0.633933 -0.241521 -0.625853 0.625727 +0.560657 -0.526308 -0.829512 -0.802544 -0.670859 0.1376 -0.991083 -0.257036 +0.3691 0.714599 0.399681 -0.317525 0.271002 0.575944 -0.506426 0.00972196 +-0.0498428 0.299066 0.767105 0.383995 -0.0707558 -0.928393 0.797721 0.546903 +0.166821 -0.883638 -0.596293 0.511645 0.46263 -0.248875 0.885323 0.692066 +-0.466133 -0.432107 -0.921983 -0.0902192 -0.0991836 -0.391786 -0.227445 0.170829 +-0.19356 0.0902635 0.688871 0.763108 0.416828 -0.274712 -0.225387 -0.250981 +0.958279 -0.0519003 -0.323055 -0.685343 0.315093 -0.0760968 -0.136304 0.711662 +-0.368057 0.920782 -0.149644 0.991639 0.72477 0.312863 -0.493577 0.588193 +0.492952 0.505702 -0.689534 -0.634408 -0.794865 -0.562177 0.25718 0.61149 +-0.852158 0.425178 0.201842 -0.356184 -0.717887 -0.778701 -0.220887 -0.820186 +-0.0936795 -0.0265722 -0.297521 -0.983691 0.949468 0.688647 0.524366 -0.671308 +0.68033 -0.645956 -0.580308 -0.0508978 0.644663 0.504026 0.446264 -0.672277 +-0.594764 0.318113 -0.918364 0.932367 0.309752 0.428791 0.543422 -0.15454 +0.623329 -0.275694 -0.235256 0.276813 -0.679186 -0.694129 0.315376 0.85814 +0.265107 -0.403794 0.154762 0.599364 -0.183366 -0.486222 -0.603675 -0.967964 +0.00159266 0.345222 -0.71807 -0.691834 0.112445 0.421346 0.762269 -0.165408 +-0.583827 0.307018 -0.406981 -0.0445757 -0.0681729 0.596643 0.159363 0.441615 +-0.255382 0.406932 0.653552 -0.677342 -0.735519 0.896659 -0.541693 0.590323 +0.816429 0.683525 0.663796 -0.105868 0.335355 0.144513 0.6088 -0.71196 +0.905091 0.461875 0.748461 -0.631851 -0.22203 0.835632 0.701367 0.494544 +0.703343 0.960029 0.0364494 0.753041 -0.460295 -0.320132 -0.0610723 -0.990114 +0.841779 -0.607848 0.564599 0.626047 -0.274692 -0.474232 0.548603 0.574891 +-0.915994 0.245424 -0.980944 -0.0317871 -0.0595176 0.965232 -0.190413 0.309468 +0.265267 0.328185 -0.755614 0.0244079 0.859598 0.599836 0.182496 0.0869868 +0.678263 0.64813 -0.140393 0.965751 0.266443 0.896842 0.487152 0.366294 +-0.374064 -0.425941 0.364628 0.0217471 -0.819208 0.996813 -0.0982184 0.752044 +0.852448 0.954876 0.831177 -0.557424 -0.570651 0.0823429 0.194555 0.547086 +-0.00831721 0.374227 -0.169066 -0.393005 0.881835 -0.172907 -0.292724 -0.637595 +0.353033 -0.128384 0.017136 -0.967027 -0.0267362 -0.784259 0.738713 -0.479217 +0.781405 -0.0243668 0.0528664 -0.42977 0.309843 -0.981927 -0.458865 -0.373984 +0.686457 -0.859277 -0.4438 -0.319241 0.925002 -0.757436 0.371107 0.785337 +0.0687281 -0.227704 -0.716049 0.618614 0.809186 -0.323491 0.21301 0.558899 +-0.473516 -0.260677 -0.653484 -0.337515 -0.471802 -0.246028 -0.657803 -0.641357 +0.257195 0.333542 0.144983 0.906458 -0.221926 -0.179038 0.292535 -0.238652 +-0.444515 -0.597292 -0.140636 -0.138139 0.457578 -0.369601 -0.993449 0.59436 +0.331135 0.318457 -0.149608 0.906395 -0.566347 -0.603843 -0.157088 -0.745638 +0.854311 0.156158 -0.0937663 -0.177936 -0.331773 0.806838 0.0753236 0.48724 +0.734952 -0.803158 -0.789472 0.758886 0.667306 -0.658141 -0.453839 0.543691 +-0.0331302 0.673922 -0.0424407 -0.134746 0.980874 0.822616 -0.805295 -0.469583 +-0.241237 0.870376 0.537135 -0.257666 0.615657 0.718748 0.268031 0.0668715 +-0.397724 -0.830642 0.091248 -0.457051 0.802427 0.700776 0.65742 0.198644 +-0.0240565 0.027776 -0.976066 0.175095 0.00973869 -0.367777 0.571263 -0.210909 +-0.636901 0.827491 0.550051 0.183547 -0.585769 -0.370358 0.166339 -0.330917 +0.565224 -0.939577 -0.458682 0.9171 0.467549 -0.759357 -0.183062 -0.284542 +0.363913 -0.886314 -0.0413776 -0.351271 0.869881 -0.231896 -0.0871829 0.615437 +0.724921 0.342138 -0.891776 0.419366 -0.258134 -0.000122475 -0.329935 0.225855 +-0.0432628 -0.216738 0.848847 0.956695 0.363199 0.704409 -0.0599769 0.239999 +0.583261 0.411418 0.166635 -0.518895 0.240378 0.225784 -0.494503 -0.403743 +-0.150441 -0.474896 0.223493 0.588753 -0.737874 0.347776 -0.0871865 0.548901 +0.615756 0.829829 -0.939853 0.172147 -0.433539 -0.840024 -0.892388 -0.501087 +-0.203193 0.535319 -0.308958 0.587202 0.416361 -0.758153 -0.00744435 0.91033 +0.340677 -0.39525 -0.648123 -0.573656 0.610198 0.517564 0.154642 0.596717 +0.367509 0.610028 0.547478 0.925487 -0.637296 0.456543 0.65985 0.065585 +0.681616 0.260005 0.557239 0.923106 0.262336 -0.720056 0.164285 -0.620676 +-0.359834 -0.882962 -0.897786 0.429535 -0.702074 -0.766166 0.964263 -0.233261 +-0.237624 -0.790538 0.582138 -0.83352 -0.288147 -0.133838 -0.774226 -0.786283 +-0.748984 0.428917 0.231277 0.0558497 0.557488 0.154205 0.987467 -0.168732 +-0.348904 0.121741 0.887333 0.116473 0.335068 -0.607775 -0.0431827 0.970477 +-0.242826 -0.85206 0.794075 -0.587371 0.440513 -0.825878 0.695418 -0.755786 +-0.810785 -0.21277 -0.443549 0.435317 -0.278752 -0.532933 -0.793485 -0.699513 +0.122329 0.104611 -0.42504 0.606581 -0.444402 -0.435393 0.267759 -0.92598 +-0.274437 -0.920847 -0.972989 0.363913 0.83342 0.69625 -0.856296 -0.124536 +0.148277 -0.249354 0.692935 -0.133297 0.157911 -0.999667 -0.0986783 0.154615 +0.398736 0.531996 0.865322 -0.640611 -0.960076 0.131621 -0.0102551 0.392264 +0.0295367 -0.352277 0.0305908 -0.0388276 0.735082 0.0192332 0.643458 0.853862 +0.763109 0.93205 -0.576725 -0.184735 0.0222924 -0.960971 -0.630598 0.09047 +-0.602926 -0.465131 0.58007 -0.231048 0.32844 -0.408513 -0.0611884 -0.19347 +-0.565888 -0.406195 -0.50918 0.930646 0.116224 -0.284601 -0.939067 0.0921216 +0.381663 0.359147 -0.79389 0.915396 0.525897 0.553779 0.294566 -0.559796 +-0.955401 0.773148 -0.030864 0.47044 -0.485715 0.577058 0.501647 0.148485 +0.649985 0.187823 0.257612 0.234403 0.562823 -0.232794 0.466006 0.866358 +-0.967552 0.698507 0.973176 0.713228 -0.50343 -0.465678 0.565198 0.240488 +0.731744 0.860012 0.285087 -0.774288 -0.31705 0.157733 0.734589 -0.548765 +-0.575229 -0.389898 0.958725 0.580675 -0.549094 -0.881739 0.158066 0.504872 +0.248021 -0.711627 0.256419 0.982309 -0.819137 0.701679 -0.788117 -0.655522 +-0.977658 0.996174 0.222797 0.698182 -0.796879 -0.217397 -0.152265 0.00811935 +0.734854 -0.230751 -0.738565 -0.416549 0.148439 -0.734261 -0.0874713 0.197338 +0.431863 -0.617537 -0.369529 -0.152348 -0.547801 -0.920963 -0.0698932 0.115991 +0.863838 0.467625 -0.590202 0.731417 -0.111158 -0.0108276 -0.141117 0.388947 +-0.460448 -0.00358 -0.431949 0.448622 0.120444 0.281721 0.27916 -0.48844 +0.748822 0.72906 -0.814608 0.720227 -0.620837 -0.933228 0.592673 -0.715689 +-0.127509 -0.880016 0.23264 0.576413 -0.124992 0.581517 -0.119071 0.100669 +-0.754226 -0.130812 -0.83735 -0.467967 0.472236 0.277411 -0.604429 -0.495482 +0.468701 0.67957 -0.183306 -0.288385 0.536939 0.455635 -0.101417 0.480532 +0.131223 0.739641 -0.75708 0.521296 -0.74665 0.681778 -0.0432743 0.957592 +0.984619 -0.793028 -0.492116 -0.101056 -0.660434 0.716401 0.479151 0.711206 +-0.836175 0.751225 0.772158 -0.164186 -0.88874 0.507996 0.704264 0.600089 +0.0560691 -0.376625 -0.548074 0.299412 -0.934393 0.514745 0.499281 -0.904859 +-0.203049 -0.0873434 -0.917847 -0.78063 0.83491 0.464976 -0.579076 -0.659313 +-0.921206 0.566957 -0.314978 -0.765169 0.190357 -0.250332 -0.96709 -0.584996 +-0.905697 0.862693 -0.534835 -0.184377 0.797527 -0.0554951 0.484088 -0.35793 +0.00261279 0.478205 0.0564249 -0.543993 -0.40644 0.963891 0.699088 0.157682 +0.140747 0.236231 -0.240204 -0.897283 -0.725133 0.37085 0.375177 -0.690336 +-0.393322 0.628132 0.435174 0.309909 0.924293 -0.585999 -0.665178 -0.173297 +-0.741262 0.286904 0.466634 -0.11632 -0.332832 -0.298046 -0.129136 0.201002 +0.576918 -0.756116 -0.444226 0.219374 -0.644529 0.592023 -0.0436092 0.0751134 +-0.17499 0.0570784 -0.362637 -0.044791 0.137197 0.0987175 0.565834 0.843653 +0.234925 -0.852282 -0.420832 0.0505005 -0.693224 -0.355616 -0.286931 -0.786463 +0.225882 0.771209 -0.398083 -0.846683 0.86721 -0.242219 -0.784639 -0.0026907 +-0.293549 0.6105 -0.320505 -0.411405 0.724511 0.912 -0.00921325 -0.921633 +-0.52302 0.802085 -0.742938 -0.0560601 0.751242 -0.82785 0.432593 -0.969704 +-0.844137 0.394251 0.895536 -0.465464 0.00182795 0.411128 -0.890464 0.825167 +0.0722815 0.923014 -0.217788 0.731359 0.919544 -0.400096 -0.801688 0.679209 +-0.753574 -0.448565 -0.779133 -0.310703 0.681793 0.376105 -0.00229828 0.886417 +-0.0785138 -0.174144 0.364852 -0.724653 -0.00245858 -0.110276 -0.14491 0.901792 +0.363281 0.0423805 -0.446579 -0.414802 0.488114 0.635499 0.984603 0.754421 +-0.232388 -0.913675 -0.829001 0.483703 0.157112 -0.0105208 0.0124018 0.982927 +0.732588 -0.403144 0.0405142 0.666896 -0.983896 -0.88312 -0.598408 -0.102636 +0.235983 -0.194344 -0.899966 0.818913 -0.307926 0.605328 0.00938062 -0.979785 +0.00486521 -0.296775 -0.336182 -0.773916 -0.135781 -0.254591 -0.887617 -0.22463 +0.776907 -0.00507311 0.575003 0.0972172 0.0917146 0.299598 0.908971 0.371128 +0.154097 0.662223 -0.327984 0.809309 0.505141 -0.801119 -0.640887 -0.175704 +-0.621285 -0.93906 0.88343 -0.335682 -0.414518 -0.270482 -0.21631 0.938979 +-0.131579 0.914072 -0.764339 0.685784 0.948479 0.952585 -0.964771 -0.631935 +0.306776 -0.212961 -0.315976 0.614698 -0.0898369 0.780489 0.360809 0.416606 +-0.468014 0.404283 -0.96396 -0.189297 -0.791442 0.773885 0.587043 -0.0782596 +-0.480517 0.70835 -0.211486 0.732444 -0.276463 -0.75612 0.726469 -0.719253 +-0.622656 -0.699469 -0.946631 -0.530526 -0.0741792 0.961648 -0.727138 -0.679362 +0.474522 -0.510806 -0.284161 0.478636 0.241942 0.793324 0.864238 -0.0188507 +-0.861661 0.0884048 0.189929 0.755653 0.498479 -0.103323 -0.214646 0.876877 +0.540655 0.468286 0.761424 0.234187 0.311882 -0.949578 -0.301205 0.351382 +0.153818 0.516557 -0.833179 0.779226 0.833771 0.332097 0.682078 -0.621843 +0.054233 0.352558 -0.312155 0.823886 -0.967821 -0.442538 -0.940638 0.928046 +-0.287713 -0.320047 0.915229 -0.506667 0.836883 0.81554 0.523616 -0.477319 +-0.666288 -0.756207 -0.4391 -0.166991 -0.463488 -0.224589 -0.567453 -0.813841 +0.921816 0.233968 0.503249 -0.780836 0.661116 -0.878693 0.272364 0.653018 +0.0982718 0.955343 -0.00116737 0.0515896 -0.900309 0.162698 -0.405466 -0.622419 +0.274121 0.00532402 -0.278421 0.187935 0.737302 -0.288707 0.468913 0.0727112 +-0.645074 0.396039 0.918114 0.699024 -0.64576 -0.346968 0.968304 0.509498 +0.959975 0.275805 0.770663 0.264169 -0.546041 0.0894624 0.916164 -0.531846 +-0.220712 0.176343 -0.285256 0.428888 -0.806397 0.470583 -0.436048 0.352457 +0.827127 0.663989 0.197963 0.295046 -0.162647 -0.629688 0.0927522 0.528304 +-0.0948724 -0.449113 0.15219 -0.681607 0.439602 -0.556948 0.827255 0.30789 +0.633612 0.177003 0.197909 0.0607861 0.813352 -0.478578 0.849208 -0.0559195 +-0.621938 -0.938186 -0.344109 0.344632 -0.653958 -0.2633 -0.401879 -0.224379 +0.569173 -0.186415 -0.394973 -0.911254 -0.126121 0.722517 -0.336122 -0.606807 +0.336334 -0.737192 0.646788 0.590685 0.908107 -0.52367 0.407099 0.7393 +0.179463 0.948656 -0.959131 0.660897 0.973779 -0.819904 0.777307 0.707572 +0.805222 0.47696 0.792415 -0.153259 -0.34436 0.489184 0.178155 -0.676351 +-0.366101 -0.905987 0.370496 0.913466 -0.576158 0.0581566 -0.630027 0.624738 +0.240351 0.423925 -0.965376 -0.6155 0.167325 0.37747 0.6683 0.800608 +0.733028 -0.985473 -0.231205 0.147117 0.860921 0.797464 0.325777 -0.272022 +0.99405 -0.719682 -0.514499 -0.625007 -0.194546 0.149532 0.769961 -0.47702 +0.969417 -0.560176 0.136726 -0.084649 0.389179 0.916409 0.362402 -0.140272 +0.572255 0.967829 0.269192 0.278367 -0.512647 -0.80402 -0.424621 -0.495134 +0.74935 0.330136 0.37711 -0.219175 0.126386 0.643323 -0.0506832 -0.637607 +0.677819 0.147174 -0.883904 -0.674671 -0.702196 -0.609653 -0.360972 -0.411869 +0.0473199 0.885646 -0.447124 -0.310008 0.0355451 -0.661485 0.839227 0.301716 +-0.785281 0.731203 -0.962014 0.882407 0.762484 -0.0631677 0.0461328 0.556399 +0.836915 -0.880616 -0.20345 0.195834 -0.280629 -0.254905 0.541897 -0.944301 +-0.953188 0.637588 -0.999833 0.204481 0.493087 0.438599 -0.372864 0.646388 +-0.172526 0.402667 -0.0226788 0.132275 0.84847 -0.975069 0.400631 0.699629 +0.60715 -0.237398 0.851343 -0.469023 -0.246306 -0.126365 -0.22573 0.801854 +0.973127 -0.336768 0.426195 -0.82333 0.686216 -0.272869 -0.376275 -0.184089 +-0.834437 0.984273 -0.690948 0.536909 -0.969076 0.0569001 0.0944958 -0.847545 +0.350913 0.742704 -0.0888435 0.661019 -0.180019 -0.850345 -0.732034 0.287116 +0.42318 -0.0784443 0.76352 -0.287245 -0.0895427 0.107832 0.240182 -0.618388 +0.733383 -0.822303 0.779953 0.349853 -0.741592 0.23154 -0.164536 0.939154 +-0.529592 -0.0682568 -0.850412 0.236524 0.951305 0.835525 0.876292 0.434137 +-0.889841 -0.0897097 0.271357 -0.113305 0.541147 -0.65919 0.247945 -0.818463 +0.103092 -0.527044 -0.896553 0.594214 -0.937021 0.284395 0.297577 0.125347 +0.495554 -0.439143 -0.251043 0.0232232 0.865299 -0.109303 -0.171189 -0.875226 +0.57307 -0.578949 -0.608173 -0.684583 -0.107306 0.0709148 -0.0246238 -0.0624843 +-0.715761 -0.273036 -0.0475207 -0.574422 -0.70413 -0.840535 -0.823665 0.810428 +0.0481544 -0.712767 -0.756264 0.224144 -0.567741 0.944005 0.259615 -0.692591 +0.979149 0.0738153 -0.596483 0.0797648 0.0513163 -0.538501 -0.800301 0.706676 +-0.557846 -0.394867 0.63447 -0.100628 0.712387 0.00607913 0.515474 -0.208223 +0.425765 0.518023 0.770432 -0.926689 -0.327345 0.82541 0.425676 -0.334855 +-0.832356 0.754433 0.639186 -0.907847 -0.646159 -0.842478 -0.7382 -0.944428 +-0.527099 -0.544425 -0.0802107 -0.536255 -0.69648 -0.947971 -0.97821 -0.671188 +-0.385232 0.671455 0.676753 -0.388442 -0.770879 -0.455934 -0.532879 0.0420204 +-0.877769 -0.0561897 0.3066 0.977451 0.400127 0.473004 -0.664074 0.538949 +0.700269 0.477385 0.416165 0.283032 -0.736692 0.96748 0.818292 0.393618 +-0.591449 -0.66396 -0.552564 -0.248555 -0.0538592 0.0149328 -0.715989 -0.301757 +-0.961856 -0.480595 -0.224266 -0.600355 -0.313135 -0.373333 0.621861 0.119805 +-0.0289787 -0.867208 -0.352495 -0.670025 0.839881 0.416516 -0.584136 0.82359 +0.873906 -0.455942 0.744804 -0.701634 -0.240905 0.44596 0.264161 -0.894824 +0.650648 -0.210614 0.695181 0.230454 0.134154 -0.378442 0.68298 0.974372 +-0.616655 -0.654828 0.106464 -0.35322 -0.855384 0.868473 -0.197215 0.922002 +-0.713525 -0.0435003 -0.864588 0.656072 0.868593 0.173013 0.00212877 -0.775055 +0.911177 0.793915 -0.374071 0.495409 -0.771561 -0.163497 -0.880465 0.09295 +0.662883 0.901321 -0.682988 0.51054 0.905844 -0.645043 -0.378337 0.849723 +0.0722367 0.944185 -0.192626 0.234598 -0.73386 -0.920794 -0.355706 0.101956 +-0.743876 -0.37457 0.789534 -0.670556 -0.477737 -0.0691285 -0.602454 -0.991518 +-0.469718 -0.939276 -0.442335 -0.407247 -0.193899 0.378604 -0.376943 0.766453 +0.814289 -0.641182 0.415069 -0.407948 -0.693805 -0.118009 -0.836475 -0.116981 +-0.329729 -0.370857 -0.437681 0.100834 0.454515 -0.971288 0.171979 -0.705728 +-0.500349 -0.146904 -0.918759 -0.193116 0.0928924 -0.251882 -0.593915 0.51246 +-0.864867 -0.312605 -0.324324 -0.877312 0.816048 -0.69731 0.96412 0.654401 +0.652711 0.186415 0.873401 -0.835052 0.398853 -0.00100471 -0.795989 -0.40831 +0.122206 -0.673676 -0.455272 -0.977259 0.691944 -0.46109 0.6438 0.763297 +-0.254397 -0.978692 -0.930729 -0.491152 0.458397 0.58434 0.355154 0.975119 +0.221987 0.498127 -0.276902 -0.5598 -0.958984 -0.45776 0.846432 -0.723353 +-0.170915 0.730709 0.451446 -0.436452 -0.387114 0.680566 -0.107194 -0.536168 +0.375747 -0.0831178 0.965975 0.947039 0.452417 0.288673 0.852116 0.882378 +-0.299774 -0.00230704 0.707474 -0.0906821 0.06061 0.77999 0.355836 0.560197 +0.623911 0.51013 0.0369807 0.501648 -0.0966267 0.41681 -0.119264 0.114759 +-0.515069 0.52296 0.962316 -0.547326 -0.304037 0.0283051 -0.439579 -0.478872 +0.918665 0.580931 0.783695 -0.604643 0.896858 -0.688057 0.217374 -0.218612 +-0.692767 0.905495 0.850366 -0.612433 -0.573719 0.606877 0.918137 -0.645591 +0.0845819 -0.384892 0.898472 -0.591445 0.261452 0.880986 -0.170558 0.748134 +-0.845194 0.489728 -0.892401 -0.523616 0.608827 0.298731 -0.513934 -0.599622 +-0.441465 0.890703 -0.883215 0.847724 0.4496 -0.0929575 0.607727 -0.0115072 +-0.302087 0.0883766 -0.0491913 0.572896 -0.656623 0.200039 -0.99019 -0.622263 +-0.0611687 0.559847 -0.160513 0.914396 -0.789758 -0.0322675 0.243944 -0.873612 +0.383492 -0.227006 0.857748 -0.691379 -0.119268 0.906544 0.0676283 -0.941901 +0.362183 0.110534 0.118316 0.355861 0.538892 -0.499587 -0.476783 -0.80109 +-0.395513 0.313769 -0.854058 0.312002 -0.980265 0.589553 -0.231006 0.255777 +0.408053 0.417829 0.481733 -0.789267 0.91658 -0.771752 -0.61247 -0.842104 +-0.907614 0.915451 0.687083 0.89316 -0.181949 0.519122 0.195216 -0.897277 +0.109486 0.648038 -0.966609 -0.191132 -0.515898 -0.400711 -0.0251581 -0.694888 +0.507398 -0.436314 -0.918196 0.886837 -0.89631 -0.298954 0.133382 0.987254 +-0.847858 -0.890704 -0.485997 -0.243752 0.404901 0.056256 -0.0530081 -0.663969 +0.207087 0.022262 0.293799 0.738427 -0.659575 -0.37452 -0.222543 -0.660175 +-0.54719 0.5073 -0.203394 0.42828 0.270223 -0.268403 -0.576576 -0.196087 +-0.201262 0.865856 0.62896 0.166951 -0.797367 -0.394524 -0.223129 -0.708701 +-0.101959 -0.725559 0.798945 0.271839 0.0692502 -0.979058 -0.99892 0.0419966 +0.53545 0.922479 0.778318 -0.781238 0.398312 -0.577787 0.897057 -0.744146 +-0.62022 -0.373106 0.908867 -0.685094 -0.393671 -0.0789112 0.591853 0.681938 +0.616694 0.0851848 -0.781406 0.650371 -0.00992323 -0.725596 -0.725729 -0.212746 +-0.629517 -0.897357 0.530401 0.197561 -0.723204 0.5815 0.486909 0.791385 +0.332906 0.875343 -0.0229728 -0.26032 0.538418 -0.840019 -0.523949 0.923199 +0.454019 0.42438 -0.000983201 0.477238 -0.554344 0.0758181 -0.443851 0.645411 +0.704459 -0.16484 -0.283569 0.419795 0.515995 -0.707621 -0.127128 -0.00579609 +0.788275 0.123504 0.21663 0.573395 -0.115169 -0.266037 0.701736 0.196113 +0.356737 -0.529321 -0.616597 0.916584 0.437721 0.578161 -0.941679 0.0760077 +-0.360035 0.079058 0.246907 0.378028 0.0462992 -0.427991 -0.167935 0.784062 +-0.867621 0.228581 -0.0104227 -0.226125 -0.119777 0.778775 0.492626 0.928746 +-0.197559 -0.939388 0.868273 0.261652 -0.900631 -0.382494 -0.347938 0.537963 +-0.114143 0.123893 -0.106055 -0.416625 -0.104318 0.12035 0.509647 -0.428684 +0.978424 0.876989 0.838603 -0.0887538 0.334778 -0.66115 -0.335466 0.343176 +-0.820025 -0.908138 0.874542 0.314593 -0.818071 -0.257017 -0.836866 0.0887811 +0.656548 -0.291373 0.933373 0.256272 -0.898607 -0.399715 -0.503581 0.394048 +0.362886 -0.549097 -0.0870603 -0.0583177 -0.72757 0.925943 -0.133231 -0.547881 +-0.108116 0.469448 -0.145514 0.558468 0.799794 0.0360063 -0.703488 0.514873 +-0.256492 -0.113745 -0.45644 0.877031 -0.155099 0.675648 0.0225446 0.889124 +-0.997824 -0.275151 -0.0816768 -0.117119 -0.199962 0.793884 0.135836 -0.517578 +-0.85956 0.762486 -0.632285 0.0615244 -0.704787 0.880425 0.528767 -0.945482 +-0.0437808 -0.369173 0.113644 -0.0113774 -0.834023 0.500225 0.966642 -0.35483 +0.690285 -0.131156 -0.759254 0.853709 0.458314 -0.797575 -0.603178 0.439594 +0.0444817 0.901667 0.0658321 0.789708 -0.10006 -0.528711 0.955701 -0.980148 +0.306586 0.866876 -0.080387 0.245783 0.717017 -0.809001 0.484824 0.782623 +-0.632013 -0.677042 -0.014166 -0.995771 0.970022 0.883048 -0.133481 0.628743 +-0.688194 -0.17207 0.686293 -0.41734 0.496601 -0.074268 0.75973 -0.490093 +0.771534 0.0304465 0.296286 -0.27083 -0.836945 0.123148 0.902198 0.043503 +0.647878 0.224745 0.609021 0.193213 0.179697 -0.605319 0.79772 0.0173175 +0.075366 0.294109 0.417857 -0.326649 -0.565692 -0.474323 -0.224209 -0.666198 +0.133962 -0.427347 0.00741124 0.63284 -0.949592 -0.392416 -0.442946 -0.733096 +-0.561296 0.924184 0.626388 0.247312 -0.681852 -0.271314 -0.635791 0.857857 +0.477755 -0.998126 0.542267 -0.684616 0.657366 0.842474 -0.731047 0.880506 +0.0999426 -0.788276 0.907031 -0.66577 -0.34713 -0.813638 -0.924886 0.0799697 +0.000974058 0.879143 -0.917237 -0.0658394 0.536149 -0.897546 0.517589 0.878819 +-0.00976123 -0.234068 -0.195261 -0.865796 0.909201 0.694289 0.181825 -0.830926 +0.68441 0.462165 -0.502413 0.0498697 -0.0708356 -0.707278 -0.863705 0.926523 +0.0847125 -0.0993972 -0.93918 0.52679 0.899829 -0.154097 0.467359 -0.377423 +0.782743 0.212666 -0.882375 0.662286 0.0817885 0.466493 -0.947296 -0.561182 +0.984956 0.995736 -0.956063 -0.675235 -0.208349 -0.279891 -0.562258 0.0238953 +-0.973069 0.308437 -0.818147 0.46848 0.72665 -0.655727 -0.541774 0.671946 +0.187228 0.634296 -0.383014 -0.0904102 0.259885 0.57266 0.959802 -0.389448 +-0.684243 -0.11016 -0.953932 -0.0495816 -0.131607 0.728629 0.697163 -0.721516 +-0.181418 -0.382948 -0.722509 -0.695144 0.0787127 -0.245262 -0.498048 -0.739869 +0.830178 0.914575 -0.454904 0.745695 -0.239102 0.553015 0.294614 -0.175759 +0.984054 -0.0581829 0.446551 0.73675 0.868628 0.707773 0.717387 0.0422369 +-0.730983 0.194695 0.0743934 0.25252 -0.267732 -0.471383 0.297828 0.0322841 +0.655256 -0.560019 -0.641681 0.661432 -0.266061 0.052572 -0.955081 -0.282528 +-0.415285 0.226273 -0.90604 0.184445 -0.989665 -0.0912558 0.61949 -0.805614 +-0.500972 0.611884 0.8492 0.7098 -0.0588433 0.348041 -0.414189 -0.858704 +-0.648221 -0.759019 -0.811462 0.271084 0.737339 0.0153722 -0.592471 -0.826956 +-0.323454 0.611526 0.859839 0.716502 0.292863 -0.9588 -0.678535 0.938754 +0.154796 -0.115514 -0.739081 0.573985 -0.631539 0.589655 -0.14831 0.549913 +0.0906076 -0.651253 0.0283252 -0.946034 0.560444 -0.0612346 -0.199005 0.220301 +-0.0975565 -0.465731 -0.933866 0.111095 -0.465958 -0.828732 0.729906 -0.921229 +0.541046 0.152101 0.627026 0.919834 0.980592 0.278033 -0.357773 0.685608 +0.163656 -0.820748 0.219899 -0.101181 0.375515 -0.933299 0.515094 -0.8771 +0.603751 0.221247 0.446117 -0.989361 0.993051 0.0945616 -0.628518 0.819361 +-0.828535 -0.801524 -0.987235 0.928514 -0.0875665 0.861287 0.716365 -0.898612 +-0.170997 0.917167 -0.71157 0.475425 0.768015 -0.696612 0.204355 0.570293 +-0.827697 -0.28734 -0.0396248 -0.306508 -0.317003 -0.914925 -0.271988 -0.21109 +-0.841498 -0.252688 0.316755 -0.38155 -0.332195 0.289861 0.7727 -0.320135 +0.510168 0.169364 -0.498838 0.209328 0.514153 0.593351 -0.380651 0.311029 +-0.602362 0.678853 0.273814 -0.366988 0.909642 -0.953147 0.882081 0.884784 +0.521452 -0.495593 0.160721 0.176382 0.458051 -0.617109 -0.172667 0.145778 +0.817753 -0.144844 0.443388 0.514065 -0.635053 0.729437 -0.547013 0.235895 +0.0339596 0.0366261 0.349729 0.57932 0.181026 -0.785278 -0.61222 0.353273 +0.081437 0.0810859 -0.458834 0.342 -0.509965 -0.213191 -0.530875 0.748608 +-0.00403304 -0.730842 0.640446 -0.812574 -0.631621 -0.693543 -0.533125 0.240443 +0.736345 0.164469 -0.232611 -0.682714 0.0391465 0.215764 0.181629 -0.170527 +-0.316153 0.849775 -0.713543 -0.992168 0.226637 0.899808 -0.983037 0.615648 +0.593865 0.613709 0.964471 -0.0694818 -0.554318 -0.944957 0.404677 0.569198 +0.854136 -0.567775 0.624205 -0.0638568 0.227571 0.423304 0.804173 0.607347 +-0.57195 0.771232 0.949745 0.913996 0.033205 -0.674982 0.450981 -0.776398 +-0.00892122 0.28499 0.224971 0.83427 -0.677952 0.780563 -0.459848 -0.169539 +0.674748 0.550088 0.309164 0.650185 0.986459 0.479641 -0.759661 -0.070167 +0.131979 0.214995 0.57041 -0.426954 0.666856 -0.367388 -0.659574 0.729844 +-0.826653 -0.334649 -0.777172 -0.312917 -0.213826 -0.648087 0.361105 0.419723 +-0.60796 0.660562 0.877929 -0.317686 0.835597 0.770875 -0.669502 -0.354348 +-0.173571 -0.558255 0.288056 -0.0195096 0.216895 -0.697269 -0.936962 -0.110495 +-0.769401 0.205658 -0.422241 -0.418914 0.224285 0.724838 0.329769 -0.176675 +-0.608851 0.504321 0.401991 0.38628 -0.864586 -0.723579 0.528884 0.139734 +0.129013 0.832588 0.636092 0.379191 -0.47732 -0.774767 0.106628 -0.458607 +0.600563 -0.0212063 -0.6852 -0.986305 -0.894318 -0.499191 -0.0669232 0.65708 +-0.17459 -0.571405 0.45184 0.451606 -0.209903 -0.144011 0.0814855 0.394845 +0.801352 -0.184869 -0.700182 -0.58335 0.122312 0.483505 -0.938643 0.763043 +-0.694568 0.738964 0.144524 0.405695 0.0687771 0.852866 0.233823 -0.634871 +-0.441766 0.666858 0.917758 -0.0621066 0.898027 0.776859 -0.591587 0.538725 +-0.129871 0.86815 0.328025 -0.797892 -0.200945 -0.00775088 -0.787212 -0.0477195 +0.411625 -0.935478 0.97188 -0.4774 0.880431 -0.295131 -0.0397297 0.742689 +-0.468279 0.665199 -0.00262621 -0.306908 0.55242 -0.876837 -0.0766511 0.588279 +-0.384238 0.0945892 0.295707 0.210992 -0.239061 -0.0312253 0.963805 0.910599 +0.59308 -0.890281 0.360783 -0.441871 -0.18166 -0.842993 0.614948 0.372101 +-0.282672 0.484205 -0.390907 -0.641843 -0.900236 -0.419012 -0.127662 0.460704 +0.721775 0.869937 -0.550456 0.663482 -0.0202616 -0.493301 -0.404294 -0.255343 +-0.621552 -0.0546371 0.741689 -0.0772868 0.599692 0.960398 -0.099038 0.557427 +0.291379 0.851408 -0.688359 -0.376174 0.60419 -0.512245 -0.200478 0.441748 +0.30017 0.669317 0.0157743 0.864596 0.46077 -0.444435 -0.690974 -0.815909 +0.934688 -0.559636 -0.944507 0.573606 -0.210941 -0.0144233 -0.178447 -0.734446 +0.372047 0.115652 -0.184899 0.186208 0.350788 -0.707895 0.145772 0.0159335 +0.250639 0.683152 0.344556 -0.650937 0.994165 0.886205 -0.261378 -0.414116 +0.125493 -0.682846 0.8503 -0.795054 -0.547047 0.201266 0.951237 -0.570226 +-0.832089 -0.76452 -0.00559059 -0.0127649 -0.623252 0.695241 -0.0741697 -0.926311 +-0.870471 0.86697 -0.409793 0.185559 0.841404 0.775766 -0.661608 0.630784 +-0.0418847 0.510854 0.832215 0.574998 -0.993502 -0.659399 0.302716 -0.949432 +0.251255 -0.256833 0.17971 0.349283 0.823358 0.0684997 0.484002 0.0554339 +-0.0812522 0.530946 -0.0502746 -0.425602 0.402146 -0.149901 -0.00779549 0.496858 +0.308736 -0.105052 0.912841 0.839152 -0.305452 0.499928 0.95626 0.321928 +-0.3285 0.0754262 -0.978408 0.276809 0.890524 -0.191066 -0.37462 0.869924 +-0.843673 -0.317329 0.324965 0.899363 0.305543 -0.618414 -0.0500692 -0.305687 +0.776532 -0.565459 -0.694585 -0.461779 0.724174 0.724395 0.401296 0.937612 +0.184945 0.596819 -0.112383 -0.109576 -0.140985 -0.774741 -0.609435 0.0236652 +0.953433 -0.486151 0.655185 0.766429 -0.701394 -0.370928 -0.820288 -0.877196 +0.572462 0.709389 -0.316934 -0.81279 0.0864481 0.582348 0.482659 -0.223883 +0.515367 0.126074 -0.424637 -0.558138 0.176037 -0.735063 -0.448309 -0.74732 +-0.0720739 -0.0230992 -0.020745 0.243751 -0.0196581 -0.776428 0.372864 0.353649 +0.285757 0.60437 0.514482 0.200558 -0.0784612 0.491931 -0.391741 -0.219148 +-0.533693 0.928068 0.782882 0.29664 -0.189146 -0.4963 0.0980167 -0.959944 +0.608752 0.144835 -0.710443 0.601716 0.948639 -0.0447879 -0.518276 -0.00486581 +-0.254559 -0.329286 0.734333 0.130947 -0.00577986 -0.721763 -0.341906 -0.421621 +-0.855017 0.174414 -0.848329 0.214249 -0.58743 0.49036 -0.593059 0.659447 +0.526415 -0.727025 0.26561 0.669341 0.843729 0.0761335 0.169667 -0.116155 +-0.526465 -0.447057 -0.615264 0.489265 -0.974332 0.956576 0.835828 0.00231343 +0.613543 -0.325269 0.900706 -0.233333 0.137425 -0.0920977 0.654766 0.513183 +-0.491512 0.680511 -0.860143 0.000219877 0.158272 0.46976 -0.634852 0.550822 +-0.551847 -0.398146 0.1887 -0.631267 -0.644479 0.300039 -0.304721 0.542797 +-0.242835 -0.813084 -0.822062 0.898453 0.961803 -0.968091 -0.0286443 -0.383386 +0.921859 -0.268503 0.330602 -0.752452 -0.36633 0.706127 -0.853998 -0.163032 +0.356645 0.571826 -0.975479 0.616479 -0.701651 -0.44157 -0.281014 -0.1878 +-0.243982 -0.0327769 -0.0568341 -0.557591 -0.702275 -0.830818 -0.160744 -0.383181 +-0.606415 -0.993561 0.935008 0.237088 -0.626452 -0.279491 -0.0299587 0.096851 +-0.811084 0.697592 -0.358233 -0.624643 0.879112 0.98145 0.134991 -0.113781 +0.677045 0.173258 0.198926 -0.130985 0.692711 0.235918 -0.463143 -0.97181 +0.128611 -0.196469 -0.143549 -0.877259 -0.22387 0.911893 0.938579 -0.602357 +-0.558379 0.0831053 0.755255 -0.0633384 0.766946 -0.217916 0.803606 -0.69906 +0.378348 -0.577776 0.290786 0.72261 0.374513 -0.0515563 0.119249 -0.883982 +0.494366 -0.501015 0.221005 0.676703 -0.343459 0.239507 -0.43485 0.484132 +-0.0240771 -0.0695587 -0.767498 -0.426817 0.349456 0.815025 0.592253 0.0434642 +0.900908 -0.0224957 -0.227291 0.712525 -0.17387 0.423376 0.699817 0.0650314 +0.715058 0.981705 0.463282 -0.488915 0.225502 -0.579498 0.474955 0.0182237 +0.857074 -0.0382085 -0.560685 0.240137 0.713133 0.950877 0.839938 -0.222778 +-0.759526 -0.48741 -0.110886 0.589902 -0.178458 -0.533093 -0.336843 0.620609 +0.0139508 0.752568 -0.156613 0.316151 -0.0609667 -0.0964161 0.966551 -0.904765 +-0.460361 0.292631 0.780214 0.315363 0.707871 0.92645 -0.71585 0.321802 +-0.694523 0.944745 0.980457 0.706664 -0.327244 0.886355 0.877686 -0.999405 +-0.737367 -0.876693 0.594778 -0.23487 0.390236 -0.79106 0.712837 -0.382474 +-0.654429 -0.600899 -0.754773 -0.115959 -0.174276 -0.921064 -0.696421 -0.168972 +0.0708496 -0.735405 0.268682 0.566339 0.956091 -0.965215 -0.528977 -0.211907 +0.0595766 -0.271321 0.0586539 0.872684 -0.164932 -0.217101 -0.110703 -0.994614 +-0.100716 -0.21279 0.0343801 0.121225 -0.481159 -0.984074 0.423633 -0.524078 +0.677134 -0.121567 -0.719651 0.403784 -0.0439599 -0.0956062 -0.872936 -0.0305165 +0.603626 0.664413 -0.66371 0.677597 -0.635079 0.677114 0.274386 -0.565885 +-0.368999 0.395814 0.593433 0.071033 -0.517066 0.679989 -0.896466 -0.19466 +0.620615 -0.902769 -0.446372 0.71205 -0.0134724 0.792839 0.442742 0.705649 +0.448554 0.0907248 -0.875912 -0.78133 0.550768 0.401435 -0.2083 -0.548377 +-0.636633 -0.509317 -0.886577 0.836475 -0.244503 0.405991 0.435771 0.172506 +0.5809 0.193259 0.469274 -0.516108 0.116578 0.720497 0.492518 0.813402 +-0.764552 0.693023 0.813783 0.754981 0.505089 0.726952 0.72732 -0.579995 +0.609565 0.490126 0.354568 0.881088 -0.16121 -0.845049 -0.776224 -0.870536 +0.249554 0.737273 -0.873171 0.978158 0.972466 -0.191672 -0.759513 0.876725 +0.480007 0.890844 -0.29484 0.381001 -0.0617632 -0.397249 0.985152 0.245097 +0.588217 -0.748707 -0.723281 0.960338 0.332118 0.507824 -0.899531 -0.850595 +-0.528361 -0.0907407 -0.66284 0.194275 0.226352 0.939166 -0.796648 -0.560345 +-0.0018087 -0.488208 0.268087 -0.691234 -0.166023 0.857149 0.887926 -0.822825 +-0.255971 0.220112 -0.598075 0.0654637 -0.587158 -0.580129 -0.112089 -0.205686 +0.922303 0.926634 0.342239 -0.450665 0.960983 -0.0389203 0.0641601 0.166471 +0.478002 -0.208739 -0.505577 0.486465 -0.611075 0.835469 -0.388308 0.918577 +-0.945503 -0.489629 0.0602579 0.852291 0.898433 -0.523384 0.428025 -0.0249408 +0.448862 0.0653039 -0.833613 0.416429 -0.418658 -0.575603 0.283643 0.0631906 +0.472831 -0.233259 0.321724 -0.521398 -0.0559032 0.904495 0.0420803 -0.68707 +-0.418759 -0.243526 0.261977 -0.20153 0.363749 0.0561165 -0.901287 0.380951 +0.0356224 0.709165 0.687935 0.0385029 -0.360781 -0.0977945 -0.0523092 0.587724 +0.606512 0.606752 -0.948712 -0.0413094 -0.163546 -0.374833 -0.742109 -0.941404 +-0.591905 -0.527455 -0.364899 0.703861 -0.250776 0.13719 -0.547711 0.990142 +-0.188902 0.564909 0.927158 -0.906163 -0.417163 0.135594 -0.170626 0.874103 +0.0848013 0.132844 -0.735145 -0.093525 -0.421543 -0.397611 0.158808 -0.0642251 +0.985356 0.733467 -0.249225 -0.402127 0.153127 -0.194697 0.966564 -0.699326 +-0.92745 0.665489 -0.347215 0.693321 -0.957146 -0.653181 0.511458 -0.753823 +-0.713669 0.106806 0.116199 -0.42533 -0.423685 -0.615305 0.353406 0.455503 +0.913431 0.771845 0.325587 0.919554 -0.777534 -0.521801 -0.22661 -0.248731 +-0.987823 0.299457 0.651216 0.705278 -0.657446 0.861857 0.241607 0.781219 +0.666632 -0.940135 -0.465348 -0.997609 -0.97654 0.837899 0.583858 0.373042 +0.994313 -0.635854 -0.878991 -0.727423 0.782306 -0.892377 0.905096 0.074571 +0.554527 0.920449 -0.772302 -0.498784 0.957279 0.989656 -0.175314 -0.0813478 +0.930287 -0.50704 -0.239235 0.821616 -0.647472 -0.11052 0.247848 -0.5883 +-0.54487 -0.173971 -0.00350076 -0.259568 -0.845643 -0.968549 0.738096 0.262694 +0.523131 -0.923979 0.744681 0.813637 0.247499 -0.961381 -0.314356 -0.0229167 +-0.695943 0.421685 -0.198657 -0.511001 0.419557 -0.879891 0.531399 -0.659729 +-0.637058 -0.935509 0.718733 0.13937 -0.0334449 -0.192238 0.359693 0.626302 +0.552849 -0.919393 0.646026 0.437715 0.000286214 0.299565 0.44429 -0.341682 +0.464539 -0.527284 -0.44486 0.820841 0.930996 0.568054 0.386079 0.468224 +-0.294328 -0.808375 -0.529592 -0.106826 -0.321099 -0.984758 -0.115137 0.398672 +0.286542 0.295766 0.222531 -0.0306655 0.330739 0.906166 -0.413205 -0.761751 +-0.308349 0.428458 0.285334 0.999387 -0.876236 -0.41015 -0.572476 -0.581781 +0.0986278 -0.701512 -0.152086 0.554128 -0.729661 0.928477 0.248127 0.250132 +-0.301041 0.298569 0.336602 0.780929 0.389382 -0.968069 -0.645047 0.648065 +0.173302 -0.1454 0.24924 -0.968054 -0.267053 -0.706765 0.750725 0.768158 +-0.450792 -0.347903 0.687592 0.578171 -0.919444 0.426823 0.600826 0.455884 +0.125016 0.503402 0.168666 -0.267666 -0.27683 -0.886591 -0.771492 -0.948732 +0.876239 -0.355067 0.901132 0.871746 0.916059 -0.29615 -0.799335 -0.844642 +0.0149953 -0.608281 -0.500099 0.538077 0.378825 0.520402 0.575124 0.859247 +-0.610797 0.328011 -0.523517 -0.898361 0.00218621 -0.887533 0.0194196 -0.33779 +-0.616134 0.0660449 -0.31806 -0.30886 0.766834 -0.978261 -0.486737 -0.399618 +-0.0917382 0.277186 0.839681 -0.473801 -0.549823 -0.602682 -0.585298 0.293436 +-0.103361 -0.555463 -0.234813 0.432113 -0.468597 0.888812 -0.22229 -0.187223 +0.781542 0.0750056 -0.536047 -0.80232 -0.915122 0.428795 0.203037 -0.293338 +0.810786 -0.0354941 -0.675073 -0.645535 0.106937 0.354792 -0.872742 -0.412236 +-0.538382 -0.763935 -0.854645 -0.912881 -0.115333 -0.743536 -0.0770939 -0.465974 +0.741225 -0.43547 0.103791 0.763534 -0.513783 -0.870602 0.737691 -0.261385 +-0.0622958 0.204415 -0.915488 0.160516 -0.67954 0.190377 -0.50775 0.620587 +-0.119934 0.405527 -0.756127 -0.470831 0.609895 0.754775 -0.52016 0.342044 +0.440928 0.382402 -0.526856 -0.604671 -0.123643 0.0473221 0.681299 0.432775 +0.35705 -0.631322 0.335415 -0.160106 -0.511203 0.108416 -0.187068 -0.19273 +0.818762 0.955804 0.253726 0.243133 -0.866393 -0.713879 0.831281 0.48583 +-0.598078 -0.237423 -0.732799 -0.837698 -0.813628 -0.568913 0.975931 -0.414931 +-0.70244 0.670657 -0.627528 0.684003 0.879295 -0.780104 0.45747 0.717542 +0.742923 0.28711 0.427397 -0.804295 -0.935748 -0.63725 0.185404 0.195977 +0.523175 0.164912 -0.226626 0.473188 -0.903959 0.111465 0.962655 -0.649899 +0.811926 -0.150801 -0.148576 -0.314315 -0.378293 0.120209 -0.717872 0.475651 +0.527778 0.38538 0.294788 -0.284074 -0.43133 0.400691 0.6078 0.152683 +0.712556 0.5142 0.401574 -0.948874 0.628844 0.97335 -0.298696 -0.601937 +-0.991927 0.576505 0.407119 -0.467578 -0.189144 0.360232 0.517798 -0.435152 +-0.835849 0.981422 0.411036 0.965548 0.692699 -0.00998499 0.371297 -0.00133145 +-0.767232 0.09019 0.602586 0.912263 0.354785 -0.333148 0.653425 -0.649789 +-0.809157 0.21328 -0.835589 0.352537 0.358959 0.781091 0.0597904 0.466797 +-0.833931 0.470528 0.122331 -0.477634 -0.417411 0.421302 -0.191153 -0.132141 +0.45709 -0.959619 0.912188 -0.99528 -0.600182 -0.56223 -0.423687 -0.193773 +0.0216373 0.146337 0.905906 0.334817 -0.324455 -0.819952 0.347551 -0.277488 +-0.319623 0.209662 0.0298132 0.939739 -0.069773 0.888707 0.996402 -0.054304 +-0.821955 0.819168 -0.853819 0.571645 -0.834139 -0.861082 -0.873796 -0.237357 +0.236371 0.744487 0.741755 -0.471208 -0.78459 -0.443649 0.271483 -0.0455994 +0.851346 -0.208521 -0.131185 -0.796203 -0.255105 -0.698859 -0.612414 -0.816121 +-0.122906 -0.600864 -0.936747 -0.321419 -0.151019 -0.827735 0.136891 0.0296146 +0.735648 0.193249 -0.426487 -0.23817 -0.71209 0.423922 -0.347415 -0.378162 +0.778483 0.18169 -0.735153 0.984382 -0.306176 -0.99738 -0.107892 -0.795631 +-0.805644 0.112209 -0.298002 0.610045 0.0361954 -0.882893 0.282081 -0.989255 +-0.162802 0.138385 -0.476159 -0.34362 -0.0208122 0.547458 -0.397081 -0.597724 +0.884562 0.954509 0.571493 -0.00982217 0.869722 -0.729849 0.0274898 0.977989 +0.13102 0.704919 0.468061 -0.815591 0.402209 -0.521649 0.471525 -0.170029 +0.34004 0.298699 -0.269258 0.954558 -0.874734 0.193975 -0.827563 -0.400525 +0.157099 -0.292881 0.306565 -0.0130616 -0.158665 -0.149573 0.839071 -0.0153065 +0.45548 0.424047 -0.837859 0.741006 0.800953 0.938368 -0.691706 0.823846 +-0.601256 -0.357712 0.179111 0.175019 -0.385855 0.813766 0.717624 -0.232948 +-0.444183 0.955079 0.836534 -0.902232 -0.81723 -0.696455 0.540988 -0.59834 +-0.456177 0.51899 -0.226569 0.286242 0.0182484 -0.569708 0.0927978 0.351204 +0.42471 0.418102 0.544486 0.806483 -0.499258 -0.749449 -0.723003 -0.700478 +0.898082 0.908541 0.699173 -0.292711 0.297043 -0.990494 0.995252 0.851631 +0.594536 -0.732215 0.328213 0.133244 -0.528041 0.529194 0.787225 -0.309067 +-0.872484 -0.526274 -0.368968 0.620617 0.59385 -0.197271 -0.531257 0.160596 +-0.911691 0.992716 0.138414 0.439126 -0.856473 0.458083 -0.724759 -0.949265 +0.445634 0.941434 0.383013 0.119187 0.360761 0.224577 -0.406873 -0.14874 +-0.850024 0.406242 -0.987686 0.419716 0.833527 -0.810417 0.30594 -0.00712326 +-0.190325 0.903821 -0.160207 -0.185619 -0.546711 -0.368094 0.835662 -0.140476 +0.398994 -0.701222 -0.607329 0.172177 -0.970453 0.830484 -0.50775 0.782039 +-0.467062 -0.00650276 0.950333 0.176548 -0.210942 -0.558266 -0.0952733 -0.0479317 +0.100437 -0.393928 -0.847001 -0.829858 -0.441968 -0.0318336 -0.490883 0.848848 +-0.631143 -0.528653 0.631995 0.695675 -0.51902 -0.396995 -0.7112 -0.740444 +-0.26705 -0.555723 -0.914737 -0.545952 -0.280876 0.852172 -0.965218 -0.79901 +0.292693 0.340534 -0.403736 -0.0187143 -0.403433 -0.653135 -0.873989 -0.252567 +-0.321953 -0.00175426 -0.0982173 0.529045 -0.341277 -0.629041 -0.599386 0.661672 +0.910626 -0.537007 0.203493 -0.00364493 0.937403 -0.464218 0.533787 0.746203 +-0.437352 0.581493 0.320334 -0.147759 0.358775 0.289687 0.779021 -0.0177836 +-0.882005 0.455478 -0.218773 -0.372343 0.989746 0.41922 -0.198826 -0.661025 +0.87591 -0.712593 -0.304432 0.826156 -0.642761 -0.933846 -0.291615 -0.316973 +0.604414 0.88602 0.782185 0.470725 0.711684 -0.061264 0.525596 -0.200641 +0.248111 -0.608594 -0.851087 0.310291 -0.372669 0.95437 0.103978 0.91879 +-0.101975 0.704781 0.305341 0.560117 0.517339 -0.660969 0.858211 0.224984 +0.437192 -0.697103 -0.335884 -0.83529 0.0265226 -0.0506648 0.937622 0.312205 +0.266575 -0.439799 -0.429115 0.589414 0.540477 0.611981 -0.592582 0.780986 +0.298469 0.289732 -0.382572 -0.257052 0.293741 -0.291227 0.375649 0.297089 +0.206021 0.580981 0.886214 -0.0433701 0.751282 0.900529 -0.214723 0.772611 +-0.172119 -0.642249 0.0190451 -0.143636 0.253911 -0.203335 0.0485596 0.17505 +-0.843601 -0.513378 -0.291131 -0.040763 0.772936 0.911256 0.395748 0.408965 +0.287581 0.520859 -0.94936 -0.553394 -0.674212 -0.0944238 -0.685162 0.890514 +0.529198 -0.500136 -0.638627 0.424193 0.467577 -0.561498 0.39007 -0.925369 +0.3854 0.0436241 -0.880083 -0.420581 0.374951 -0.337581 -0.624367 0.443054 +0.132368 -0.878239 -0.574338 -0.274575 0.00250376 0.494147 0.173526 0.883387 +0.61281 0.174375 -0.622462 -0.0826392 -0.412087 0.0339736 0.441503 -0.591437 +0.68225 0.844676 -0.122762 -0.179799 -0.660691 -0.485314 -0.559874 -0.565694 +0.649297 -0.625909 0.759782 -0.870365 -0.372888 -0.267214 0.630475 0.540693 +-0.311311 0.804323 0.861152 0.86655 0.751852 -0.556321 0.374448 -0.869674 +0.671019 0.110837 -0.897409 -0.725767 -0.0471085 -0.221898 -0.339532 -0.454421 +0.195124 -0.869949 -0.279884 0.793026 0.296529 -0.815951 -0.58896 0.923199 +-0.709055 0.470964 0.835874 0.0816438 0.307834 -0.603159 -0.528858 -0.844923 +-0.721763 0.838714 -0.871618 -0.182521 -0.0532893 -0.0895496 -0.916913 -0.196797 +-0.311177 -0.963831 -0.81429 -0.783186 0.160698 -0.525185 -0.0447396 0.0220367 +-0.602121 -0.792035 -0.571744 0.186665 0.580744 0.928993 -0.542637 0.545755 +-0.878623 -0.289613 0.0795839 0.424377 0.695898 -0.236941 -0.500899 -0.900809 +-0.27813 0.325782 0.104022 -0.648674 0.385746 0.858498 -0.778167 0.640713 +-0.920418 -0.297414 0.951722 -0.502752 -0.500822 0.906769 0.475276 -0.120436 +0.0555665 -0.781139 -0.100632 -0.240305 0.350214 -0.236548 -0.856435 -0.536652 +0.82334 0.100009 0.635653 0.423638 -0.742337 -0.882165 -0.947683 -0.902723 +0.633898 0.696032 -0.840314 -0.758485 0.840569 0.297607 -0.0833301 0.0548925 +-0.946265 0.785038 0.0966939 -0.805429 0.869914 -0.642478 -0.131833 -0.149584 +0.723076 0.201727 0.722296 0.292561 0.546842 -0.991661 -0.240245 -0.576672 +-0.298388 -0.230718 -0.960268 0.525073 -0.0687227 0.426996 -0.84886 -0.352525 +0.875025 -0.136292 -0.0825568 -0.401207 -0.143353 0.897022 -0.586978 0.815228 +0.991454 0.693501 0.420691 -0.252937 -0.883019 -0.80479 -0.282766 0.132104 +0.50084 0.261296 -0.292088 0.171744 -0.975827 0.966368 -0.02166 -0.457527 +-0.867127 0.596761 0.909639 -0.0600934 -0.991778 -0.0624672 0.167349 0.652688 +-0.72436 0.474212 0.511686 0.47024 -0.325579 0.761913 -0.591578 -0.550693 +-0.87061 0.159126 -0.666693 0.51595 0.308097 -0.794654 -0.955128 -0.683876 +-0.0890715 -0.658886 0.259221 -0.487484 -0.598891 -0.597186 -0.518363 0.631827 +0.157736 -0.119963 0.56765 -0.630407 0.0792633 -0.40219 0.23451 0.275624 +-0.59349 0.874425 0.172097 0.308708 -0.0750917 -0.0565186 0.30194 0.430169 +0.751406 -0.472457 -0.754903 0.175155 -0.828196 -0.271119 0.441171 -0.822592 +-0.874723 -0.902089 0.779307 -0.549314 0.0049205 -0.814337 -0.569034 -0.388881 +-0.0496898 -0.438871 -0.164657 -0.133288 0.0280757 0.604918 0.434283 0.133385 +-0.44948 -0.417847 0.14142 0.890699 -0.630288 -0.505602 -0.0243172 0.467915 +-0.357174 0.165959 -0.620437 -0.925041 0.882595 -0.690612 -0.246178 -0.745699 +-0.661864 0.135524 0.893137 0.459743 0.81759 0.759988 0.919215 0.172754 +-0.979926 0.185689 0.365976 -0.408455 0.496844 0.828914 0.116831 -0.537032 +0.438368 0.32504 -0.0374737 0.466047 0.526118 0.173433 -0.417122 0.942193 +0.851893 0.778213 0.462288 0.993282 0.390593 -0.982581 0.295066 -0.321388 +0.614328 -0.807427 -0.562029 0.0568302 0.660809 -0.642214 -0.928537 -0.852186 +0.249547 0.175475 0.933737 -0.28369 0.229133 -0.147816 0.443864 -0.203126 +-0.9688 0.450049 0.20203 0.784042 -0.295913 -0.0312097 -0.457373 -0.770108 +0.533278 -0.373477 -0.379462 0.438474 0.200825 -0.0519506 -0.425382 0.505706 +0.355871 0.386051 0.743153 0.454655 0.744657 0.953363 -0.35094 -0.977463 +0.366017 -0.62106 0.905681 -0.947607 0.906391 0.797143 0.266247 0.528978 +-0.549458 -0.684604 0.0390662 -0.32929 -0.677886 -0.784919 -0.786702 -0.610963 +0.321161 -0.701703 -0.196161 0.675761 -0.395796 -0.276971 0.439669 -0.806306 +0.635941 0.640764 0.952784 -0.654622 -0.421039 -0.201594 -0.394228 -0.448705 +-0.3584 -0.341399 -0.0177754 -0.513204 -0.671774 0.961536 0.346114 -0.487067 +-0.60647 0.815841 0.703981 -0.821304 0.0687581 0.809137 -0.000827548 0.41432 +-0.522778 0.371105 0.116334 -0.59484 0.912115 -0.611119 -0.587923 0.269186 +0.267031 0.965863 0.697034 0.702101 0.781557 0.99254 -0.49076 -0.815809 +0.87365 -0.839719 -0.279633 -0.22592 0.813012 0.0435874 0.747437 0.86291 +-0.133208 0.796063 0.85827 0.770385 0.78936 -0.00305904 -0.714272 0.198962 +0.45192 0.938234 0.00246251 0.929763 -0.33744 0.51791 -0.855774 -0.424807 +-0.484192 0.694311 -0.107501 -0.783608 0.341487 0.126003 -0.630579 0.0317058 +-0.523726 -0.282109 0.350271 0.0073639 0.224109 -0.525064 0.819749 -0.126559 +0.349715 -0.818691 0.979166 0.335877 0.827511 0.448404 -0.178738 -0.998246 +-0.986554 0.843464 0.0494969 0.874156 0.644035 0.377021 -0.108501 0.927281 +-0.165659 0.217427 0.696053 -0.418239 0.722399 0.340772 -0.133902 0.0457679 +-0.322195 0.864682 0.296428 -0.455825 -0.161267 -0.94023 0.59127 -0.930389 +-0.607985 -0.666585 0.815694 0.0222016 -0.352874 -0.558811 -0.25617 0.216572 +-0.741508 -0.965064 -0.171648 0.795252 -0.806555 0.0642285 0.262478 0.1701 +0.0294231 -0.022182 -0.569997 -0.302406 0.406219 0.0899895 -0.669984 0.1125 +0.567577 -0.191888 -0.941946 -0.136822 0.06772 0.532028 0.754898 -0.387807 +-0.355954 -0.527357 -0.766761 0.823577 -0.23552 -0.692847 0.674303 0.279432 +0.414774 0.793844 -0.0556157 -0.123008 -0.0587105 0.260584 -0.322527 -0.287282 +0.219779 0.904389 -0.986921 0.431746 0.423658 -0.967195 0.499086 -0.996652 +-0.909703 0.539895 -0.630127 0.869508 0.122599 0.658514 0.425301 -0.860719 +-0.199796 0.661064 -0.105205 -0.66879 0.44428 0.360143 0.492939 -0.460633 +-0.591228 0.955616 -0.928397 -0.33865 -0.0100055 0.678019 0.859405 -0.884136 +0.257959 0.938057 0.733089 -0.508656 -0.327347 -0.226158 -0.788497 0.890343 +0.0917658 0.0452882 0.736755 -0.718124 0.702182 0.623431 -0.307694 0.707526 +-0.448969 -0.0976383 0.261963 -0.060521 -0.407749 0.0671337 0.722232 0.917006 +0.0939932 -0.493438 0.731232 -0.637236 -0.729693 -0.899482 -0.606368 -0.818409 +0.0924388 -0.724056 0.0637412 -0.858471 0.306947 -0.56491 -0.177466 -0.140946 +0.963139 0.657961 -0.550621 -0.532091 0.388969 -0.168796 0.200818 0.954923 +-0.927948 -0.144509 0.851824 0.282163 -0.6838 0.440361 0.793712 0.237032 +-0.761038 -0.344333 0.482373 0.272288 0.330062 -0.89687 -0.750929 -0.895303 +0.891593 0.17512 0.0368649 0.656235 -0.602655 -0.52724 -0.324825 -0.218512 +-0.178757 0.106361 -0.786419 0.385929 0.482041 0.418832 -0.0239656 -0.699096 +0.476948 0.386084 -0.491765 0.218255 0.195142 -0.229045 -0.201467 -0.716236 +-0.245364 -0.178718 0.0261941 0.79052 0.79242 -0.992083 -0.692832 0.41532 +-0.0163223 0.52435 0.557524 0.823774 0.955016 0.0161157 -0.981033 0.143466 +-0.32114 -0.926067 -0.970764 0.534577 0.454701 0.926327 0.24691 -0.0345573 +0.746455 0.290984 0.820033 -0.975666 0.28493 -0.68386 -0.0184387 0.349946 +0.121368 0.824574 0.909234 0.972388 -0.875856 0.931241 -0.190719 0.419245 +0.957067 0.750502 -0.189851 -0.403203 0.790796 0.310838 0.57588 -0.832113 +-0.99678 -0.177133 0.0847001 0.149754 -0.223304 0.0277731 -0.746891 0.124499 +0.328892 -0.558507 0.952343 0.63907 -0.160313 0.359808 -0.0896632 -0.920504 +-0.703425 0.599164 0.454539 0.280253 0.343914 0.268915 0.121279 0.0706275 +0.0819806 -0.0260664 -0.452012 0.534075 0.665468 -0.777891 0.473708 0.82371 +-0.433046 0.034782 0.522489 0.121652 -0.393345 0.677849 0.845486 -0.523482 +0.0787604 0.748632 -0.224027 -0.739522 -0.411641 0.389571 -0.999132 -0.795857 +-0.0229049 0.691355 -0.165205 -0.592761 -0.325611 -0.720616 -0.102312 -0.330572 +0.865303 0.156614 -0.79352 0.255691 0.0807876 -0.626587 0.793079 0.0290817 +-0.945279 -0.0846664 -0.374888 -0.667183 -0.504733 0.235353 -0.194729 0.451198 +-0.624138 -0.522172 0.485696 -0.188533 -0.861529 0.71042 -0.107355 0.129584 +-0.032633 0.103963 -0.973725 0.6503 0.598923 0.543365 -0.222287 0.200471 +0.50997 0.287462 0.546289 0.092789 0.247406 0.306928 0.907567 -0.0817465 +-0.602545 0.429731 -0.160718 0.409995 0.0603658 0.699852 0.944123 -0.279073 +-0.617229 0.94587 -0.293599 0.249853 0.185483 -0.15985 0.376199 0.478009 +-0.913821 0.902843 -0.0319189 -0.163233 0.06097 0.303983 0.388982 0.825583 +0.803066 0.0602229 0.607606 0.264056 -0.0273412 0.368949 -0.448388 0.0894237 +0.474698 -0.0853695 -0.276576 0.12158 -0.466526 -0.106598 0.837411 -0.962005 +0.963205 -0.36027 -0.46135 -0.450732 -0.688112 0.909647 -0.485183 -0.726725 +-0.98335 -0.483217 0.440138 -0.882965 0.591247 0.705897 0.51467 0.311796 +0.932707 -0.482583 0.50795 0.905327 -0.136499 -0.159968 0.572432 -0.833733 +0.308466 -0.918981 0.736131 -0.241078 0.566423 -0.820824 0.0762153 0.998902 +-0.574397 -0.896001 -0.0140756 -0.787536 -0.608351 -0.146387 -0.714798 0.937753 +-0.12184 0.95313 -0.86626 0.164525 -0.780993 -0.286156 0.223559 0.186948 +-0.922137 0.14814 0.484396 -0.208987 -0.999587 0.378318 -0.326022 0.613935 +0.084696 -0.884513 -0.572624 0.0844671 -0.577091 0.275735 0.825845 -0.0805973 +0.925467 -0.330806 -0.466913 0.611224 0.453998 -0.353312 -0.431593 -0.293111 +0.560446 0.913154 0.0906239 -0.663937 -0.347225 -0.329733 -0.0634993 0.460402 +-0.383723 0.114834 -0.905004 -0.691624 0.835869 0.344849 -0.939217 0.537941 +-0.721011 -0.348403 -0.00576813 -0.989891 0.0723988 -0.567613 -0.779642 -0.78354 +0.385344 -0.455507 -0.0233818 0.788528 0.109993 -0.213506 0.456872 -0.834098 +-0.48394 -0.98133 -0.919482 0.17167 -0.371616 0.148954 -0.383733 0.758057 +-0.375511 -0.558951 -0.502408 0.891249 -0.353771 0.560189 -0.16795 -0.543868 +-0.37115 -0.573654 0.510089 0.906864 0.433786 0.510185 0.971383 -0.101245 +-0.234985 -0.683994 0.629377 0.714775 -0.25377 0.821737 0.147973 -0.902029 +0.622774 0.109474 -0.925719 0.954841 -0.838217 -0.838764 0.794163 -0.359638 +-0.969295 -0.70625 -0.169544 -0.944458 -0.715546 0.86016 0.708005 -0.945322 +0.46898 -0.814756 -0.0936694 -0.625662 0.290876 -0.292345 0.804004 -0.756511 +-0.942462 0.461271 -0.133129 0.187726 0.0946201 0.696192 0.359844 -0.844139 +0.563431 0.314016 -0.618401 -0.349053 -0.779491 -0.229991 -0.23926 -0.866743 +0.655119 -0.297929 0.882511 -0.970511 0.438275 0.927748 0.818598 -0.695924 +0.27305 0.391222 -0.55341 0.874844 -0.69446 0.0146682 -0.818413 0.331227 +-0.629138 -0.77631 -0.409139 -0.972164 -0.482111 0.0919363 -0.048589 0.616701 +0.603334 0.440657 -0.708531 0.148558 0.741351 0.171211 -0.913832 0.225193 +-0.290597 0.985929 -0.18809 0.973706 -0.404376 0.997051 -0.14134 0.679776 +0.87582 -0.122859 -0.716285 -0.412934 0.71662 -0.164979 -0.750002 -0.219348 +-0.342228 0.515422 0.356727 0.716068 0.255808 -0.981862 0.299258 0.0274295 +-0.309099 0.407465 -0.940287 -0.642382 0.153391 0.331409 0.506176 0.707616 +-0.974934 0.919957 -0.14204 -0.100708 0.286887 -0.312046 0.323156 -0.146763 +0.665122 0.930822 0.78843 0.0628672 -0.176518 0.810625 0.0252852 -0.838717 +-0.630099 -0.31493 -0.435586 0.778668 -0.161566 0.108783 -0.233434 -0.590801 +0.786437 0.677349 0.905807 0.825616 0.97916 0.884624 0.498115 0.42734 +-0.295858 0.593155 -0.259452 -0.941386 0.492692 -0.445883 0.404013 -0.419882 +-0.795611 0.863705 0.0558309 -0.614871 -0.585717 -0.582341 0.116653 -0.671626 +-0.524893 0.338942 0.334323 -0.755656 0.448694 -0.53751 0.890865 0.728529 +-0.647052 -0.743385 0.710565 0.780498 -0.413726 0.912974 0.750723 0.361914 +0.274769 -0.810813 -0.22343 0.838632 0.603144 -0.780761 -0.39045 -0.74793 +-0.225211 0.115451 -0.0529903 -0.85687 -0.970864 0.711897 -0.163225 0.742498 +-0.698407 0.871296 -0.432346 0.297334 0.578215 0.0895254 0.713119 -0.98793 +-0.380986 -0.125795 -0.435093 -0.354766 0.718332 0.343689 -0.670844 0.373268 +-0.979723 -0.937316 0.311361 -0.291178 0.516959 0.977806 -0.815439 -0.674165 +-0.0323153 -0.710142 -0.743586 0.0624365 -0.701897 -0.190656 0.226054 0.292736 +-0.493086 0.0295618 -0.205672 0.65815 0.129321 0.378478 0.50234 -0.216347 +0.584741 0.84211 0.167401 0.607226 -0.714133 -0.217052 0.412324 0.729219 +0.118591 -0.39914 0.0803751 0.6693 0.566324 0.721258 0.262219 -0.616252 +-0.997376 -0.604019 0.0656538 0.599502 0.00110348 -0.637884 -0.779426 -0.15533 +0.902245 -0.83549 -0.0556138 0.06506 0.651397 0.970983 0.750116 -0.313178 +0.123484 0.0431771 0.060113 0.47014 -0.276801 0.324975 0.0506168 -0.492554 +0.724213 0.68835 0.331324 -0.702835 -0.178587 -0.228648 -0.0399587 0.128594 +-0.0320557 -0.554456 0.665615 -0.089894 0.304825 -0.330259 0.14179 -0.812656 +0.626568 -0.644126 0.937721 -0.882729 0.704299 0.610393 -0.0757684 0.924555 +-0.625918 -0.948106 0.0951738 -0.993843 -0.502306 -0.489336 -0.282158 -0.318153 +-0.207382 0.044949 0.0964022 -0.484303 -0.365384 -0.555911 -0.90306 0.360545 +-0.230588 -0.207239 -0.347432 -0.0525925 0.24211 0.420735 -0.496557 0.612099 +-0.110829 0.428517 0.896458 0.0240659 -0.0684408 0.158986 0.992357 0.789784 +-0.594865 0.180221 -0.509125 -0.784086 -0.603065 0.902279 -0.13072 -0.0459181 +0.972982 -0.128882 -0.191688 -0.271181 0.467487 0.834183 -0.226382 0.124324 +0.226513 -0.713675 -0.133761 0.390153 0.266047 -0.688886 -0.65987 0.0485102 +0.856414 -0.0471387 -0.835046 0.744284 -0.484911 -0.937073 -0.916864 -0.3921 +0.173184 0.481602 -0.582463 0.0924304 0.944067 -0.955617 -0.579323 0.282798 +0.0778271 0.273025 -0.21682 -0.910587 0.249759 -0.903923 0.8988 -0.0383336 +0.278796 -0.383595 -0.337323 -0.0574443 0.32618 -0.518353 0.586899 0.882512 +-0.145354 -0.365954 -0.350825 -0.453288 -0.340702 -0.366973 0.840828 -0.903173 +-0.826925 -0.524238 -0.725683 -0.363874 0.882786 -0.893936 0.834338 -0.845758 +0.981676 0.38459 0.403841 -0.852946 0.831358 0.134174 0.600342 0.319108 +-0.965339 -0.529092 -0.110751 -0.0104939 0.879482 -0.649905 -0.575851 0.43798 +-0.562991 0.0273841 -0.296924 0.374767 -0.0715699 0.59238 -0.257965 0.467256 +-0.163342 0.675786 0.0404688 0.772686 -0.800894 -0.0960582 0.792491 -0.277204 +-0.838616 -0.704292 -0.606351 0.512386 -0.0721938 -0.373044 -0.482231 0.381387 +-0.300435 -0.811809 0.0690514 0.793722 -0.850233 -0.571292 -0.676329 -0.236226 +-0.916339 0.461819 -0.7495 -0.130893 -0.299153 0.856143 0.200783 -0.027939 +-0.782393 -0.379879 0.26394 -0.0156787 0.553081 -0.0766997 0.0507427 -0.923302 +0.860352 -0.170888 0.968314 -0.181919 0.546342 -0.973947 0.312326 -0.799889 +0.81222 -0.451001 -0.68649 0.142295 0.170818 0.760639 -0.681591 0.385237 +0.217836 0.307764 0.314993 0.232972 -0.59703 -0.478095 -0.980271 -0.135897 +0.553113 0.547028 0.957202 0.798325 0.627305 0.0203087 -0.0433017 -0.553673 +-0.0016148 0.951573 -0.418186 -0.496682 -0.239602 0.73593 -0.473037 0.621046 +0.433566 -0.580368 -0.0956536 0.210872 -0.740542 -0.332272 0.850168 -0.0238131 +-0.205609 0.153521 -0.402918 -0.713328 -0.265156 -0.773804 0.725339 0.470349 +0.558929 0.412309 0.730158 -0.0374842 0.479966 0.898242 0.440661 0.497333 +0.629008 0.437205 -0.361182 -0.663844 0.157557 -0.199986 0.113008 -0.41816 +-0.0826236 -0.978743 0.815084 0.39091 -0.338941 0.880036 -0.13348 -0.299471 +0.584767 0.365066 -0.636932 -0.157548 0.542492 -0.193568 -0.0480755 0.30407 +0.361588 0.229671 0.987737 0.157145 -0.472845 -0.3861 -0.858493 -0.471023 +0.724432 0.402472 0.54433 0.687866 -0.103772 0.314791 0.558369 0.870504 +0.901182 -0.117562 -0.687705 -0.434755 -0.532181 -0.407797 -0.975511 0.280664 +-0.1908 -0.588684 -0.937916 0.975736 0.795355 0.50423 -0.708375 0.879924 +0.280243 -0.819291 -0.280556 -0.266857 0.941041 0.275321 0.87149 0.349788 +-0.377843 -0.75705 0.958412 0.88434 0.627061 -0.282291 -0.270561 0.727935 +-0.573253 0.999137 -0.137561 0.787423 -0.277337 0.603983 0.709329 0.71357 +-0.786407 -0.541805 -0.41953 0.0447377 0.0205872 0.602401 0.562479 -0.0216093 +-0.0703607 -0.160516 0.541279 0.130353 0.541861 -0.0802796 -0.144014 0.751182 +0.601665 0.138491 -0.680005 -0.267557 0.381164 0.955646 0.264988 -0.876559 +-0.827176 -0.616917 0.396616 0.382655 -0.10695 -0.506198 -0.741015 -0.473331 +0.88219 -0.745805 0.965667 0.962275 0.950847 -0.407496 0.617847 0.836703 +-0.0415932 0.439522 -0.07451 -0.470155 0.456856 0.875438 0.610125 0.604677 +0.270323 0.320618 -0.0947187 -0.365721 0.760394 -0.472468 0.896321 0.224609 +-0.158006 -0.14951 0.717 0.655573 -0.454379 0.895668 -0.657176 0.248163 +0.138563 -0.0180113 0.191786 0.900287 -0.623111 0.0718001 -0.419325 -0.928102 +0.721988 0.450695 0.054242 0.675887 -0.046098 -0.0776113 0.649494 -0.541712 +-0.973227 0.811297 0.671414 0.254526 0.658319 0.57909 0.600238 -0.675435 +-0.011479 0.86599 0.366494 0.225368 0.140601 -0.000124131 0.144893 0.225741 +-0.0838095 0.387244 -0.689906 0.586899 0.246606 0.218082 -0.774383 -0.177423 +-0.725591 0.175092 0.102378 0.965872 -0.587109 0.543606 -0.0260682 -0.51752 +0.197836 -0.702652 0.520644 0.819619 -0.678164 0.947498 -0.277995 0.107026 +0.776415 -0.875923 0.394003 -0.354281 0.70118 -0.695215 -0.256926 0.0904048 +0.481263 0.146732 -0.425491 0.537589 0.355505 -0.688914 0.989679 -0.663574 +0.915144 0.721881 -0.799716 -0.337425 0.1607 0.381086 -0.954813 -0.90889 +0.861045 0.809379 0.0106808 0.188282 -0.92879 -0.139722 0.235875 0.912959 +0.317596 0.0962255 -0.52784 0.329931 0.619167 -0.369354 0.57385 0.76421 +-0.788329 -0.375513 -0.635246 0.448801 0.614954 -0.0946107 0.431591 -0.475603 +-0.247791 -0.387756 0.501257 0.161509 -0.416007 0.965461 -0.490639 0.951325 +0.351507 -0.5273 0.75251 -0.265674 0.715974 0.228488 0.55418 -0.878948 +-0.231026 0.968163 -0.661585 -0.999387 0.540818 -0.0698159 0.521574 -0.00717663 +0.960331 -0.484705 -0.341116 -0.613373 0.937889 -0.318486 -0.726292 0.527913 +-0.119951 0.300227 -0.44361 -0.56629 0.334748 -0.722119 0.797099 -0.14651 +-0.204771 -0.143151 0.805168 -0.886228 0.0897569 0.547813 -0.237215 0.124713 +0.405914 0.636952 -0.842242 -0.0302225 0.839292 -0.75642 -0.259522 0.396902 +0.38835 0.433439 0.397809 -0.568495 -0.23167 -0.0718805 0.193332 0.0820198 +-0.469228 -0.608177 0.260098 -0.651517 0.367638 -0.650733 0.523926 0.347477 +0.191905 -0.0680753 -0.364185 0.137717 -0.440258 0.312023 -0.725152 0.180157 +-0.103302 0.896225 0.416362 -0.519851 0.774741 0.160886 0.708706 0.721492 +-0.466633 -0.0893367 0.826321 -0.870924 0.761161 0.513968 0.329094 -0.386737 +0.907783 0.365883 -0.366647 0.00331088 0.804544 0.20207 -0.633814 -0.555848 +-0.235618 -0.0339699 -0.0185517 0.360198 0.551649 0.964854 -0.668951 -0.648484 +0.939624 0.34939 -0.744987 0.583514 0.825694 0.369501 -0.455276 -0.478728 +0.867588 0.0923404 0.473362 -0.391421 -0.625188 0.405277 -0.663635 0.23118 +0.98559 0.452073 0.397196 -0.161284 0.824009 0.0686514 -0.243402 -0.458581 +-0.64569 0.941453 -0.71447 -0.113639 -0.492668 0.791628 -0.181362 -0.478111 +-0.0637608 -0.468836 -0.0765535 -0.171667 0.517801 -0.698574 0.962859 -0.893231 +0.451662 0.053278 -0.892541 0.779971 0.526298 -0.187434 0.479513 0.769857 +0.464148 0.910832 0.754622 0.56699 -0.512335 -0.443822 -0.959895 0.00641124 +-0.612024 -0.974763 0.0887326 0.723811 0.250143 -0.678394 0.93651 0.687853 +-0.0962185 0.453788 -0.894264 -0.4403 -0.503982 -0.362084 0.898738 -0.921332 +-0.795003 -0.490026 -0.10242 -0.768762 -0.360123 0.20174 0.227832 0.779859 +-0.869027 -0.166382 -0.837505 0.2924 -0.996497 0.833509 -0.71889 -0.704882 +-0.618075 -0.0733225 -0.972386 0.383851 -0.832165 -0.0710698 0.0938433 -0.0574702 +0.105864 0.95241 -0.468853 0.977143 0.098734 0.621518 0.0742271 -0.225418 +0.758995 0.084791 0.522413 -0.535609 0.738139 -0.56859 -0.880642 -0.833513 +0.575114 0.104168 0.384118 0.948417 -0.881103 -0.720524 -0.453562 -0.60447 +0.453197 -0.484345 -0.498019 0.0352992 -0.506009 -0.813873 -0.866188 0.123789 +0.458891 -0.997015 -0.873448 0.384451 -0.864472 -0.981493 0.886432 -0.821239 +-0.174388 0.731022 0.564594 0.0486276 0.578099 -0.0255768 0.220408 -0.353769 +-0.250461 0.310739 0.54473 -0.0545715 0.806352 -0.10376 0.134289 0.42747 +-0.633519 0.0503947 0.899446 -0.5244 0.877891 -0.540384 -0.237581 -0.236054 +0.51793 -0.402829 -0.74295 -0.50237 0.486262 -0.522252 0.17971 -0.0238329 +0.918786 -0.51196 -0.314827 -0.400451 -0.220271 0.28387 0.309916 -0.139415 +-0.454818 -0.845796 -0.434315 -0.304371 -0.664384 0.15454 -0.198632 -0.0817048 +0.321019 -0.69302 0.0532293 -0.131409 0.53806 -0.624413 0.0382679 -0.71237 +-0.318035 0.46381 0.557568 0.63931 0.909057 0.123634 0.499409 -0.761453 +0.0792408 -0.343298 0.274612 -0.762256 -0.527155 -0.491915 0.258529 -0.485005 +0.831757 0.654417 0.76289 -0.98712 0.540921 -0.358934 0.0907502 -0.795737 +0.438672 0.545536 -0.40142 -0.95785 0.860667 0.31558 0.316762 0.765004 +0.536493 0.973878 -0.480902 -0.227973 0.693516 0.989617 -0.378439 0.265221 +-0.644759 0.301819 -0.644533 0.601933 -0.641316 0.181153 -0.86458 -0.135988 +-0.542538 -0.848576 0.692349 0.079111 0.270207 0.283374 0.0606738 -0.29633 +-0.756621 0.897779 -0.269115 0.164742 0.501106 -0.244866 -0.32088 -0.914074 +-0.0498213 -0.0570648 0.263523 0.908372 0.564612 -0.705888 -0.86702 0.82604 +0.524106 -0.605483 0.537845 0.810716 0.542551 -0.708089 -0.30362 -0.919583 +0.0033156 0.236522 -0.274942 0.907076 0.991233 -0.488817 -0.927317 0.604774 +0.753357 0.437084 -0.321181 -0.330611 -0.88642 -0.500423 0.435738 0.883124 +0.726302 0.0567875 0.619763 -0.0224197 -0.56383 0.792938 0.517057 -0.774178 +-0.0755045 0.52396 -0.316418 -0.527674 0.61262 0.0490231 0.820156 -0.461446 +0.921259 0.74196 0.701823 -0.368448 0.0144466 0.0792542 -0.7888 -0.925565 +0.976048 -0.350421 -0.454161 -0.426072 0.720985 0.208408 0.0451211 -0.866218 +0.274607 0.681934 -0.996008 0.746247 -0.807708 0.408563 -0.923163 -0.37162 +-0.756702 0.875637 0.356668 0.567545 -0.699811 -0.882049 -0.854333 0.362533 +-0.512753 0.774731 -0.67637 -0.745905 -0.774444 0.124573 -0.570468 0.243402 +-0.0898509 -0.22061 -0.458399 -0.0416534 -0.0878776 0.142848 -0.477647 0.756049 +0.000349967 0.480484 -0.232482 0.732368 0.429491 0.470299 0.768061 0.741892 +0.890118 0.0577898 0.152233 0.417615 -0.941858 0.319885 -0.190016 0.71424 +-0.978877 -0.382177 0.944849 0.100975 -0.15484 -0.802377 -0.601933 -0.54424 +-0.228456 0.171383 0.232305 0.103878 -0.0456658 0.163971 0.771114 0.0675747 +0.0165751 0.62803 0.0934436 -0.327452 -0.670034 -0.777859 -0.397378 -0.543197 +0.504346 0.329616 0.687922 -0.925564 0.503927 -0.344951 0.238153 -0.575422 +-0.225979 -0.488465 -0.21703 0.375165 -0.463176 -0.607798 0.378912 0.736663 +-0.140162 -0.114695 -0.463715 -0.359241 -0.0816379 -0.838987 -0.298994 0.661456 +-0.923774 0.996942 0.00563778 0.492051 -0.809241 -0.220833 0.496805 -0.913763 +0.140333 -0.0130841 -0.854971 -0.760718 0.0336346 0.0254133 -0.170119 -0.638502 +0.361199 0.241009 0.856447 0.165383 0.0618192 -0.319219 -0.483658 -0.606498 +-0.124282 0.909326 0.388856 -0.0583138 -0.574562 -0.457529 0.824842 -0.623682 +0.38279 -0.935983 0.825104 0.382438 0.6676 0.801026 0.587021 -0.872922 +0.229531 -0.331683 -0.343916 0.835561 0.10239 -0.429101 0.967624 0.821956 +-0.135739 -0.353168 -0.0449242 0.188729 0.536394 0.992154 0.0872412 0.938832 +-0.994855 0.374559 0.0957442 -0.614064 -0.221976 0.973031 -0.446563 -0.419641 +-0.302373 -0.299059 -0.872026 -0.711552 0.0355826 -0.651896 -0.738868 -0.854359 +0.377706 -0.255825 -0.737457 -0.771 -0.333372 0.151784 -0.524131 -0.482389 +-0.111203 -0.470208 -0.781669 0.638474 -0.681036 -0.219878 0.324534 -0.497162 +0.861592 0.459932 -0.954288 0.341893 0.949 0.324577 -0.613932 0.773538 +-0.33621 0.348251 0.418902 0.139857 -0.666187 0.159527 0.736503 0.152294 +-0.466221 0.397112 -0.606685 -0.771545 -0.302752 0.415823 0.64901 0.0614916 +0.581623 0.774078 0.708457 0.962784 -0.711574 0.940553 0.580483 0.540611 +-0.28569 -0.412809 -0.00786611 -0.54289 -0.898176 0.380764 -0.688689 0.504092 +-0.811939 -0.274285 0.815974 0.481681 -0.32469 -0.934366 0.839547 -0.169832 +0.209099 -0.571355 -0.0470802 0.218184 -0.517936 -0.821072 -0.123108 -0.389733 +0.515922 -0.0245071 0.429742 0.826203 -0.283113 -0.315026 0.598175 -0.118725 +0.00876872 -0.837834 -0.0497919 -0.0266431 -0.984383 -0.179382 0.676681 0.241681 +-0.294095 0.408535 -0.856501 0.385449 0.264363 0.580878 0.369414 -0.426799 +-0.835825 -0.544945 -0.734543 0.780376 0.298703 0.90176 -0.286362 0.955803 +0.392917 0.456737 0.292057 -0.404861 0.467663 0.325697 -0.350189 -0.986631 +0.0282557 0.234152 0.0634116 0.945357 0.495868 -0.816892 0.602026 -0.707111 +0.299164 0.529442 -0.256736 0.184076 -0.548297 0.848613 -0.40698 -0.696608 +0.0445485 -0.531856 -0.0068861 -0.876519 -0.674682 0.973914 0.0447032 0.514157 +-0.0992711 -0.652818 -0.0439884 -0.641035 0.723269 0.859504 -0.905632 -0.882526 +-0.890704 0.782478 -0.424662 -0.192941 -0.66712 -0.349342 -0.6031 0.964571 +0.526555 -0.0567282 0.581412 0.316658 -0.311291 -0.344182 -0.176196 0.0270604 +0.793437 -0.604303 -0.928391 -0.799126 -0.630315 -0.610741 -0.588965 -0.1293 +-0.906492 0.272001 0.341823 0.796484 0.0523215 0.123696 0.904695 -0.12076 +-0.972747 -0.648288 -0.602745 -0.722191 -0.351104 0.500287 0.088745 -0.319842 +0.500934 0.282794 0.0454934 0.605164 -0.780366 -0.329965 0.939782 -0.178307 +-0.838816 0.874248 0.18245 -0.969468 -0.91579 -0.0267874 -0.759045 -0.589663 +0.211185 0.465236 -0.240739 -0.498714 -0.675289 0.587301 -0.337304 -0.872029 +-0.276362 0.622924 0.585823 0.277861 0.063359 -0.754191 0.423178 0.286404 +0.322527 0.338383 0.622437 0.809099 -0.037747 -0.21445 0.00934567 -0.290484 +-0.182961 0.0311626 0.966787 -0.367836 0.177457 -0.173187 -0.43698 -0.39583 +-0.758299 -0.70009 -0.865822 0.612413 0.897207 -0.255269 -0.466869 0.0620859 +0.0918929 -0.34017 -0.402086 -0.162409 -0.348218 -0.827295 0.547759 -0.0633793 +-0.427105 0.89858 0.709572 0.00684876 0.476413 0.83969 -0.478957 0.632089 +-0.371331 -0.672297 0.528203 0.767076 -0.58556 -0.442409 -0.418912 0.135802 +0.267323 -0.200532 0.454927 -0.896557 0.938315 0.55772 -0.563894 -0.74007 +0.870471 -0.72489 -0.972334 0.395925 -0.105143 0.629998 0.518278 -0.517841 +-0.29891 0.832678 0.549625 0.271397 -0.823728 0.875052 -0.456435 -0.448438 +-0.0586764 0.194515 0.407848 0.14095 0.619632 -0.980324 -0.117258 -0.815876 +-0.933897 -0.28261 0.634805 0.301492 -0.972994 -0.134614 -0.12992 0.701162 +0.639765 -0.406018 -0.59692 0.570878 0.640079 -0.825857 -0.291862 0.34047 +-0.583488 0.12816 0.688513 -0.575937 0.53116 0.845981 0.116178 -0.549486 +-0.777821 -0.177186 0.730038 0.98904 -0.89302 0.885844 0.840692 0.631682 +0.632508 0.219905 -0.244135 -0.412468 -0.668984 0.943456 -0.0197695 0.104622 +-0.0940114 0.233033 -0.747028 0.376862 -0.980243 -0.284161 0.221297 -0.957587 +-0.901751 -0.402335 0.615905 -0.468134 0.247774 0.397941 -0.884356 -0.888632 +0.130646 0.0827703 -0.603369 0.271076 0.423045 -0.260751 -0.373238 0.419404 +-0.687241 -0.523622 0.814121 -0.55475 0.880876 0.663568 0.812579 0.376562 +-0.262174 0.356007 0.267313 -0.658261 0.0691339 -0.663666 -0.18604 0.395529 +-0.165158 0.488524 0.855688 -0.523008 -0.129683 0.46563 0.78824 -0.791651 +-0.581014 0.597263 -0.0503741 -0.165992 -0.8116 0.79565 0.92139 0.23766 +-0.672821 0.60898 0.752071 0.483987 0.146269 -0.91847 0.108537 0.243277 +0.923749 -0.243402 0.308673 -0.911232 -0.677737 -0.440247 0.744561 -0.398138 +0.575828 0.407175 0.760658 -0.172748 -0.00405966 0.415096 -0.679837 0.934977 +0.0950945 -0.0456896 -0.872209 0.989618 -0.049148 -0.555535 -0.321886 0.272169 +0.487764 -0.27916 0.871749 -0.984377 -0.376352 0.561644 0.229217 -0.994861 +0.872511 -0.101974 0.105318 -0.140537 -0.183839 -0.0312317 -0.866099 -0.298308 +0.699842 0.155432 0.87801 0.64462 0.00403796 0.466432 -0.795627 -0.685231 +-0.683326 0.751886 -0.69546 -0.568289 -0.76068 -0.508528 -0.484421 0.249769 +-0.528628 -0.291938 -0.141746 -0.770612 -0.186257 0.883314 0.388875 -0.234146 +0.350193 -0.428158 -0.7459 -0.349548 0.572079 -0.0250603 -0.228663 -0.977659 +-0.388133 -0.876622 -0.253835 -0.557926 0.458291 0.639308 -0.0519916 -0.04663 +0.161414 -0.00827725 -0.107576 0.629214 -0.633143 0.348901 -0.749198 -0.74827 +-0.0587521 -0.759471 0.947034 -0.225698 -0.0076309 0.166646 0.72231 0.962406 +0.228604 -0.656118 0.492903 0.591451 -0.0412384 -0.763194 0.218953 -0.75096 +-0.0853158 -0.0288549 -0.395504 0.596218 0.532552 -0.0724938 0.599071 0.685863 +-0.309642 0.0939375 -0.143125 -0.722295 0.357981 0.498287 -0.774542 0.786052 +0.261744 -0.306346 0.472413 0.705548 0.481577 -0.582633 -0.716086 -0.336843 +0.09798 -0.556612 -0.511358 -0.975902 -0.234911 0.101811 -0.0825996 -0.694234 +-0.0738821 -0.525627 -0.651907 0.375882 -0.250062 0.713097 0.124152 -0.769629 +0.217827 -0.70236 0.770399 -0.361043 -0.776906 0.577841 0.283512 -0.0524186 +0.373881 0.0340662 -0.696774 0.76993 -0.0190527 -0.989262 0.318189 0.285332 +0.0795496 0.0930517 -0.354266 -0.865884 -0.647234 0.190744 -0.212696 -0.607302 +0.697017 -0.3633 0.763994 0.56485 0.852337 0.65899 -0.852101 -0.00132943 +0.840541 0.238459 -0.594806 -0.96931 -0.102222 -0.47928 -0.0224324 0.0384352 +0.496916 0.577207 -0.441211 -0.877902 -0.618756 -0.677445 -0.849987 0.0307652 +-0.391906 -0.934762 -0.476748 0.904321 -0.666687 0.456262 -0.913208 0.538686 +-0.622405 0.747127 0.355453 0.941675 -0.138281 -0.364041 0.859529 -0.705589 +-0.220003 -0.828672 -0.418765 -0.304503 -0.56044 -0.0464992 0.980377 0.174231 +-0.873058 -0.367132 -0.811555 -0.34624 -0.146387 -0.089031 -0.343529 0.640726 +-0.463947 -0.158464 -0.469379 0.618198 -0.866839 0.893599 -0.378412 0.473208 +-0.433498 0.1337 0.133971 0.797691 0.689436 -0.900095 0.647485 0.229876 +0.822318 -0.0500753 0.654512 -0.801272 0.973569 -0.908658 -0.213578 -0.596733 +-0.175229 -0.30907 -0.229341 -0.799842 0.14742 -0.71894 -0.271957 -0.809688 +0.756969 0.0647562 -0.556409 -0.867341 0.935732 0.705752 0.867598 0.403568 +0.900701 0.616795 -0.804695 -0.357841 0.849394 0.968658 -0.153075 -0.0127006 +0.459091 0.244803 -0.988288 0.50804 0.310159 -0.619608 0.104331 -0.271515 +-0.0131555 0.081407 -0.53846 0.72394 0.37893 -0.00165161 0.0607774 0.833515 +0.0147606 -0.791332 0.347137 0.15768 0.533896 -0.555295 -0.162536 -0.230331 +-0.618749 -0.0898566 -0.630924 0.374219 -0.959814 0.315794 0.701011 0.477475 +0.0400638 0.568849 -0.760913 -0.68221 0.514091 -0.312234 -0.345115 0.261302 +-0.20384 -0.318684 0.166508 0.37568 0.0633076 0.231149 -0.813706 0.651435 +-0.043047 0.192414 0.327987 -0.293963 0.875594 0.89737 0.275166 -0.151287 +0.447596 0.840841 -0.933354 0.249121 -0.595451 -0.259476 -0.52932 -0.772351 +0.738218 -0.287759 -0.716446 -0.769356 -0.347781 -0.893608 -0.560328 0.716437 +-0.41101 -0.804579 0.977996 -0.351573 -0.392059 -0.757424 0.375409 0.0162358 +0.0480087 0.934702 -0.672329 0.635712 -0.00300719 0.214493 -0.832019 -0.771661 +-0.421777 -0.271635 0.718182 0.583991 -0.626458 -0.00333879 0.727638 0.823556 +-0.0382401 -0.262535 0.972411 -0.399773 -0.669322 -0.422892 0.206397 -0.543495 +0.703215 -0.855285 -0.604492 -0.282483 0.441433 -0.24338 -0.154623 -0.48984 +-0.58621 0.541519 0.546088 0.794191 -0.882634 -0.605676 -0.298874 0.374352 +-0.126557 0.555681 -0.287025 0.318666 0.530153 -0.397346 0.576145 -0.638613 +-0.917444 0.296461 0.955836 -0.65721 0.695861 0.043674 -0.624715 0.690593 +0.986136 -0.660492 -0.733043 0.576596 -0.553081 -0.775878 -0.931387 0.573468 +-0.527571 -0.575773 -0.579764 0.788955 0.315556 -0.335398 -0.184458 0.72793 +0.0136059 0.0681429 0.548535 0.142222 0.0239615 0.995879 -0.866157 -0.142694 +-0.557506 -0.0331198 -0.0317959 0.515413 0.283685 0.604645 0.922669 -0.154334 +0.883074 -0.505844 -0.460389 0.485507 0.401237 0.265223 0.104808 0.428291 +-0.661414 0.39231 -0.25108 0.57457 0.387117 -0.877487 -0.749304 0.404519 +0.534068 -0.331007 -0.146343 -0.977265 0.20961 0.160137 0.437703 -0.609875 +-0.308816 -0.665959 0.47042 0.0504511 -0.626521 0.811507 -0.852126 0.760364 +-0.078426 -0.438817 0.381848 -0.0238299 0.565028 -0.570837 0.534991 -0.889088 +-0.931507 0.186301 0.797062 -0.223884 -0.178746 0.786467 0.891901 -0.766474 +0.170792 0.938991 0.213343 0.33078 0.972223 0.157726 0.754286 -0.469261 +-0.153329 0.636921 0.888783 -0.6106 -0.702787 -0.120373 -0.0259913 -0.573057 +-0.681333 0.351697 0.819066 0.782317 0.299589 -0.209447 -0.0239501 -0.708697 +-0.0485829 -0.849968 0.366031 0.894566 -0.236988 0.417351 -0.027951 -0.454019 +-0.504835 -0.286129 -0.744047 -0.974466 0.422891 0.305965 -0.658884 0.455997 +0.443154 -0.872624 -0.69793 -0.217703 0.119623 0.382854 0.731145 0.764561 +-0.103426 -0.429499 0.861196 0.513499 0.467221 0.278728 0.888892 -0.859868 +-0.236591 0.982268 -0.123918 -0.870957 -0.485913 -0.384631 0.269559 0.681465 +-0.969833 -0.419319 0.64387 -0.824699 -0.601057 0.0015978 0.526771 -0.182932 +0.167587 -0.992645 -0.771173 0.278499 -0.0384297 -0.0274552 0.418631 -0.410953 +-0.265885 0.301537 -0.14445 0.463352 0.590728 -0.158784 -0.0902518 0.678023 +-0.807479 0.661826 -0.403457 -0.430091 0.668091 0.59243 -0.310691 0.454404 +-0.575875 -0.37056 -0.359989 -0.7231 -0.712069 -0.528939 0.641205 -0.226798 +-0.218395 0.206113 -0.29861 -0.879979 0.0130812 0.311978 0.727739 -0.388292 +-0.927151 -0.558819 -0.519273 -0.0980931 0.665045 0.665278 -0.232994 0.351635 +-0.977552 -0.80713 -0.647368 0.637197 0.0915763 0.809541 0.274054 -0.224862 +-0.164315 0.364527 -0.800353 -0.792172 0.847013 0.187365 0.0990939 -0.412477 +0.372143 -0.551978 0.402478 0.312149 -0.0522783 -0.856704 0.901229 -0.118029 +-0.345782 -0.821606 -0.679754 0.990239 -0.0118953 0.214492 0.69436 -0.0135066 +-0.436876 0.929784 0.497388 0.200406 -0.598338 0.589664 -0.852718 0.820035 +0.0563828 -0.95758 -0.845192 -0.798894 0.707567 -0.738946 0.958976 0.965312 +-0.135131 -0.42393 -0.39051 0.791436 0.532899 0.910974 0.193791 -0.200857 +0.873451 -0.58441 -0.118604 -0.798794 -0.0241556 0.309326 0.402356 -0.854476 +-0.714225 0.669105 0.153772 -0.335128 -0.545302 -0.910632 -0.428904 0.0103926 +-0.0911475 -0.0617885 0.525746 -0.993839 0.262267 -0.730372 0.0696819 -0.561545 +-0.421976 0.889024 -0.211543 -0.643264 0.0494218 0.343296 0.119638 -0.107548 +0.36477 -0.506497 -0.784439 0.736339 -0.908276 0.276037 0.615321 0.280225 +-0.570541 0.0991791 -0.0575483 -0.612905 0.760565 -0.11731 0.498152 0.720806 +-0.173592 -0.932767 -0.324539 0.551885 0.542661 0.982325 0.141416 0.0749308 +-0.64489 -0.937608 -0.424643 -0.89868 0.676486 0.470915 0.541542 0.645032 +-0.58852 -0.517797 0.91728 0.797466 0.171727 0.537008 0.413464 0.0792674 +0.725099 -0.467204 0.419716 -0.453448 -0.12609 -0.600627 -0.876101 -0.0280678 +0.500841 -0.629449 0.216681 -0.331148 -0.574679 -0.648917 -0.488191 0.577152 +-0.739027 0.228226 -0.567767 -0.969028 -0.253798 -0.717974 0.0696748 0.0938428 +-0.927949 -0.423073 0.787491 0.331996 0.0850664 0.7873 0.163322 0.436217 +0.0308512 0.228962 0.0324198 0.494983 0.874798 0.206818 -0.0354002 -0.0951359 +-0.298199 0.635572 -0.750356 -0.16748 -0.213532 -0.246433 0.239039 -0.347236 +-0.625589 0.14159 0.82336 -0.450564 0.553692 -0.598211 0.299441 0.759206 +0.348087 -0.713231 0.372781 0.385948 0.642597 -0.738866 -0.895538 -0.743501 +-0.382141 -0.396326 -0.971747 0.696216 -0.292185 0.573439 0.247653 -0.147936 +0.80625 0.800385 -0.700048 0.351293 -0.926384 0.257988 0.55101 -0.815838 +0.409352 -0.0711105 -0.701948 0.925536 0.310476 -0.0162135 -0.969555 -0.790082 +-0.528257 -0.209494 -0.483273 -0.155396 0.604412 0.990433 0.519163 -0.795194 +0.769942 0.442149 0.421451 0.588982 0.969506 0.201319 0.0616305 0.94586 +-0.973679 0.215293 -0.941432 0.908672 0.136433 -0.188619 -0.379484 -0.104493 +-0.415368 -0.919933 -0.223428 0.236506 0.410394 -0.264152 -0.117417 0.243977 +0.322721 -0.305795 -0.877695 -0.289087 -0.252315 0.34939 -0.183321 0.709864 +-0.261912 -0.687879 0.565977 -0.834074 0.158382 -0.518495 0.885207 0.697517 +0.205533 -0.042898 0.8289 0.0454625 -0.0248576 0.763017 0.962756 -0.572692 +0.959316 -0.036971 -0.094245 0.323684 0.663768 -0.199927 0.351647 0.81876 +-0.826478 -0.365443 0.420705 0.962953 0.794163 0.427182 -0.611511 -0.61819 +0.475511 -0.793381 -0.723674 -0.852891 -0.889669 0.640189 0.856983 -0.290165 +0.633274 0.292767 -0.253832 0.242778 0.873079 -0.99642 0.892524 0.361816 +-0.863646 -0.913512 -0.288336 -0.756333 -0.397216 0.686055 -0.136304 -0.678875 +-0.633119 -0.744407 -0.588538 -0.00867756 -0.226401 0.0968277 0.362938 0.565491 +0.915974 -0.737677 -0.0173621 -0.384381 0.0729694 0.215846 0.904642 0.237143 +-0.185859 0.631033 -0.801478 0.997759 -0.723299 0.93095 0.773143 0.594227 +-0.289559 0.322607 0.757116 0.559505 0.949622 -0.27274 -0.792751 0.391485 +0.289462 -0.822898 0.0272 -0.445521 0.620849 -0.00287989 0.312331 -0.797289 +-0.154895 0.767109 -0.267342 -0.953723 0.543938 -0.866447 -0.0941029 -0.339166 +0.519829 -0.821429 0.75125 -0.113211 -0.617758 0.296394 0.028915 0.370434 +-0.391275 0.576168 -0.961182 0.48575 0.798456 0.0891443 0.832443 -0.964255 +0.912362 0.819835 0.900146 0.0447154 0.639345 0.702846 0.911199 0.0560238 +0.0315657 -0.358377 0.349247 0.630195 0.249739 -0.969036 0.744419 0.565511 +0.280934 0.125016 -0.580872 0.536871 0.348812 -0.88015 -0.660975 -0.999603 +-0.15396 0.313619 0.261226 -0.222399 -0.71731 -0.451114 0.311605 -0.303305 +-0.033923 -0.940143 -0.648723 -0.776813 0.381103 -0.368571 0.270384 0.0804864 +0.293465 0.729439 -0.794396 -0.165949 -0.481165 0.565788 -0.951154 -0.347625 +0.885893 -0.648988 0.676499 -0.0471971 -0.748788 -0.460324 -0.019368 -0.957997 +0.202859 -0.954417 0.33712 -0.117888 0.400289 -0.941898 0.75673 0.303229 +0.596352 0.454783 0.858148 0.771329 -0.720131 0.99016 0.994014 0.759047 +-0.592595 -0.629853 0.733491 -0.459211 -0.441861 0.0822931 -0.409895 -0.0787478 +0.184709 0.533202 -0.847097 -0.907619 0.0118464 0.936569 0.196118 0.254834 +-0.884053 -0.532799 0.910126 0.475674 0.666932 -0.628023 -0.576535 -0.469368 +0.891465 -0.793515 0.50095 0.842043 -0.462611 0.0398849 0.62048 0.596908 +0.43778 0.300052 -0.0114264 -0.323756 0.571497 -0.330773 0.805934 -0.284496 +-0.792036 -0.0501875 0.437801 0.148841 0.734703 0.30062 -0.715432 0.108541 +0.845658 -0.162659 0.154013 -0.0147165 -0.102836 -0.518214 -0.0524601 0.211388 +0.774781 0.709874 -0.68275 -0.899831 -0.562339 0.421571 0.669019 0.749238 +0.948515 0.834915 0.27058 0.269523 -0.721323 0.232853 0.123963 -0.8937 +-0.265647 -0.589781 0.14842 -0.845417 -0.698621 -0.220769 0.851933 -0.798709 +0.559397 -0.899814 -0.726456 -0.41406 -0.339211 0.557953 0.52204 0.932899 +-0.022377 0.950529 -0.667494 -0.215668 -0.938877 -0.214596 -0.809057 0.046996 +-0.408067 -0.980112 0.238443 -0.752431 -0.799308 -0.336314 0.319919 0.189053 +-0.763031 0.277874 0.120553 -0.854431 0.867596 -0.510476 -0.385128 -0.992872 +-0.0576368 0.137547 0.563772 -0.864928 -0.769947 -0.434662 -0.342907 0.620904 +-0.0160516 -0.132959 0.244994 -0.188478 -0.777315 0.992548 -0.0024895 0.979159 +-0.730022 -0.00247484 0.990202 0.312306 0.237458 -0.35138 0.137266 0.455564 +0.956368 0.310525 -0.854778 0.411043 -0.952062 0.358463 0.231315 -0.0518105 +-0.0672578 -0.207477 0.288971 0.0380662 0.690969 -0.268031 0.919081 -0.115396 +-0.704587 -0.154296 0.136428 0.954856 0.330782 0.481386 0.471715 -0.219455 +-0.203376 0.920095 0.697111 0.55034 0.383709 -0.262638 -0.817549 0.227347 +-0.463615 -0.291141 0.0250162 -0.00726496 -0.198275 0.58227 -0.211953 0.593673 +0.857279 0.841782 -0.449536 0.64487 -0.0307082 -0.0592299 0.648799 0.563618 +0.341086 -0.806764 0.890553 0.7288 0.389373 0.0534525 0.768573 -0.853393 +0.735197 -0.527257 -0.0361665 -0.0291081 0.524811 -0.753464 0.590635 0.242473 +0.758816 -0.904507 -0.294953 0.400438 0.625616 -0.542324 -0.846579 0.207886 +-0.773352 0.584384 -0.906816 0.790825 0.564684 -0.997325 0.363822 -0.0303743 +0.849792 0.34236 -0.47525 0.187017 0.809634 -0.330487 -0.0429083 -0.451028 +-0.518092 -0.772305 -0.785787 -0.0447383 0.194206 0.98632 -0.195761 -0.700767 +-0.522136 -0.931827 -0.800064 -0.154929 -0.274584 -0.987216 0.515634 -0.833795 +0.665241 -0.869177 -0.747338 -0.0971025 -0.502152 0.244928 0.811075 -0.423818 +0.630245 -0.945272 0.859781 -0.986722 0.231161 -0.615765 0.772432 0.61465 +0.884009 -0.935077 0.361179 -0.517252 0.247166 -0.107838 0.275589 0.0451575 +0.239435 -0.932808 -0.389149 -0.541961 0.612902 -0.285752 0.315727 0.632086 +0.439833 0.462677 -0.675846 0.0639894 -0.971488 -0.497908 -0.994998 -0.983985 +-0.665924 0.158148 -0.574551 -0.539711 0.329338 0.658037 -0.836134 -0.549203 +0.323902 -0.767664 0.743178 -0.20366 -0.702825 0.572041 -0.0672957 -0.820981 +0.929342 -0.232172 0.912706 0.492563 0.594423 -0.765973 -0.777843 0.222314 +-0.353925 -0.714375 -0.745331 -0.590585 0.608246 0.316576 0.25868 -0.181157 +-0.954547 -0.268678 -0.0259193 0.636473 -0.00576454 0.504652 -0.983029 -0.999909 +-0.977427 -0.439742 -0.634293 -0.443093 -0.208878 -0.917314 0.460906 0.668095 +0.404642 0.172564 -0.313897 0.0348753 0.314359 0.582387 0.587393 -0.406708 +-0.683042 -0.730176 0.28103 0.0451851 -0.536919 -0.440717 0.647332 -0.499174 +0.181887 0.957391 -0.937752 0.599208 -0.537083 -0.426277 -0.11741 -0.50889 +0.246802 -0.644743 0.906881 -0.0991696 -0.00592176 0.808702 -0.0879378 -0.136421 +-0.654269 0.913209 0.936144 0.186601 0.286651 -0.505364 -0.711188 0.216235 +0.897288 0.68245 0.773807 -0.519927 0.482965 0.963589 0.901341 -0.5257 +0.0480231 -0.66276 0.274623 -0.612045 0.546233 -0.565404 0.521747 0.0284632 +0.556798 0.111723 -0.317132 0.582086 0.743024 -0.231451 0.842579 -0.639296 +-0.17357 0.131176 0.67723 -0.844804 0.273531 0.41979 0.146505 -0.209657 +-0.621485 -0.292841 0.473998 0.0377861 -0.150556 0.27686 0.795891 0.154968 +-0.880345 -0.421512 -0.893228 -0.558276 -0.660662 0.233274 0.279943 -0.724258 +-0.00866459 -0.869644 -0.510631 -0.675563 0.874323 -0.647973 0.361705 -0.0513744 +-0.765622 -0.840489 0.349422 -0.45233 0.372522 -0.879064 -0.255937 0.883011 +0.289411 0.796227 -0.906529 0.303926 -0.720834 0.0183671 -0.244382 0.266483 +0.20845 -0.849936 0.0364291 0.769035 0.388537 0.208324 0.719498 -0.817213 +0.571492 0.296124 -0.612299 -0.268751 -0.59594 -0.612136 0.527542 -0.401115 +-0.554466 0.040609 0.27548 -0.765129 0.200401 0.0717073 0.968369 0.20067 +0.491465 -0.79106 0.011206 -0.793763 -0.246114 0.612065 -0.16963 0.0736798 +-0.496521 -0.157787 0.868321 -0.521676 -0.685509 -0.240769 -0.0398775 0.552004 +0.165768 -0.963096 -0.568903 -0.983895 0.824196 0.0279871 0.454328 0.218824 +0.740034 -0.912918 -0.887235 -0.599089 0.79243 -0.512696 0.518684 -0.00402916 +-0.327851 0.914753 0.890236 -0.656269 0.852599 -0.427016 0.365611 0.612482 +0.066393 0.255606 -0.843267 -0.643871 -0.112525 -0.464752 0.81926 0.463016 +-0.467603 0.410669 -0.423947 0.119199 -0.687074 -0.784492 0.63345 -0.286635 +0.98679 0.456341 -0.678906 0.0648139 -0.737 0.248312 0.731778 -0.409536 +0.513261 0.661747 0.565116 -0.625691 0.648478 -0.163854 0.143801 0.499486 +0.840303 -0.817532 -0.231689 0.39123 -0.903837 -0.47848 0.225207 -0.852077 +0.123674 -0.311777 0.290866 -0.0950451 -0.426041 0.86066 -0.748283 -0.632109 +-0.521492 0.0864328 -0.32038 0.840318 -0.77951 -0.606943 0.782581 0.777126 +-0.15473 -0.511288 -0.730831 0.793147 -0.586367 0.0114341 0.200563 0.879166 +0.250878 -0.199742 -0.729809 -0.487566 0.422522 0.864251 -0.0122899 -0.0645909 +0.397044 -0.205551 0.886822 -0.436877 0.369261 0.480061 0.318214 0.575161 +-0.841199 0.463341 0.281459 -0.848436 0.756315 0.572097 -0.846394 -0.746386 +-0.44147 -0.181421 -0.623874 -0.901199 -0.761866 -0.702611 0.66056 0.560011 +0.00865089 0.617429 0.60499 0.0953529 -0.0678855 -0.701857 -0.802685 -0.219635 +0.420718 -0.839643 -0.332753 -0.0244583 -0.254837 -0.157819 -0.155316 0.596616 +0.721415 -0.690868 -0.533421 0.857715 -0.526885 -0.887416 -0.554687 -0.315093 +-0.0237967 0.247744 0.0436885 0.0905536 0.697041 -0.942072 -0.73151 0.357572 +-0.0985748 0.2026 -0.533896 0.827953 -0.147183 0.18746 0.553788 -0.560407 +0.244526 -0.0242629 0.959511 -0.35888 0.827606 0.525406 0.916333 0.116075 +-0.862214 0.0870938 0.355415 0.25719 -0.912298 0.832491 0.291841 -0.209333 +-0.103273 0.299104 0.102417 -0.755506 0.395904 0.449318 -0.922041 0.343038 +-0.996375 0.539566 -0.810872 -0.457363 -0.00370834 -0.915863 -0.0582603 -0.773698 +-0.502701 0.281822 0.333183 -0.984507 0.568097 0.635937 -0.32079 -0.505801 +0.853921 -0.36294 0.152173 0.703791 0.173053 0.747136 -0.708884 -0.807983 +-0.146087 0.983002 -0.0854224 -0.899636 -0.945061 0.545917 -0.844186 -0.956619 +-0.159242 0.40135 -0.970597 0.814538 0.248151 -0.984629 0.0420052 0.150303 +0.68965 -0.0845069 -0.118973 -0.0804514 -0.342862 -0.809644 0.484086 -0.940726 +-0.591145 0.284674 0.491459 -0.0577902 -0.102593 -0.776112 -0.712163 0.795008 +-0.415303 -0.79179 -0.962326 0.959955 -0.405948 -0.173242 0.690971 0.631169 +-0.472481 -0.726465 0.330005 -0.521806 0.674279 -0.651179 -0.199559 -0.0987495 +-0.777557 -0.788969 -0.835652 -0.13577 0.506319 0.995402 -0.210915 0.143186 +0.523246 -0.71789 -0.963673 0.264485 0.989123 -0.411849 0.746188 0.0228331 +-0.783776 0.708437 -0.923628 -0.34587 0.184657 -0.955679 0.874086 0.0372084 +-0.821056 -0.172536 -0.871285 -0.812582 -0.426327 0.489858 0.505255 0.787761 +0.523894 0.509191 0.450586 -0.948326 0.336666 0.328266 0.175533 0.132165 +-0.0335831 -0.713004 -0.271654 -0.362875 -0.987953 -0.142638 0.349005 0.328507 +0.0100541 -0.799865 -0.733318 -0.792683 -0.745214 0.613791 0.753187 0.362633 +0.884437 0.500743 0.742149 0.738966 -0.666168 0.50721 -0.412618 -0.956246 +0.732696 -0.908065 0.535723 0.535157 0.351496 -0.902803 -0.683144 0.138511 +-0.132169 -0.434749 -0.72639 0.314277 -0.516514 0.61994 0.0519247 -0.308297 +0.317812 -0.37567 -0.495581 0.750164 -0.569595 -0.657367 -0.831786 0.372993 +-0.932849 0.260294 -0.989796 0.358031 0.32691 0.612817 0.666925 -0.604385 +-0.414279 -0.470107 0.846858 -0.310571 0.971106 0.667517 -0.140636 -0.287537 +0.35593 0.240565 0.773082 0.827102 0.891107 0.818325 -0.633923 -0.716162 +0.569729 0.48686 -0.573935 -0.0971379 0.242509 0.621819 0.343014 -0.889115 +-0.22017 0.67562 -0.106311 0.0444585 -0.020977 0.695225 0.00345053 0.715914 +0.674576 -0.421233 0.65987 -0.431844 0.542729 0.605938 0.858969 0.438134 +0.963366 -0.837117 0.0781909 -0.838091 -0.168628 -0.2336 0.937015 0.739941 +0.718574 0.581652 -0.858404 -0.401037 -0.00716871 -0.707419 -0.467581 -0.78914 +-0.151921 -0.94791 0.6188 0.817459 -0.709341 -0.926268 0.0723514 0.336622 +0.96258 -0.75766 0.396941 0.718143 -0.169828 0.122031 -0.0367065 0.7384 +0.263628 -0.880443 -0.124994 0.266299 -0.257957 -0.0265027 0.921781 0.844244 +0.998924 -0.233981 0.673804 0.185795 -0.399473 -0.367174 0.850937 0.784937 +-0.562042 0.346308 0.765645 -0.946488 0.623402 0.530048 -0.14034 -0.347501 +-0.999026 -0.186878 0.17968 -0.46803 0.507831 0.843023 -0.837577 0.531084 +-0.10777 -0.88443 0.280961 0.19961 0.516423 -0.0250554 -0.0374467 0.944339 +0.648775 0.43716 -0.0294552 -0.291237 0.429182 -0.014207 -0.999934 0.616593 +0.5151 -0.370435 0.925594 0.127702 0.91067 -0.950674 -0.852667 -0.451298 +0.551099 0.201026 -0.216906 0.435788 -0.0886131 0.835681 -0.452632 0.06121 +-0.762853 -0.275637 -0.0452351 -0.43197 0.348678 0.692471 -0.0250651 -0.837511 +-0.000705068 0.693438 0.329145 0.784132 -0.837982 -0.270238 0.876447 0.288744 +0.581061 0.875979 -0.22214 -0.977312 -0.286251 0.654071 -0.431568 -0.132034 +0.118309 0.37006 -0.278813 -0.166397 0.344885 -0.41479 -0.708495 -0.401663 +0.50952 0.85496 -0.42861 0.258136 0.864074 -0.705577 -0.547031 0.548996 +0.603454 -0.379478 -0.447613 -0.704614 0.294644 -0.646423 -0.662817 -0.353713 +0.629235 -0.855449 -0.501383 -0.180815 0.0642744 0.978021 -0.885866 0.667011 +-0.277067 -0.800078 0.357491 0.852214 0.214084 0.602324 0.630773 -0.934377 +0.822629 -0.42572 -0.0414185 -0.238885 -0.897346 0.952023 0.468097 0.50996 +0.187288 -0.396971 -0.909384 -0.229735 0.723638 -0.0262056 -0.663937 -0.517033 +-0.744808 -0.305843 -0.0132199 0.0133952 0.592778 -0.817288 0.785724 0.226325 +0.115543 -0.674744 -0.430768 0.475621 -0.201807 0.223091 -0.162097 -0.525051 +-0.280492 0.0154554 -0.850462 -0.793395 0.630453 -0.482961 -0.0385223 -0.377634 +-0.113907 -0.562943 -0.49774 -0.96475 -0.803074 -0.648262 0.7712 -0.263702 +-0.42579 0.264327 0.772499 0.707879 -0.663871 -0.0649428 0.845919 -0.573576 +-0.968266 -0.011629 0.618734 -0.539617 0.501684 0.156367 0.260198 0.326613 +-0.616168 0.731211 -0.346115 0.838324 0.680605 -0.582237 0.588383 -0.736307 +0.22 0.781366 0.404332 0.363306 0.280824 0.0860145 -0.844068 -0.346392 +-0.989464 0.816089 0.396796 0.13281 0.306754 0.0244165 -0.558434 -0.041283 +-0.571711 -0.561174 -0.756804 -0.761599 0.726301 -0.435965 -0.42099 0.310841 +-0.3506 -0.177054 -0.100774 0.828329 0.903417 0.444617 0.786963 -0.364767 +0.576912 -0.247691 0.940025 0.124626 -0.345186 -0.799237 0.972112 0.293386 +-0.756064 0.0174836 0.346254 0.729743 0.177827 -0.989281 -0.626815 -0.181518 +0.0113047 0.710335 -0.157297 0.8192 -0.7834 -0.972748 0.880057 0.686708 +-0.984164 -0.776617 0.224398 0.397543 0.665649 0.254794 0.802654 0.728762 +0.331912 0.983285 -0.161468 -0.634742 0.608703 -0.442285 0.636728 0.566193 +-0.141833 0.931464 -0.392285 -0.117315 -0.665514 -0.718371 -0.68684 0.134075 +0.0653097 -0.0704623 -0.254018 0.905615 0.45013 -0.657428 -0.404572 0.000768281 +-0.685062 0.280918 0.325373 -0.885701 0.336282 0.216995 0.641761 -0.608141 +-0.607014 0.749325 0.587225 -0.0221953 -0.0550681 0.646176 0.42147 0.338693 +0.635026 0.20767 0.662579 -0.0780125 -0.850308 -0.438233 0.166219 -0.623084 +0.861369 -0.456771 -0.915508 -0.469572 0.451801 0.0122024 0.0242943 0.322577 +-0.414223 0.784582 -0.433078 0.799838 -0.324865 -0.991578 -0.622669 0.178575 +0.0565888 0.135022 0.619722 0.671557 0.425162 -0.421601 -0.25108 0.821844 +-0.797878 -0.220905 0.0967337 -0.743334 -0.649678 -0.979725 0.179823 0.741467 +-0.456997 0.616709 -0.802383 0.504038 -0.273702 0.192112 -0.273834 0.586739 +-0.184189 0.347775 0.980186 -0.107538 -0.619015 -0.866729 -0.691914 -0.87061 +-0.147123 -0.123446 0.933143 -0.627955 -0.864982 0.857844 0.446014 0.636984 +0.579715 -0.664341 -0.663416 0.60679 0.961587 -0.955314 -0.46082 0.323185 +-0.763326 -0.317488 -0.0296931 -0.543851 0.196844 -0.503798 -0.326354 -0.043125 +-0.470543 -0.541783 -0.314201 -0.795537 -0.759185 0.0990609 0.911611 -0.64058 +0.0664862 0.722826 0.899792 0.741519 0.782599 0.0647453 0.457447 0.695179 +0.58767 -0.818951 -0.0449839 0.446339 0.0756951 0.0465723 0.899595 -0.645389 +-0.604101 -0.215408 0.316787 0.99631 -0.280395 0.256987 -0.791317 -0.420584 +0.00783592 0.389534 0.827462 0.736468 -0.485448 -0.206538 0.202916 -0.706972 +0.851653 -0.615325 0.958712 -0.782672 -0.727878 0.547352 -0.64593 0.118389 +0.221741 0.89213 -0.801569 0.883675 0.289008 0.426343 -0.843248 -0.956447 +-0.1651 0.121533 0.617531 -0.735839 0.547591 -0.715481 0.960951 0.313266 +0.804189 -0.616054 0.91116 0.606297 0.65658 -0.48108 0.748657 0.16065 +0.794865 0.0766061 -0.980672 0.706476 -0.816405 0.184429 -0.911435 0.537995 +0.716987 0.0314115 -0.671708 -0.400309 0.685982 0.432049 -0.806327 -0.412623 +0.745035 0.0077021 -0.43329 0.758352 0.34165 -0.0448048 -0.635356 -0.0756354 +-0.824857 -0.498955 0.236824 0.468947 -0.0306672 0.596619 -0.686569 0.458268 +-0.0301541 -0.000230301 -0.764087 -0.40606 -0.812309 0.260076 0.910427 -0.0361387 +-0.281342 0.996378 -0.174217 0.396589 0.828647 0.62871 -0.0241627 -0.901862 +-0.989947 0.279349 0.6173 0.506768 -0.598962 -0.467246 -0.479589 0.795945 +-0.568429 -0.708814 -0.305729 0.556525 0.2365 -0.12609 -0.950731 -0.849946 +-0.393335 0.110022 0.408178 -0.189781 0.153311 -0.0509175 0.13667 -0.635806 +0.515497 0.226554 -0.457446 0.963648 0.138001 0.198869 0.55655 0.275074 +0.833916 -0.907625 -0.431839 0.580657 0.844465 -0.59836 0.709453 -0.607478 +0.708596 0.323194 -0.363549 -0.152327 0.801959 0.194822 -0.796287 0.643948 +-0.438857 0.921563 0.289893 -0.00920486 0.440235 -0.935067 -0.150133 -0.0879078 +-0.439521 0.360491 0.483873 0.622308 -0.719552 0.247959 -0.174353 -0.753308 +0.823863 -0.581082 -0.724696 0.966331 0.928865 -0.207342 0.370228 0.369655 +0.0637058 -0.95021 -0.293585 -0.568655 0.812117 0.118339 -0.589146 -0.151276 +-0.479777 0.787033 -0.66087 -0.891266 0.521678 0.83649 -0.42658 -0.756782 +-0.614751 -0.23329 -0.463254 -0.982015 0.742681 -0.524214 -0.286417 -0.197657 +0.836815 0.623114 0.195545 -0.169787 0.890554 0.488276 -0.0398315 0.809048 +-0.982284 -0.872347 0.0571053 0.977138 -0.785018 -0.25923 0.196843 0.428123 +-0.398294 -0.581749 0.0954772 -0.469722 0.147785 -0.0476722 0.580913 -0.871628 +-0.616744 -0.838678 -0.359308 -0.0478123 0.823345 0.641562 0.53659 0.969992 +0.544305 -0.142675 0.378207 0.890251 -0.136662 -0.867295 0.809838 -0.159524 +0.690661 -0.208898 0.0603975 0.935953 0.520713 0.0285134 0.84775 -0.830052 +0.485369 -0.660915 0.102891 0.635658 -0.549607 -0.199088 0.116683 -0.644873 +-0.204462 0.41009 0.239874 -0.135912 -0.52821 0.741063 0.418835 0.886441 +-0.659746 -0.990784 0.526589 0.476916 -0.632939 -0.789347 -0.261617 -0.43198 +-0.812314 0.552784 -0.502973 -0.520641 -0.642169 -0.85452 0.566397 0.0104621 +-0.534805 -0.663166 -0.00239012 0.724684 0.492722 -0.509403 -0.863882 0.365751 +0.784838 -0.769144 0.271731 -0.304991 -0.18287 -0.937801 -0.202343 -0.0235132 +0.410138 -0.00510835 -0.894632 0.74949 -0.135095 -0.099285 -0.889814 -0.852642 +-0.244566 -0.982174 -0.22027 -0.445252 -0.532723 -0.23535 -0.832387 -0.516421 +-0.945681 0.187503 0.27538 -0.782043 0.334733 -0.859677 -0.192137 0.680349 +0.749007 -0.861941 0.33958 -0.772802 -0.184557 0.375975 0.317242 0.803211 +0.180729 -0.827121 -0.932489 0.212849 -0.0774885 -0.561804 0.832561 0.924228 +-0.51261 0.934506 -0.0985754 0.615137 0.0265231 0.966255 -0.905823 -0.222526 +-0.212689 -0.908656 -0.511251 0.384387 0.222447 0.44556 0.431341 0.886168 +0.81375 -0.20064 0.24307 -0.99242 -0.585578 -0.974598 0.366026 -0.463103 +-0.898744 0.0204658 0.348743 -0.461792 0.402921 0.992579 -0.972558 -0.136229 +0.58008 0.0991207 -0.689031 -0.839114 -0.968505 -0.298291 -0.487098 -0.618124 +-0.621908 -0.982348 -0.0978592 0.0026808 -0.754653 0.835372 -0.626442 0.0567296 +0.542684 -0.845997 -0.930758 -0.062581 0.709223 -0.630462 0.475657 0.4694 +0.233525 -0.639955 0.461843 -0.498573 0.135962 0.648516 -0.860887 0.593932 +0.881612 -0.484931 0.709647 0.146055 0.157837 -0.461421 0.800285 -0.904641 +0.524459 0.684703 -0.832042 -0.339311 0.0214582 -0.36108 -0.876202 -0.297081 +-0.963736 -0.225418 0.0667202 -0.141799 -0.0067285 0.416775 0.608885 -0.445757 +0.0835383 -0.783474 -0.941268 0.717977 -0.40279 -0.400818 -0.201124 -0.91622 +0.343427 0.765246 0.712287 -0.286136 0.493127 -0.659244 -0.0693339 0.830604 +-0.60618 -0.367933 -0.307954 -0.722405 -0.486379 -0.749567 0.392966 0.470268 +-0.329486 -0.892206 -0.967454 -0.0256706 -0.322041 -0.231606 -0.273662 0.467779 +0.00864375 -0.81182 -0.548585 -0.0300353 -0.0434251 0.796928 0.669132 -0.863061 +-0.0340044 0.945618 0.208824 -0.637676 -0.00122878 0.181622 -0.217756 0.919925 +-0.438567 0.894487 -0.123102 -0.0219841 0.615826 -0.209102 -0.407801 -0.565796 +0.715973 -0.0374182 -0.152052 -0.879616 -0.111176 0.487921 0.623314 -0.442354 +-0.939463 0.998591 -0.840935 -0.717716 -0.928034 0.760342 -0.460224 -0.711057 +-0.339058 0.446081 -0.529201 0.169856 -0.713303 -0.28214 0.23864 -0.64956 +-0.368286 0.342269 -0.0480571 -0.767477 -0.237158 -0.374401 -0.417466 0.103495 +0.70439 0.947576 0.88951 -0.484411 0.82739 -0.0317333 -0.374721 0.728774 +-0.164127 0.998379 3.58187e-05 -0.478777 -0.886255 -0.718046 -0.530109 -0.372583 +0.447814 0.751623 -0.844977 -0.0501045 0.328442 -0.554447 0.32604 -0.512797 +0.125453 0.948951 -0.251164 -0.0734488 -0.724174 0.382493 0.565093 -0.380303 +-0.959134 0.129028 0.905471 -0.430826 0.33407 -0.865566 -0.102439 -0.847552 +-0.671577 0.547515 -0.405553 -0.533779 0.792841 0.940761 -0.240287 -0.790082 +0.261696 -0.468283 0.636685 0.172508 -0.712444 -0.511514 0.0697376 0.323731 +0.967268 0.0701916 0.70247 0.961297 0.532989 0.209927 -0.863799 -0.988658 +-0.738586 -0.957943 -0.227758 0.439528 0.638227 -0.361157 -0.550217 -0.0740309 +-0.167978 -0.671522 -0.590948 0.788766 0.900721 -0.436472 0.701945 -0.283663 +-0.933055 0.308208 -0.48667 -0.965686 0.424975 0.916878 0.870325 0.307718 +-0.440769 -0.136783 -0.717385 0.978844 -0.978524 0.894935 -0.955621 0.0347861 +-0.402571 0.932431 -0.69001 -0.854947 -0.704255 -0.843845 0.439145 0.332507 +0.884315 0.358231 -0.0204979 -0.905149 0.311102 -0.134503 -0.504413 -0.351413 +0.93749 -0.419078 -0.606983 -0.861235 -0.528741 -0.316415 0.0760611 0.556028 +-0.481772 0.0528745 0.912388 -0.648943 -0.528738 -0.0836405 0.45518 0.134116 +0.65148 -0.0730722 -0.102746 -0.248844 -0.275548 0.245518 -0.402454 -0.434698 +-0.736554 0.94961 0.725272 0.0492115 0.755981 0.876823 -0.969465 0.806371 +-0.691828 0.047525 0.496619 0.528133 -0.411473 -0.441943 0.133401 -0.361174 +-0.533397 0.840733 0.126147 0.612444 0.284063 0.598789 0.878335 -0.0490234 +0.604006 0.818177 -0.723031 -0.113028 0.672895 0.157053 -0.367267 -0.514891 +-0.226723 0.715447 0.0342616 0.0163529 -0.7168 -0.454648 0.615421 -0.639414 +0.788543 -0.114448 -0.618044 0.931844 0.397526 -0.323861 0.766333 -0.685741 +0.672859 -0.165548 -0.0151693 -0.0820926 0.217384 -0.899237 0.90086 -0.968222 +0.309018 0.896308 -0.405664 -0.497062 0.916715 0.0237754 -0.106368 -0.861573 +-0.269966 0.102866 0.762425 0.2448 -0.432779 -0.96265 -0.627808 0.205983 +0.310784 -0.173406 0.518453 0.344953 0.0330906 0.931382 -0.240309 -0.474299 +0.982172 -0.60229 0.707335 0.920388 0.528837 -0.567362 -0.379323 0.271828 +-0.854471 0.885482 0.569127 -0.279502 -0.984145 -0.986498 0.0491782 -0.856641 +0.251908 0.345603 -0.117219 0.047237 -0.872522 0.137715 -0.76625 0.14018 +-0.397734 -0.298491 -0.12443 -0.516682 -0.565237 -0.787377 0.0348365 -0.110158 +-0.904191 -0.440638 0.267592 0.838202 0.644222 0.0461281 -0.323435 -0.181573 +-0.193219 0.123638 -0.726347 0.257066 0.622249 -0.394583 0.927198 -0.616079 +-0.881052 -0.725467 0.999209 0.0472901 -0.585616 -0.366093 -0.243887 -0.512779 +-0.929443 0.916092 -0.327464 0.494227 -0.55818 -0.772939 -0.585813 -0.0464067 +-0.980349 0.595058 0.0355612 0.423679 -0.105675 0.274351 0.658272 0.478176 +0.00210862 0.767072 -0.85446 -0.796965 0.244109 -0.269706 -0.911463 -0.355583 +0.812399 0.711786 -0.69391 0.516279 -0.715963 -0.648673 -0.226655 -0.420628 +-0.489381 0.661046 0.958852 -0.148027 -0.161704 0.324932 -0.967644 -0.249043 +-0.754152 0.627913 -0.411467 -0.441104 -0.713304 -0.654139 -0.469572 -0.393992 +-0.873313 0.0239746 0.782447 -0.743247 0.600311 0.372719 0.701501 0.610132 +0.478536 0.468219 -0.571597 0.714447 -0.16895 -0.168505 -0.870466 0.498229 +-0.559904 -0.857032 0.333161 -0.28656 -0.301776 0.486585 -0.765691 -0.913841 +0.730426 -0.225736 -0.747767 0.582975 0.499248 0.517178 0.371442 0.597353 +0.606516 0.048935 -0.556591 -0.148378 -0.752258 0.00501431 -0.0688888 -0.417933 +0.581317 -0.588115 -0.547754 -0.36809 0.514811 -0.653504 0.540169 0.0116083 +0.539994 0.0387363 -0.373906 -0.195572 0.681116 -0.537351 -0.480147 0.341481 +-0.726982 0.416172 -0.442743 0.873262 0.77925 0.866927 0.0864211 0.59553 +0.88649 0.266731 0.937636 0.868009 0.20473 0.524346 -0.438782 -0.554437 +0.426115 -0.164787 0.64804 -0.0793962 0.00412427 -0.300663 0.0455931 0.520787 +0.51715 0.98294 0.100624 -0.972808 0.0351265 -0.595614 -0.0868222 -0.00845374 +-0.108488 0.787103 -0.379717 0.0959567 -0.880038 -0.600296 0.388735 0.084587 +-0.864644 -0.667847 -0.240725 -0.253896 -0.88752 -0.772616 -0.570779 0.395807 +-0.21042 0.947049 0.475964 0.975556 -0.00100742 -0.438765 -0.293878 0.683117 +0.0379649 0.0255203 0.41284 -0.726212 0.535715 0.0914284 -0.941792 -0.134525 +0.493006 0.550706 0.179805 -0.281732 0.825291 -0.732768 -0.776553 -0.80783 +0.519644 0.505448 -0.141743 -0.00348875 0.0889648 0.714917 -0.00428693 0.164767 +0.103408 -0.717194 -0.341366 -0.515549 -0.119209 0.70495 -0.932573 -0.786965 +0.0231636 0.945253 0.104304 -0.519617 0.569347 -0.325106 -0.0486517 -0.212616 +-0.0491609 -0.15152 0.217699 0.336631 -0.517949 0.851969 0.656025 0.203582 +0.466604 0.728384 0.376079 -0.240832 -0.983118 0.914609 0.950797 0.301587 +0.798194 -0.582151 -0.841621 -0.801487 0.200817 0.0549527 -0.517497 -0.803304 +0.514074 0.135644 -0.177831 -0.862979 -0.449721 0.240401 -0.915253 0.131752 +-0.00652486 0.901605 -0.878675 -0.69349 0.90813 0.591722 -0.493227 -0.895225 +0.173175 -0.0949145 0.662523 0.993257 0.500343 -0.262429 -0.933478 -0.836239 +-0.363235 0.647656 -0.0540754 0.517371 -0.897888 -0.127308 0.76276 0.95806 +0.73717 -0.579742 -0.515394 -0.0900528 -0.422909 -0.867229 0.118616 -0.619266 +-0.789218 0.395874 -0.263162 -0.218993 -0.989462 -0.412965 -0.34815 -0.252564 +-0.167916 -0.867763 0.562551 -0.132474 -0.828412 -0.239798 -0.527397 0.525177 +-0.677053 0.60444 0.166432 -0.622612 -0.99513 -0.904785 0.469131 -0.122162 +-0.86848 0.743779 0.136043 -0.0355452 -0.858098 0.337151 -0.20756 0.754075 +0.898261 0.333916 0.578844 0.0165041 -0.482019 0.268773 -0.232733 -0.511812 +-0.310141 0.984661 -0.0355772 -0.0615404 0.261641 0.772658 -0.415472 -0.739663 +-0.931102 -0.96816 -0.456587 -0.761168 -0.181398 0.427283 -0.569672 0.325545 +0.548456 0.437026 -0.0967424 0.874929 -0.945728 0.219869 -0.28097 -0.0350449 +-0.924421 0.0953952 -0.945492 -0.741848 -0.88119 -0.788247 0.154273 0.823235 +-0.349462 -0.300058 0.516437 0.790399 0.0226538 -0.397157 -0.652717 -0.210641 +-0.0566707 -0.958777 0.944967 0.571243 0.0727161 0.954246 -0.989825 0.312317 +0.0674175 -0.199475 0.602463 0.140729 -0.523178 0.944059 -0.133752 -0.55164 +-0.858503 0.430255 -0.320692 0.274377 0.981339 -0.487528 0.65521 0.0438374 +0.633114 -0.331395 -0.1199 -0.430513 0.601308 -0.342459 -0.0434577 -0.23422 +0.0754465 0.685361 -0.405587 0.831622 0.147556 0.803707 0.751314 0.867704 +-0.798783 0.575314 -0.0780584 0.374875 -0.78028 -0.55593 -0.652663 0.0566913 +0.545555 0.333988 0.293725 -0.458525 0.725412 0.210956 0.0573337 0.659658 +-0.919578 -0.276029 -0.394873 0.0204002 -0.492932 0.356923 -0.966322 -0.217896 +0.254969 -0.724236 0.629989 0.909324 -0.492372 -0.91706 -0.988393 -0.784333 +-0.64209 -0.846022 0.747568 -0.742917 -0.467237 0.808793 -0.607423 0.783012 +-0.062119 -0.0346325 -0.981145 -0.242132 0.468866 0.177845 0.279318 -0.407476 +-0.82309 -0.475214 0.816436 0.80076 -0.828438 -0.0744201 -0.755459 -0.592288 +0.188374 -0.824065 -0.364972 0.265613 -0.0671335 0.862794 -0.559167 -0.185972 +0.956574 0.443286 0.938111 0.99978 -0.61782 0.606602 -0.710399 -0.399743 +0.373872 -0.536204 0.879088 0.830825 -0.37226 -0.62618 -0.737087 0.528716 +-0.247862 -0.08905 -0.885543 0.631119 0.999098 0.950532 -0.865904 0.301747 +-0.543677 -0.777999 -0.103366 -0.767815 0.206858 -0.327054 0.269201 0.834288 +0.584777 -0.0853758 -0.391491 -0.874293 -0.160799 -0.864734 0.420523 0.137826 +-0.104722 -0.664662 -0.188868 -0.367055 -0.602064 -0.943215 0.368623 0.130933 +0.755609 0.954666 0.538894 0.323516 0.691233 -0.427272 -0.583608 -0.143928 +-0.872202 -0.0515559 0.462139 0.544525 -0.582221 -0.119367 -0.723396 0.663627 +-0.0425203 0.780898 -0.431425 0.25698 0.421757 0.54623 -0.185291 0.06734 +-0.526959 -0.255149 -0.852612 0.00240849 -0.596438 0.487974 0.996254 -0.277034 +-0.250355 -0.542272 -0.0105174 0.965026 0.842351 0.742194 0.360429 0.392727 +-0.0712163 0.215971 -0.655292 -0.417113 -0.604008 0.505837 0.188779 0.778084 +0.72285 0.0481556 0.338723 -0.620417 -0.0949132 0.170445 -0.886654 -0.667965 +0.0722872 -0.884601 -0.398315 -0.570663 -0.717769 0.293513 0.86843 0.131688 +0.635362 -0.217584 -0.801661 -0.159571 -0.64837 0.170806 -0.0798785 0.00159534 +-0.522543 0.623366 -0.975635 0.486717 -0.697985 -0.480893 0.242301 0.907825 +-0.682965 -0.862529 -0.529999 -0.469402 -0.0689268 0.638641 -0.261971 0.162454 +0.924986 -0.838339 0.41012 -0.328706 0.0662599 0.841739 0.787578 0.621908 +0.855472 0.881251 0.036657 -0.778922 0.213021 0.511113 -0.634199 -0.989152 +0.702894 -0.237175 0.525947 -0.593405 -0.934287 0.942147 0.223931 0.175514 +0.360713 0.796448 0.00851988 0.649489 0.439841 -0.908649 -0.743818 0.980769 +-0.887181 -0.988196 0.326568 0.529733 -0.17162 -0.474393 0.779824 0.836944 +0.469429 -0.546156 0.0698695 0.699024 0.601318 0.350035 -0.394446 -0.905387 +0.960154 -0.711228 -0.778727 0.480277 -0.643098 0.129766 0.839766 -0.683655 +0.152151 0.482563 0.257712 0.12372 0.852753 -0.958938 0.57036 0.157611 +-0.0485753 0.556195 -0.229038 0.588178 -0.70367 -0.597682 0.822591 -0.521196 +0.436099 -0.126062 -0.4454 0.134319 0.0551376 0.796622 0.202384 0.890468 +0.965482 0.626513 -0.562947 -0.269078 0.39698 -0.742422 0.130553 0.929076 +0.683358 -0.97097 -0.730346 -0.68618 -0.0400286 0.235318 -0.867485 -0.346546 +0.333295 -0.445525 -0.963462 -0.533717 -0.449516 -0.601454 -0.245269 -0.299874 +-0.447599 0.153277 0.601545 -0.917766 0.631199 0.671554 -0.348887 0.971254 +-0.987207 -0.0343355 -0.264064 -0.632789 -0.645582 0.850846 -0.43561 -0.139635 +0.507676 0.745846 -0.57733 -0.116314 -0.804799 -0.871462 0.231639 -0.457229 +-0.352731 -0.483039 -0.608581 -0.240055 -0.194946 0.390388 0.0721848 0.37785 +-0.108104 -0.372327 0.56838 -0.513627 0.789168 0.587824 -0.939963 0.0481087 +-0.0373395 -0.477224 0.386216 0.981896 -0.442703 0.978169 -0.535139 0.0158854 +-0.768252 -0.79301 0.720239 -0.911349 0.897648 -0.690076 0.215503 0.499193 +0.501812 0.255198 0.1391 -0.158408 -0.153084 0.220766 0.332727 0.583619 +-0.745589 -0.953123 0.740416 -0.965433 -0.946512 -0.984059 -0.221339 0.166907 +-0.983864 0.676227 0.55923 0.0408475 -0.923848 0.768858 0.656617 -0.820871 +0.205957 -0.321971 0.997178 0.863801 -0.95386 -0.212687 -0.552148 -0.994185 +-0.751285 0.891413 -0.251897 0.219731 -0.846847 0.491592 0.437694 0.305215 +-0.49895 -0.943796 0.107967 0.858461 0.739407 0.935811 -0.872678 0.667908 +-0.662264 0.617156 0.219431 0.923692 0.968059 0.905166 0.188744 -0.21665 +0.265055 -0.160066 0.275978 -0.180617 0.838283 -0.840746 0.622687 -0.586854 +-0.563731 -0.00539522 -0.436826 -0.268258 -0.167928 -0.151694 0.836768 0.0803586 +0.678223 0.192053 0.294282 -0.792568 0.520835 -0.374463 0.73826 -0.804014 +-0.422662 0.920872 -0.74267 -0.913076 -0.482928 -0.427512 0.0909748 0.476928 +-0.395764 0.573938 -0.339744 0.0564879 0.121589 0.327182 0.76153 0.029828 +0.357279 -0.0736123 -0.216815 0.993638 0.554024 0.945262 0.9521 0.992713 +0.41563 0.835111 0.333971 0.243163 0.854872 -0.244089 0.821639 -0.601421 +-0.547932 -0.802817 0.165144 -0.918539 0.0972188 -0.296996 -0.214255 -0.767947 +0.939733 -0.107441 -0.176512 0.927349 -0.739474 0.422475 -0.970313 0.188903 +-0.963026 0.594481 -0.228628 -0.341258 -0.933545 -0.716736 -0.943601 -0.480241 +-0.976579 -0.734036 0.139383 -0.525071 0.275555 0.733044 -0.164632 0.877818 +0.469534 -0.157197 -0.340027 -0.229847 -0.907174 -0.812643 -0.377661 -0.668763 +0.160111 -0.981113 -0.454339 -0.839043 -0.272351 0.81987 0.199865 -0.449337 +0.748273 0.510208 -0.994967 0.925383 -0.24439 0.999317 -0.226718 0.471643 +-0.867453 -0.532115 0.0845664 -0.819005 0.0369521 -0.0195426 0.542037 0.15077 +-0.689657 -0.948521 0.617848 -0.52699 -0.572121 0.167283 -0.65349 -0.00733644 +-0.705351 0.432267 -0.416052 -0.255617 0.2413 -0.96528 0.741295 0.595977 +-0.746777 -0.218203 -0.882464 0.451746 0.714665 -0.281248 -0.800118 -0.54971 +-0.740157 -0.354166 -0.155435 -0.32114 0.324222 0.163949 0.918079 0.841913 +0.0871473 0.811038 0.610476 0.542277 -0.380087 -0.624198 0.176843 -0.322804 +-0.966303 -0.610082 0.351537 0.537812 -0.56573 0.896842 0.0409576 0.938087 +-0.89567 0.550195 -0.421399 -0.773171 -0.095841 0.89622 0.224035 0.425158 +-0.23045 0.0829561 -0.960155 -0.878914 -0.693009 0.843461 -0.698353 -0.125659 +0.361473 -0.514447 -0.171557 0.475797 -0.0174048 -0.528989 -0.971387 0.288903 +0.863352 -0.613576 0.402034 0.926998 -0.562214 0.791953 0.29749 0.131722 +-0.358312 -0.319234 -0.541508 -0.476338 -0.724377 -0.0146154 0.0106356 -0.161128 +0.348456 -0.460724 0.553631 0.491866 0.583169 0.914039 0.762895 0.812704 +0.646607 -0.547933 0.775984 0.306783 0.5141 -0.744085 -0.90439 -0.121258 +-0.0858139 -0.0963209 0.159597 -0.90429 0.707903 -0.75263 0.405992 0.362285 +0.0398405 0.941671 -0.886079 0.0271912 0.213453 -0.836911 0.485894 -0.555229 +-0.292586 0.667731 -0.555299 0.814736 0.342754 0.570431 0.89559 0.194648 +0.175206 -0.125579 0.156772 -0.674121 0.149871 -0.929366 -0.754064 0.0298566 +0.185215 -0.214766 0.126068 -0.917025 0.880563 0.683523 -0.805319 -0.130271 +0.223479 0.302833 -0.423818 -0.283243 -0.147496 0.674922 -0.275212 0.287667 +-0.844565 -0.649853 0.0212764 -0.119313 -0.871784 -0.202159 0.588148 0.708281 +-0.620201 -0.448051 -0.497644 0.59911 0.367225 0.178448 -0.857665 -0.885693 +0.136695 -0.223891 0.875414 0.925696 0.717649 0.0990003 0.339096 0.151777 +-0.700985 0.328839 0.0452361 0.510211 0.231076 -0.822707 0.578956 0.618465 +-0.66974 -0.504158 0.997141 -0.983956 -0.601804 0.83153 -0.251907 0.131129 +-0.23875 -0.276582 -0.763665 -0.286273 -0.578402 -0.605575 0.487201 -0.264368 +-0.279441 -0.75415 0.653356 0.313241 -0.162724 0.550417 -0.422391 -0.67508 +0.556955 0.692698 -0.559814 -0.740492 0.55263 -0.948635 0.944135 0.452505 +0.887133 -0.381995 0.565063 -0.918914 0.0693192 -0.354579 -0.201351 -0.528456 +0.488967 -0.813855 0.700582 -0.591998 0.00517579 -0.259065 0.730442 -0.162142 +-0.188417 0.54958 -0.466756 0.958246 -0.770873 -0.351427 0.256662 -0.887696 +0.940295 -0.359559 -0.383567 -0.418849 -0.0287466 -0.2082 0.912299 0.906447 +0.355532 0.219688 -0.592271 0.408647 0.963538 0.442974 0.255207 -0.54769 +0.999579 -0.647976 -0.430347 0.313431 0.956103 0.0244352 -0.21198 -0.781166 +-0.609333 0.695023 -0.00585951 -0.429169 -0.468694 0.64518 0.565546 0.786551 +0.539956 -0.76661 0.479248 -0.395474 0.989707 -0.869991 0.35182 -0.200015 +-0.610083 0.456946 -0.749989 -0.540906 -0.25171 -0.55211 0.122659 0.182224 +-0.289133 0.118245 -0.706109 0.000286182 -0.507599 0.659099 -0.352538 -0.548111 +-0.575608 0.431426 -0.435646 -0.0638061 0.573575 -0.772363 -0.543486 0.171232 +0.361416 0.79796 -0.0645699 0.121489 -0.174803 0.689077 -0.950937 -0.772784 +0.355538 0.997686 -0.324652 0.408147 0.100385 -0.83699 0.362303 0.812052 +0.57894 -0.42062 0.105521 -0.0371584 0.294148 -0.960073 -0.987327 -0.716768 +0.675003 -0.950628 0.962732 0.145438 0.0151505 0.670395 -0.702705 -0.955056 +0.368931 0.25731 0.848675 0.393233 0.365112 0.704958 -0.964903 -0.337374 +-0.0870159 -0.895422 0.530613 0.3966 0.420916 0.913206 0.92198 -0.08298 +0.525101 -0.81229 0.565656 -0.533193 -0.202546 0.475332 -0.218514 -0.88693 +-0.924348 -0.269925 0.180285 0.344104 -0.300888 -0.519645 -0.504408 0.0156576 +-0.275531 0.39835 -0.512057 -0.0724003 0.314598 -0.299159 0.524368 -0.874405 +-0.862982 -0.511945 -0.349759 0.142268 -0.123326 -0.418009 0.302254 -0.0370469 +-0.472337 -0.34847 -0.0240024 -0.320894 0.652825 -0.565138 0.952537 -0.976899 +0.162668 0.97598 0.328564 -0.641333 -0.157184 0.715958 0.139089 0.171088 +-0.715707 -0.792925 0.851959 0.0239201 0.229325 0.888776 0.242874 -0.0956594 +0.0730154 -0.22137 -0.930213 0.691392 -0.0133478 -0.183844 0.828858 0.719249 +0.710041 -0.0774391 -0.214347 -0.0990236 0.389698 0.976301 -0.893467 0.198271 +-0.755695 0.741752 -0.31524 0.812909 -0.769951 -0.288885 0.267208 -0.218886 +-0.886653 -0.633374 0.808661 0.745247 0.124286 -0.5126 -0.995492 -0.5198 +-0.692688 -0.147346 0.187424 -0.925055 -0.439214 -0.111269 -0.975173 -0.658201 +-0.831075 0.673083 -0.873982 0.888561 -0.909797 -0.477867 0.93234 -0.282008 +-0.290956 0.856362 -0.537572 0.862711 0.0502476 0.436749 0.634669 -0.055289 +-0.948314 -0.463479 -0.271359 0.83194 0.876005 -0.380152 0.564686 0.842261 +0.651726 -0.349592 -0.672053 0.811869 0.169962 -0.133927 -0.172151 0.0341328 +0.759291 0.358957 -0.58414 -0.530041 0.60161 -0.528868 -0.0799708 -0.307838 +0.671058 -0.459334 -0.689521 0.266444 -0.388679 -0.924294 -0.772005 -0.165673 +-0.642888 -0.736954 -0.424283 -0.104637 0.246528 0.137349 0.0379861 0.832927 +-0.170774 0.0669082 -0.6996 -0.579342 0.34972 -0.348279 -0.35229 -0.270538 +-0.945031 -0.524023 -0.552039 -0.114057 0.234116 0.501137 0.977221 -0.395418 +-0.409068 0.69399 0.374419 -0.0462875 -0.0465554 0.766255 0.774782 0.675965 +0.779158 -0.166837 0.821032 -0.714979 0.686341 0.539111 0.566031 0.277188 +0.538449 -0.848217 0.206875 0.862397 -0.38221 0.405983 0.282527 0.737116 +0.898407 -0.176659 0.0464721 -0.174439 -0.270702 0.100901 0.520358 -0.561523 +-0.979069 0.967672 0.792619 -0.610577 -0.974206 -0.751801 0.74998 -0.749505 +0.263804 0.723652 0.739677 -0.842901 -0.860151 -0.705391 -0.62765 -0.382012 +-0.130688 -0.30586 0.0984786 -0.262746 0.489062 -0.202678 -0.427006 0.896134 +0.516793 -0.0821588 -0.223608 -0.479332 -0.338764 -0.166683 0.511858 -0.188652 +-0.308261 0.0582935 -0.907996 0.145248 0.173322 0.894237 0.930443 0.37919 +-0.055568 -0.843438 0.895721 -0.894053 -0.602729 -0.347945 0.548196 0.767499 +-0.360557 -0.832566 0.938689 -0.968412 -0.498284 -0.0476192 -0.630211 0.169322 +-0.340761 0.225727 0.626826 0.770033 -0.589029 -0.869995 0.635105 0.140516 +-0.275869 0.150278 0.226437 -0.35612 0.307429 -0.514314 -0.102084 0.787112 +-0.56936 0.715269 0.483321 -0.677539 0.718327 -0.996698 0.288105 -0.329191 +0.0826611 -0.905288 0.948848 0.561249 0.103266 0.4488 -0.35026 -0.197099 +-0.880391 0.224373 0.950568 -0.3324 0.396463 0.578104 -0.967929 0.271137 +0.993101 -0.461551 -0.621999 0.619373 0.783432 0.365015 -0.34766 -0.600584 +0.00402216 0.290309 -0.904297 0.656952 0.191966 0.370522 0.332878 -0.24234 +0.214094 0.438921 -0.78707 0.688227 0.90262 0.885032 -0.451939 -0.305912 +-0.777585 -0.708842 -0.858883 -0.251773 0.374764 0.595089 0.312957 0.775746 +-0.740073 -0.108861 0.455241 0.86918 0.569907 -0.962557 -0.25648 0.804496 +-0.912671 0.499386 -0.95459 0.381183 -0.848648 0.988888 0.707242 0.510946 +-0.0352051 -0.0379785 0.4072 -0.0128833 0.807337 0.425928 0.570978 -0.910252 +0.626974 0.482988 -0.410612 0.175324 0.130045 -0.64675 0.20158 0.252041 +0.093055 -0.381027 0.343075 0.32612 -0.0966218 -0.24313 -0.0175112 -0.152642 +0.848891 0.0384485 -0.0553651 0.589269 -0.78618 -0.126579 -0.719034 0.482478 +-0.729124 0.43077 -0.00256574 0.33618 0.517282 0.329004 -0.295313 0.785522 +0.858593 0.167835 0.483022 0.119475 -0.515303 0.565839 -0.0836063 -0.654593 +-0.730218 0.591172 -0.898234 0.986936 0.836221 -0.975197 -0.810416 -0.76165 +0.695011 -0.868217 0.470301 -0.99774 0.692654 -0.0821989 -0.0844141 -0.423707 +0.400773 -0.0689255 0.0364469 0.876054 0.0382845 0.0188337 -0.350705 -0.151997 +-0.720572 0.586418 -0.199424 0.926402 0.615271 0.111343 0.427535 -0.369212 +-0.53713 -0.27109 -0.856338 0.554745 0.123548 0.522981 0.628222 -0.299325 +0.953218 -0.683508 0.684732 0.871014 -0.164698 -0.639858 -0.329335 0.517082 +0.0442618 -0.516209 0.15372 0.669799 0.506915 -0.571725 0.554727 -0.544378 +0.436668 0.928487 0.347232 -0.43956 -0.685853 -0.355098 0.574867 0.577127 +0.403338 0.200018 0.121288 0.0687721 0.395435 0.20708 0.929302 0.133507 +-0.0135593 -0.0567897 0.716383 -0.829264 -0.447934 0.797416 0.113515 0.57257 +-0.469182 -0.69959 -0.886091 -0.48694 -0.328326 0.63613 0.72095 -0.105447 +-0.347547 0.834653 0.326223 -0.232592 0.442301 -0.584429 -0.161556 0.221195 +-0.817152 -0.648083 -0.6338 -0.617803 0.877637 -0.309426 0.986573 -0.761129 +0.0437569 -0.917417 -0.901463 0.187357 0.262695 0.0747365 -0.75528 0.998739 +-0.707196 -0.956231 -0.0671567 0.533672 -0.756212 -0.024034 0.130722 -0.219808 +-0.135062 0.522076 -0.63458 -0.357056 0.770788 -0.60991 -0.279767 -0.308377 +0.559967 -0.91155 -0.649344 -0.202197 0.0450569 0.0936384 0.960643 0.862273 +0.321983 -0.58597 0.817368 -0.983835 -0.369924 -0.712908 -0.806488 -0.481701 +0.185647 -0.00648949 0.966832 0.442513 0.850818 0.018954 0.710457 -0.277024 +-0.972975 0.0417475 -0.652856 -0.418745 0.791432 -0.260435 0.755233 0.586012 +0.982456 -0.0963127 0.297784 0.437391 0.0971326 -0.654282 -0.813028 -0.845197 +-0.923037 -0.141157 -0.419079 -0.135268 0.340604 0.906165 0.440158 0.465527 +0.145523 0.263577 0.71804 -0.89 -0.45117 0.899872 0.53504 -0.94317 +0.524796 0.768644 -0.802586 -0.0936898 -0.749671 -0.0920919 0.749551 -0.626382 +-0.80644 -0.891784 0.31891 -0.120768 0.16823 -0.516945 -0.345036 -0.568261 +0.793169 -0.978639 0.27872 -0.959108 -0.338635 -0.117787 0.152006 -0.855402 +-0.870878 -0.474037 -0.901367 -0.212822 0.443774 0.341581 -0.249137 0.542928 +0.0741436 0.130848 0.354614 -0.265943 -0.668795 0.483405 0.685919 -0.383351 +0.878892 -0.131983 0.560014 -0.424243 0.116246 0.331165 0.533075 0.0968753 +-0.403953 0.380238 -0.242981 0.222949 0.712495 -0.216949 0.932865 -0.0829776 +-0.69437 0.174616 0.783624 -0.576855 0.0601987 -0.0695508 -0.545245 -0.441067 +0.102256 0.980114 0.118383 0.556969 0.344759 -0.240915 0.154121 -0.140074 +-0.799409 -0.444041 0.964764 -0.844537 -0.658997 0.636795 -0.362719 -0.0759832 +-0.0020397 -0.390442 -0.807246 -0.426076 -0.786194 0.712275 -0.016741 -0.435245 +-0.022729 0.975231 -0.591688 0.814654 -0.565707 -0.335615 -0.803594 -0.897355 +0.659914 -0.433625 -0.0638004 -0.799626 0.844321 0.174313 0.484576 -0.518126 +0.0825412 0.995173 -0.030989 -0.577059 0.113051 0.53154 -0.837545 -0.869107 +-0.985299 0.251115 0.392605 -0.0264367 0.411883 0.861677 0.440783 -0.700776 +0.657025 0.228187 0.483658 0.0184127 0.510077 0.640849 -0.429233 0.645621 +-0.212764 0.979465 -0.0700215 0.852905 0.745117 -0.740672 0.592321 0.476026 +-0.0570856 -0.206335 -0.567143 0.251576 0.973209 -0.0473433 -0.550067 0.153031 +0.361088 0.423245 -0.958558 0.243484 0.746056 -0.695582 0.312399 -0.823769 +0.74667 -0.839898 0.870564 -0.55274 0.240814 0.220124 -0.909308 -0.315429 +0.332682 -0.374113 -0.888994 -0.699781 -0.519364 -0.68096 0.0941501 0.500746 +-0.478334 0.642977 0.578055 -0.402882 0.287253 0.26079 -0.545313 -0.790074 +0.279175 0.79182 -0.0225746 0.105242 -0.0304137 -0.668448 0.331735 -0.55909 +-0.0788047 -0.381013 0.292915 0.553269 0.168335 0.213994 -0.51418 -0.391753 +0.265128 0.840426 -0.822027 0.560019 -0.397816 0.177753 -0.0649444 -0.75469 +-0.837923 0.475437 -0.775741 0.111428 0.713371 0.927307 0.824662 0.630516 +-0.554579 -0.34954 0.281128 0.571655 -0.400387 0.541733 -0.439061 0.237519 +-0.737327 0.315332 -0.467477 -0.682537 0.370516 0.319608 0.27339 0.36382 +-0.185508 0.33086 0.676371 -0.701803 -0.254673 -0.900504 -0.50075 0.551068 +0.972067 0.507886 -0.650132 -0.135926 0.306056 -0.256413 0.922394 -0.156155 +0.395757 -0.527971 0.159301 -0.263157 0.587493 -0.478528 -0.621343 -0.289296 +-0.855766 0.494758 -0.146443 0.666901 0.399917 0.204614 -0.929095 0.276574 +0.106647 0.129908 0.801299 -0.469317 0.912648 0.813049 0.709985 0.0299976 +-0.447052 -0.294152 -0.984121 0.826067 -0.758664 0.859195 -0.887033 -0.126497 +-0.525572 0.297714 -0.467697 -0.996458 -0.156444 -0.780756 0.684544 -0.849622 +0.338088 0.0297275 0.176656 -0.107333 0.66221 0.470726 0.425236 0.712842 +0.265663 -0.679335 0.928894 -0.514168 -0.652477 -0.60961 -0.581951 0.475835 +-0.682929 0.850813 -0.828784 0.92308 -0.731889 0.410259 0.900516 -0.224582 +-0.985953 0.171351 -0.259284 -0.358424 -0.427112 0.171932 0.0957721 -0.918852 +0.649038 -0.181069 0.847588 -0.0878832 -0.660489 -0.190686 0.291881 -0.371576 +0.386358 -0.526922 0.0181347 0.132002 0.799416 -0.0414992 0.346399 0.987424 +0.0904239 0.919841 0.472689 -0.299126 -0.30447 0.839527 -0.186602 -0.0457745 +-0.314095 -0.0583921 -0.174376 -0.458928 0.89156 0.318632 0.776904 0.598496 +-0.502987 0.248515 0.776473 0.685687 0.187229 -0.331967 -0.740824 0.192051 +0.453311 0.456026 -0.197498 -0.0530535 -0.811066 0.215611 0.05142 0.827801 +0.668463 -0.816578 -0.630663 -0.947085 -0.560805 -0.55766 0.582363 -0.176172 +-0.571445 -0.931439 -0.00676455 0.994012 0.514398 -0.066941 0.13035 0.614353 +0.499379 -0.203294 0.872702 0.329388 0.347085 -0.684774 0.186549 -0.741651 +-0.496264 0.169345 -0.0523917 0.00680297 0.321116 -0.0408015 0.827076 0.405007 +-0.742955 -0.496809 -0.655286 0.608952 0.941601 -0.400993 0.436962 -0.859172 +-0.343765 0.42654 -0.878849 0.887708 0.136542 0.333953 0.278177 -0.883513 +0.334913 0.549629 0.260482 0.214592 -0.812072 0.806985 -0.672151 0.223634 +0.350486 0.700689 0.264024 -0.0858438 -0.736967 0.910123 -0.0365574 -0.721711 +-0.758495 -0.71386 0.269364 0.654538 -0.127509 0.490754 0.505888 -0.227744 +-0.410972 0.825348 0.556706 0.93449 -0.315437 0.046301 -0.355252 -0.499265 +-0.198761 0.693901 0.0809512 0.598022 0.216152 -0.0557807 0.633541 -0.920389 +-0.105208 0.820162 -0.841928 0.197307 0.775155 0.479185 -0.0129137 -0.920868 +-0.00289153 -0.848301 0.497239 -0.116999 -0.778492 -0.449622 -0.307548 0.707701 +0.643452 0.805278 -0.868296 -0.663651 0.964767 -0.598762 -0.95075 0.814099 +0.702587 0.022535 -0.382656 0.605942 -0.69756 0.38932 -0.194961 -0.371336 +0.725439 -0.73543 0.35924 0.221953 0.502839 0.170354 0.0902493 0.89545 +0.272991 -0.23815 -0.368274 -0.527361 -0.204286 0.144316 -0.55093 0.673088 +-0.221703 -0.277757 0.760379 0.261115 0.122372 -0.785284 -0.302733 0.707354 +-0.83038 0.631834 -0.848415 0.814266 -0.943272 -0.189483 -0.0581163 0.34286 +-0.744309 -0.560878 -0.157826 0.253617 -0.500915 -0.0487691 -0.349202 -0.270705 +-0.360954 -0.664127 0.859286 -0.280102 0.654414 -0.51319 -0.108095 -0.576189 +0.862022 -0.302638 -0.285045 -0.571026 -0.276549 -0.122277 -0.0148892 0.0524154 +-0.781367 -0.0358786 -0.862979 0.796873 0.718916 0.624263 0.492487 -0.412841 +-0.674732 0.44741 0.12108 0.165215 0.308106 0.877464 0.350762 -0.137168 +0.944773 -0.525673 0.539535 0.805693 -0.590677 -0.473832 -0.86767 0.230023 +-0.704677 -0.951173 0.238569 0.247775 -0.738827 -0.339384 -0.993212 -0.114532 +-0.903368 -0.0239983 -0.321369 -0.0601956 -0.808445 0.158124 0.624174 0.421578 +-0.849332 0.27961 -0.472397 -0.994164 -0.765143 -0.987517 -0.349657 -0.401462 +-0.640832 0.244533 -0.27625 0.841018 0.950529 0.621075 0.918131 -0.225662 +0.745814 -0.428672 0.646151 0.0741225 -0.0211338 0.464879 -0.851963 -0.916987 +-0.101954 -0.276708 -0.0872924 -0.49987 0.755351 -0.846396 0.710409 0.334835 +0.24353 -0.213543 -0.857267 0.322163 0.826677 0.459816 -0.569691 0.343797 +-0.498103 -0.0150314 -0.0622409 0.0777802 0.739183 -0.0612893 0.90107 0.211244 +0.783052 -0.32894 -0.61945 0.532135 0.282544 -0.993743 -0.118648 0.971226 +-0.0875874 -0.0864152 0.471729 -0.366368 -0.71376 -0.384434 -0.686004 0.868823 +-0.821418 0.670089 -0.0223627 -0.242403 -0.85078 -0.168284 0.158154 0.652704 +0.519088 -0.176841 -0.778506 0.170754 0.293266 -0.732885 -0.199528 -0.880297 +0.954958 -0.207707 -0.95033 -0.29616 0.381677 -0.835554 0.500021 0.272155 +-0.341774 0.503913 0.328025 0.530894 -0.426435 0.997955 -0.00143635 -0.236397 +0.675025 -0.705682 -0.117268 -0.59063 -0.261205 -0.909041 0.835805 -0.180595 +0.194336 0.217548 -0.0826236 0.322955 0.787922 0.635806 -0.601225 0.849099 +-0.883491 -0.532006 0.819639 0.00105429 0.921199 0.736782 -0.00753231 -0.0718162 +0.637852 -0.892649 0.827382 -0.336917 0.633483 -0.330272 -0.560808 -0.552755 +0.419203 -0.24472 -0.788399 0.827093 0.174324 -0.881508 0.288636 -0.167812 +-0.631573 -0.919389 -0.316457 -0.123103 0.191612 0.679214 -0.650922 -0.0655893 +-0.754231 -0.307079 0.286307 -0.707389 -0.555264 -0.532295 -0.979045 0.174008 +0.0956924 -0.376153 0.215392 0.931178 0.471885 0.350595 0.0816649 0.559682 +0.995234 -0.17001 -0.225094 -0.0199892 -0.476462 -0.620546 0.670361 -0.734298 +0.0618002 0.511107 0.126024 -0.911874 -0.515122 0.199259 -0.153888 -0.14643 +0.55341 0.814418 -0.401288 0.0908439 -0.411111 -0.159649 -0.094307 -0.901488 +0.268385 -0.42747 0.769464 0.743663 0.991108 -0.12387 0.382316 0.100802 +-0.997442 0.38077 -0.821689 0.210547 -0.818763 -0.969185 -0.995689 0.098865 +-0.941008 0.0415596 0.209826 -0.562129 0.737192 0.801041 -0.233382 -0.832159 +-0.756248 -0.713343 -0.845329 0.45093 0.980933 0.182862 -0.542358 -0.286078 +-0.0376019 0.958241 -0.304717 0.746084 0.433264 0.442267 0.404 0.54026 +-0.0714448 -0.714976 -0.96135 -0.222457 0.694713 0.740249 0.196941 -0.677119 +0.0420683 0.252027 -0.162027 -0.651752 0.0830012 0.664514 -0.73259 0.71592 +-0.820265 0.360586 -0.734685 0.140403 -0.956773 -0.189421 0.939188 0.210828 +-0.58817 -0.0206047 0.971823 -0.634373 -0.623086 -0.539548 0.606546 0.944775 +-0.981771 -0.846209 0.0250994 -0.294033 0.913781 0.234707 0.943602 -0.823085 +0.71755 0.25391 -0.265289 -0.186836 -0.0160964 0.733051 0.0945265 0.0544957 +-0.189257 0.291791 0.213208 0.276115 0.526883 -0.497135 -0.23261 0.357334 +-0.834497 -0.516587 -0.701262 0.758542 0.604283 -0.898403 0.483098 -0.725842 +0.286748 0.923059 -0.878815 -0.566687 0.109317 -0.454299 0.993513 -0.613102 +0.0633329 0.335537 -0.488599 0.458213 -0.876552 -0.594897 -0.805268 -0.113543 +-0.806828 0.252615 0.939087 0.9549 -0.468198 0.339006 -0.27214 -0.73677 +0.377358 0.7833 0.00540191 0.500714 -0.32138 0.0955231 0.911839 -0.86314 +-0.52298 -0.419656 0.48054 -0.568488 0.84489 0.700685 -0.935709 -0.649709 +0.779817 0.0622625 -0.70091 -0.299574 0.714823 -0.319211 0.0138431 0.534249 +-0.0930375 -0.928566 -0.501586 0.88442 -0.313336 0.0877296 -0.388998 -0.656063 +0.918037 0.965761 -0.526943 0.72899 -0.187046 0.569136 0.641175 -0.881373 +-0.868506 0.708643 -0.845511 0.0423333 -0.653447 0.104797 -0.971814 -0.0592641 +0.113582 0.0982362 0.296222 0.844357 0.618947 -0.76513 -0.357092 -0.226115 +-0.892713 -0.107977 0.780329 -0.117651 0.70063 0.113163 -0.881551 0.124592 +0.679055 -0.253271 -0.389185 0.273218 -0.168828 0.984187 -0.53537 -0.366435 +0.178635 0.0965333 -0.809133 -0.646821 0.598732 -0.690665 -0.12513 0.00995571 +0.596674 -0.0551118 -0.849999 -0.202192 0.720032 0.71466 0.433842 0.330282 +-0.360911 -0.0179244 0.617987 0.206179 0.439985 0.941844 0.260142 0.958835 +-0.130109 -0.608319 -0.407372 0.258944 -0.546059 -0.149142 -0.414605 -0.930047 +0.246275 -0.307401 0.885364 0.931141 0.850374 -0.507991 0.993946 0.860865 +-0.00735639 -0.376057 -0.141489 -0.0791886 -0.94232 0.262036 -0.332814 0.864286 +-0.623501 -0.108497 -0.915583 -0.197976 -0.0446641 -0.98592 0.0157384 -0.285527 +0.0800298 -0.211889 0.183531 -0.0259725 -0.140507 0.331835 -0.441566 -0.0824537 +0.349123 0.101694 0.648666 0.423303 0.0503596 -0.634703 -0.758321 0.878317 +0.968075 -0.888882 -0.885247 0.239309 -0.430522 -0.557886 0.981217 -0.861691 +-0.25365 -0.251681 0.41785 0.255933 0.790183 -0.082351 -0.145108 -0.714586 +0.325073 0.906998 -0.146159 -0.832511 0.191264 -0.742264 0.342077 -0.0963672 +0.475946 0.68986 0.0607583 -0.617167 -0.866828 -0.35384 0.658142 0.6789 +0.998507 -0.322951 0.907556 -0.574775 0.905785 -0.941915 -0.971645 -0.716665 +-0.669851 0.267652 0.273679 -0.0975457 0.235855 0.946079 0.683143 -0.732098 +0.48798 0.528768 0.166133 -0.59308 -0.569879 -0.573397 0.260883 0.32438 +-0.511057 -0.640244 -0.492433 -0.573725 -0.0806553 0.124341 -0.277098 -0.638164 +-0.747998 -0.484261 -0.849188 0.115952 0.180504 -0.667777 -0.969912 0.0727628 +0.963349 0.761828 -0.745403 -0.43181 -0.487012 0.827165 -0.646577 -0.160079 +-0.764275 0.907474 0.329591 0.159052 0.290096 0.163844 -0.327156 0.387687 +0.615459 0.56839 0.487407 0.917093 0.0743702 -0.484865 0.461471 0.917078 +-0.708641 0.835115 -0.372658 0.254261 -0.423061 0.268536 0.485171 -0.664508 +-0.660714 0.978831 0.241741 -0.737719 -0.0879775 -0.0736933 0.328497 0.62788 +0.365053 0.219433 -0.973205 -0.354778 -0.325695 0.831896 0.639059 -0.630742 +0.784274 -0.6332 -0.133621 -0.568539 0.423926 0.530975 0.772903 0.969602 +0.689438 -0.272964 0.691828 -0.127472 0.157738 0.113051 -0.589811 -0.750684 +0.381831 -0.0884335 0.0316414 -0.230055 -0.0134921 -0.284282 0.59055 0.749157 +0.403634 0.829692 0.245198 0.247367 0.887491 -0.314775 -0.00336517 0.915281 +0.407755 -0.141263 0.0458666 0.710067 0.413619 -0.754431 0.411961 -0.326802 +0.501326 -0.222584 0.20897 0.731039 -0.225906 -0.81537 -0.225643 -0.624335 +-0.331887 0.360021 0.629249 0.011293 0.294649 0.993715 0.913614 0.512187 +-0.966964 0.413302 -0.228988 0.600816 0.949428 0.491869 -0.135294 -0.61582 +-0.743862 -0.671765 0.630707 0.465107 0.898169 -0.693695 0.777233 -0.095741 +-0.603113 0.402744 -0.806204 0.347373 0.310882 -0.43267 -0.26291 -0.542884 +-0.247632 0.294954 0.781344 -0.356017 -0.900273 -0.382095 -0.562438 0.941904 +0.0925794 -0.160435 0.378564 -0.893988 -0.965652 -0.222735 0.000143474 0.226441 +-0.611725 0.338148 -0.239605 0.609967 -0.259542 -0.454734 -0.639997 0.346785 +-0.710872 0.728833 0.27258 0.950759 -0.797826 -0.301731 -0.101216 0.425688 +0.374105 0.587368 0.659061 0.353339 -0.499129 -0.97268 0.25812 -0.210001 +0.364602 0.345639 -0.229452 -0.515252 -0.0821484 -0.349889 0.391311 0.880473 +-0.392072 0.27623 -0.0272775 0.681752 -0.313177 0.335266 -0.141426 -0.102619 +0.290725 -0.989626 0.071846 -0.233169 0.569509 -0.739351 -0.389236 -0.671164 +-0.846608 0.266524 0.966217 0.151338 -0.895552 -0.437395 -0.700916 0.224747 +0.868884 -0.113134 -0.0122065 -0.117899 0.423913 0.232129 -0.351079 0.470261 +0.283962 -0.17001 0.0315349 0.256011 -0.639937 -0.37519 0.305536 0.614595 +0.199122 -0.216066 0.00690402 0.900753 -0.439018 -0.368711 0.624255 0.1382 +-0.0846128 0.0448389 -0.792859 -0.683196 -0.111982 0.4918 -0.773415 -0.637275 +-0.69179 0.922291 0.514366 -0.359919 0.919197 -0.212761 -0.0490307 0.159089 +-0.592126 0.913464 0.373748 0.686366 -0.0837567 0.582358 0.542379 -0.710981 +0.776816 -0.0300756 0.593407 0.385193 -0.18663 -0.101923 -0.448378 0.79683 +0.876291 0.682979 0.00792547 0.590353 0.0662863 0.827135 0.36273 0.703052 +0.619674 -0.738234 0.117859 0.897781 -0.763085 -0.59241 -0.300285 0.763047 +0.151579 0.447337 0.13128 -0.542545 -0.548617 -0.968609 -0.345168 -0.261123 +-0.412593 0.649262 -0.0421784 -0.970225 0.274411 -0.692277 0.692538 0.718578 +0.323079 0.506911 0.97922 0.658567 -0.37656 0.274636 -0.327808 -0.163211 +-0.198701 0.898417 -0.686527 -0.455088 0.294022 -0.627006 -0.36186 -0.913923 +0.424909 -0.0379385 -0.965039 -0.977996 -0.0997874 0.328052 -0.014271 0.736479 +0.787764 0.777855 -0.477795 0.749913 0.740409 0.194397 -0.514953 -0.0555138 +0.555525 0.927322 0.194017 -0.622111 0.399491 0.846684 -0.602196 -0.51277 +0.114974 0.128285 -0.391519 0.684282 0.656746 -0.072509 0.86117 0.191379 +-0.141111 0.417114 0.427917 -0.0169738 0.581725 -0.173114 0.205534 0.831369 +-0.667783 0.920361 -0.164443 -0.699943 0.328983 0.178066 0.324884 0.483594 +0.290897 0.590753 0.800007 -0.406528 0.0108895 -0.481459 0.762413 -0.87964 +-0.0374459 0.455109 0.583535 -0.407589 -0.641308 0.743001 -0.0543311 0.931398 +0.105705 -0.808965 0.622163 0.119456 -0.0576327 0.86564 -0.485867 0.536879 +-0.853874 0.378509 0.543008 -0.199228 -0.214181 -0.837815 -0.321409 -0.353931 +-0.722147 -0.252559 0.152847 -0.275855 -0.811723 -0.416028 -0.459245 -0.793537 +0.193833 0.423986 -0.281668 -0.529538 -0.414685 0.195773 0.530865 0.663184 +-0.658142 0.916743 0.103524 0.893851 0.248385 -0.863959 -0.493926 0.600878 +0.652699 0.372216 0.90989 -0.859484 0.459355 -0.664908 -0.943507 -0.264866 +0.267349 0.263592 0.942405 -0.160659 -0.690987 -0.137588 -0.126636 -0.763782 +0.420644 0.414345 0.270858 -0.751345 0.522227 0.75386 0.24366 0.713402 +0.920577 -0.37329 -0.673177 0.519007 -0.0448376 -0.801103 -0.132771 0.87576 +0.572886 0.965373 0.720584 0.0116552 0.157656 0.567011 0.0979474 0.858477 +-0.191483 0.0111142 -0.0405819 0.439271 -0.00114045 0.138384 0.952113 0.238512 +-0.878561 0.766138 -0.829573 -0.813322 0.69347 -0.384524 0.0914315 0.470025 +0.615343 -0.770406 -0.0247067 0.602883 -0.608007 0.42336 0.501264 -0.714984 +-0.890308 0.412663 0.482641 0.217433 -0.593223 0.0251279 -0.830907 -0.538826 +0.284212 -0.740456 -0.250777 0.610698 -0.43747 -0.931171 0.726396 0.511639 +-0.975656 0.393448 -0.900851 -0.685102 0.952177 -0.523442 -0.115032 -0.583663 +0.743824 -0.520495 -0.680266 0.807349 0.83317 0.114616 -0.513738 -0.73344 +0.229743 0.930853 -0.689057 0.94333 0.378999 0.404477 -0.678043 -0.515842 +-0.200405 0.333877 -0.20619 -0.110618 -0.27048 0.971163 -0.0294844 0.241777 +0.711951 -0.664789 -0.668293 0.561827 -0.868251 -0.296878 0.606881 -0.998199 +-0.792886 0.066126 0.941762 0.205742 0.343292 -0.43991 0.159765 0.302223 +0.123834 -0.246352 0.688239 -0.800765 -0.632175 0.753347 -0.263937 0.245751 +-0.85339 -0.543006 -0.813026 -0.213682 -0.299409 0.880484 -0.0594784 -0.115971 +0.0247822 -0.986925 0.532953 0.910922 -0.445822 0.0334869 0.920333 0.882088 +0.42718 0.658115 0.369245 0.895163 -0.824924 0.175481 0.472521 0.0824934 +0.379481 0.345051 0.849693 0.504958 -0.189682 -0.943164 -0.703458 0.444428 +0.861471 0.244628 -0.243541 -0.792561 0.245301 -0.295087 -0.0212582 -0.378426 +0.979916 0.414535 0.659639 -0.387006 -0.417387 0.478365 -0.332829 0.777529 +0.616686 -0.37674 0.121101 -0.108845 -0.950854 -0.836815 -0.395289 0.65502 +0.991669 -0.274754 -0.136351 -0.728001 -0.876925 -0.37137 0.175147 0.723281 +0.832188 0.924674 -0.596478 -0.869862 0.881561 0.741873 0.651392 0.51925 +-0.427572 0.00906724 -0.558908 -0.589578 -0.338921 0.830095 0.26632 -0.740495 +-0.446695 -0.0702259 0.997073 -0.701311 0.899308 -0.129431 -0.567768 0.941529 +-0.790527 -0.672531 0.392716 -0.203615 0.850462 0.299535 -0.0747023 0.418255 +-0.59688 0.0231533 -0.0109927 -0.240299 -0.222859 -0.547847 0.478953 -0.604809 +0.239525 -0.867907 0.398413 0.367716 0.275771 -0.885413 -0.393816 0.143464 +0.930022 -0.675525 -0.0909771 0.0710653 0.0960455 -0.0694187 -0.052106 -0.591057 +-0.0231766 -0.864838 0.6411 0.344139 -0.201789 -0.262545 -0.557 -0.345325 +0.59342 0.152716 0.434344 0.89218 0.0986881 -0.780129 -0.868729 0.625606 +0.00818566 -0.488817 0.741293 0.42078 -0.263251 -0.840337 0.500478 0.142849 +0.660305 -0.480487 0.25653 0.165858 0.547334 0.211187 0.169976 -0.708666 +-0.272326 -0.863905 -0.978446 -0.0991408 -0.369753 -0.438594 0.823899 0.309049 +-0.0849499 -0.837982 0.539864 0.643419 0.0885973 -0.486783 -0.978469 -0.0165461 +0.317965 0.782542 0.0914338 0.31265 -0.129641 0.688271 -0.86896 0.731073 +-0.66639 0.95396 -0.25294 -0.661787 -0.119636 0.0576572 0.51083 0.823934 +-0.0862847 -0.831097 0.622062 0.480839 -0.837853 0.0321093 -0.203866 -0.459344 +-0.515805 -0.922669 -0.835204 0.444568 -0.0733216 0.794002 -0.323481 -0.0936258 +0.133534 -0.166693 -0.190366 -0.678033 -0.468401 -0.531849 0.564241 -0.122906 +0.881661 0.044731 -0.478211 -0.380869 0.890735 -0.860411 -0.794993 -0.194394 +0.0201941 0.732144 0.553071 0.766648 0.523756 0.952517 -0.0856112 0.143381 +0.198553 -0.0327278 -0.945738 -0.756521 0.331658 0.0809548 -0.89392 -0.885436 +0.647726 -0.516117 0.553898 -0.271229 -0.407122 0.199254 -0.509396 -0.33208 +-0.899161 -0.0597467 -0.74211 0.91456 -0.551628 0.525144 -0.374348 -0.978749 +0.964722 0.0358027 0.187102 0.0683323 -0.937071 -0.705447 -0.804941 -0.50421 +-0.151172 -0.337901 -0.96729 -0.915654 -0.465939 0.256953 -0.290618 -0.225787 +0.152924 -0.820449 -0.064029 -0.270565 0.972987 -0.346386 0.780181 0.517794 +-0.45025 0.613471 0.608074 0.891807 0.250031 0.525261 0.945701 -0.803949 +0.458817 -0.133452 0.499495 -0.693867 -0.122164 -0.121782 0.756054 0.59001 +0.729794 0.12912 0.579871 0.808181 -0.937923 0.752947 -0.888688 -0.0572164 +-0.0213048 0.234291 0.0756045 0.146937 -0.806819 0.376335 -0.927768 0.51411 +-0.442081 -0.491403 -0.756449 0.633985 0.353856 -0.211605 0.46728 0.684738 +-0.587787 -0.648858 0.867078 0.727426 -0.380667 -0.171875 -0.793082 -0.719459 +-0.379344 -0.0453489 0.300836 0.00645384 0.921641 0.0624578 0.279266 -0.817832 +-0.93532 0.3827 0.999977 -0.455193 0.180612 0.674355 0.785228 -0.880989 +0.276895 -0.0498514 -0.743932 -0.94604 0.0460987 0.556896 0.580312 0.476311 +-0.815368 -0.757894 0.00689569 0.26726 -0.825702 -0.40052 0.986792 0.679104 +0.0618043 0.122066 0.988848 0.128116 -0.0267133 -0.974641 0.877536 0.119517 +-0.623966 -0.782174 -0.220243 0.00570844 0.123463 0.473008 -0.721568 0.573985 +0.629938 -0.191704 0.044033 0.189455 -0.319255 -0.399956 0.903219 0.784092 +0.971801 0.41164 -0.128211 -0.885582 -0.23368 0.55743 0.759247 0.960679 +-0.709077 0.867762 0.65299 -0.928537 0.377655 0.912603 0.975816 0.161785 +-0.357524 -0.548823 0.938905 0.203863 0.34696 0.670413 -0.19962 -0.789242 +-0.702756 -0.153727 -0.821328 0.0472297 0.378057 0.248361 -0.277278 -0.913699 +0.541585 -0.172727 0.764302 -0.861468 0.20947 0.812251 -0.728814 0.257396 +0.682423 -0.192835 -0.167988 -0.833954 0.706607 -0.0935099 -0.98626 0.951032 +0.549769 0.872987 -0.793829 -0.293233 -0.515632 0.472482 0.529231 -0.218298 +0.00249768 -0.508924 -0.630586 -0.159767 0.826932 -0.525461 0.430755 -0.881606 +0.338152 0.362913 0.731648 -0.154969 -0.293888 0.714924 0.679079 0.705427 +-0.360239 -0.546798 0.972064 -0.585367 -0.753076 0.282928 -0.0254499 -0.904648 +-0.977429 0.0421894 -0.769564 -0.180918 -0.516198 0.660201 0.537819 0.724147 +-0.374937 0.75315 0.360724 0.501295 -0.344399 0.108865 -0.685019 -0.362472 +0.902537 -0.844042 -0.902645 0.0327107 0.746802 -0.896137 0.89488 -0.38186 +0.00799492 -0.0255363 -0.158411 0.865279 0.562249 -0.786371 -0.990776 -0.98752 +-0.0287431 0.626907 -0.827029 -0.046212 -0.021303 -0.339383 -0.495085 0.112493 +-0.593129 0.0889764 0.793592 0.190739 0.697384 0.29409 -0.739642 0.574616 +0.533346 -0.79939 -0.0947867 -0.758435 -0.252366 0.420454 0.0992783 -0.90679 +0.791362 0.108924 -0.852472 -0.410327 0.89312 0.37903 -0.910593 -0.979168 +0.822607 0.113178 -0.780245 -0.0861847 0.203481 -0.960967 0.794187 0.499256 +0.0157146 -0.854559 0.959378 -0.752122 -0.431942 -0.914425 -0.100344 -0.703418 +0.639176 -0.492071 0.630305 0.0156427 0.391215 -0.231858 -0.99141 0.709872 +0.715364 -0.0279243 -0.809327 -0.64058 -0.760974 0.823927 -0.350474 -0.900163 +-0.343778 0.790012 0.302519 0.845171 0.470429 -0.74919 0.106579 -0.198452 +0.345597 0.678188 -0.249415 -0.0986324 0.31822 -0.682419 -0.0894058 -0.159801 +-0.927773 -0.0583743 0.707291 -0.407067 0.189784 -0.358025 0.483922 -0.67485 +-0.858836 0.784199 -0.757571 -0.172145 0.594192 0.934726 -0.783253 -0.547583 +-0.422483 0.0463805 -0.91506 0.477381 0.639314 -0.505029 0.614802 0.718891 +-0.137746 -0.276347 0.421175 0.675612 0.922327 0.81178 -0.0665909 -0.47881 +0.651853 -0.528218 0.225201 -0.74441 0.25099 -0.114694 -0.255129 -0.177056 +-0.80798 0.782718 0.422031 0.86857 0.938546 0.0929628 0.834163 -0.317626 +-0.408741 -0.945791 0.84471 -0.612027 0.810331 0.894789 0.13357 0.359048 +0.293323 -0.980481 0.937842 0.0598322 -0.840713 -0.957666 -0.407442 -0.993255 +0.60878 -0.904276 0.976301 -0.911836 -0.37507 0.926083 -0.552848 0.588328 +-0.895595 -0.458053 -0.915578 -0.364804 -0.873578 0.346265 -0.864188 0.271065 +0.554131 0.887265 0.968452 0.499216 0.446189 -0.885185 -0.267792 -0.0813319 +-0.973781 -0.917278 -0.922124 0.755966 -0.560364 -0.152761 0.73279 0.214736 +-0.0959491 0.355175 -0.305867 0.493368 0.689713 -0.68866 -0.974056 0.853615 +0.872727 0.0279295 0.91701 -0.503722 0.810464 -0.596978 -0.457862 0.233401 +0.862179 0.110614 -0.962337 -0.0959645 0.727667 -0.486606 -0.618321 0.226816 +-0.0372636 -0.341771 0.449044 0.505915 0.887379 0.537463 -0.390808 -0.676399 +0.877213 0.328224 0.826247 -0.383743 0.770792 0.357184 -0.224052 -0.357501 +-0.774513 0.651501 -0.584021 0.748626 0.276732 0.277809 0.399628 0.290414 +-0.11288 0.492465 0.854089 -0.387016 0.553205 0.286692 0.386178 0.434708 +-0.271317 0.825526 -0.0900205 -0.606965 -0.550913 -0.374639 -0.828632 0.901892 +-0.215649 0.716365 -0.591051 -0.682146 0.0558905 0.946952 0.43916 0.315786 +-0.421451 -0.237249 0.605612 0.0499465 0.969081 -0.495375 -0.522025 0.997612 +-0.932361 -0.660013 0.757458 -0.322021 -0.897498 -0.727323 -0.0540161 0.905532 +-0.145957 0.102737 -0.835887 0.503569 -0.912842 0.95257 -0.426563 -0.938148 +-0.647317 0.995824 0.723835 -0.716276 -0.207958 0.263358 0.82976 -0.714866 +0.0152628 -0.0180885 0.89722 -0.0578 -0.231579 -0.833811 0.373745 -0.0693651 +-0.512399 -0.690217 0.941337 -0.366201 -0.537408 0.416734 -0.613837 0.8855 +0.672429 0.880776 -0.792689 -0.204073 -0.906482 0.922812 0.104828 0.460221 +0.619748 0.769417 -0.873343 0.664736 -0.0494597 -0.249347 0.900202 -0.458901 +0.659488 0.192534 0.163689 0.0586922 -0.902261 -0.172069 -0.82588 -0.149118 +0.077176 0.308493 -0.106334 0.993873 0.520081 0.376014 -0.788564 -0.533899 +0.130135 0.74021 -0.528029 0.223747 -0.737436 0.579668 -0.788358 -0.130166 +0.501493 -0.74121 -0.0851298 -0.308201 0.0299741 -0.242361 -0.330355 0.452635 +0.745454 0.335935 -0.199234 -0.433497 0.112833 0.752673 -0.119819 -0.986114 +0.919548 0.578935 0.542923 -0.10352 -0.766806 -0.978232 -0.34755 0.788593 +0.62738 0.0990158 -0.166868 0.194295 0.351127 0.814015 0.676045 -0.356309 +0.510406 -0.419944 0.523977 0.392391 -0.334614 -0.344021 0.266684 -0.142563 +-0.758684 0.211365 -0.605222 -0.592752 -0.677406 -0.661907 0.188426 -0.851318 +0.260054 -0.933099 -0.112497 -0.71334 0.617495 0.233812 -0.810667 -0.0764758 +0.20642 0.395384 -0.24246 -0.983552 -0.634481 -0.0824766 0.0806025 0.532388 +0.0280422 0.365149 0.167271 -0.0171417 0.274566 -0.822412 -0.0184639 -0.853725 +0.412007 0.18347 -0.0791277 0.391852 -0.276179 -0.0103696 -0.100715 0.698667 +0.511202 0.427406 0.72993 0.127507 0.361402 -0.952601 0.18617 0.221879 +0.209074 -0.49027 -0.199655 0.328483 0.638837 0.220071 0.567806 -0.955906 +-0.116366 0.8109 -0.303113 -0.839278 0.853005 -0.121356 0.588508 0.365637 +0.058076 -0.980878 0.35331 -0.15642 -0.2379 0.229284 0.541109 -0.186901 +-0.787957 0.934787 0.706604 0.532961 -0.256714 0.309883 0.396585 -0.261672 +0.355373 -0.179306 -0.411972 0.368987 -0.917634 0.948915 -0.584951 -0.829728 +0.637541 -0.173326 0.210325 0.607454 0.572296 0.841261 0.0494415 -0.0763956 +-0.591643 -0.444647 -0.504743 0.434822 0.849002 -0.211766 -0.0788843 0.989326 +-0.337477 0.385435 0.445913 0.309361 0.918501 0.6652 0.944211 0.0257118 +-0.23916 -0.451166 -0.609886 -0.0659227 -0.0375864 0.737618 0.367575 -0.820003 +0.496646 -0.576896 0.767511 -0.689981 0.705403 0.712963 -0.0780863 -0.333201 +0.608137 0.487054 0.100392 0.300656 -0.84303 0.719292 -0.982492 0.980654 +-0.818826 -0.0389666 -0.476579 -0.184201 -0.632971 0.420708 0.0329246 0.56942 +-0.865627 -0.239283 0.872223 0.986551 0.974816 0.729962 -0.204364 0.942937 +-0.686741 0.234766 -0.0289711 0.32923 0.0281623 0.651585 0.505194 0.278144 +-0.869217 0.942754 0.656311 -0.884832 -0.755165 0.722221 -0.555994 0.181614 +-0.794462 0.96172 -0.444081 0.497709 -0.576258 -0.507055 -0.960692 0.897876 +-0.189972 0.47366 -0.620641 0.831582 0.908929 0.399992 -0.620239 0.866167 +0.166999 0.57064 0.386637 0.293375 -0.235856 -0.925089 0.908138 -0.459595 +0.84173 0.361143 0.277008 -0.699575 -0.328956 -0.949933 0.587514 0.0271074 +0.892804 -0.805868 -0.971652 -0.0706002 0.780361 -0.427233 0.569584 0.921465 +-0.701738 0.553394 -0.434867 0.950728 -0.602964 -0.231112 0.142276 0.436999 +-0.921229 0.963686 0.0121928 0.478565 -0.903602 -0.797991 0.763195 -0.551912 +-0.119594 -0.366926 0.991877 -0.533825 0.79025 -0.26983 -0.843712 -0.633321 +0.514414 -0.731802 0.388953 0.695488 0.281179 0.0614743 0.854952 -0.639278 +0.653624 -0.93081 -0.703172 -0.952874 0.467182 0.439103 0.664818 -0.870386 +-0.461089 0.681186 -0.837432 -0.551937 -0.915217 0.724061 -0.980872 0.949939 +-0.412469 0.18445 -0.63193 0.467245 0.110388 -0.871162 0.407215 -0.554955 +0.604099 -0.592378 -0.503853 0.199651 0.215938 -0.0685861 0.936613 -0.34603 +-0.916616 0.105062 -0.113299 -0.849665 -0.153681 -0.24699 -0.0431739 -0.99078 +0.688881 0.0168708 -0.273708 0.559642 0.202772 0.0186263 -0.825888 0.175398 +0.327059 -0.781869 -0.179969 0.923801 -0.601341 -0.908216 -0.18981 -0.337681 +0.450217 -0.940719 -0.374239 0.707066 -0.946993 -0.568042 0.457238 0.25565 +-0.134222 -0.426903 0.13369 0.124935 -0.867752 -0.958096 0.40148 0.590237 +0.511295 0.322837 0.0731732 -0.380006 -0.11069 0.774001 0.174249 0.168671 +0.589268 -0.657451 -0.866506 0.261098 -0.413224 0.673675 0.0814509 -0.470938 +-0.868213 0.604029 0.744615 0.599093 0.0384209 0.125244 -0.685501 -0.0630482 +-0.0304775 -0.108923 -0.429019 0.196518 -0.859279 -0.794601 -0.911809 0.163866 +0.644154 -0.562387 -0.790462 -0.595303 -0.553399 0.697125 -0.725724 0.469391 +-0.152077 0.741402 -0.0546205 -0.932208 0.840667 -0.293023 0.588662 0.606879 +-0.252727 -0.93542 -0.92383 0.692652 -0.59087 -0.454228 0.880038 -0.520625 +-0.0330253 0.327793 -0.175133 0.5013 0.542762 0.878107 -0.445413 0.198224 +-0.174487 -0.549524 0.037043 -0.673611 0.818549 -0.520281 0.624963 0.846791 +0.567396 0.336605 -0.0631226 -0.0271266 0.564415 -0.813487 0.149925 -0.935113 +0.379675 0.431089 -0.880337 -0.09441 0.950797 -0.375657 0.774873 0.339918 +-0.892763 0.876422 0.618538 0.134364 0.931439 0.959874 0.760375 0.12029 +-0.632104 0.593841 0.772795 0.516281 0.634152 0.974791 0.823063 -0.166161 +0.315663 0.768764 0.433545 0.311113 -0.324854 0.957896 -0.490663 -0.737455 +-0.304496 0.733789 0.793955 0.411901 -0.498453 0.293996 0.420119 0.422718 +0.670829 0.773441 0.696162 -0.513205 -0.202708 0.427208 -0.0306869 -0.841357 +0.920577 0.765176 -0.853106 0.370126 -0.989349 -0.546866 -0.575291 0.287968 +-0.757095 0.192672 0.814395 -0.453257 0.604847 -0.876354 0.367886 -0.0151331 +0.235559 0.875296 0.477356 -0.218342 0.26972 -0.808785 -0.682001 -0.647294 +-0.752228 -0.524457 -0.84528 -0.548262 0.0279057 0.746114 0.170418 0.0449894 +-0.392635 -0.597178 -0.939452 0.46004 0.422517 0.0810758 -0.850889 0.449146 +-0.409177 0.415453 -0.54126 -0.0305021 -0.31647 -0.0866191 0.224091 -0.719058 +-0.810073 0.187324 -0.832119 -0.189144 -0.830587 0.593345 0.770149 -0.330896 +-0.535108 0.273231 -0.0951172 -0.928801 0.389627 -0.232366 0.882369 -0.853362 +-0.497017 0.601427 -0.554973 0.608969 -0.781784 -0.180138 -0.0446734 0.149021 +0.454688 0.633539 -0.0790617 0.388466 -0.616397 -0.863969 0.410837 -0.680489 +-0.148318 -0.339283 0.163559 -0.0209041 -0.300157 0.430034 0.940282 0.602268 +-0.518671 0.275683 0.698899 -0.575999 -0.502948 0.182458 0.48962 -0.440142 +-0.617709 0.936434 -0.936071 -0.0633253 0.570726 -0.408753 -0.0703058 -0.0714649 +0.101372 -0.546566 -0.671765 0.986878 0.638177 -0.452032 0.639692 -0.769896 +0.174799 -0.0577958 0.322054 0.658358 -0.709421 -0.945225 -0.735239 -0.513385 +-0.109145 -0.227472 0.751624 -0.315295 -0.66989 -0.748413 -0.539431 0.72071 +0.966609 -0.432091 0.292787 0.91216 0.361899 -0.884765 0.110524 -0.243311 +-0.839594 0.737413 -0.020524 -0.577383 0.274459 -0.641296 0.294426 0.266055 +-0.0777944 -0.12732 0.519281 0.0816115 -0.238187 0.645786 -0.319999 0.885084 +-0.783431 0.243143 -0.78833 0.320227 -0.601606 0.430834 0.191957 0.204063 +-0.938407 0.98457 -0.306877 -0.546397 0.974052 0.331455 0.972354 0.943355 +0.586176 -0.828675 -0.323056 0.160293 -0.920361 -0.0660152 0.622205 0.641198 +0.872164 -0.338022 -0.143586 0.745673 -0.27235 -0.942767 -0.846036 -0.658522 +-0.347873 0.14824 -0.827163 0.0277554 0.215965 0.462571 0.150729 -0.719356 +0.710976 -0.0125055 -0.661091 0.0458706 0.279894 -0.452641 -0.805444 -0.949556 +0.303348 0.904368 0.50278 0.0118716 0.574233 -0.482165 -0.328897 0.85348 +0.494556 0.750216 0.279848 0.79234 0.299291 -0.332139 0.402305 -0.708261 +-0.185838 -0.168782 0.512185 0.411594 -0.182905 0.855864 -0.650474 -0.0487407 +0.274737 0.00184485 0.119464 0.0808393 0.455276 0.328098 0.790185 0.771224 +-0.750247 0.991348 0.575928 0.392401 -0.419237 -0.791278 0.7272 -0.662481 +0.518297 0.866057 -0.0971389 -0.656726 -0.00456969 -0.530444 0.74639 0.545359 +-0.913198 0.168062 0.44004 0.47359 -0.893752 -0.632574 0.0189093 -0.285474 +0.121985 -0.0851743 -0.358886 0.443117 0.232953 0.383373 0.428068 0.330468 +-0.952961 -0.689825 0.902817 0.988628 -0.242252 -0.0696776 0.403773 0.610098 +-0.558115 0.0430609 -0.152619 -0.856945 -0.743948 -0.964333 0.0213278 -0.350069 +0.951536 -0.715168 0.908198 0.0755313 -0.302643 -0.0346488 -0.932556 -0.953335 +0.716817 0.169996 0.446301 -0.890338 -0.650838 0.288421 0.0217752 0.827143 +-0.423832 -0.319625 0.57522 0.492049 -0.954419 0.0321517 -0.571249 -0.428418 +-0.929349 -0.147587 -0.777471 -0.105646 -0.233346 0.448064 -0.637381 -0.24875 +-0.505605 0.705017 -0.0959733 -0.750152 -0.9875 0.237013 0.611796 -0.0658917 +-0.754473 0.975777 -0.311153 0.811346 0.816528 0.479834 -0.417514 -0.0501505 +-0.336015 -0.436469 0.246355 -0.860231 -0.795712 0.132214 0.220806 0.224177 +-0.464325 -0.807899 0.226076 0.463425 0.277786 -0.0949832 -0.628236 0.685393 +-0.610457 -0.830874 0.0182248 0.487999 -0.434955 0.417479 0.662097 -0.590251 +-0.868883 0.28932 -0.52939 0.583749 -0.853499 -0.446555 0.640106 -0.312221 +-0.571267 0.499154 0.449614 0.395598 -0.0409316 -0.914739 0.419068 -0.0674042 +-0.411804 0.270978 0.264104 -0.324432 -0.519737 -0.662117 0.763018 -0.222477 +0.524455 -0.560286 -0.562702 0.292157 -0.533457 0.584337 -0.508795 -0.929743 +-0.762652 -0.971874 0.802773 0.791144 0.00753262 0.766991 0.540942 0.622855 +0.18138 -0.690126 0.60004 -0.94918 -0.190943 0.163418 -0.196051 0.122354 +-0.85054 -0.616725 0.0901593 0.598235 0.122568 0.877437 0.273597 -0.357027 +0.431568 -0.892009 0.840537 0.741927 0.580244 -0.352159 -0.57254 -0.727205 +0.0600962 -0.0731579 0.564756 0.229222 0.713273 -0.771259 0.114384 0.0744715 +0.816392 -0.98539 -0.640545 0.681416 0.601987 -0.169311 0.835319 0.545517 +-0.638803 0.904986 -0.985946 0.0495214 0.808597 0.192554 -0.00420704 0.350903 +0.353323 0.639512 -0.423534 0.765067 0.76902 -0.433274 -0.486244 -0.889671 +-0.398864 0.353809 0.317748 -0.151293 0.721683 -0.462832 -0.144684 0.394665 +0.498871 0.226772 -0.696744 -0.708177 0.688459 0.938859 0.249073 -0.349694 +-0.543234 -0.775247 0.450643 -0.847143 -0.239568 -0.226471 0.160416 -0.915136 +-0.311468 -0.136463 -0.072374 -0.231853 -0.706321 -0.342557 -0.856242 -0.523405 +-0.0887504 0.878851 0.357334 -0.20889 0.6194 0.623697 0.682307 -0.643001 +0.786759 0.497659 0.523058 0.352989 -0.377757 -0.568991 0.575593 0.248978 +-0.44774 -0.526464 0.137441 0.0368045 -0.138769 -0.719269 -0.636638 0.205365 +0.754234 0.290974 0.118056 0.926953 0.340107 0.647463 -0.165792 0.524386 +0.862808 -0.808229 0.986318 -0.333334 0.938955 0.504754 -0.948564 -0.627975 +-0.737627 -0.850771 -0.872538 -0.337812 0.281918 -0.121811 -0.0542474 0.247375 +-0.306369 0.127887 0.728652 0.0133278 0.751216 -0.125756 -0.356234 -0.19106 +0.202586 0.309792 -0.453417 0.692834 0.69547 0.70986 -0.85682 0.760528 +-0.131201 0.144543 -0.178906 -0.157251 -0.533544 0.888226 0.208771 -0.977268 +-0.504413 -0.0699119 -0.435211 -0.91065 0.312126 0.75234 0.97395 0.544 +0.894817 0.511993 0.287178 -0.23484 -0.581139 -0.584932 -0.625012 0.0210486 +-0.286104 0.254178 -0.542006 0.161124 0.766974 0.742791 0.912037 0.632687 +-0.60916 -0.885383 -0.756673 -0.777782 0.277766 0.991106 0.900554 -0.391421 +-0.142503 -0.818095 -0.45911 -0.918373 -0.298651 -0.277392 0.725643 -0.854794 +-0.649908 -0.187901 0.0247095 -0.60228 0.793194 -0.617519 -0.997789 -0.274494 +-0.280149 0.898711 -0.360574 -0.976312 0.476091 0.916732 -0.169414 -0.72465 +-0.411932 -0.32515 0.871157 0.599611 0.134385 -0.102408 0.394689 0.7496 +0.104619 -0.175166 0.904801 0.0569862 -0.0476467 0.376232 -0.110904 0.740176 +0.52391 0.230445 -0.167388 -0.522466 0.227577 0.29069 -0.0534199 0.0569272 +0.625561 0.549869 0.861022 0.10075 0.72685 -0.0568357 0.509931 0.0672989 +-0.346833 -0.551593 -0.389969 0.0073665 0.288691 -0.804029 0.088699 0.532961 +-0.767316 -0.343539 -0.357081 -0.0846586 0.600049 0.835556 0.816295 -0.263728 +0.58262 -0.116763 0.636783 -0.618889 -0.416884 -0.309726 -0.468009 0.871142 +-0.823144 0.986674 0.95286 -0.361432 0.55619 0.958338 -0.136065 0.00978749 +0.157041 -0.134212 0.276699 0.145281 -0.485878 0.862085 0.902173 -0.76561 +-0.138389 -0.182146 0.889744 0.297919 0.740105 0.147681 0.503145 -0.736469 +-0.685033 -0.485946 0.201931 0.296399 0.480032 0.935205 0.238879 -0.803755 +-0.615923 0.079203 -0.319049 -0.402563 -0.124385 -0.320356 -0.438738 0.347248 +-0.26052 0.160195 0.763041 -0.255672 0.994378 0.909226 -0.0298997 -0.997844 +-0.276995 -0.453403 0.634612 0.0875058 0.650583 -0.96219 0.523689 -0.100822 +-0.177809 -0.937384 -0.28952 -0.220639 0.271869 0.790844 -0.139988 0.387136 +-0.157078 0.472966 -0.67483 -0.991139 -0.822019 -0.444225 0.934609 0.994294 +-0.209155 -0.386623 0.541155 0.466955 0.684132 -0.637023 -0.000662698 -0.366198 +0.5711 0.205397 -0.738076 0.182721 -0.283388 -0.842837 0.19663 -0.599122 +-0.674715 -0.0732164 -0.941004 -0.512716 0.927311 0.184827 -0.281494 -0.300882 +-0.547956 0.999928 0.959472 0.0852394 0.689922 0.514692 -0.127357 0.413696 +-0.0377045 0.197385 0.991193 -0.987554 -0.991909 -0.741119 -0.0827873 -0.851644 +0.789856 -0.0561885 -0.918343 0.134567 0.329217 0.687128 0.467436 -0.435116 +-0.471794 0.73237 0.977324 0.694653 -0.451916 0.454989 0.00498822 -0.257135 +0.748528 0.450546 -0.743392 -0.450777 0.758868 -0.320118 0.728743 0.0153246 +-0.531501 -0.892419 0.633288 0.658013 0.263826 0.12886 0.385882 0.0323802 +0.687212 -0.24275 0.751322 -0.730946 0.937416 0.0921673 0.405329 0.241475 +-0.213351 0.774039 -0.049899 -0.25581 0.000732646 0.684335 0.151096 0.649219 +0.26154 0.333546 -0.80676 -0.119055 0.364801 0.177554 -0.691678 -0.62992 +0.52007 -0.12052 0.983154 0.806358 -0.00997916 0.889552 -0.877461 -0.215677 +0.757724 -0.741531 0.156651 -0.68095 -0.0755776 0.486172 -0.359773 0.0925162 +-0.692822 -0.0141875 0.81207 -0.00906921 -0.00493599 0.47499 -0.625689 0.90352 +0.649982 -0.812876 0.895096 -0.0379297 -0.338638 -0.478548 -0.0943941 0.272687 +0.724685 -0.022035 0.0457361 -0.716353 0.344336 0.176737 -0.126939 -0.752648 +-0.936457 -0.233943 -0.648857 -0.45973 0.73649 0.932867 0.757983 0.962803 +0.170945 0.490496 0.952495 0.763113 -0.68094 0.720786 -0.667562 0.950296 +0.977082 -0.497909 0.727733 0.610678 0.0265574 0.00265843 0.391433 -0.765324 +0.619972 0.541125 0.708 0.997773 -0.272605 0.712599 0.0736995 0.272346 +-0.940861 0.0762346 0.0136436 -0.537222 0.594253 -0.907104 -0.372755 0.22729 +0.873806 -0.528205 0.477191 -0.943149 -0.439462 0.117662 -0.252288 0.516592 +0.657385 -0.518584 -0.946717 -0.854304 -0.952449 -0.752462 0.207444 0.0728009 +-0.645599 0.340758 0.657169 -0.331184 -0.598246 -0.274908 -0.0250179 -0.304901 +0.686562 -0.654303 0.27842 -0.115524 0.473662 0.0127028 0.553789 0.990883 +0.393672 0.600265 -0.920467 0.532092 -0.349666 -0.615626 0.633596 -0.841394 +0.131594 -0.708877 0.585439 0.45468 0.378988 -0.0539827 -0.596616 0.645908 +0.892736 0.0992729 -0.0382379 0.427434 -0.350509 -0.360955 0.979282 0.139371 +0.267914 -0.492926 -0.622307 -0.674663 0.164849 -0.229132 -0.035842 0.959332 +-0.731852 0.327502 -0.575435 -0.0297323 0.980193 -0.612321 -0.280145 0.0856629 +0.643568 -0.513787 -0.134338 0.232088 -0.149599 -0.584207 -0.579692 0.157425 +0.614703 0.736502 -0.0833472 0.514622 -0.293587 -0.650099 0.533982 0.186323 +-0.675352 -0.119661 -0.515183 -0.210644 -0.85384 0.307861 0.700693 -0.877282 +0.274578 0.473508 0.406831 -0.538001 0.956363 0.646266 -0.546682 0.992454 +-0.87327 -0.00296215 0.0414035 0.0500699 -0.670198 0.853049 0.914707 0.116119 +0.190999 -0.700027 -0.859726 -0.639689 -0.501863 0.951785 0.43509 -0.938298 +0.907065 0.087347 0.317729 -0.55167 0.694181 -0.298263 -0.173535 -0.405605 +0.894403 -0.584206 -0.0723924 0.633117 0.570955 -0.560545 0.467796 0.122046 +-0.796304 0.528693 0.00108817 -0.890026 -0.820986 0.412875 0.221054 -0.558606 +0.219785 -0.199144 0.467752 0.0898112 -0.5489 -0.178627 -0.974027 -0.70176 +-0.279536 -0.355732 0.829754 0.206678 0.92681 0.725132 0.59638 -0.652078 +0.901265 0.691778 -0.10057 0.967704 0.233985 -0.877128 -0.40284 0.149152 +-0.764962 -0.204784 0.770602 -0.837699 0.776018 0.632944 0.201403 -0.586494 +-0.132137 0.720944 -0.452181 0.0467145 0.515932 -0.23395 -0.944926 -0.525222 +0.180312 -0.85565 0.960342 0.854501 0.25741 -0.336411 0.473119 0.792189 +-0.6289 -0.0291849 0.0420405 -0.452139 0.238573 0.429904 0.270788 -0.750278 +0.847802 0.426038 0.353717 -0.950472 0.981075 0.888408 0.766313 -0.765033 +0.283318 0.683637 -0.594716 -0.258368 -0.949117 -0.306491 -0.793554 0.163335 +0.571415 -0.561182 0.741436 -0.11306 -0.226107 -0.542048 -0.623548 -0.686956 +0.2674 -0.838761 -0.117915 -0.193575 0.0629765 0.705599 0.0882624 -0.255399 +0.791962 -0.154414 0.155621 -0.496132 -0.378271 0.939525 0.970834 0.564463 +0.335219 0.801393 -0.211062 -0.0313083 0.268018 -0.299146 -0.232611 0.714823 +-0.426097 0.567041 0.649474 0.0358228 -0.299913 -0.0713698 -0.633735 -0.784617 +0.0232393 0.662918 0.0372392 0.231156 -0.691952 0.433214 -0.603794 -0.213686 +0.905391 0.415682 0.402408 -0.211226 0.240961 0.636125 -0.0358785 0.492232 +0.107998 0.778871 0.011083 0.514138 0.63688 -0.634362 0.161362 -0.00531217 +-0.684938 0.930207 0.806177 0.46788 -0.00147245 0.466066 0.847943 -0.677591 +-0.00649523 0.806737 -0.302778 -0.145562 -0.863794 -0.0302537 0.772421 0.187482 +0.619861 -0.0637037 -0.110914 0.0793783 0.256422 -0.0290565 -0.392131 0.864709 +-0.0191528 0.927415 -0.082349 0.525604 -0.931214 -0.466625 -0.914915 0.872849 +-0.17235 0.646809 0.949734 -0.81783 -0.322976 0.127121 -0.200871 0.0826042 +-0.632413 0.0674995 0.978769 -0.318435 -0.186217 -0.663021 0.57249 0.926005 +0.0181546 0.0713998 0.709013 -0.385123 0.946755 -0.0728979 -0.103564 -0.188298 +-0.683118 0.320875 -0.391775 -0.335778 -0.0798763 -0.972134 0.219379 0.492908 +0.579168 0.799142 0.295507 -0.764597 -0.761547 -0.26899 0.872283 0.0791589 +-0.606292 0.794086 0.137936 0.637808 0.0615395 -0.389156 -0.614971 0.924965 +0.713525 0.884743 0.661499 0.615001 0.396643 0.619282 -0.887594 0.863704 +0.124719 -0.669662 0.0415935 0.892271 0.296006 -0.419755 -0.34637 0.161909 +0.953529 -0.461741 -0.476569 -0.150034 0.703462 -0.918889 -0.914346 -0.635682 +0.625844 -0.910335 0.412728 0.684072 -0.573945 -0.506028 0.150957 0.164161 +-0.455554 0.302384 0.94253 -0.149663 -0.681389 0.0460208 0.501568 0.00589114 +0.473585 0.858584 -0.630107 0.962347 -0.902829 -0.423111 0.516332 -0.101748 +0.491872 0.668381 -0.402207 0.712402 0.574147 0.810886 0.221889 -0.789166 +0.555292 -0.966892 -0.250653 -0.698821 -0.770122 0.468273 -0.189857 0.486777 +-0.274678 0.475475 0.090513 0.0941176 0.833517 -0.0989901 0.732688 0.929906 +0.933572 0.558267 -0.959083 -0.0707562 -0.371505 0.797705 0.464027 0.922195 +0.719289 0.503181 0.582471 0.763781 -0.0555772 -0.39836 -0.0366971 0.115712 +-0.522027 -0.321389 0.131675 0.89057 0.716248 -0.446274 0.974616 0.543703 +0.419614 0.463716 0.0980643 -0.985997 -0.407129 -0.948701 -0.115993 -0.546362 +-0.0715668 0.849654 0.403235 -0.910678 -0.117649 -0.604286 0.184488 0.729098 +-0.93474 -0.599825 0.0214467 0.670089 0.363606 0.988076 0.432029 0.148693 +0.819119 -0.251876 0.271394 -0.764731 0.607854 0.562658 0.699353 -0.222141 +0.9961 0.262391 -0.479401 0.275457 0.461772 0.816849 -0.762862 -0.697602 +0.581109 0.350793 -0.120216 -0.312196 -0.929956 0.407073 -0.312881 -0.705924 +-0.668388 0.984213 0.273338 0.639527 0.501369 -0.614373 0.214894 -0.218285 +-0.124574 0.7385 -0.00144546 -0.0154488 -0.0514818 0.703353 0.875083 0.169949 +0.11434 0.471679 -0.665672 0.598294 -0.213896 -0.10477 -0.45066 -0.832872 +0.574354 0.606272 -0.71956 -0.597004 -0.394706 -0.183679 -0.304551 0.535606 +0.572686 0.214173 -0.812911 0.32976 -0.611692 0.244669 -0.0058671 -0.10343 +-0.197952 0.346636 -0.587875 -0.352256 -0.277861 0.507426 -0.911851 0.406888 +-0.0069995 -0.171561 0.767617 -0.682493 -0.493422 -0.556888 -0.412298 -0.633811 +-0.299201 0.488389 -0.642966 0.551488 0.456489 -0.952984 -0.414757 -0.593406 +0.343825 0.725008 0.24153 -0.851154 -0.374948 0.122291 -0.766575 0.725006 +-0.779711 0.385846 0.323872 -0.765733 -0.202113 -0.143466 0.298488 -0.26644 +-0.503339 -0.662685 0.0770419 -0.119041 0.863646 0.525176 -0.130999 -0.422811 +0.422938 0.147297 0.16718 0.437515 -0.36838 -0.630864 -0.800768 0.961757 +-0.0641101 -0.715403 0.246984 -0.452333 -0.387947 0.343553 0.273382 -0.902628 +-0.541774 -0.914521 -0.593925 -0.6866 0.453686 -0.563833 0.622579 0.622065 +-0.539202 -0.667677 0.338388 -0.753619 0.597776 -0.649447 -0.490685 -0.760126 +-0.368934 -0.984469 -0.162553 0.535268 -0.0581524 -0.270395 0.117763 0.376106 +0.421615 -0.269914 0.0908834 -0.428551 -0.0659017 -0.674737 0.343036 -0.809389 +0.381187 0.054868 -0.736517 -0.0805571 0.238274 0.392724 -0.858288 -0.555801 +-0.668288 0.0322469 -0.17407 0.709696 -0.228347 -0.405828 -0.741468 0.112184 +0.586689 0.877233 0.353419 -0.269228 0.246214 0.0663341 -0.265378 0.0738752 +-0.846392 -0.896188 0.599184 -0.989711 0.815948 -0.891413 -0.717648 0.928854 +0.847613 0.497684 0.653577 0.256727 -0.941993 0.687621 0.885548 -0.0328761 +-0.835823 -0.633593 -0.778862 0.101114 -0.297876 0.514077 -0.0219575 -0.35025 +0.020711 0.559037 0.316685 -0.583087 0.540192 -0.435422 -0.675302 -0.521982 +0.745565 -0.292312 -0.0292307 -0.239998 -0.381024 -0.450953 0.0987404 -0.942122 +-0.742454 0.257428 0.934171 0.809179 0.19012 0.2545 0.907287 0.284899 +-0.672138 -0.161404 0.3675 0.0488093 0.931938 0.176262 0.88015 -0.329395 +-0.025253 0.316535 -0.206743 0.0107128 0.702844 -0.384482 0.30496 0.368379 +0.84283 -0.132163 -0.871323 0.839478 0.451141 0.275397 -0.67559 0.884972 +-0.424877 -0.0780003 -0.675793 0.0674848 0.120192 0.85349 0.825394 -0.23963 +0.964721 0.288912 0.784952 0.0211033 0.776431 -0.168673 -0.827909 -0.0470922 +-0.137226 -0.295394 -0.758961 -0.358091 0.719381 0.22567 0.465528 0.238049 +0.846867 0.593485 0.402443 0.0197375 -0.326613 -0.389345 0.210102 0.585761 +-0.251388 0.975586 0.765576 0.0105263 0.0485571 -0.144259 -0.225171 -0.846924 +0.904802 -0.306201 0.973132 0.0169053 0.54403 0.146896 -0.67209 -0.100314 +-0.305925 -0.649057 -0.961895 0.10197 0.773901 0.251404 -0.68321 -0.999172 +0.803232 0.831024 -0.194258 -0.21741 0.519616 -0.26428 -0.871257 0.459452 +0.495183 -0.315436 0.988942 0.0946434 -0.145408 -0.780088 0.478292 -0.440063 +0.140639 -0.666605 -0.394771 0.209669 -0.882781 -0.866785 0.822876 0.313566 +0.289734 -0.351428 0.0652073 0.0207896 -0.880111 -0.289536 0.655548 -0.866614 +-0.55384 -0.263566 0.324455 -0.907539 -0.429209 -0.674557 0.171382 -0.749217 +0.573479 -0.606619 -0.99615 -0.841321 -0.624034 -0.16957 0.40645 -0.857816 +0.6124 0.515271 -0.476764 0.712873 -0.13435 0.456959 0.976651 0.049353 +-0.38961 -0.554669 -0.961053 0.597428 -0.980611 -0.306856 0.237047 -0.0528948 +0.436825 0.067787 0.553998 -0.973296 0.589735 -0.965539 0.933691 -0.092189 +-0.756253 0.657371 -0.131657 -0.393731 -0.401185 -0.61353 0.0998119 -0.0482496 +0.88094 0.068662 -0.311243 -0.541921 0.6701 -0.631771 0.6582 0.837739 +0.553374 -0.311691 0.895415 0.427898 -0.466342 0.639683 0.0199094 -0.290336 +-0.27462 -0.924421 0.433571 0.152194 0.391239 0.572982 -0.898181 -0.437818 +0.400034 0.193773 -0.397168 -0.61091 0.0983465 -0.122479 0.214126 0.148631 +-0.639838 0.703216 -0.709621 -0.159355 -0.979139 0.227143 0.646861 -0.882124 +0.435646 0.598844 0.553529 0.0650148 -0.482796 0.131495 -0.909386 -0.984489 +-0.91282 -0.486764 0.565165 -0.365891 -0.625747 -0.968751 -0.5831 0.760851 +0.41417 0.88422 -0.528985 -0.79639 0.769148 0.0281669 0.278321 0.233352 +0.043172 -0.119929 0.744422 0.204351 -0.181731 0.207236 0.00826885 -0.89295 +0.481915 0.327717 0.041896 -0.408631 -0.0673356 -0.873874 -0.508949 0.513303 +-0.670448 -0.135228 -0.224288 0.429496 0.716588 0.108394 -0.672017 0.813268 +-0.823246 0.284042 -0.89564 -0.660131 -0.622931 0.386008 0.642158 -0.46408 +0.124811 0.91243 -0.131516 0.580109 0.273929 0.620618 -0.60207 -0.940485 +0.242091 -0.842635 0.558778 -0.708394 0.959491 0.807801 0.260162 -0.860087 +0.701188 -0.286316 0.665152 0.0836808 0.0777449 0.665974 0.190459 0.229637 +-0.573788 0.553263 0.401587 -0.254484 0.453416 0.320535 0.124292 -0.674375 +-0.772557 0.286658 0.286858 -0.610604 0.164543 -0.461166 -0.111085 -0.467779 +0.755912 -0.835414 -0.523273 0.124686 0.625215 0.254365 -0.621343 0.721486 +0.723409 0.800257 -0.473727 -0.977582 -0.692884 0.415379 0.536753 0.757392 +0.836582 -0.563446 0.361799 0.49473 -0.65864 -0.873374 0.991183 0.520681 +-0.0842182 0.655348 0.417902 -0.607633 0.288775 -0.92892 0.96663 -0.822085 +0.962041 -0.131105 -0.235819 0.988614 -0.637875 -0.738374 0.741394 -0.474423 +0.466231 -0.931568 0.460443 -0.20345 -0.628494 -0.994319 0.931444 0.675085 +0.972864 -0.20814 0.460001 -0.885232 0.124898 -0.985502 0.888845 -0.579836 +-0.29524 -0.680225 0.122174 -0.219773 0.64414 -0.447162 0.359855 0.266702 +-0.668839 -0.772446 0.581573 -0.0510943 -0.212979 0.966907 0.613242 0.857691 +-0.0390333 -0.919343 0.916039 0.0784157 0.861652 -0.650292 -0.994993 -0.646119 +-0.92435 -0.640192 0.861895 -0.751346 0.64982 -0.566795 0.724396 -0.911267 +0.87906 0.649922 0.854086 -0.556599 0.352613 -0.790212 0.0402968 0.187952 +-0.0738641 0.202716 0.0614971 -0.151917 0.416292 0.530612 0.774077 -0.394695 +-0.133099 -0.693308 -0.385959 0.669784 -0.851992 0.331418 -0.496843 -0.887921 +0.840795 0.221318 0.823693 0.680852 -0.248194 0.869303 0.702691 0.942566 +0.226746 -0.649925 -0.411488 0.193243 0.85133 0.435078 0.199276 -0.310649 +-0.326584 0.252741 0.768958 0.318801 -0.300594 0.867793 -0.253636 0.702688 +0.930336 -0.221198 -0.419854 0.40996 0.221548 -0.105628 0.92983 -0.256735 +0.597607 0.00693479 -0.509817 0.437797 -0.983077 0.508448 0.809127 0.196139 +-0.407975 -0.976637 0.950385 -0.764164 0.853928 -0.417241 0.765138 -0.343425 +0.27828 0.432838 -0.276489 -0.193367 -0.376719 0.0728322 -0.243358 0.393985 +0.950319 -0.818687 0.629642 -0.359023 0.0925039 -0.382067 -0.573574 0.982943 +-0.350449 -0.399127 -0.93732 -0.444581 0.698315 0.237874 -0.475988 -0.835617 +0.536712 -0.822973 0.259625 0.297349 0.79306 0.13849 0.755881 -0.78431 +0.431106 -0.127735 -0.463165 -0.591191 -0.153523 -0.211218 0.503748 0.23995 +-0.365947 -0.33267 -0.293726 -0.212914 0.336077 0.934874 -0.627893 -0.691594 +-0.0518001 0.0367222 -0.393038 -0.321993 -0.739019 0.335645 -0.67634 0.180534 +-0.259305 0.0203263 0.877685 -0.466853 0.849428 -0.61377 0.477269 -0.15404 +-0.879647 -0.90787 -0.358828 0.862563 0.795065 -0.0406532 -0.551764 0.174125 +0.643761 0.690572 0.289164 0.38959 0.410595 -0.720023 0.57238 -0.917611 +0.674706 -0.590643 0.159813 0.4123 0.767407 -0.517906 -0.316851 -0.298961 +0.363192 0.188104 -0.210612 -0.473926 0.279279 0.938374 -0.358034 0.0612207 +0.931987 0.35805 0.846323 0.408925 -0.646355 0.500204 -0.429592 -0.519569 +0.515194 -0.386515 -0.404967 -0.226663 -0.975967 -0.630693 0.307084 0.927822 +-0.942307 -0.791655 -0.898573 0.480521 0.380706 0.303901 0.456812 0.991757 +-0.048805 0.631629 0.89261 -0.821022 -0.969259 0.640607 0.371623 -0.896981 +-0.43813 -0.713409 0.415642 -0.125709 0.50242 0.476583 -0.74203 0.786028 +-0.195922 0.196466 0.440618 -0.507517 0.199694 -0.667823 0.151653 0.620218 +-0.75496 -0.652103 -0.940331 -0.184016 0.998388 0.406921 -0.119219 0.716519 +0.318588 0.704902 0.291492 0.983082 0.50794 0.88594 -0.880253 -0.836508 +0.0566302 -0.853426 0.420597 0.399746 -0.78373 -0.412174 0.415964 0.137116 +0.241168 -0.237681 0.236262 0.958907 -0.467803 -0.287174 0.917187 0.80971 +-0.183402 -0.249486 -0.0956603 -0.329253 0.32755 -0.55554 0.0461645 0.151975 +-0.832858 0.00999473 0.799883 0.611502 -0.0333815 0.0269128 0.788707 -0.05049 +-0.466655 -0.0359917 -0.178252 -0.75571 -0.352506 -0.385766 -0.775035 -0.225194 +0.653347 -0.214511 0.392336 0.351973 0.675455 -0.432383 -0.590565 -0.00247393 +0.83193 0.427776 -0.397143 -0.524797 0.0329433 -0.712917 0.586987 -0.597506 +0.955054 -0.422828 -0.156757 -0.900635 -0.993511 -0.453753 -0.900185 0.184881 +0.32201 -0.872906 -0.18668 -0.826279 -0.203369 -0.905251 -0.993372 -0.439943 +-0.785225 -0.105336 -0.637984 0.818458 0.570591 -0.403852 -0.946671 0.224589 +0.200085 -0.849365 0.607434 0.0208227 -0.654719 0.803037 0.618628 0.807793 +-0.693831 -0.813777 0.864736 -0.716155 -0.180395 0.240294 -0.614494 -0.338928 +0.75223 -0.550192 -0.48055 0.952716 -0.348465 -0.581164 0.994858 -0.279835 +-0.558747 -0.165934 0.440945 -0.68293 -0.61582 0.593773 0.710021 -0.722819 +0.0810007 0.930372 -0.791776 -0.770294 -0.272479 -0.524799 0.697685 -0.970154 +0.948796 0.577075 -0.558255 0.575764 -0.2287 -0.195658 0.230724 -0.987664 +-0.741981 -0.083787 0.285034 0.544847 0.00336 -0.219707 0.512473 0.0111617 +0.487292 0.0635702 -0.711597 -0.0247088 -0.370464 -0.404298 -0.666299 -0.101871 +0.598502 0.510439 -0.756427 -0.512909 0.583027 0.375139 0.156568 0.131014 +-0.17058 0.990818 0.612171 0.120444 0.103895 0.541877 0.0448434 -0.16348 +-0.397441 -0.467477 0.719242 -0.465148 -0.439904 -0.964904 -0.43302 -0.816664 +0.453677 -0.824843 0.797395 0.549664 -0.948966 0.546001 -0.880261 -0.273346 +-0.953964 0.620678 -0.520965 -0.253769 -0.272652 -0.679127 -0.982491 -0.566005 +0.64798 -0.266019 -0.573181 0.977262 -0.463859 -0.330665 -0.734435 -0.92418 +0.803465 0.735973 -0.0784778 0.359947 -0.656448 -0.0861305 -0.0149736 0.938578 +-0.855584 -0.921477 -0.831869 -0.33965 0.693436 -0.963245 0.56718 -0.0405202 +-0.634494 -0.621353 -0.67548 -0.619686 -0.616101 0.806266 -0.746468 0.823212 +-0.234292 0.62324 -0.404441 -0.0396719 -0.353624 -0.0309763 -0.0210264 -0.765736 +0.794504 0.721823 0.323607 0.0348415 -0.450974 -0.311555 0.143033 -0.101537 +0.307413 -0.228631 -0.709472 -0.479056 -0.183105 0.241753 -0.258827 -0.431294 +0.729868 -0.867868 -0.819651 0.982833 -0.0388093 0.473378 0.167372 0.31321 +-0.431609 0.969556 0.544448 -0.350157 0.67349 -0.463998 0.188472 -0.487228 +-0.352616 -0.734989 -0.164356 -0.721236 -0.0695177 -0.963942 -0.216112 -0.344447 +0.737561 0.146819 0.823387 -0.894282 -0.198945 -0.193143 -0.409891 0.650166 +0.379543 0.831259 -0.0890597 -0.285106 0.19873 -0.349228 0.722469 -0.0811125 +0.162026 0.788818 0.22839 0.640705 0.341505 -0.563131 0.0293779 -0.0870272 +-0.965161 -0.309858 -0.401846 0.479686 -0.388533 0.266861 0.404528 -0.698517 +0.218193 -0.700151 -0.111992 -0.77773 -0.537417 0.0594156 -0.791989 -0.341195 +-0.0491561 0.188822 -0.807967 -0.438611 -0.408479 0.0560279 0.0305076 -0.165252 +-0.133245 -0.842566 0.375244 -0.787213 -0.862269 0.466999 -0.798118 0.195476 +0.299756 0.479351 -0.222634 0.80622 -0.379803 0.71845 -0.11904 0.41572 +0.92435 0.739867 -0.503637 0.532559 -0.541676 0.581079 0.316796 -0.521131 +0.0671036 -0.923564 0.970237 0.438984 0.964438 0.931545 -0.858427 -0.867754 +0.469373 -0.690432 0.632152 0.30219 0.516518 0.376453 0.942618 -0.510809 +-0.374131 -0.616714 -0.235787 0.381932 0.340483 -0.0552866 0.154077 -0.97495 +0.0478047 0.334196 -0.63611 0.379448 0.60729 -0.299805 0.701503 -0.37992 +0.916858 0.50276 0.614059 0.980054 0.6831 -0.0876382 -0.317726 -0.706322 +-0.164709 -0.359572 0.793866 -0.129485 0.758523 0.441986 -0.171055 0.490299 +-0.64881 -0.222841 0.538741 0.722652 0.306283 0.0446685 0.0302669 0.340515 +-0.0870664 -0.921692 -0.288006 0.401609 -0.699856 -0.464328 0.605429 0.201644 +0.443318 0.775192 0.339284 0.923055 0.272059 -0.926282 -0.84369 0.640364 +-0.435417 0.305676 0.183887 0.18005 0.93121 -0.597983 0.633152 -0.748446 +-0.444077 -0.152974 0.901408 0.00567173 0.337209 0.249761 -0.465012 -0.572423 +0.14441 -0.217803 0.886623 -0.298584 -0.992069 -0.910329 -0.865043 -0.79585 +0.0427073 0.169323 -0.610172 0.606651 -0.925988 0.248012 0.438596 0.80506 +0.580341 0.278589 -0.98893 0.999265 0.794102 0.809174 -0.0091269 0.349602 +-0.785846 -0.639567 0.411711 -0.517947 -0.331774 -0.00407746 -0.306337 0.998251 +-0.0411384 0.862358 -0.265456 0.834848 -0.168149 -0.652118 -0.286001 -0.955105 +-0.973704 0.054507 -0.421655 -0.7494 0.734801 0.733003 0.716725 -0.675356 +0.411991 -0.493809 0.140858 0.594907 -0.470983 0.563757 0.493642 -0.913018 +0.0848154 0.588962 0.52998 -0.612874 0.180051 0.98097 0.786611 -0.317053 +-0.345644 -0.437166 0.810846 0.858096 0.665159 0.478925 -0.0875771 0.0923788 +-0.241872 -0.0142244 0.147105 0.311358 -0.481969 0.53812 0.788871 -0.263556 +0.831506 0.640901 -0.932048 0.998328 -0.556773 -0.508118 0.937576 -0.67691 +-0.647504 -0.246892 -0.436839 -0.43205 0.656722 0.900011 -0.940555 -0.482263 +-0.749823 -0.919295 -0.680736 -0.293111 -0.581066 -0.28322 -0.138873 -0.544922 +-0.23649 0.571688 -0.364229 0.779989 -0.367618 -0.281898 0.597353 0.192759 +0.262706 -0.238745 -0.188718 -0.254212 0.37893 0.793777 -0.729617 -0.415413 +0.0467543 0.767762 -0.829876 0.775823 -0.313896 -0.0956588 0.97448 -0.21157 +-0.439962 0.461296 -0.221232 -0.979795 0.790144 -0.248104 0.242984 -0.88226 +0.0864715 0.982388 0.171117 -0.249684 -0.334482 -0.808296 -0.221967 0.822003 +0.632996 0.94374 -0.775281 -0.686826 -0.778744 -0.759771 0.927022 0.0224117 +0.379151 -0.615238 -0.0501672 0.641635 -0.337415 0.703021 -0.580354 0.875055 +-0.141639 -0.156486 -0.250025 -0.568296 -0.242664 -0.396983 -0.608354 0.675347 +0.62325 -0.391065 -0.762547 -0.809897 0.283655 -0.288219 0.350484 0.156588 +-0.776012 0.274076 0.294224 0.368845 0.796698 -0.454758 -0.834285 -0.955352 +-0.634363 -0.80141 -0.706988 -0.550012 0.948761 -0.412028 -0.416648 -0.928917 +-0.0891207 0.376098 -0.964987 -0.917623 0.94218 0.967984 -0.885209 0.953605 +-0.282277 -0.827035 -0.193524 0.663693 0.254509 0.634436 0.796459 0.720589 +0.88988 0.0108032 -0.228537 -0.0757205 -0.349577 -0.891614 -0.287738 0.796168 +0.196442 0.45566 -0.663953 0.332061 0.624401 -0.41001 0.877254 -0.578532 +0.907596 -0.606834 -0.720908 0.949873 0.307714 -0.720114 0.589878 0.0596667 +0.598985 -0.777062 -0.239063 0.244857 -0.866087 0.500555 -0.313432 0.999761 +-0.647462 -0.615176 0.861202 0.406797 -0.460893 -0.290523 0.659345 0.165012 +-0.96857 0.849776 -0.569581 0.694598 0.638149 -0.109018 -0.589715 0.826114 +-0.0027549 -0.930053 0.89528 0.976338 0.710978 -0.0452181 0.523359 -0.810643 +-0.670165 0.0473472 0.497387 0.694714 -0.458602 0.958052 -0.0847757 -0.857943 +-0.285355 -0.0624846 0.297264 0.0787774 0.572124 -0.0933931 -0.965279 0.910607 +-0.802499 -0.195514 0.600725 -0.736912 -0.0388842 0.217021 -0.901233 0.851295 +-0.835873 -0.0623102 -0.830387 0.960948 0.397927 -0.705977 0.313747 0.537092 +0.952972 -0.506664 0.00583154 0.860835 0.278171 0.530486 0.549018 -0.994979 +0.19622 -0.933826 -0.760742 0.248686 -0.603 -0.35062 -0.0153036 -0.577148 +-0.941617 0.517287 -0.268814 -0.210716 -0.0391231 -0.209571 0.533472 -0.80421 +-0.662987 0.839977 -0.348736 0.987334 0.136113 -0.936907 0.676846 -0.183018 +-0.244292 -0.501728 0.680024 -0.948987 -0.256957 -0.0360509 0.0846798 -0.3269 +-0.914367 -0.70277 -0.219623 -0.0701372 0.291313 0.848735 -0.766073 0.290009 +-0.239939 0.551149 0.828111 -0.921141 0.555425 0.904696 0.0177353 -0.72478 +-0.69786 -0.227274 0.389082 -0.491666 0.35536 0.290257 0.503103 0.201486 +-0.634598 0.969934 0.402552 -0.0453698 0.786254 0.9334 0.630699 0.881358 +-0.00591691 0.304347 -0.792962 0.823663 0.0365753 0.229457 -0.378103 -0.140421 +0.974196 0.451824 -0.0269083 -0.509734 0.408524 -0.893785 0.736339 0.827325 +0.12172 -0.884968 -0.613209 -0.778287 -0.985988 -0.383091 -0.91481 0.463101 +0.661399 -0.675849 0.040684 0.245202 0.472531 -0.035824 -0.93978 -0.134191 +0.587334 0.107128 -0.797056 0.945834 -0.990166 -0.117561 0.679656 0.958143 +-0.960443 -0.302675 0.29185 0.15371 0.0143037 0.372646 -0.519729 -0.974672 +-0.910563 -0.375314 -0.375177 -0.882413 0.728729 -0.10515 -0.827114 -0.950809 +0.692252 0.755329 0.606595 0.972517 0.418286 -0.11729 -0.571962 -0.813254 +0.803214 0.36952 0.289499 -0.336532 0.916552 0.221312 0.51359 -0.537217 +-0.561784 -0.529544 -0.802465 -0.0332391 0.428501 -0.219429 -0.278968 -0.284951 +-0.562281 0.274244 0.90186 -0.891902 0.900667 0.291199 0.00631785 -0.638341 +-0.49093 -0.530458 0.0828044 0.482718 -0.680165 -0.269098 -0.594883 0.849732 +0.879348 -0.298821 0.390532 0.102698 0.706264 -0.124483 -0.14492 -0.318506 +-0.358964 0.348387 -0.723543 -0.399297 -0.698828 0.455239 0.391509 0.548327 +-0.392957 0.422771 -0.627696 -0.192509 0.0241379 0.0278262 -0.312123 0.380219 +0.68006 0.626891 0.0441748 0.451729 -0.879991 0.0161236 -0.513503 0.310096 +0.365854 -0.984841 0.219854 -0.366791 0.519929 -0.580663 0.876846 0.730039 +-0.581241 -0.0153402 0.014145 0.981295 -0.498005 0.327281 -0.965842 -0.864351 +-0.105895 -0.855385 -0.138845 -0.964329 -0.842362 0.456257 -0.957012 -0.828246 +0.292177 -0.416624 0.71723 -0.623425 0.298619 0.488671 0.49368 -0.36694 +0.560037 -0.717505 0.68229 -0.162798 -0.42066 -0.0649666 0.312833 0.110852 +0.838137 0.767129 -0.256094 -0.657869 0.99366 0.875143 -0.0659944 -0.129317 +0.967663 0.195352 -0.507424 0.810117 -0.438656 0.321165 -0.387351 -0.922342 +0.426811 -0.895498 0.380813 0.454062 -0.842164 0.942753 -0.361861 -0.62961 +-0.0222192 -0.377454 0.870297 -0.863223 -0.179788 -0.820079 -0.220045 -0.520223 +-0.771642 0.499579 0.980336 -0.89382 0.138686 -0.0278531 0.48178 0.499688 +0.4789 0.198088 0.240406 -0.00892653 0.187878 -0.94387 0.420187 -0.827594 +-0.224953 0.499761 0.208712 0.426446 -0.416422 0.913984 -0.897736 0.0182281 +0.799346 0.535787 -0.815264 0.658569 0.752995 0.493531 -0.998731 0.358444 +0.205353 0.158476 -0.975775 0.405028 0.429149 0.970673 0.593034 0.162828 +-0.934039 0.702637 -0.894025 -0.625242 -0.130516 -0.17667 -0.328593 0.781197 +0.238078 -0.255501 0.97914 0.431254 0.522377 0.326107 0.648545 0.976772 +0.208661 -0.590069 -0.533551 -0.649294 0.76325 0.589831 0.234321 -0.0510115 +-0.69793 0.68513 0.930427 0.588933 0.774451 0.237988 -0.808147 0.169682 +0.0349228 0.514847 0.778509 -0.129969 0.0390609 -0.207936 -0.297653 0.472766 +0.512546 0.159146 0.727731 -0.177057 -0.809416 -0.602289 -0.787647 0.38428 +-0.186697 0.779926 0.660422 0.500904 -0.0689695 0.0559962 0.333259 -0.0574155 +-0.728707 -0.0706758 -0.888296 -0.238565 -0.250264 0.839343 0.493229 -0.576019 +-0.809987 0.220358 0.205609 0.757369 0.143384 0.615678 0.330835 0.977295 +-0.391994 -0.684258 0.205786 -0.00734942 0.726512 -0.71284 -0.0306872 0.456416 +0.499907 0.567074 -0.205645 0.251682 -0.186756 0.280597 -0.0836714 -0.108558 +-0.28285 0.0691123 0.530537 -0.185215 -0.606915 0.0682439 0.0027849 0.559894 +0.991504 -0.59958 -0.125012 0.831124 -0.662051 -0.764216 -0.731422 -0.351546 +0.0504676 0.349729 0.858409 0.0808612 -0.826867 0.43127 -0.254422 -0.630537 +0.3472 0.216606 0.227496 0.239261 0.416589 -0.974391 -0.766833 -0.789926 +-0.612068 0.932691 0.578923 -0.137452 0.000133821 -0.952855 0.0602413 -0.231185 +-0.801073 0.0313484 -0.580106 0.161526 -0.722227 -0.0439152 0.553315 0.906336 +0.0287729 -0.964495 0.955237 -0.447544 -0.0758286 0.528293 0.201741 -0.739478 +-0.781629 -0.284645 -0.483844 0.362895 -0.42788 -0.786034 0.850566 0.872203 +0.000988529 -0.872803 0.395764 -0.0222731 -0.462379 -0.363251 0.800724 -0.170503 +0.317611 0.694185 0.97882 -0.519405 -0.835364 0.771746 -0.618922 -0.0419782 +0.555083 0.230567 -0.573056 -0.401002 -0.660464 0.101558 -0.896003 0.474492 +0.541582 -0.388696 0.723882 0.278064 0.957648 -0.645315 0.0103556 -0.228311 +-0.876491 0.895205 -0.059744 0.556219 0.953718 0.982976 0.996312 0.802643 +-0.268706 -0.950022 0.648118 -0.218916 -0.536437 -0.89109 0.477512 -0.703463 +0.840411 -0.234881 -0.98169 0.665541 -0.675073 -0.79018 0.122206 0.107823 +0.940919 -0.588458 0.0397954 -0.973241 -0.768445 -0.843359 -0.114625 -0.712586 +-0.763167 0.336097 0.92266 0.358382 -0.598842 -0.775323 0.980411 -0.806153 +-0.312086 0.157702 0.789472 -0.503158 -0.257445 -0.743381 -0.828678 0.86506 +-0.0126923 -0.392215 -0.13923 0.83301 -0.524511 -0.176745 -0.114381 0.28772 +-0.0400626 0.657065 0.58184 0.600973 0.362788 -0.950236 -0.314557 0.184622 +0.0749907 0.697958 0.330292 -0.640931 0.11142 0.925076 -0.694668 -0.638676 +0.493009 0.145296 -0.520822 -0.98083 -0.914793 0.733923 -0.373969 -0.440337 +-0.970714 -0.175843 0.98078 -0.737724 -0.0116679 -0.0424787 -0.794543 0.294647 +-0.139649 -0.897596 0.0889451 0.331298 0.880008 0.851879 0.135868 -0.899387 +-0.507133 0.936525 -0.857716 -0.633908 -0.655703 -0.554029 -0.402635 -0.446275 +-0.985789 0.610474 -0.938237 -0.0277712 -0.785777 -0.500821 0.592228 0.541555 +-0.985032 0.177672 -0.384303 -0.961241 0.928837 -0.272532 0.132935 0.878376 +0.465095 0.675375 0.438776 0.538609 -0.763695 -0.14723 -0.531163 -0.592394 +-0.838288 0.000891291 -0.519412 -0.0231059 -0.733383 0.948007 -0.158819 -0.297876 +-0.925951 -0.1423 -0.51796 0.0954837 0.159675 -0.916505 -0.203607 -0.017358 +-0.92074 0.99374 -0.0859041 0.770165 0.722163 -0.653699 -0.130248 -0.207295 +-0.462486 0.0955302 -0.698791 -0.212344 0.200033 0.647105 0.821219 -0.132371 +-0.565166 0.0770586 0.961235 -0.508404 -0.442225 -0.953534 -0.293995 -0.708842 +-0.849335 0.209508 -0.448546 -0.556959 0.934118 -0.0660197 0.0713486 0.739346 +0.890078 0.402817 -0.800801 -0.191642 -0.766558 0.982021 -0.278174 -0.0073298 +-0.963572 0.284708 -0.58032 -0.706186 -0.95045 0.0150127 0.0315615 0.96933 +0.840222 -0.683602 0.910108 -0.343273 0.441095 0.63458 0.89769 0.554707 +0.491723 -0.774222 -0.692531 -0.0468481 0.706801 -0.339504 0.59126 -0.686917 +-0.445663 -0.649241 -0.863431 -0.710597 -0.921198 -0.901963 -0.129142 0.760962 +0.0320171 -0.285886 0.338763 -0.768237 0.252418 -0.205757 -0.574938 -0.879478 +0.301201 -0.413578 -0.519134 0.047605 0.462966 -0.441339 -0.94419 -0.427017 +-0.358283 -0.96023 -0.598302 -0.0410851 0.557403 -0.534843 0.747025 -0.134568 +0.880795 0.610099 -0.582609 -0.456949 0.95577 0.576349 0.684508 0.665622 +-0.237965 0.384696 -0.179683 0.324595 -0.992583 0.0704854 0.401968 0.796009 +-0.00203615 0.69546 0.328352 -0.509609 -0.447603 -0.265674 -0.475372 -0.0344349 +-0.589852 0.338638 -0.361372 -0.868961 -0.736954 0.113487 0.704388 0.555416 +-0.130052 -0.0963523 0.362398 0.762927 0.0542655 -0.558715 0.613645 0.611645 +-0.0890763 0.073031 -0.520539 0.53027 -0.0493678 0.27893 -0.324707 0.48077 +0.485537 -0.209992 -0.278468 0.0241694 0.504499 0.0158526 0.212986 0.896538 +-0.918242 -0.347432 0.0817963 -0.190843 0.898233 -0.91068 -0.212327 0.761878 +0.0486397 -0.154782 0.17479 -0.282162 0.319754 -0.349857 -0.819006 0.953552 +-0.600682 0.33818 -0.569613 -0.966094 0.389177 0.00301871 -0.460958 -0.802867 +0.897449 0.218671 0.834667 0.383977 0.24897 -0.471332 0.311505 0.275869 +-0.955746 0.310375 -0.782398 -0.559921 0.0162922 -0.368741 0.689078 0.788591 +0.312957 0.474791 0.789484 0.12461 0.0376771 0.358785 0.264312 -0.090945 +-0.187699 0.693019 0.0338453 0.981572 -0.667717 -0.222581 0.969189 -0.492898 +-0.162957 0.414095 -0.525001 -0.542582 0.761473 0.867993 -0.479436 0.969725 +0.122143 -0.367049 -0.211531 -0.813606 -0.735177 -0.588383 -0.363287 -0.682746 +-0.0615493 -0.111727 0.0677509 -0.994696 -0.482459 0.71518 0.714496 0.816877 +0.477809 -0.845984 -0.104193 0.841676 0.98396 -0.14268 -0.174282 0.178472 +0.227179 -0.00360693 0.695781 -0.551831 0.36939 0.227701 0.849255 -0.591003 +0.327169 0.788534 -0.511301 -0.22985 -0.817921 0.331116 -0.214407 -0.910214 +-0.708966 0.208188 -0.508084 -0.540582 -0.193875 0.608349 0.967027 -0.279604 +0.364089 0.768508 -0.430323 0.781235 0.229113 -0.531661 0.315563 -0.797436 +-0.771633 -0.964051 0.887155 0.0490612 -0.49456 0.60161 -0.577165 -0.42747 +0.631762 -0.10653 -0.87284 -0.791872 -0.397926 -0.815688 -0.443718 0.676639 +0.237383 0.627652 0.581267 -0.0624467 0.481185 -0.734953 0.105723 -0.930586 +0.281403 0.460436 -0.00877237 -0.219244 0.891316 -0.769947 -0.576876 -0.577317 +-0.264914 0.949003 0.242688 0.122196 -0.537458 0.642368 -0.401507 -0.305504 +-0.644836 -0.679715 0.308287 -0.116654 -0.350678 0.827556 0.269841 0.875639 +-0.0122482 0.788323 -0.0636885 -0.920086 -0.558517 -0.581069 -6.7954e-05 0.377795 +-0.83225 0.981355 -0.231438 -0.0760357 -0.381715 -0.107074 -0.117899 0.190844 +0.947034 -0.0348618 0.250442 0.191565 -0.775705 0.154775 -0.0833674 0.672069 +-0.651433 -0.85605 -0.218248 0.339136 0.812395 0.793409 0.203541 0.140841 +-0.15254 0.249303 -0.773216 0.477813 -0.726266 -0.186391 -0.042282 0.863566 +-0.22177 0.165006 0.119711 -0.99751 0.462757 -0.0655601 -0.141857 0.907958 +0.457659 0.189563 0.373878 -0.584828 -0.839178 -0.413517 -0.902242 -0.962533 +0.636505 0.614248 -0.307533 -0.0669895 0.68695 0.974162 -0.414596 0.909689 +-0.771077 -0.738859 -0.750467 0.519689 -0.998582 -0.0267039 0.972495 0.0175519 +0.765825 -0.287436 0.222765 0.961867 -0.305154 0.788899 -0.295583 0.709795 +-0.246841 0.961723 -0.777986 0.893427 -0.423192 -0.109563 -0.925778 -0.753771 +0.104348 0.302678 -0.912214 0.00249155 -0.312287 0.396746 0.168541 0.115341 +0.014949 -0.252524 -0.657262 -0.20561 0.199603 0.228653 0.720772 -0.918958 +-0.774701 0.975592 -0.946264 -0.849281 -0.455914 0.192243 0.424375 0.56935 +0.66413 0.862284 0.34288 0.819815 0.280028 -0.0379026 0.776205 -0.0816372 +-0.693112 0.654071 -0.385478 -0.673351 0.674679 -0.128085 -0.327999 0.123251 +-0.863902 -0.605326 -0.768949 -0.732213 -0.859094 -0.910892 -0.753148 0.852136 +0.139327 0.647198 -0.695638 -0.650699 0.488065 0.710881 -0.052738 0.979065 +0.96188 -0.882517 -0.487372 -0.895156 -0.731849 -0.752382 -0.0555075 -0.841653 +0.289452 0.190389 -0.439215 0.963425 -0.180696 -0.41886 0.626262 -0.832502 +0.0952616 0.145581 -0.944876 -0.890151 -0.990307 -0.899171 -0.906756 0.715892 +-0.758892 -0.167672 -0.989394 0.903334 -0.220127 -0.353353 0.656034 0.0925861 +0.257189 -0.913204 0.124925 -0.641496 -0.503652 -0.30457 0.0317497 -0.808368 +0.811121 0.674702 -0.0342996 -0.664897 -0.0646336 -0.654337 0.825959 -0.422053 +0.850755 0.0808313 -0.0784897 -0.66403 -0.293737 -0.549064 0.453074 0.550516 +-0.506625 0.500224 0.502962 0.271969 0.539411 0.329842 -0.549577 0.0854797 +-0.351406 0.052171 0.941238 0.03936 -0.123868 0.150834 0.81009 0.975996 +0.599451 0.36938 0.6028 0.653908 -0.721486 -0.396746 -0.646534 0.923577 +-0.232604 -0.897794 -0.0260559 0.91711 -0.838969 -0.0474446 -0.251691 -0.0617259 +0.060493 -0.464392 0.661492 -0.285598 -0.635514 -0.369137 0.352977 -0.890196 +-0.955907 -0.116436 0.812475 -0.899991 -0.408582 0.916462 -0.60746 0.00521365 +-0.982504 -0.106176 -0.0219168 -0.509379 -0.419312 -0.878456 -0.503178 -0.484892 +-0.978184 0.338475 0.462099 -0.621855 0.479982 0.361033 -0.151682 0.197591 +-0.144616 0.646619 -0.0578232 -0.742414 0.541164 -0.67586 0.381051 0.51102 +0.351967 -0.890665 0.120717 -0.0687964 0.986809 -0.934492 0.887835 -0.113176 +-0.70413 -0.629716 -0.939221 0.0804935 0.644462 -0.4129 0.67533 0.209738 +0.521936 -0.787522 0.892707 0.670515 0.461472 -0.904075 -0.107031 -0.940442 +-0.98956 -0.603699 -0.31856 0.276867 -0.317106 0.348596 0.773518 -0.154266 +-0.8903 -0.884725 -0.868828 0.188125 -0.300871 0.530784 0.131985 0.105447 +-0.144031 0.304302 -0.985802 -0.384027 0.37946 -0.332699 0.517149 -0.455308 +-0.119757 0.677374 0.925894 -0.929066 0.786887 0.960437 0.788471 0.715683 +0.958458 0.568038 0.222981 -0.817089 0.939071 0.249736 0.320322 -0.487564 +0.703385 -0.393002 -0.688667 -0.903855 -0.971126 0.712135 -0.668344 -0.580313 +0.0283297 0.392803 0.873114 -0.787694 0.557397 0.0225545 -0.0324734 -0.131235 +0.712484 0.1031 -0.0644722 0.895062 -0.617746 0.389033 0.587848 0.61443 +0.957954 0.323512 -0.915179 0.958706 0.502953 0.183585 0.794429 0.447973 +0.0684171 -0.859266 0.199364 -0.00677877 0.775452 0.959018 0.815097 0.76503 +0.032451 -0.0488488 0.305582 0.864427 0.495644 -0.345989 -0.563957 0.604405 +-0.465654 -0.40132 0.284185 -0.36625 -0.455115 -0.558626 0.399088 -0.804661 +0.148858 -0.55583 0.745466 0.348599 -0.984103 -0.306385 -0.147229 0.0302473 +-0.199802 0.493632 -0.478577 0.443527 0.759946 0.600887 0.00843066 0.0412703 +-0.799267 0.333701 -0.38604 0.635409 0.281086 0.211121 0.718651 -0.512993 +0.950882 -0.173535 0.495208 -0.507966 0.885123 -0.79731 -0.334338 -0.844913 +0.676898 0.686809 0.673109 0.608432 -0.262318 0.897646 0.547983 0.742935 +-0.839834 0.51153 0.304554 -0.534904 -0.665482 -0.105767 0.447829 -0.395065 +0.24932 -0.959949 -0.845937 0.790385 -0.36664 -0.0685263 -0.763679 -0.341931 +0.770678 0.104919 0.67285 -0.475033 -0.281144 -0.535127 -0.104696 -0.167921 +0.406637 -0.400048 -0.529971 0.945332 -0.716183 0.554581 -0.858926 0.530261 +-0.130121 0.45542 -0.799044 -0.514247 -0.885435 0.0658838 -0.112793 0.922899 +-0.632733 -0.839631 0.657114 -0.0595196 0.85263 -0.483647 -0.588631 0.434639 +-0.763286 0.829716 -0.774419 -0.135791 -0.226617 -0.971946 0.450276 -0.748912 +-0.829521 -0.219481 0.00672118 -0.794178 -0.568094 0.184311 0.603022 -0.0555631 +-0.818178 -0.904793 0.518201 -0.14007 -0.86115 0.624831 -0.536512 0.268663 +0.747958 -0.978679 0.647341 0.187085 0.788826 0.944593 0.60351 0.378025 +0.896682 0.152103 -0.640573 -0.916862 0.809931 -0.718852 0.746217 -0.288638 +0.132065 0.853987 -0.946194 0.178117 -0.234832 -0.787313 0.724442 -0.804484 +0.841424 -0.935334 -0.219099 0.853492 -0.425391 -0.666394 0.804367 0.450022 +-0.0559757 0.89209 -0.666535 -0.27427 -0.950254 0.386653 0.669156 -0.469244 +-0.639528 0.746106 0.900671 0.298351 -0.558404 0.187357 -0.474758 0.856625 +0.943668 0.272076 -0.47407 0.246344 0.502997 -0.183403 0.849963 0.0174011 +0.677586 -0.502934 0.454683 0.605003 -0.92176 -0.616544 0.487946 0.397674 +-0.551589 0.609696 -0.489814 0.925535 -0.413836 -0.967745 -0.76 0.00678453 +-0.836005 -0.798824 0.893406 -0.748916 -0.439515 -0.106358 -0.455938 0.830748 +0.0613894 -0.367138 -0.901316 0.340187 -0.329082 0.448266 -0.0103162 -0.510146 +-0.925967 -0.348735 -0.617499 -0.466985 0.0377553 0.305652 -0.373743 -0.563813 +-0.215901 0.971575 -0.387115 -0.552134 -0.335928 0.891275 0.107977 -0.353687 +0.346958 0.0134376 0.972283 -0.0779874 0.960555 0.44081 0.313072 -0.20081 +0.50655 0.966124 0.531481 0.536602 -0.0962096 -0.645679 -0.748907 -0.114082 +-0.730333 -0.309869 -0.558686 -0.33768 0.27867 0.701115 0.105935 -0.930818 +0.470554 0.381202 0.607257 -0.267815 0.566203 0.409737 0.553764 0.258616 +-0.367004 0.738815 -0.0804347 -0.0459079 0.721225 -0.582668 0.622424 -0.292641 +0.545229 0.166704 -0.202632 -0.481201 -0.878181 0.0831667 0.758087 0.259266 +0.754528 0.474816 0.00861407 0.406863 -0.604234 -0.435677 -0.54182 0.709244 +-0.913399 -0.364028 0.572926 0.307614 -0.425578 -0.963852 -0.643343 0.261065 +-0.603916 0.909204 0.196812 -0.351592 -0.445108 0.398432 0.616995 0.623206 +0.850149 -0.0909519 -0.29138 -0.602343 -0.669736 -0.629829 0.172692 -0.473004 +0.248849 0.0156421 0.17716 0.0974834 0.152069 0.802682 0.543331 -0.506565 +0.729818 0.122228 -0.0971823 -0.244587 0.415095 0.977121 0.210393 0.0410674 +0.879973 0.135216 -0.704358 -0.917243 -0.840452 0.276222 0.93666 -0.692741 +-0.933786 0.664264 0.173459 0.375414 -0.8766 0.788061 -0.399528 -0.0286686 +-0.642726 -0.618546 -0.537998 0.641385 -0.292247 -0.0933617 0.873355 -0.487486 +0.183198 0.671922 0.838543 0.191269 -0.377824 0.967969 0.0460472 -0.386277 +-0.0989322 -0.614006 -0.42701 -0.636265 0.0925185 -0.539117 0.354915 -0.504088 +0.167572 0.457611 0.54502 0.0310795 0.519358 0.275429 0.916363 0.881313 +-0.0726403 0.414511 -0.716541 -0.391977 0.690113 0.716706 0.281276 -0.842286 +0.287011 -0.432998 0.781827 -0.166975 -0.194825 0.455087 -0.760107 -0.836116 +-0.170192 0.876408 -0.834564 -0.960086 -0.952722 0.52316 0.0729177 0.501935 +-0.662812 0.875393 0.843351 -0.187418 0.773837 0.735443 -0.717014 0.553597 +-0.157824 -0.159628 -0.419416 0.15577 -0.812527 0.360696 -0.217718 0.0164864 +-0.740506 -0.103478 0.0169908 0.419559 0.821638 0.62033 0.65779 -0.343858 +0.452492 0.2548 -0.795943 -0.694096 -0.52172 -0.544809 0.531331 -0.960923 +-0.657693 -0.882995 0.0375964 0.22507 -0.920386 0.330874 -0.615008 0.585572 +0.205102 0.581671 0.789423 -0.845662 -0.209172 0.564361 0.667472 0.578153 +0.0689673 -0.0126824 0.241653 -0.327017 -0.512004 -0.449905 0.164354 -0.211784 +-0.297128 0.886296 0.348349 0.633904 0.388161 -0.335727 -0.842603 -0.572757 +0.283042 0.113655 -0.763819 0.566521 -0.804337 0.790946 -0.422361 0.066902 +0.54913 0.123015 0.829041 -0.391733 0.39943 -0.636955 -0.695998 0.0905171 +0.175117 0.606036 -0.673416 0.249112 -0.496315 -0.167191 -0.091044 0.513134 +0.877112 0.396982 0.685741 -0.792368 -0.235322 0.618024 -0.137511 0.12308 +0.490078 0.0671532 0.162762 -0.420424 -0.0875615 -0.199071 -0.783905 -0.241668 +0.64501 0.304917 0.418164 -0.212675 0.521454 0.708504 -0.0821817 0.0594873 +-0.820473 0.0948298 -0.886739 -0.550107 -0.652213 -0.819744 -0.0997843 0.353467 +0.306612 -0.39133 -0.348201 0.448639 -0.789163 0.0186648 0.295967 0.914176 +-0.533277 -0.0339372 0.104407 0.324413 0.212383 -0.878661 0.209887 0.306651 +-0.881642 0.25031 -0.415166 0.855903 0.214193 0.025399 -0.22203 0.571824 +0.71636 0.396948 -0.892458 0.858979 0.904456 -0.624258 -0.997935 -0.209621 +-0.302727 0.358524 -0.281995 -0.245178 0.00841442 -0.11592 -0.774032 0.561263 +0.948927 0.16215 -0.390985 -0.424176 0.379584 0.206267 -0.286016 0.558752 +-0.47546 0.6948 -0.971628 -0.3329 0.464283 0.822603 0.590005 -0.128156 +-0.265066 -0.712716 0.355359 -0.210927 0.86857 -0.405269 0.0154551 -0.0524003 +-0.0342695 0.785197 -0.12004 -0.619969 0.0305008 -0.323594 -0.0334806 0.0765711 +0.234872 -0.665406 -0.677282 0.392269 0.739396 -0.241054 0.167588 0.774975 +-0.764842 -0.122105 0.85323 -0.707777 -0.631841 0.436807 -0.160758 -0.0016953 +0.567043 0.614199 -0.0145614 0.142769 -0.377262 -0.237247 0.461966 0.690182 +0.0134212 -0.0299085 0.0534913 -0.374947 -0.627306 -0.356386 0.476337 -0.891982 +0.468098 -0.574631 -0.456699 -0.918161 0.208839 0.566924 -0.115736 0.869802 +0.0793177 0.490222 -0.185521 0.189923 -0.0943652 0.562403 -0.410622 -0.712502 +-0.951183 -0.12032 0.776452 0.529138 -0.84233 0.972017 -0.605747 -0.0206698 +-0.256617 0.729897 -0.727987 -0.526322 -0.0425027 0.168154 0.0810821 -0.540821 +-0.548331 0.853898 -0.504343 -0.0463173 -0.0713747 -0.314358 0.606325 -0.419281 +0.892865 -0.604713 0.574714 0.125193 0.486 -0.727891 0.576456 0.967208 +0.568343 -0.982626 0.312736 -0.681818 0.317003 -0.121853 -0.0536441 0.860819 +0.826723 0.318229 -0.736094 0.0134885 0.965055 -0.247302 -0.688274 0.482682 +-0.0292887 -0.358691 0.261033 -0.0598555 -0.876009 -0.557208 0.744197 0.276602 +-0.604998 0.332384 -0.983015 -0.304436 0.923102 0.749504 -0.757294 -0.377615 +-0.0648532 0.922708 -0.930013 -0.752686 -0.744714 0.0273013 0.0490791 0.857023 +-0.424368 0.826781 -0.879546 0.311477 0.700447 0.160418 -0.998176 -0.242925 +-0.209553 -0.192164 -0.442874 -0.816464 -0.989184 0.332274 -0.790085 0.54333 +-0.874551 0.0181679 -0.516911 -0.994742 -0.102463 0.348485 -0.0252379 -0.938111 +-0.640902 0.18803 0.64721 0.0115315 0.787931 -0.321811 0.39656 -0.803182 +0.0414234 -0.690448 -0.0515842 0.470013 0.446467 -0.109847 -0.43762 -0.888103 +-0.244172 -0.810811 -0.463355 0.508295 -0.954523 0.752755 0.819407 0.336853 +-0.645397 -0.708511 -0.269597 0.0576244 -0.907121 -0.908286 0.840547 0.271441 +0.213379 0.204338 -0.224331 -0.470491 -0.747464 0.586295 -0.193571 0.727277 +0.667593 0.846802 -0.92505 -0.967607 -0.21128 -0.20069 0.8426 -0.912126 +-0.094351 0.754726 0.692247 -0.8727 -0.435482 0.729205 0.329841 -0.239777 +0.482003 0.540016 0.400182 0.584533 0.594352 -0.224742 -0.99018 -0.365495 +-0.123584 -0.547139 0.170261 0.704244 0.704143 -0.46706 0.128778 0.543696 +-0.209179 -0.400937 -0.458475 -0.338609 -0.924137 -0.130142 -0.384185 -0.267361 +0.394728 -0.300397 0.502588 -5.66998e-05 -0.754345 0.733919 -0.225551 -0.225447 +0.798904 0.313307 0.885807 -0.804789 0.841102 -0.17677 0.665423 0.934713 +0.133434 0.862782 0.706749 0.743111 0.803831 -0.405349 -0.680002 -0.65964 +0.709679 -0.578185 0.742372 0.913493 0.750212 -0.81846 0.817477 0.779722 +-0.646891 0.480178 -0.833644 -0.297043 -0.855037 -0.323747 0.196813 0.841262 +0.27306 -0.867964 -0.36413 -0.527862 0.899337 -0.651062 -0.0152727 0.510921 +-0.62046 -0.860057 -0.603597 -0.497356 -0.85335 -0.667626 0.981406 0.663257 +-0.236741 0.87578 -0.635824 -0.0714842 -0.577548 0.248457 -0.314388 -0.774441 +0.0308561 0.877784 0.882683 0.599996 0.69647 0.0172356 0.016956 0.925496 +0.888874 0.411776 0.660213 -0.981331 -0.861061 -0.283163 -0.36206 0.218147 +0.171534 0.600916 0.34933 0.158056 -0.214328 0.354213 0.797588 0.630514 +0.766312 0.484621 -0.592262 -0.498101 0.976096 0.702271 -0.765422 0.709424 +0.0999393 -0.768355 -0.480068 0.266339 0.133088 -0.829619 -0.164323 0.110434 +-0.300064 -0.235681 0.341673 -0.241589 -0.342955 0.0950661 -0.820896 0.304435 +-0.501493 0.746096 0.728828 0.483865 -0.471456 0.0280791 -0.723644 0.860073 +0.142364 -0.795489 -0.708879 -0.317509 -0.201062 0.923447 0.367666 0.0252843 +-0.476622 -0.347662 -0.855173 0.00143293 0.141859 -0.303242 0.358551 -0.0809706 +0.932145 -0.18086 -0.978378 0.979316 -0.338207 -0.365419 0.328332 0.396093 +0.964991 -0.140835 0.301633 -0.0695005 0.0705005 -0.957443 -0.804295 0.601779 +0.830231 -0.879194 -0.156087 -0.697821 -0.700792 0.601835 0.727405 -0.282395 +-0.931165 0.331703 0.789664 0.693819 0.678749 0.449265 -0.955396 0.298338 +0.176182 0.87002 -0.446887 0.657141 0.773813 -0.883434 0.938524 -0.479869 +-0.249151 -0.725152 0.266159 -0.0654869 0.0862028 0.763146 0.900775 -0.581974 +0.845321 -0.0729742 -0.831248 -0.903661 0.324603 0.339655 0.815701 -0.0998833 +-0.559835 -0.851241 -0.663833 -0.906784 -0.433688 0.176868 -0.390089 -0.478584 +0.144606 0.369814 0.0372999 0.412716 0.494503 -0.82662 -0.572932 -0.174767 +0.0859566 0.925116 -0.285663 0.508513 -0.411593 -0.715404 -0.373222 -0.460061 +0.551503 0.667559 -0.436541 0.0951149 -0.752639 0.931708 0.546945 0.359672 +-0.212842 -0.298282 0.0607391 0.030647 0.401654 -0.96886 -0.5564 -0.229788 +-0.924008 -0.811365 0.639315 0.26512 -0.769191 -0.902165 -0.251788 0.848436 +0.808648 0.805774 -0.472114 0.705025 0.55845 0.17971 0.289988 -0.307662 +-0.361655 -0.759789 0.989953 -0.0391764 -0.051465 0.900116 -0.393512 0.440551 +0.0763763 0.489862 -0.666779 0.562786 0.291706 0.170673 0.787105 -0.289259 +-0.257504 -0.43626 0.792029 0.274716 -0.617916 -0.654418 -0.958838 0.0568095 +0.616259 -0.914804 -0.0190587 -0.704978 -0.242336 -0.973583 0.496185 -0.615579 +0.920462 0.866854 -0.829198 -0.136917 -0.492731 -0.922408 -0.951137 0.727202 +0.00348854 -0.391947 -0.231838 0.493274 -0.996519 -0.260075 0.771868 0.870124 +0.830233 -0.925175 0.996539 0.826752 -0.418671 0.417069 -0.828469 0.228377 +0.821491 -0.49821 -0.163306 -0.818344 -0.0498616 -0.170444 0.0328762 -0.731516 +0.667227 -0.332722 0.953548 -0.405401 0.620377 -0.939604 -0.755965 -0.0372982 +-0.092582 0.692445 0.944956 -0.20967 -0.941755 0.0343647 0.968934 -0.566135 +-0.141614 0.356234 -0.131954 -0.51963 -0.0972306 -0.995663 0.184744 0.135003 +0.46079 -0.0962763 0.666713 -0.13341 0.380956 -0.00794642 -0.61904 0.328261 +0.430556 -0.112199 -0.77223 -0.711065 0.352103 -0.057003 -0.120917 -0.418046 +0.703284 -0.343972 -0.934621 0.18446 0.194894 0.0768015 0.748957 0.893926 +-0.6781 0.591317 -0.876744 0.341167 0.840744 0.479815 -0.998961 -0.668906 +-0.564083 -0.120834 0.356981 0.989786 0.227531 0.680774 0.978001 0.715466 +-0.414349 0.160306 -0.100453 -0.19362 0.706187 -0.221035 -0.632907 -0.632393 +0.747987 0.955967 0.396999 -0.967516 0.563976 0.781441 0.872177 0.211161 +-0.48628 0.343442 0.924508 -0.473322 -0.105208 0.954776 0.412598 -0.276284 +0.641808 0.664805 0.422078 0.804798 0.624479 0.193849 0.463262 0.674536 +0.940558 0.876727 0.357005 0.757128 0.312283 -0.967821 0.528998 0.677824 +-0.583199 0.316136 0.0934153 0.175373 0.363483 0.264127 -0.98363 -0.228808 +0.311756 -0.54244 -0.593852 -0.66438 0.342554 0.00448297 0.391012 0.501337 +0.82219 0.114693 0.857205 -0.113997 -0.80673 0.12687 -0.0537883 -0.877063 +-0.128875 -0.624697 -0.98395 -0.926508 0.664611 0.729306 -0.827396 -0.359327 +-0.24602 0.52598 -0.0437766 0.574809 -0.993097 0.727501 -0.316276 -0.348622 +-0.285874 0.490093 0.125751 -0.393087 -0.714803 0.434096 -0.411678 -0.253062 +0.141284 -0.218594 -0.290909 -0.0756113 0.319561 0.33128 -0.869283 0.475909 +-0.933981 0.481987 -0.118591 -0.611428 0.796587 0.654279 -0.450943 0.225717 +0.584282 0.0561487 -0.551652 -0.706212 0.782172 0.457304 0.826883 -0.294561 +-0.00654909 -0.0238666 -0.606697 0.171336 0.522634 0.414978 0.67485 0.159151 +-0.66459 0.154426 0.60672 0.336923 0.785555 -0.737444 0.917125 0.0064614 +-0.577299 -0.834931 -0.358861 -0.765279 0.834001 0.471985 -0.160271 0.0363573 +-0.290718 0.186945 -0.0422565 0.671869 -0.0464416 -0.527829 0.179027 -0.094191 +0.823146 -0.0989166 -0.185364 -0.412318 0.105894 -0.31185 0.76524 -0.468312 +-0.537756 0.944155 -0.113883 -0.636604 -0.575465 -0.00326705 0.314706 -0.507163 +0.51412 0.521641 0.938342 -0.499935 -0.205773 -0.495695 -0.160574 0.184923 +-0.742075 -0.842996 -0.808609 -0.690305 -0.676926 -0.343345 0.445905 0.486126 +-0.0634245 -0.207896 -0.16498 -0.925668 0.582142 -0.666177 -0.841095 -0.453497 +-0.154675 0.622874 0.669864 0.00453511 -0.958206 -0.702163 0.237264 -0.511588 +0.653803 -0.441264 -0.0604796 -0.602637 0.167087 0.128361 0.389147 0.271361 +0.574152 -0.275057 -0.883065 0.195813 0.643444 -0.930003 -0.904643 -0.609023 +-0.868801 0.112228 0.697994 0.645571 -0.63435 0.783179 0.732564 -0.934264 +0.814669 -0.194712 0.150047 0.947009 -0.826012 0.896548 0.781659 -0.189373 +-0.504756 0.358911 0.0557541 -0.482806 0.8569 -0.21997 0.885924 -0.908434 +0.6879 0.0709806 0.387706 -0.321125 0.19731 0.115749 0.354793 0.495713 +0.295946 0.44123 -0.339491 0.825531 0.271526 0.686722 0.45988 0.471292 +-0.70877 0.656621 -0.799589 -0.285575 -0.191575 -0.647724 -0.611062 -0.236987 +-0.933419 0.967166 0.688633 -0.0451107 -0.608065 0.0354303 0.234907 -0.335263 +0.0183814 0.15336 -0.797535 0.303284 0.0978846 0.310774 -0.184561 -0.207435 +-0.378662 0.802281 0.523453 -0.45621 -0.224442 -0.0527786 0.28046 -0.85757 +-0.563993 0.720886 0.745362 0.936508 0.105535 -0.40803 -0.673072 -0.509342 +-0.558965 -0.534701 -0.949386 -0.497307 -0.845344 0.952257 0.774218 -0.784747 +-0.226164 -0.353859 -0.0276497 -0.138868 0.893743 0.263379 -0.742459 -0.73528 +0.920107 0.257864 0.398545 0.143756 0.760314 0.455289 -0.501466 -0.596911 +0.408561 -0.727019 0.912709 0.533152 0.329288 -0.348257 0.965502 0.34198 +-0.411456 0.652547 -0.299001 -0.896395 -0.656623 0.0781634 0.380077 0.914864 +-0.326664 -0.131558 -0.491358 0.832212 -0.468633 0.576658 0.901296 -0.366231 +-0.270571 0.3933 -0.0355827 0.864757 -0.149494 0.185708 -0.608046 0.415472 +0.299774 0.282516 -0.483964 -0.841935 -0.483778 0.425422 0.446914 0.480453 +0.529066 -0.362368 0.247862 0.889101 0.248018 -0.426146 -0.93691 0.0142508 +0.394014 -0.992437 -0.0965593 0.425013 -0.584837 -0.34293 -0.121579 -0.240481 +-0.381852 0.980143 0.557916 -0.207325 -0.265601 -0.0745425 0.916415 0.0431458 +0.787258 0.27153 0.185874 -0.183988 -0.32713 0.817681 0.0656985 0.606756 +0.0447763 -0.0805468 0.94682 -0.166576 0.578229 0.739584 0.698273 -0.14163 +0.488017 0.857431 0.875631 0.564616 -0.344284 -0.933559 -0.704433 0.450133 +0.707089 -0.458679 -0.01303 -0.274325 -0.427044 -0.392301 -0.925996 -0.948434 +-0.783134 0.910236 -0.650189 -0.95997 -0.24753 -0.219915 -0.406262 0.607386 +0.812164 0.691252 0.808511 -0.230207 -0.00842888 -0.764701 -0.479814 -0.157139 +-0.416275 0.394686 0.367218 -0.966156 0.582522 -0.614079 0.954274 0.473963 +-0.549753 -0.00547251 -0.36182 -0.712263 0.530485 0.621769 -0.539101 -0.271036 +-0.618533 -0.218757 0.155714 0.422001 -0.21221 0.562021 0.739202 0.769531 +-0.0498263 -0.0162003 0.267082 0.775233 0.91126 0.749903 0.735397 0.724286 +0.81932 -0.843928 0.529529 0.259539 -0.184566 -0.245879 0.905974 -0.856265 +-0.903726 -0.248198 -0.770753 0.474829 -0.952649 0.0330828 -0.556191 0.956247 +-0.624436 0.47964 0.131432 -0.168345 -0.477246 -0.0911477 0.778222 0.135703 +0.735938 0.658457 0.206606 0.421425 0.385614 -0.812726 -0.306028 -0.419352 +0.0394456 0.847125 0.668017 0.110562 0.337858 0.183032 -0.551017 0.783097 +-0.704871 -0.480713 0.646156 0.16095 -0.765813 0.735973 0.625862 0.729738 +0.18318 0.0945581 0.55991 0.628873 -0.960968 -0.329497 -0.809604 -0.0621605 +0.7643 0.65972 -0.103192 0.023295 0.957597 0.835945 -0.19354 -0.298343 +0.601999 -0.650217 0.787204 -0.0923997 -0.043043 -0.502477 0.819477 0.91156 +-0.80225 0.629247 0.485568 0.884574 0.661799 -0.0913704 -0.717703 0.0780696 +0.852178 -0.55987 -0.782186 0.392126 -0.165152 -0.364592 -0.571183 0.854628 +-0.993015 -0.884956 -0.876392 0.303986 -0.653503 -0.934443 0.30092 -0.239616 +-0.373432 -0.994714 -0.0860847 -0.127951 -0.226855 0.898356 -0.118759 -0.15347 +0.753139 0.587493 -0.76116 0.800912 -0.0664921 0.717756 0.546394 -0.818198 +-0.848135 0.920414 0.089797 -0.10953 0.487352 -0.0413274 0.160116 -0.922569 +0.620857 0.913376 -0.5371 -0.888848 -0.547893 0.965342 -0.0102596 0.642646 +0.228929 -0.383441 0.616893 -0.215024 -0.110073 0.0767176 0.664356 0.051058 +-0.141747 -0.351581 0.631057 -0.134139 -0.873394 -0.342096 -0.370005 0.686414 +-0.476121 0.953787 0.846469 -0.970234 -0.908107 0.871893 0.278422 0.96444 +0.154088 -0.856321 0.299098 0.465107 -0.982717 0.729739 -0.330896 -0.523069 +-0.647891 0.518537 0.265766 -0.8496 -0.365555 0.250577 -0.860084 0.965434 +0.180901 0.839412 0.0102612 0.519798 0.433035 0.525283 -0.227114 -0.787815 +-0.623962 0.745481 0.822129 0.189897 0.473787 -0.145218 0.685099 0.933544 +-0.990604 0.119522 0.22156 -0.116173 0.727771 0.229791 -0.636448 -0.977407 +0.347856 -0.82244 0.565478 0.633358 0.69042 -0.572761 0.816634 0.921053 +0.50877 0.935481 -0.297248 -0.295278 0.475637 0.833435 0.390233 -0.901122 +-0.604076 0.291104 -0.723547 0.783539 -0.735368 0.977447 -0.000195883 -0.315096 +-0.0472228 0.48099 -0.989383 -0.83706 0.278294 0.0993613 0.134936 0.675335 +0.228965 -0.915804 -0.138968 -0.802494 -0.563767 0.179447 0.246339 -0.156208 +-0.557728 -0.00987051 0.240962 0.789866 0.732192 0.71669 0.367024 -0.738044 +-0.258237 -0.348335 0.323778 0.0357073 -0.0524682 0.558493 -0.33209 0.720644 +-0.526678 0.688981 0.205941 0.279382 -0.455743 0.175003 0.106483 0.472977 +0.604514 0.24659 0.850118 0.916246 0.55859 -0.68052 -0.794915 0.0871143 +0.440163 0.240024 -0.584987 -0.106263 0.255702 0.451313 0.705061 -0.13135 +0.282462 0.612703 0.712391 0.247212 0.924635 -0.924864 -0.0714029 -0.424631 +0.121823 -0.862768 -0.774174 -0.426802 -0.55929 0.0617382 0.204368 0.286078 +0.509855 -0.190018 0.16875 -0.285439 -0.949994 -0.643695 0.285811 -0.855972 +-0.381486 -0.207199 0.0960123 -0.181356 0.992789 0.756944 0.69183 0.118718 +-0.783188 -0.946586 0.0521069 -0.127942 -0.0577861 0.332436 0.0785184 -0.536647 +0.923994 -0.483284 0.333174 0.0843593 0.4227 -0.675179 0.0593178 0.751924 +0.44757 0.469096 -0.817663 -0.614827 -0.149585 0.596369 -0.189046 -0.0777454 +0.273003 0.68871 -0.148789 -0.328606 -0.335955 -0.67944 0.412775 0.769597 +-0.731963 0.346327 0.517231 0.287071 0.152039 0.428483 -0.651829 0.744116 +0.635242 -0.609571 -0.542329 -0.851562 -0.961134 0.389616 -0.376796 -0.126802 +-0.0180099 -0.331095 0.251956 -0.914776 -0.903607 -0.461179 -0.675812 -0.544263 +0.562364 0.401615 -0.25766 -0.00929416 0.265503 -0.836285 0.946206 -0.0850661 +0.669014 0.744431 -0.473584 0.476114 0.125088 0.6667 0.592061 0.475967 +-0.584397 0.535709 0.853683 0.269452 0.25484 0.0672744 0.179976 -0.013398 +0.867427 -0.883255 -0.470908 0.229988 0.85815 -0.292816 -0.311314 -0.0952967 +0.772391 0.71723 -0.298444 0.860807 0.905866 0.801083 -0.257112 0.865618 +0.91475 0.35208 0.739183 0.5542 0.885793 -0.762854 -0.114436 -0.390397 +-0.00238038 0.13775 -0.176457 0.8346 -0.817934 -0.676072 -0.792165 -0.534726 +0.545058 -0.495617 -0.517554 -0.996651 -0.812834 0.601195 -0.0579808 0.931626 +0.702873 0.864469 -0.0558588 0.84158 0.220361 -0.911474 0.381343 0.933388 +0.340707 0.42134 0.98726 -0.843155 0.852878 0.591611 -0.259672 0.0175789 +-0.577658 -0.876924 0.00399223 -0.193853 0.203345 -0.276663 -0.502468 -0.180009 +0.0177999 0.00340674 0.056276 -0.198192 -0.312252 0.633585 0.598034 0.197541 +-0.159061 0.800112 0.784389 0.0723555 0.0359479 0.759342 -0.34009 0.905375 +0.338589 -0.310562 0.883088 0.753153 -0.750019 0.0217613 0.0432865 0.767058 +-0.657262 0.101825 0.149319 0.509225 -0.30078 0.00550695 0.14276 0.927615 +0.893967 0.256508 0.246723 -0.684237 0.140062 0.280849 -0.0466129 -0.328157 +-0.90317 0.446809 0.405565 0.895497 0.106392 -0.597579 0.898757 -0.364794 +0.581448 -0.313556 -0.374284 0.221787 -0.444622 -0.0981259 0.791659 0.714229 +0.499203 -0.985318 -0.950079 -0.433976 -0.459 -0.80906 -0.319202 -0.563101 +0.333075 -0.854522 -0.378698 0.564525 0.0147096 0.75404 -0.0901849 -0.723399 +-0.892629 0.700876 -0.76047 -0.698236 0.721126 0.645856 -0.123505 -0.711135 +-0.740339 -0.796952 0.22256 -0.652009 0.454916 -0.173672 0.647484 0.962477 +-0.46539 0.652972 -0.668187 -0.409683 -0.253592 -0.808649 0.0459738 0.346145 +-0.131851 0.481449 0.274155 0.327115 0.538323 -0.855945 0.376928 -0.464248 +-0.311477 0.60781 0.0647915 0.0349144 -0.906979 -0.221873 -0.293571 -0.0705909 +0.255457 0.393087 -0.200897 0.724084 0.752364 0.359745 -0.0612326 -0.343136 +-0.959241 0.204038 -0.877381 0.183352 0.936718 0.669003 -0.822116 -0.688967 +-0.0105198 0.11415 0.676121 -0.0160809 0.207737 -0.899675 -0.742513 -0.600623 +0.139435 0.192258 0.0616812 0.137983 0.817877 -0.947131 0.941711 -0.14502 +-0.408732 0.837576 -0.80274 -0.183649 -0.0150065 -0.0972932 -0.0893301 0.570324 +-0.855058 0.000896283 0.963632 0.269734 0.669349 0.869792 -0.22901 -0.380569 +0.244925 0.665405 -0.546693 -0.744555 0.781028 0.257806 -0.26532 -0.776705 +0.167019 0.945111 -0.267772 0.527467 0.694969 -0.387071 0.87623 -0.813872 +-0.174104 0.503103 0.313091 0.709993 0.763812 -0.642976 0.546306 -0.197767 +0.24718 0.855926 -0.99392 0.185421 -0.080989 -0.193255 -0.13245 0.817247 +0.538442 -0.806945 0.38069 0.512923 -0.704145 0.897306 0.180391 -0.908193 +0.522868 0.0509071 0.604966 -0.70499 -0.338617 -0.160258 0.606294 -0.272594 +-0.105343 0.71768 0.622049 -0.802764 -0.683397 -0.266077 0.998037 -0.0913231 +-0.435137 0.938807 0.894503 -0.454815 0.149053 -0.924636 0.365601 0.186184 +0.8702 -0.621265 0.791263 0.0014155 -0.416484 0.616878 0.0670925 -0.632963 +0.0549841 0.442197 -0.878079 0.776771 0.256464 0.6385 -0.763827 -0.217914 +0.468603 0.337946 0.276022 -0.65522 0.208541 -0.0905303 -0.305621 0.852601 +0.979409 -0.51722 0.106743 0.0763094 -0.797137 -0.88488 0.504488 -0.168023 +-0.266514 0.260147 -0.416327 -0.475632 -0.121679 0.752852 -0.450344 -0.796255 +-0.666477 -0.686081 0.0558797 0.891521 -0.213814 -0.632339 0.132522 0.669797 +0.478548 0.25804 -0.73034 -0.763098 -0.7187 -0.123103 0.396324 0.747569 +0.250672 -0.0969102 0.565463 -0.269419 -0.113583 0.885196 0.221078 -0.754703 +0.809342 -0.679751 -0.952205 0.869309 -0.144359 0.203847 -0.39146 0.626885 +0.126664 0.689631 -0.990055 0.102341 -0.548834 -0.436249 0.638882 0.257144 +0.679681 -0.662895 -0.682011 0.908557 -0.286349 0.502272 0.0131963 0.458774 +0.956644 0.585121 0.123999 -0.528068 0.018217 -0.109967 -0.49207 -0.963983 +0.661237 -0.437022 0.285641 -0.542122 0.34798 0.483353 0.200802 -0.575863 +-0.293233 0.101943 0.776871 -0.716736 0.339757 0.348393 -0.877006 0.0756994 +-0.192361 -0.429056 0.698857 0.0690558 0.571109 0.689003 0.558945 -0.20103 +0.304939 -0.75176 -0.234605 -0.531447 0.962697 -0.81432 0.287845 0.0611473 +0.0303345 0.50117 0.256422 0.390316 -0.943237 0.880831 0.812167 -0.918173 +-0.460962 -0.456693 -0.256297 0.400444 -0.0476327 0.112099 0.933638 -0.0833243 +0.0664529 -0.490261 0.818026 -0.579211 -0.405074 -0.293812 -0.835751 0.818004 +0.589462 0.752656 -0.851615 0.598916 -0.991793 0.59601 -0.387809 -0.234004 +0.312491 -0.744039 -0.393213 0.12193 -0.205172 0.964511 -0.396016 0.823664 +0.241052 -0.527564 0.757131 -0.0885936 -0.440873 -0.0562625 -0.108217 0.997197 +-0.348426 0.939195 0.764351 0.111117 -0.509492 0.794485 0.547293 0.811958 +0.265172 -0.726696 -0.646237 0.852409 -0.752579 -0.529954 -0.892903 0.744079 +0.991331 -0.968149 0.582996 -0.799841 0.130517 -0.0319984 -0.369265 0.661045 +0.905755 -0.101298 -0.520091 0.470791 0.827143 0.148135 -0.843935 -0.00181772 +0.517024 -0.391846 0.360668 -0.288355 0.40142 0.962982 0.370957 -0.375467 +-0.639948 -0.908811 0.925173 -0.258794 -0.986795 -0.958077 -0.771582 0.833089 +0.323493 0.219279 0.202369 -0.662371 0.216746 -0.212691 -0.595568 -0.237929 +-0.253571 -0.302909 0.00829868 0.593948 -0.661691 0.252085 0.290047 0.340127 +-0.0323342 -0.0986575 0.471169 0.606045 0.472742 0.856805 0.478151 0.262277 +-0.823422 -0.999551 -0.701375 -0.628034 0.810717 0.478998 -0.439586 -0.402394 +-0.0149096 0.462762 -0.218376 -0.128703 0.583629 0.540675 -0.950508 -0.945796 +0.196795 -0.681972 0.199658 -0.0528746 0.852323 -0.781498 -0.180707 0.928392 +-0.0355948 0.245186 0.941033 -0.930629 -0.607334 -0.173449 0.189164 -0.794443 +0.211917 0.959464 0.346092 -0.150506 -0.943057 -0.513279 0.495248 -0.598726 +-0.706505 -0.22289 0.798774 0.579023 -0.662528 -0.703043 0.466128 -0.976256 +-0.0865377 0.920782 -0.313851 -0.6782 0.499931 -0.288394 0.515319 -0.955472 +0.10862 0.255546 0.442373 -0.830397 0.936627 -0.750215 0.594367 0.814511 +0.106111 -0.645144 -0.159128 0.0610745 0.434246 -0.577104 0.634405 -0.660151 +0.135706 0.975158 0.0848757 -0.221776 -0.48962 -0.581868 -0.732632 -0.269339 +-0.326039 -0.608257 -0.764748 0.246634 0.743877 -0.427327 0.341363 -0.534626 +0.213119 -0.414106 -0.453311 0.91909 -0.195049 0.585568 0.8036 -0.580623 +-0.289366 -0.0875174 0.116103 -0.715581 0.49478 0.27594 -0.896851 0.0897983 +-0.579688 0.423732 0.150584 -0.222251 0.913455 0.00843966 -0.696864 0.616172 +-0.625069 0.3232 -0.658514 -0.383288 0.304153 -0.260416 0.995483 -0.192514 +0.608195 -0.121528 -0.500296 -0.120621 0.63437 -0.15617 0.555762 -0.503402 +0.56234 0.920326 -0.655406 0.556227 -0.41102 -0.122466 -0.503406 0.212939 +0.539643 -0.374674 -0.254096 -0.85075 0.637897 0.751731 -0.764317 -0.44745 +0.238889 -0.763641 -0.618631 0.569259 -0.882638 0.228504 0.688651 -0.433042 +0.795766 0.735439 -0.421045 0.459934 0.659391 0.574466 -0.860603 0.239672 +-0.538707 -0.409461 0.333454 0.882338 -0.189935 0.217746 -0.250618 0.249167 +-0.193758 -0.773611 0.0261545 -0.170627 0.297779 0.0666907 -0.0758429 0.291201 +-0.275088 -0.989135 0.52482 0.243216 -0.0715602 0.244083 -0.742632 0.996286 +-0.604519 0.919673 -0.731785 -0.388208 0.804942 -0.616248 -0.646098 0.343847 +-0.545362 0.521995 0.325602 -0.0462079 -0.0576605 -0.196755 -0.32192 -0.0395811 +-0.929555 -0.795383 -0.769878 0.937597 -0.572317 -0.545074 0.844056 0.440964 +0.648816 -0.0202996 -0.188947 -0.828698 -0.351649 -0.729544 0.32248 -0.814613 +-0.103441 0.916185 -0.64055 -0.374267 -0.266359 -0.691093 0.329788 -0.916444 +0.0855057 -0.663682 0.824731 0.390845 -0.430675 -0.16314 0.151002 -0.750227 +0.0942286 0.815537 0.991439 0.186997 -0.692234 0.195049 0.339283 -0.666759 +-0.481371 0.410785 0.0426052 -0.235143 0.334306 0.00832484 -0.753941 -0.660511 +0.452498 -0.864517 0.348422 0.203458 0.914861 0.406036 -0.0652651 0.0171851 +0.989941 -0.218013 0.533689 -0.297949 0.461208 0.838649 0.139251 -0.0197546 +-0.535147 -0.96055 -0.917169 0.920994 0.953047 -0.49934 -0.516132 0.806737 +0.681463 0.357143 -0.466521 -0.613908 -0.329098 -0.00111562 -0.567387 0.360135 +-0.925069 0.228135 0.43766 0.669042 -0.782738 -0.854043 0.0615008 -0.62869 +-0.964794 -0.402917 0.173154 0.263791 0.191719 0.921239 -0.726624 0.0206387 +-0.177547 0.92641 0.0257005 0.567644 0.25378 -0.317255 0.326914 0.955374 +-0.481678 -0.561897 -0.810486 -0.011175 -0.20251 0.0821776 -0.225426 0.828019 +0.319734 0.0455197 -0.650943 0.403695 -0.13328 0.0532351 -0.555217 0.483623 +-0.709679 0.359185 -0.653807 0.40202 0.791759 -0.628203 -0.775551 -0.1609 +-0.00967711 -0.278382 -0.0138448 -0.850629 -0.90164 -0.863227 -0.147169 -0.835083 +0.572079 -0.858894 -0.540333 -0.0858082 0.699962 0.676926 -0.920167 0.57445 +0.94329 -0.0960854 0.448321 -0.181658 0.622784 0.319869 -0.649597 0.526803 +-0.385788 0.81949 0.779691 0.650257 0.622329 0.177045 -0.346547 0.147598 +0.815096 -0.256498 -0.10321 0.330242 -0.253005 0.708998 0.793137 0.642095 +-0.906686 -0.465188 0.641827 -0.888046 0.948462 0.578915 -0.85646 0.415115 +0.189503 -0.231009 -0.504437 0.145098 -0.439487 0.600806 -0.111601 -0.867408 +0.960378 0.263207 -0.255279 -0.831335 -0.250174 -0.566223 0.413952 0.174853 +0.210605 0.915587 -0.95212 -0.781721 0.126896 -0.652111 0.216699 0.97238 +0.569672 -0.811293 -0.060879 0.836581 0.594458 -0.17383 0.273041 -0.579067 +0.438901 -0.738221 -0.171059 -0.515204 0.725874 -0.999104 -0.946137 0.198549 +-0.562374 -0.271372 -0.923062 0.928222 0.678984 -0.178428 -0.565382 -0.417847 +0.0589951 0.846803 -0.982789 -0.83878 -0.823362 0.382187 0.559251 -0.85245 +0.281434 0.186205 0.518949 0.579525 -0.578728 -0.313613 0.566895 0.989014 +0.385349 -0.844833 0.965636 -0.29242 -0.0320836 0.188487 -0.486568 0.609471 +0.812515 -0.0955862 -0.221162 0.293421 0.133897 -0.316121 0.17491 -0.0731692 +-0.851469 -0.629898 -0.430684 -0.959584 0.926379 0.772077 0.666256 0.0218093 +0.841021 0.897457 -0.924708 -0.420437 -0.169368 0.382381 0.976445 -0.404921 +0.283016 0.883067 -0.0180705 0.414147 0.9427 0.595938 0.167437 -0.286301 +0.604149 -0.468205 -0.225634 -0.114448 -0.144297 -0.524006 0.818634 0.736907 +-0.0805167 -0.499092 -0.198474 -0.794759 -0.02127 0.730269 0.627705 0.113475 +0.903352 -0.0252357 0.870841 -0.148878 0.213653 0.197376 -0.0670939 -0.475582 +0.629193 -0.739515 -0.198465 0.721853 -0.28623 0.970282 -0.940538 0.230602 +-0.281755 -0.773608 -0.39371 0.371552 -0.00568323 -0.252002 0.189924 0.825681 +-0.682856 -0.442933 0.782342 -0.551643 -0.301092 0.58446 -0.698666 -0.0942016 +0.381089 0.248401 -0.175918 -0.477737 -0.968251 0.0262816 0.439686 0.778217 +-0.23532 0.853349 -0.715212 0.542211 -0.917156 -0.976299 0.335364 -0.728281 +-0.879117 0.816838 0.741221 -0.304429 -0.620405 0.0690136 -0.402444 -0.87388 +0.411968 0.630165 -0.847352 0.481918 -0.217918 0.565266 -0.0122791 -0.795835 +0.0234592 0.870668 0.438645 -0.603354 0.602228 0.912884 0.688535 -0.606993 +-0.654541 0.646906 -0.29001 -0.965252 -0.275964 0.664379 -0.00808228 0.0235506 +0.0100944 0.152887 -0.304005 -0.795911 0.369806 0.43199 0.734702 0.747264 +0.446445 0.333043 0.930935 -0.694211 -0.601388 0.147061 -0.0998489 -0.93187 +0.74102 0.948449 -0.519778 -0.432951 0.665825 -0.130346 0.816236 0.886446 +-0.345459 -0.705149 -0.343866 -0.463113 -0.45104 0.215277 0.498107 0.55857 +0.172837 -0.25636 -0.727345 -0.501137 -0.900514 -0.535885 -0.673991 -0.627859 +-0.840898 -0.225774 0.937815 0.685105 0.833471 0.929874 -0.479996 -0.635103 +-0.849378 0.0766661 -0.621978 0.863871 0.711126 -0.391414 0.955512 0.760642 +0.771356 -0.257743 -0.321609 -0.492456 0.380348 -0.408613 0.94531 -0.719525 +0.40955 0.357061 -0.375443 0.129784 -0.844371 -0.693414 -0.131407 -0.417468 +0.0317405 -0.242657 0.137224 0.489892 0.0742063 0.622838 -0.536855 -0.144005 +0.838209 -0.94144 -0.396847 -0.5825 -0.00177164 -0.2439 0.698392 -0.79463 +-0.0847977 -0.28233 -0.0612805 0.964329 -0.594445 0.393508 -0.271259 0.0163982 +0.858929 -0.801424 0.817041 -0.496205 0.0243399 0.933555 -0.454056 0.738247 +0.201018 0.88881 -0.918101 -0.596397 0.76459 0.286093 0.0988432 0.979148 +-0.0484204 -0.468678 -0.126223 0.178388 0.943972 0.518688 0.982847 -0.223554 +0.0139024 -0.876422 0.180538 0.732026 0.540794 0.791659 0.488013 0.92101 +-0.573541 -0.966942 -0.345976 -0.264077 -0.354252 0.111363 -0.0798913 -0.953628 +-0.886551 -0.609552 -0.512374 -0.250939 0.0299737 -0.161727 -0.850325 0.784233 +-0.65672 -0.810091 0.720265 -0.367129 0.0745166 -0.755664 -0.716485 0.694168 +-0.224685 -0.254047 0.778674 0.478427 0.736657 -0.397138 -0.250502 -0.562233 +-0.757017 -0.24048 0.939309 -0.300419 -0.936982 0.461805 -0.281682 -0.267151 +-0.812877 -0.594169 -0.630813 0.704813 0.349527 -0.0717624 -0.158619 0.625095 +-0.79515 0.949354 0.0317152 0.417216 -0.831035 0.544364 -0.249483 0.0506718 +-0.560894 -0.155408 0.705131 -0.773296 -0.543498 0.625823 -0.555176 0.617108 +-0.335133 0.957534 -0.0844158 0.727917 0.210453 -0.875149 -0.468757 0.669607 +0.89199 0.264511 0.192064 0.697532 -0.274442 -0.595215 0.525028 -0.894577 +-0.690688 0.328797 -0.779329 -0.601845 -0.0847156 -0.27547 0.658439 -0.0165512 +0.804787 0.49006 -0.463583 0.933438 -0.961176 0.784489 0.952389 -0.725538 +-0.259765 0.0255164 -0.72265 0.43701 -0.991672 0.436923 -0.15044 -0.449078 +-0.701744 -0.596686 0.505973 -0.335453 0.715539 0.811012 -0.496299 0.0725392 +-0.488745 -0.155034 0.478185 0.900486 -0.868652 0.544572 0.179341 0.210153 +0.0340945 -0.174927 -0.655313 0.294701 0.087628 0.789314 0.541003 0.626333 +-0.759713 -0.726705 0.248022 0.837257 0.827688 0.248072 -0.275017 0.815465 +-0.446743 -0.950319 -0.664201 -0.655403 0.937845 -0.529307 0.966991 0.29705 +-0.595593 0.0431616 -0.317064 -0.515757 -0.295014 -0.179958 0.906339 -0.679403 +0.830869 -0.583668 -0.936455 -0.904527 0.145552 0.331073 0.103653 0.0448009 +-0.3558 -0.789052 0.499721 0.0566035 0.691236 -0.780277 -0.517583 -0.5023 +-0.962397 0.721471 0.958446 -0.289021 -0.729467 0.0894384 -0.940042 0.790251 +0.0555765 -0.158012 -0.481045 -0.784203 0.254878 -0.442009 -0.217187 0.149968 +0.771778 0.469362 0.295287 -0.238196 0.525796 0.841417 0.471167 -0.223849 +0.418275 -0.823732 0.675104 -0.529826 -0.217189 -0.735826 0.694598 0.0404085 +-0.737136 -0.635519 -0.816541 -0.53935 0.900962 -0.628396 0.189722 -0.779302 +-0.535194 0.53962 0.975443 0.348913 0.150123 -0.26131 0.520848 -0.730596 +0.978975 -0.0471649 0.201077 0.873904 0.288306 -0.379299 0.994282 0.549067 +-0.505652 0.258319 -0.600744 0.127497 0.314517 0.678104 0.106161 0.757435 +-0.308022 0.0824012 0.550073 -0.810625 0.665014 -0.668955 0.559599 0.957784 +-0.79884 0.670301 -0.367139 -0.891605 0.323452 0.199292 0.381776 -0.639931 +-0.256317 -0.536244 -0.325341 0.521513 -0.670016 -0.396123 -0.511194 -0.430955 +0.975777 0.14726 -0.773959 -0.511971 0.70116 -0.457476 0.601153 0.581795 +0.227825 -0.860724 0.370203 -0.0947922 -0.97406 0.0451292 -0.239343 -0.817037 +-0.470012 0.604172 -0.0921631 -0.717006 -0.0819806 0.403823 -0.139446 0.833008 +0.822054 0.227319 -0.0375581 -0.0493148 -0.260897 -0.62889 -0.370465 -0.0977058 +0.598783 0.812078 -0.0660498 0.259183 -0.506962 -0.510327 -0.942989 -0.468865 +-0.259301 0.743864 -0.218953 0.715528 0.196164 0.232278 -0.395251 0.139116 +0.791498 0.106472 0.0452309 0.629534 0.954354 0.311 -0.142481 -0.14749 +0.611771 0.875423 0.122703 -0.715426 -0.777026 -0.658008 0.488373 0.73403 +0.928229 -0.275799 0.639149 -0.615548 0.0611227 -0.805727 -0.145858 0.0201392 +0.435509 0.463819 -0.240368 -0.0902166 0.0443554 -0.478563 0.0194528 0.376945 +0.471205 -0.27338 -0.035732 -0.729623 0.722559 0.108647 -0.16389 0.613536 +0.978695 0.632154 0.679019 0.111165 -0.152862 0.364563 -0.149085 -0.0789087 +0.622036 0.794577 -0.330212 0.752239 0.0228988 0.920498 -0.711901 -0.00787498 +-0.469051 0.917879 -0.0811375 0.20919 0.557763 -0.84167 0.0757235 0.575219 +0.800904 -0.308932 0.376545 -0.384286 0.432287 -0.935728 0.357876 0.591294 +-0.768239 -0.508914 -0.226472 -0.381764 -0.308265 -0.501238 -0.358439 -0.711269 +0.863075 -0.649126 -0.559737 0.242747 -0.0833645 -0.48658 0.545111 -0.749735 +0.560645 0.0981928 0.98915 0.386877 0.998202 -0.923064 -0.143429 0.0120489 +-0.172888 -0.987736 -0.019919 0.900102 -0.706244 -0.800856 -0.863956 -0.134379 +-0.657668 0.618311 0.579982 0.852182 -0.621864 -0.65489 -0.0406368 0.235367 +0.528019 0.954676 -0.761864 -0.840649 -0.566082 0.516921 0.511785 0.0612233 +0.737796 0.317777 0.373947 -0.155693 0.839091 0.578526 0.283004 0.328822 +0.482275 -0.246011 -0.514408 -0.996551 0.186639 -0.353908 -0.710367 -0.95679 +-0.542976 0.379978 0.388341 -0.50985 -0.71483 -0.305278 -0.380838 -0.672205 +-0.0465311 0.777669 0.340097 0.100179 -0.531904 -0.723961 -0.981274 -0.0394776 +0.244866 0.0632913 -0.101809 0.376018 -0.553911 0.506234 0.843822 0.261087 +-0.34388 -0.985927 0.649291 0.30278 0.920758 0.180314 0.634717 -0.35386 +0.142797 -0.701537 0.163084 -0.211039 0.661914 -0.363659 -0.873628 0.728903 +0.815882 -0.217997 -0.466938 -0.0983389 -0.745205 0.664456 0.494475 0.0985773 +-0.2489 -0.321198 0.5543 0.391957 -0.827394 -0.67636 0.435296 0.3459 +-0.513688 -0.916884 0.882012 0.0695999 0.0376325 0.510818 -0.536005 -0.705857 +0.5442 0.41657 0.402025 -0.0543298 0.865691 -0.763821 0.106548 -0.838279 +-0.820634 -0.405408 -0.139101 -0.797438 -0.0440854 0.823462 0.758196 -0.581836 +-0.283799 0.76933 0.593534 -0.456088 0.387223 0.616003 -0.738034 -0.21752 +0.323996 0.614662 -0.950994 -0.40592 0.154952 -0.601096 -0.909662 0.277428 +0.685618 0.517136 0.886496 -0.485098 -0.788357 -0.208862 -0.725962 0.458484 +0.982799 -0.0979862 -0.94766 -0.885644 0.080183 0.263394 0.828962 0.53429 +0.430696 -0.368712 -0.474724 0.490441 0.875802 0.847952 0.740507 0.529319 +-0.32743 -0.869403 0.709334 -0.575641 -0.527952 -0.0762286 -0.237205 -0.822635 +-0.350666 -0.684212 -0.457443 -0.740521 0.996867 0.573595 0.730673 -0.260659 +-0.558065 -0.231694 0.506373 0.371054 -0.359671 -0.327323 0.440685 -0.233344 +0.492332 0.704796 0.546572 -0.197951 -0.581357 0.838951 -0.0710844 -0.0748296 +0.301623 -0.222486 -0.36994 0.758046 -0.604416 0.0381278 0.0866519 0.0076825 +-0.108616 0.473392 -0.0826879 0.20341 -0.587521 0.762725 0.235206 -0.956744 +-0.222462 -0.131956 0.330108 0.326434 0.0916936 0.959663 0.198013 0.973006 +-0.0065452 -0.157656 -0.568667 0.640993 0.371594 0.229192 -0.612711 0.807077 +-0.124147 -0.330151 -0.377112 0.0423615 -0.289726 0.664887 0.139732 -0.744687 +0.369068 -0.207116 -0.812014 0.431813 0.901761 0.184991 0.809224 0.664435 +-0.140696 0.658488 -0.380659 -0.100359 0.132319 0.290516 -0.7908 -0.303609 +0.950275 0.294591 0.813284 0.255675 0.379241 0.752181 0.21117 -0.0879986 +-0.788587 0.674907 -0.639197 0.843933 0.546026 0.133486 0.340824 0.737389 +0.551478 -0.665144 0.572637 -0.251883 0.667913 -0.652631 0.262991 -0.628928 +-0.00829559 0.827264 -0.659673 0.677435 -0.582898 0.861656 0.807052 -0.241922 +0.53029 0.276406 -0.850369 0.606148 0.417719 0.322676 -0.718059 0.814904 +0.0509127 -0.77916 0.38724 -0.0618599 0.321472 0.294822 0.536563 0.222844 +0.183128 -0.961351 0.469498 -0.107124 -0.998764 -0.974323 -0.561324 -0.778491 +0.705104 -0.16619 0.246858 0.853025 0.933275 -0.96025 -0.2306 -0.581463 +-0.135804 -0.291501 -0.453964 -0.0667871 -0.0116701 -0.530398 -0.636346 -0.989861 +-0.883888 0.868279 0.686281 0.365628 -0.280309 -0.613791 -0.2066 0.274597 +0.291794 0.775417 0.23292 0.0894797 0.292737 -0.163122 -0.638439 -0.594163 +-0.830332 -0.275543 -0.585718 0.270686 0.383448 -0.836213 0.777362 0.100967 +0.664511 0.30164 -0.128448 -0.948827 0.862502 -0.430376 -0.942581 0.0512758 +0.711924 -0.285207 -0.654959 -0.988625 0.392955 -0.359291 0.863404 -0.106388 +-0.659953 0.917055 -0.799197 0.651361 0.370245 0.391718 0.223717 0.723495 +0.123549 -0.945111 -0.555769 -0.649814 0.499219 -0.619066 -0.601799 0.69068 +-0.618715 0.32131 0.759993 -0.0737941 -0.229136 -0.391153 0.0804427 -0.0470107 +-0.705316 0.341965 0.61163 -0.48823 -0.791244 -0.859084 0.325526 0.469497 +-0.38023 -0.0987179 -0.939405 0.435456 0.393173 -0.892511 0.631725 0.58999 +0.942535 0.0601412 -0.392017 0.285243 0.870367 -0.147963 0.332054 0.395072 +-0.483855 -0.0679516 -0.824674 -0.564758 0.56754 -0.57824 -0.624811 -0.711699 +-0.2866 -0.174484 -0.926319 0.34033 0.624304 -0.384439 -0.42727 -0.446075 +0.213221 0.51746 -0.717439 0.833329 -0.769489 0.325338 0.596314 0.224083 +0.0602668 0.344342 0.489977 -0.580508 0.843116 -0.315491 0.168088 -0.601734 +0.321409 0.129467 -0.292062 0.46742 0.521776 0.903115 -0.424467 0.0117525 +0.777867 0.75377 -0.158987 0.149591 0.0631847 -0.526191 0.926621 -0.952158 +-0.108637 -0.591344 -0.457731 -0.33968 0.835762 0.178632 0.0384074 -0.474663 +0.363637 -0.350786 -0.601748 -0.756875 0.854744 0.372593 -0.175902 0.303099 +-0.0330089 0.146971 -0.769861 -0.99727 0.46859 -0.195382 -0.455002 -0.172157 +0.0297913 0.539815 -0.983084 0.38095 0.0792756 0.70725 0.820313 0.487679 +0.0484071 0.0412326 0.914358 -0.536642 -0.958456 0.340165 0.0820479 0.992099 +-0.159312 -0.449366 -0.0792356 0.181913 0.539605 0.950556 0.387085 -0.0460472 +0.308555 0.816409 -0.226476 -0.976578 -0.95974 0.92481 -0.10954 0.944659 +-0.487201 0.334477 -0.222606 0.887994 -0.245868 0.924337 -0.191241 0.258974 +-0.516916 -0.431767 -0.362052 -0.956869 0.140973 -0.525674 -0.829216 -0.864134 +0.467598 -0.0623155 -0.562673 0.387059 0.417803 -0.156728 -0.132967 -0.851912 +-0.0159641 0.681031 0.789737 0.61295 -0.382811 -0.437122 -0.575667 0.139461 +0.201726 -0.0284665 0.126787 -0.770721 -0.378973 -0.871242 -0.93124 0.167806 +-0.906587 0.755051 0.805754 -0.466284 0.846402 -0.265639 -0.399551 0.783611 +-0.330639 0.799403 -0.365028 0.152432 -0.457075 -0.880786 0.951629 -0.637468 +0.0939051 0.972762 0.673671 -0.0251475 -0.416985 -0.586914 -0.212876 -0.518802 +0.26211 -0.158193 0.0879568 0.133352 0.294339 0.806577 0.347484 0.284492 +0.18738 0.601394 -0.288238 0.929328 -0.430584 0.144805 -0.0861466 0.9678 +-0.672234 -0.577955 -0.226058 0.795892 0.372343 0.433359 -0.307655 -0.355279 +-0.91036 -0.593156 -0.0141378 0.367605 -0.69358 -0.889241 -0.390859 0.67733 +0.986818 0.965071 0.535801 0.19849 -0.598978 -0.787907 -0.977443 0.297804 +0.594224 -0.532425 0.28695 -0.972223 0.155023 0.323215 0.256217 0.506544 +-0.927605 -0.829722 0.276827 0.356957 0.832604 -0.96117 0.531935 -0.147619 +0.89414 -0.248586 -0.0725506 -0.825005 0.51739 0.465548 0.381324 0.908398 +0.736161 0.0285865 0.0647281 -0.631369 0.562227 0.329487 0.435297 -0.89194 +0.168549 0.237941 0.0677357 0.690194 -0.657008 0.348647 0.438995 0.119896 +-0.490611 -0.240686 -0.412573 0.472571 0.751665 -0.264279 0.911799 -0.870605 +0.982511 -0.626581 -0.46597 0.60857 -0.575409 0.697278 0.671233 -0.559026 +0.670154 -0.810728 0.0135843 -0.252631 -0.964883 -0.64613 0.0921187 0.202064 +0.560799 0.432354 0.906522 -0.611299 -0.641625 0.0577759 -0.883151 -0.415086 +-0.612934 0.25347 -0.619802 -0.689669 -0.772393 0.328471 -0.154783 0.20487 +0.927717 0.232525 0.24183 -0.411393 0.169979 0.203034 -0.391018 0.781991 +-0.0575303 0.244628 -0.331141 0.156427 -0.436854 -0.620626 0.497404 0.936758 +-0.755519 -0.694919 -0.0139654 0.258019 -0.871405 -0.0450511 -0.492955 -0.298025 +0.202794 -0.141868 -0.938724 0.311757 -0.0128749 -0.112618 -0.524556 0.873593 +-0.334348 -0.705892 0.758689 -0.700964 0.260453 0.212106 0.67753 0.149304 +-0.119876 0.0868582 0.166572 0.462281 0.345725 0.184584 0.671379 0.134625 +-0.143818 0.879489 -0.434038 -0.804062 0.879466 0.420275 0.757427 -0.635403 +-0.531995 -0.642183 -0.813272 0.501051 0.389997 -0.420186 -0.645479 -0.111166 +-0.302184 -0.774725 -0.315015 -0.978614 -0.275317 0.716474 0.0844563 0.428733 +0.283421 0.260302 -0.881416 -0.798459 -0.83066 0.551997 0.437974 0.515384 +0.755976 0.845284 0.561146 -0.0527445 -0.262402 -0.187658 -0.311828 0.867852 +-0.989924 -0.219227 -0.550345 -0.154239 0.467149 -0.672575 -0.300683 0.0634565 +-0.724787 0.352666 -0.110587 -0.554322 0.00744583 -0.975196 -0.86003 -0.966098 +0.151237 0.633514 0.776802 0.71245 0.0024771 0.62805 -0.940123 0.04355 +0.601368 0.15256 -0.534149 0.107194 0.583994 0.72257 0.488926 -0.127211 +-0.296958 -0.655767 0.815496 0.62545 -0.66598 -0.696658 0.422174 0.227705 +-0.838788 -0.255448 -0.418342 -0.239067 -0.468444 -0.493054 -0.617915 0.46068 +-0.10102 -0.844915 -0.772289 -0.255899 0.855761 -0.865344 0.465499 0.993729 +-0.696099 0.602138 -0.866223 0.616719 -0.638643 -0.117135 -0.467626 0.682793 +-0.467108 0.926499 0.633912 0.879862 -0.490802 -0.25296 0.454019 -0.851356 +0.294904 -0.56879 -0.889959 -0.585637 0.329798 0.886105 -0.283169 -0.632372 +0.854875 0.799757 -0.336953 -0.140972 -0.687957 0.890311 -0.628454 0.915021 +-0.631309 -0.296261 0.323326 -0.923162 0.132575 -0.051929 -0.123272 -0.780163 +0.247462 0.138162 0.970424 -0.0159447 0.765595 -0.63247 0.526467 0.329408 +0.558882 0.991274 0.762702 0.148037 -0.812295 0.320623 -0.360074 0.890414 +-0.193575 0.836558 0.66645 0.369587 0.894989 0.724637 0.134832 -0.103241 +-0.373098 0.522283 -0.509777 -0.408407 0.281541 0.491888 0.295896 0.885464 +-0.435318 -0.15438 0.295375 -0.0130003 -0.370649 -0.939891 0.979149 0.441866 +-0.0458628 0.0889234 -0.00384797 -0.172882 0.654266 0.0200125 0.93788 -0.229084 +0.232796 0.331426 0.137932 -0.1588 0.746055 -0.611013 0.0580773 -0.984885 +-0.274608 0.0274619 0.236169 -0.00557469 0.63567 -0.41614 -0.738035 0.678355 +-0.777497 -0.274965 -0.978902 -0.94074 -0.998772 -0.371096 0.918989 0.470693 +-0.351333 0.600498 -0.279957 0.982019 0.686641 0.463126 -0.951743 -0.774277 +-0.693266 0.587143 0.806982 -0.0391043 0.687868 0.836473 0.758257 0.814607 +-0.155583 0.559107 -0.180078 -0.901172 -0.564174 0.950115 0.658405 -0.995456 +-0.179338 -0.769771 0.63757 -0.800916 -0.941813 0.901739 -0.835243 -0.399236 +0.200282 0.56488 -0.695449 -0.784017 -0.169102 0.163009 -0.681538 -0.422385 +0.877868 -0.858239 -0.0760585 0.969674 0.0520049 0.650256 -0.174781 -0.592959 +-0.643602 0.490123 0.0763367 -0.133388 0.603845 -0.399696 0.421458 -0.623528 +0.621015 0.394125 0.58665 -0.318446 -0.242279 -0.0396681 -0.215221 0.910531 +0.679511 -0.69743 0.219824 -0.109131 -0.908851 0.362093 -0.323557 -0.842242 +-0.572823 0.174681 0.121563 -0.798144 0.918647 -0.0353657 -0.618057 -0.963881 +0.875206 0.628925 -0.285123 -0.745414 -0.951678 0.627636 0.4282 -0.261089 +-0.180566 0.0979852 0.161239 0.501575 -0.340417 0.793822 -0.609995 -0.209603 +-0.522707 0.472491 -0.49147 -0.626946 0.731457 -0.92191 0.381342 0.535288 +0.230116 -0.411899 -0.376975 -0.0727894 0.407803 0.797609 -0.617944 -0.102145 +0.470748 -0.680442 -0.052813 0.485381 0.259645 0.314615 0.982611 0.798367 +0.767657 0.413682 0.403979 -0.364973 -0.0227396 -0.587921 -0.459537 -0.56456 +-0.817581 0.0230745 0.122747 -0.272514 -0.151073 -0.571134 -0.12752 0.308456 +-0.234365 -0.896628 -0.543475 -0.928624 0.755612 0.511077 -0.599918 -0.599189 +-0.614712 0.0293457 -0.508606 -0.920826 0.164886 0.904763 -0.528188 0.0844406 +0.902556 0.119671 0.994113 -0.269736 -0.424784 0.264042 -0.657939 -0.806347 +-0.750066 -0.245443 -0.808003 0.442991 -0.209324 -0.808908 -0.981794 -0.510847 +-0.610594 0.900685 0.754698 -0.95254 0.420727 -0.330646 -0.906228 -0.181319 +0.067648 0.377454 0.519654 -0.886214 -0.720197 0.137773 -0.220185 0.760907 +-0.698287 0.697118 -0.598066 -0.491931 0.661839 -0.178514 0.446478 0.725278 +0.854846 -0.959739 0.449098 0.829102 -0.676333 0.786899 0.379883 -0.454514 +-0.170446 -0.570646 0.513767 0.689225 0.0637064 0.047249 0.194648 0.70846 +-0.914489 -0.84392 -0.378201 -0.361538 -0.356328 0.127385 -0.67819 0.168057 +0.125882 0.453762 0.630228 -0.307048 0.0558355 0.423292 -0.156626 0.409801 +0.545793 -0.272674 -0.228218 -0.18991 -0.940324 0.648011 0.48258 -0.539391 +0.652456 -0.809515 0.320749 -0.509295 0.136827 0.341681 -0.374427 -0.216659 +0.674087 -0.0444064 0.15684 0.0964682 -0.254558 0.862153 0.816423 0.29775 +-0.228888 0.203158 -0.720184 0.665157 -0.155045 -0.483388 -0.476821 -0.378136 +-0.261212 -0.853161 -0.908703 0.118185 0.539272 0.15899 0.9865 0.275421 +-0.895025 -0.826869 -0.27963 -0.242447 -0.163778 -0.692896 0.66349 0.0390357 +-0.427301 -0.277379 -0.231296 -0.415472 -0.752861 -0.299575 0.729758 -0.213146 +0.375921 -0.565423 0.096258 -0.583626 -0.263709 0.675703 -0.0166036 0.0170838 +-0.639753 0.126037 -0.106663 0.220402 0.257187 -0.743703 -0.403632 0.268798 +-0.95692 -0.875367 0.337192 -0.509973 -0.731753 -0.894748 -0.598928 -0.808364 +0.512275 -0.583381 -0.974964 0.847309 0.921829 -0.676939 -0.796804 0.0290198 +0.140113 -0.915027 0.793142 0.977794 -0.894313 -0.250609 -0.513954 0.188916 +-0.597928 0.982209 -0.572229 0.191877 0.127513 0.284272 -0.624505 0.600551 +-0.0618661 0.974959 -0.936933 -0.757253 0.865399 -0.810305 -0.25958 -0.62859 +0.179969 -0.394173 -0.272225 -0.273774 0.705135 -0.529459 0.534434 0.198125 +-0.00457802 0.906561 0.432007 0.311682 0.504192 0.881337 0.803117 0.409709 +-0.623662 0.414641 -0.774825 -0.883711 0.133717 0.697851 -0.0338443 0.382461 +-0.487514 -0.613888 0.160689 -0.111202 -0.96655 -0.702182 0.0501156 -0.206706 +-0.550074 0.749546 -0.431205 -0.567424 -0.680566 0.942111 -0.721449 -0.403556 +0.235001 0.191921 0.439872 -0.279121 -0.688673 -0.193997 -0.672952 0.62718 +-0.444838 -0.231392 0.209668 -0.342187 0.432978 0.289592 0.554435 -0.318237 +-0.27749 0.354259 -0.107901 0.240673 -0.82693 -0.0822021 0.580248 0.954766 +-0.770102 0.697206 -0.98903 -0.652434 0.86804 -0.0104531 0.49113 0.792418 +0.657355 0.689204 -0.0956647 0.225194 -0.12617 0.302542 0.808653 -0.0638344 +0.100763 0.488962 -0.472099 0.415373 0.255599 -0.767797 -0.759042 -0.981816 +0.82712 0.512842 -0.574906 -0.675571 -0.108577 0.134561 0.691657 0.364584 +0.717932 0.644293 -0.891336 -0.14146 -0.752995 0.466326 0.0956557 0.748409 +-0.639551 0.993796 0.23663 -0.860338 0.546328 -0.0134221 -0.190639 -0.774242 +-0.168998 0.809897 -0.0724687 0.880509 0.924059 0.914387 -0.356067 -0.70861 +-0.665771 0.0469613 -0.344686 -0.639886 -0.794659 -0.752005 -0.538779 -0.554446 +0.358273 0.810189 0.589195 0.0768694 -0.363041 0.466094 -0.612151 -0.798805 +-0.176668 0.773198 -0.531688 0.653239 -0.487518 -0.748874 -0.115973 -0.95675 +0.379019 -0.187013 -0.694737 0.435753 0.733395 -0.375554 0.901036 0.576703 +-0.878736 0.859948 0.594482 0.731464 0.656825 0.185427 0.703121 0.475483 +0.451083 -0.605168 -0.567243 -0.829023 -0.855582 0.0894606 -0.701407 -0.934292 +-0.734215 -0.871833 -0.751409 -0.851524 0.442948 0.324741 0.0601873 -0.545492 +-0.645031 -0.159748 -0.73442 -0.0663618 0.524607 -0.30848 0.984521 -0.14582 +0.251307 -0.84424 0.527263 -0.119836 0.814 0.513187 0.663162 0.053065 +0.171631 0.608003 -0.390446 0.0240444 0.632319 0.302603 -0.974016 -0.550811 +-0.519843 0.20318 0.646409 -0.469461 0.815997 0.828373 0.525019 -0.33928 +-0.312998 -0.930874 0.748211 0.50108 -0.426059 0.24332 -0.761835 -0.888036 +-0.0430873 0.93541 0.607379 -0.930788 0.748549 -0.629869 -0.327984 -0.802965 +-0.893623 -0.94416 0.644368 -0.793722 -0.371427 -0.574178 0.538288 -0.599681 +0.991865 0.942398 0.502691 -0.721589 -0.0177585 0.69164 -0.739599 0.308632 +-0.948865 -0.462305 0.481357 0.239694 -0.687471 0.972791 -0.759844 -0.101514 +-0.427971 0.817675 0.37791 0.717362 0.780244 0.687148 0.817492 -0.356595 +0.408544 0.481804 0.634608 -0.292359 -0.333752 -0.730047 -0.146216 -0.379925 +-0.411169 0.480939 0.111173 0.719619 0.791424 -0.478602 -0.543974 0.983891 +0.328765 -0.252362 0.148485 -0.707759 0.783393 0.360622 -0.813371 -0.387891 +-0.732258 0.0508194 -0.468909 -0.104074 -0.402039 0.562892 -0.797813 -0.351684 +-0.531397 0.563291 0.757849 0.419854 0.0848375 -0.538672 -0.130978 0.29123 +0.581819 0.769303 -0.768847 0.296335 0.46928 0.686351 -0.452858 0.42095 +-0.468421 0.354316 0.320273 -0.683124 0.733479 0.959525 -0.466906 -0.562437 +-0.320985 0.662557 -0.469076 0.731449 -0.792907 -0.522255 -0.810503 -0.0463208 +-0.135518 -0.548003 0.821454 -0.596468 -0.221672 0.722425 0.677631 0.239664 +0.240495 0.518917 -0.560083 -0.533732 -0.316851 -0.384751 0.472647 -0.736067 +0.963678 0.279479 0.730123 0.767116 0.368007 -0.722811 -0.896892 0.947205 +0.363038 0.890507 -0.57866 -0.448616 -0.486435 0.378788 -0.0279786 -0.259052 +0.783014 0.730993 -0.845192 -0.448047 0.815635 -0.755785 0.676373 -0.367349 +-0.0086781 -0.325064 -0.795016 -0.764885 -0.497666 0.546077 0.15676 -0.347416 +-0.442516 0.831899 0.539601 -0.946358 0.42282 -0.733471 0.986251 -0.216558 +0.149417 -0.976062 0.843743 -0.709507 -0.949645 -0.444824 0.623921 -0.212131 +0.889061 -0.714132 0.886256 -0.524226 0.260209 -0.425858 -0.335331 -0.608121 +0.163371 -0.653703 -0.731777 -0.000247172 -0.188642 0.924377 0.298805 -0.388973 +0.762605 -0.842116 0.869683 -0.830962 0.677016 0.142839 -0.12232 0.522901 +-0.690976 -0.576243 0.773121 0.520893 -0.24379 0.197899 -0.222619 0.359383 +-0.462497 -0.296712 0.673668 0.87853 -0.46955 -0.69347 0.111819 0.845106 +0.175018 -0.934832 0.679228 0.637092 -0.0536522 -0.826904 0.908255 -0.239506 +0.145944 -0.31197 0.548688 0.900027 0.390772 0.910796 -0.22158 -0.549628 +0.24904 0.135123 -0.10011 -0.514924 -0.984626 0.938774 -0.904509 -0.770618 +-0.639954 0.877993 -0.188124 -0.182481 0.146301 -0.285402 -0.0191776 0.528271 +-0.387525 0.482188 0.979864 -0.349333 -0.545409 0.399055 -0.883834 0.979338 +-0.699892 -0.672811 -0.831444 0.613173 0.13007 -0.189966 -0.142866 0.160236 +0.0910655 -0.996865 0.0246345 -0.904468 -0.274297 -0.293687 -0.728378 -0.326509 +-0.309902 0.428136 -0.612639 -0.0769603 -0.889623 0.22853 -0.235892 0.534631 +0.78105 -0.525496 0.103986 0.125321 -0.00833412 -0.780349 -0.156386 0.23734 +0.958042 0.2222 -0.516709 0.302859 0.356197 0.621717 -0.375293 -0.325277 +-0.950257 -0.567975 -0.557345 0.227985 0.962381 0.0284058 -0.946306 0.993726 +0.689634 -0.0610698 -0.181399 0.341457 0.303838 0.48898 0.234354 0.840447 +-0.280721 -0.220603 0.613225 0.369206 -0.991763 -0.37548 -0.561312 -0.559419 +-0.562699 0.464465 -0.484657 -0.845516 0.286717 -0.325758 0.359892 0.250142 +-0.108194 -0.228172 0.946117 -0.502686 -0.0465551 0.712636 0.772485 0.179967 +-0.737207 -0.408187 0.466146 0.953815 0.157193 -0.050292 -0.515917 0.516513 +0.543843 -0.0965304 0.884514 -0.637205 -0.796977 -0.926221 0.798812 -0.185254 +-0.753853 -0.665576 -0.236124 -0.371611 0.561697 -0.752251 0.84445 -0.721008 +0.415113 -0.419192 0.81641 -0.498895 0.156293 0.675782 -0.582893 -0.507618 +0.4038 0.53983 -0.748939 -0.0885593 0.832176 -0.930937 -0.179189 0.895717 +-0.616491 -0.0931225 -0.190058 0.969533 0.271779 0.502087 0.859372 -0.962636 +-0.576212 -0.0748974 0.131519 0.12715 -0.953877 0.89019 0.632441 0.908584 +0.515387 -0.161986 -0.844445 -0.172084 0.179543 -0.09881 -0.646958 0.218213 +-0.846388 -0.731861 -0.0872301 0.792956 -0.00136626 -0.616736 -0.198031 -0.0934711 +0.193242 -0.18113 -0.149347 0.852692 0.414392 0.455737 0.77598 0.651056 +0.085765 -0.943946 -0.295603 0.162231 0.618967 0.406141 0.667482 -0.163063 +0.651067 0.481217 -0.848668 -0.730323 0.702711 0.674271 0.639327 0.11048 +0.792505 -0.148969 0.670314 0.155321 0.236991 -0.725394 -0.85646 -0.861638 +0.0494774 -0.0744954 0.406126 -0.854873 -0.959164 0.948478 0.124809 -0.80229 +-0.628362 0.375658 0.545496 0.076435 -0.467406 -0.345889 -0.110965 -0.503293 +-0.976087 0.459429 -0.260363 0.846721 -0.0974471 -0.673193 0.476279 0.749357 +0.857776 0.0693236 -0.409274 -0.428415 0.673289 -0.136668 0.824272 0.381379 +0.820045 0.804361 -0.317322 0.142192 -0.310016 0.854062 0.402185 0.831183 +-0.296965 0.034647 -0.719021 -0.853171 0.948462 -0.317786 -0.682242 0.851529 +-0.360539 -0.28977 -0.540494 -0.871484 -0.0713698 -0.202932 0.283497 0.32302 +-0.368837 -0.902355 0.0806888 0.937038 0.0197885 0.855694 0.6758 0.624621 +-0.642331 0.114485 -0.214602 -0.430039 -0.12427 0.267638 0.173853 -0.447229 +0.30979 0.280358 -0.567427 0.169455 0.205752 -0.689963 0.714521 0.0473829 +0.383499 0.0804055 0.550963 0.0282557 0.349583 -0.812192 0.992022 -0.586029 +-0.0443168 -0.695056 -0.491459 0.289843 0.0399156 0.729499 -0.59989 -0.686555 +-0.329796 0.392133 0.818108 0.897126 -0.755773 -0.225375 -0.276367 0.433383 +-0.438587 0.308626 0.753066 0.570264 -0.6305 -0.00913223 0.694738 -0.0574015 +-0.000567365 0.56681 0.781076 -0.141968 0.983244 0.492774 0.533332 0.229013 +0.19993 0.200886 0.0562647 0.477792 -0.385539 -0.929566 0.992027 0.869331 +0.355324 -0.0744283 -0.280209 0.147904 -0.837536 -0.575321 -0.026675 0.576413 +-0.854892 0.448117 -0.632357 0.884104 0.460515 -0.38821 -0.309308 -0.83903 +0.545732 0.821317 -0.301445 0.132048 0.432038 0.319904 -0.324767 0.655713 +0.32467 -0.22967 0.904307 0.727212 -0.776325 0.0210347 -0.182459 -0.865849 +-0.948423 -0.102846 0.522964 -0.9679 -0.540413 0.9555 -0.906271 0.366339 +0.905601 -0.824081 0.806826 0.635544 -0.581854 -0.668167 0.636123 -0.954634 +-0.435015 -0.0557779 0.702212 0.874607 -0.653595 -0.212491 -0.784918 0.126354 +0.937068 0.672375 0.577975 -0.607661 -0.0178115 0.44509 -0.821401 -0.0571128 +0.0953985 0.212275 -0.532983 -0.320107 0.386387 0.19727 0.132351 0.103074 +0.653617 -0.279407 -0.926383 0.361078 -0.774375 -0.175768 -0.725556 0.834164 +0.651801 0.94774 0.254977 0.316746 0.213899 0.00485267 0.922421 -0.488591 +-0.3543 -0.471387 0.965173 0.173607 0.846795 -0.446685 -0.468995 0.541162 +-0.932263 -0.700538 0.0437374 -0.600939 0.637763 -0.853614 -0.89898 -0.59456 +0.822556 0.441414 0.664329 0.541246 -0.499665 0.342649 -0.441652 -0.56069 +0.524078 0.809887 0.655461 -0.168242 -0.610231 0.579368 0.031113 -0.166155 +-0.526537 -0.400588 -0.587946 0.529077 -0.390321 -0.203477 -0.253867 -0.660506 +0.865728 -0.896361 -0.166965 0.334866 0.237346 0.545053 -0.33189 -0.66649 +-0.465374 0.977072 -0.0195884 -0.978674 -0.986898 -0.0328485 0.579987 -0.71977 +-0.274641 -0.741784 -0.411774 -0.0662335 -0.413689 -0.105837 -0.65194 0.00284367 +-0.630715 -0.462553 -0.697124 -0.423515 -0.948907 0.422678 -0.845514 0.392979 +-0.612671 0.965431 0.221359 0.449319 0.305557 0.406974 0.703473 0.359746 +0.557118 0.655683 0.770181 0.166699 0.390762 0.267572 -0.630432 0.506798 +0.642224 0.581337 0.995115 -0.154745 -0.642818 -0.0617701 0.225192 -0.871905 +0.684701 0.000151154 0.866918 0.279185 -0.0704296 -0.574974 0.354941 -0.258214 +0.259761 -0.631192 -0.457332 0.285686 0.699099 -0.896124 -0.99771 -0.221524 +0.765276 -0.626306 0.705763 0.612461 -0.947382 0.988387 0.864967 -0.344337 +0.369436 0.302681 0.93184 -0.489951 -0.178039 -0.554152 -0.636793 0.0947663 +-0.745905 0.765296 -0.0878794 0.54381 -0.566166 0.0709023 -0.621111 -0.658188 +-0.439942 -0.393803 0.0993992 -0.0673843 -0.71495 -0.5793 0.796486 0.596146 +0.347069 -0.0333286 0.663615 0.716399 0.928039 0.0243541 0.0211747 -0.647925 +0.231801 -0.953452 -0.28938 -0.785405 0.0021042 -0.418424 -0.954474 0.0944015 +-0.795226 -0.786352 -0.629143 -0.0268838 0.612522 -0.707865 -0.464972 -0.190053 +0.221904 0.148953 -0.874814 -0.950534 0.303472 -0.203122 -0.297299 -0.844548 +0.140824 -0.858117 -0.46766 0.937109 -0.666551 -0.0215576 -0.0413337 0.526174 +0.937529 -0.950909 -0.0802493 -0.368285 -0.952247 0.177659 0.7287 0.225324 +-0.296159 -0.952219 -0.435089 -0.306847 -0.0509877 0.0222074 -0.929953 0.435227 +-0.623887 0.928342 0.219252 0.839628 -0.153282 -0.152008 0.0605999 0.598386 +0.12803 -0.440865 -0.201706 -0.810531 0.274716 0.294492 0.226332 -0.735106 +0.652479 0.420165 -0.482305 -0.945197 -0.042351 -0.358698 -0.155276 -0.82037 +0.322464 -0.139477 -0.687325 0.389929 0.380014 -0.360332 -0.992663 0.968118 +0.498006 -0.987473 -0.0485686 -0.447246 0.0918458 -0.644389 0.755311 0.887464 +0.429836 0.345143 -0.485296 0.182335 -0.356696 0.582101 0.832393 0.607575 +-0.223757 0.351515 0.115408 0.780621 -0.480247 -0.195 -0.773274 0.935187 +-0.128869 -0.928501 -0.661209 0.820022 -0.247699 0.168445 -0.48247 0.564638 +0.739054 -0.619004 -0.122714 0.236034 -0.430382 -0.923658 -0.683358 0.24331 +0.395269 0.606288 0.98815 -0.192725 0.0080007 -0.834696 0.131245 0.578261 +0.479883 0.455326 0.101033 0.817782 -0.80053 0.600643 -0.947445 0.590112 +0.937189 -0.470375 -0.959809 0.631907 -0.865896 0.467946 -0.10058 -0.289725 +-0.421509 0.387252 0.271291 -0.798807 -0.191348 -0.76576 0.566838 -0.648024 +0.0543221 -0.97846 -0.755844 0.495572 -0.546768 0.68395 0.710712 0.869045 +-0.0680898 -0.694386 0.683653 -0.745838 0.420444 0.90945 0.866767 0.573934 +-0.0782296 0.339832 -0.0350136 0.0327823 0.816112 -0.535942 0.821392 0.436657 +0.130665 -0.77761 0.073332 0.529 -0.0310249 0.209788 -0.168761 0.429739 +-0.206022 -0.174666 -0.591531 -0.274372 0.990813 -0.410182 0.357321 0.557301 +-0.257423 0.898744 0.0316753 -0.621787 0.0729736 -0.721405 -0.78409 0.252105 +0.25796 -0.646719 0.797532 0.657129 0.0252002 -0.264597 0.0280809 0.0296184 +0.903781 -0.359993 -0.0370503 -0.252323 -0.755103 -0.968228 0.332395 0.152309 +0.715643 0.202338 0.0211722 0.114315 -0.915303 -0.923349 -0.844118 -0.170521 +-0.559759 -0.325486 -0.6104 0.048279 0.612685 0.533573 -0.389062 0.0201878 +-0.414804 0.378705 -0.0365641 0.725253 -0.426036 -0.872704 -0.783059 -0.894508 +0.195722 0.331857 0.405579 -0.196618 -0.646433 0.31528 -0.685225 0.142291 +0.557115 -0.250782 0.109774 -0.136143 -0.771967 0.203548 -0.218052 0.389333 +-0.629642 -0.12249 0.865808 -0.091847 -0.838728 -0.982414 0.216325 -0.262573 +0.109992 -0.280158 -0.479389 0.129597 0.268368 0.673147 -0.962008 -0.866278 +-0.16216 -0.59445 0.376369 0.543022 0.559321 -0.687589 0.78088 0.942087 +-0.914894 -0.839347 0.891765 0.309621 0.530463 0.310419 0.0591803 0.548127 +0.077753 0.671682 0.689121 0.319091 -0.258157 -0.233634 -0.121386 -0.667556 +-0.864087 0.135174 0.451474 0.800652 -0.788833 0.0185349 0.824255 -0.101176 +-0.495449 -0.0897356 -0.481195 -0.329414 0.63027 -0.847425 0.481735 -0.715652 +-0.479162 0.835453 0.192061 0.0202158 0.114332 -0.592705 0.54729 -0.413141 +-0.125399 0.732418 -0.69633 -0.133807 -0.201421 -0.776236 -0.907875 0.505893 +-0.360225 -0.817624 0.342119 -0.397985 0.331854 -0.256212 -0.633924 -0.632303 +-0.472471 -0.920919 0.187211 0.0398026 0.4989 0.0805651 0.0742864 0.950357 +0.390164 0.380505 0.358938 0.006135 0.532438 -0.780838 0.507366 -0.834666 +0.305488 -0.0339484 -0.0659418 -0.945186 -0.0063168 -0.322266 0.739375 0.990767 +-0.305596 -0.887935 0.0151104 -0.701757 0.774948 -0.238107 -0.0178909 -0.87515 +-0.274157 0.530351 0.291663 0.847541 -0.00723269 -0.231056 0.448725 0.691927 +-0.997664 -0.78874 -0.777246 -0.090291 0.334912 -0.58018 -0.827108 -0.909759 +0.613561 -0.848892 -0.402654 -0.191104 -0.473759 -0.682979 0.139817 -0.596996 +0.479488 0.129539 0.73461 0.818347 0.975974 0.840722 -0.467352 0.333716 +0.132463 -0.890211 -0.175518 -0.251334 0.209338 -0.65694 0.284632 -0.0846382 +-0.208428 0.439492 -0.704196 0.75804 -0.709925 -0.533397 0.714339 0.90422 +-0.637903 0.0814424 -0.227628 0.687734 0.105665 0.754281 0.0383247 -0.20825 +0.905862 0.0235782 -0.318191 0.33822 -0.108553 -0.474966 0.572027 0.0572129 +-0.560315 0.827218 0.448415 0.572057 0.520588 0.48663 -0.0396718 0.261578 +-0.885042 -0.512612 0.463418 0.82466 -0.055316 -0.580829 -0.281855 0.277118 +0.846699 0.269458 0.664875 0.109804 -0.799353 0.484617 -0.0811441 0.675031 +0.983116 -0.320686 -0.967268 0.422405 -0.875115 -0.876388 0.244567 0.832954 +-0.711578 0.980622 0.38807 -0.056876 0.0154746 0.0850274 0.383304 0.725276 +-0.615692 0.453829 -0.114977 -0.671071 -0.182657 0.424096 -0.674289 0.608264 +0.979723 -0.14854 -0.526936 0.348416 0.337652 -0.370859 0.384555 -0.523567 +0.667058 0.647991 -0.525271 -0.387758 -0.997505 0.499909 -0.696958 0.0438556 +-0.344948 0.91037 0.310014 -0.786479 0.231515 0.83267 -0.800147 -0.71553 +-0.311102 0.290886 0.0941962 -0.146718 -0.0788699 -0.304247 -0.297134 0.312001 +-0.135024 0.333654 0.224173 -0.48049 -0.137087 -0.0851665 -0.063134 -0.370265 +-0.167541 -0.567091 0.269331 0.0842452 -0.0742686 -0.801058 0.0182561 0.770316 +0.200225 -0.824877 -0.118187 0.303305 -0.363584 -0.59466 -0.328064 0.986639 +0.69955 -0.446219 0.513832 0.940837 0.039409 -0.764758 0.553287 -0.114898 +-0.275923 0.57232 0.525424 -0.974437 -0.776375 -0.996626 0.546344 0.6603 +-0.180902 -0.369212 0.989044 -0.30809 0.993703 -0.994958 0.687437 0.594484 +-0.955314 0.653012 -0.542373 -0.863294 -0.150448 0.586242 -0.742387 -0.136533 +-0.53176 -0.0034602 0.610657 0.283423 -0.678439 0.273139 -0.92601 -0.637018 +-0.3506 -0.766942 -0.357359 0.427682 -0.384695 0.66865 -0.274092 0.396424 +0.578505 -0.835379 0.300984 -0.944219 -0.564666 0.350301 0.984021 0.404488 +0.742556 -0.570024 0.106047 -0.279436 -0.382923 0.356421 0.432863 0.884236 +0.863228 -0.120595 -0.202818 0.842471 -0.347364 -0.836418 -0.653095 -0.00384722 +0.141851 0.42798 0.159145 0.0873448 0.547416 0.637176 0.80213 -0.159199 +-0.998928 0.7877 0.806591 -0.583023 -0.64463 0.180916 -0.179182 -0.206517 +-0.491129 -0.338378 0.168081 0.174024 -0.933346 -0.267203 -0.658137 -0.782135 +-0.543445 -0.946734 -0.581929 0.997398 0.35883 -0.889394 0.744214 -0.841229 +0.241667 0.0268001 0.782658 0.848009 0.0369494 0.882349 -0.426744 -0.346987 +0.862106 0.252457 -0.439019 0.440632 -0.618553 -0.40721 -0.00100412 0.289788 +0.935614 -0.746169 0.116288 -0.0702415 -0.248752 -0.459585 0.888645 0.517373 +-0.0638119 0.421087 -0.43006 0.619832 0.532893 0.388006 -0.850096 -0.166677 +-0.0533826 0.0597424 0.284244 -0.392274 -0.48001 -0.860994 -0.575622 0.961669 +0.319127 0.431032 -0.353745 0.622434 -0.0175861 -0.160517 0.0479902 0.759641 +-0.279297 -0.372989 0.461996 0.361456 0.812175 0.364688 -0.938057 0.672262 +-0.998169 0.862792 0.365382 0.0944088 -0.00568185 -0.914102 0.345984 0.922671 +0.748825 0.0697302 -0.0838671 -0.512355 -0.645202 0.280872 0.542005 -0.512991 +0.717398 0.0148824 -0.756246 0.668985 0.551587 0.933034 -0.0302685 0.57869 +0.0135831 0.961429 0.798888 -0.490134 0.0788875 -0.732927 -0.847448 0.815737 +0.34141 -0.0631161 -0.610386 0.528839 0.516286 0.296187 -0.109325 -0.645514 +0.461527 -0.251398 0.378351 -0.447978 -0.621262 -0.677811 0.784492 0.100396 +0.888894 -0.654193 -0.827866 -0.352366 -0.554857 -0.865394 -0.0173624 0.1884 +-0.276482 0.225799 -0.379563 -0.868872 0.921386 -0.509194 0.249485 -0.194679 +-0.432662 0.0761289 0.0314111 0.924523 0.602866 -0.0592413 0.253429 0.323095 +-0.246217 0.69923 -0.936107 0.35813 0.0303942 -0.378067 0.259794 0.170069 +0.598878 -0.0956435 -0.419756 -0.812831 0.942492 0.000759372 -0.419882 0.194993 +-0.872005 -0.110201 -0.281762 -0.316407 0.281128 0.259073 0.985252 0.779942 +-0.551026 0.506062 0.621188 0.316797 0.787958 0.375718 -0.377522 -0.709219 +0.868502 -0.565741 -0.64381 -0.0949202 -0.800112 -0.187901 -0.36674 0.902865 +0.593779 0.306037 0.260546 -0.289094 0.387811 -0.854141 -0.298593 -0.746131 +-0.403865 -0.0599061 -0.175985 -0.103992 -0.182054 0.122747 -0.793396 -0.0752806 +0.118987 0.32932 -0.357681 -0.407338 0.293571 -0.838911 0.0936832 -0.127899 +-0.307963 0.573313 0.176062 -0.501988 0.131799 0.779664 0.27436 -0.846411 +-0.6298 -0.0892439 0.206789 0.536271 0.610512 -0.788464 -0.169622 -0.468959 +-0.566494 0.744672 0.283892 -0.00565353 -0.0362827 0.200455 -0.473492 -0.967341 +-0.0173342 0.768724 0.327515 0.0419136 -0.756228 -0.433718 0.21463 -0.682303 +-0.861236 0.970447 0.937002 -0.164183 0.292068 0.487319 0.381598 0.578987 +0.762385 0.942806 -0.360376 -0.532665 0.917836 -0.421796 0.054024 -0.521111 +0.961201 0.792211 0.548377 -0.50753 0.345851 0.113151 -0.148371 -0.467866 +0.475471 0.641824 0.515887 -0.549656 0.418083 -0.692525 0.797605 0.238006 +0.740897 -0.585185 0.771689 0.715425 -0.717804 0.1123 0.090004 0.645284 +-0.200492 0.439643 0.39152 -0.87713 -0.820466 -0.267014 0.858388 -0.684192 +-0.572121 -0.6481 -0.836354 -0.727361 -0.57808 0.0535239 -0.512827 -0.302114 +-0.885128 0.971046 -0.046249 0.744135 0.462079 0.737962 -0.00550365 -0.731318 +0.345713 -0.707811 0.669868 0.860885 0.316897 -0.38473 -0.850745 0.744343 +-0.826244 -0.907294 -0.632241 -0.0685697 -0.860307 0.191838 -0.8719 -0.244189 +-0.476754 0.6518 -0.0621155 -0.108737 0.45466 -0.326862 0.561656 0.614533 +-0.260912 0.0790318 -0.693098 0.686324 0.569608 0.504235 -0.92998 0.841807 +-0.505985 -0.00248717 -0.584705 -0.978566 0.523799 -0.994243 0.401884 -0.408141 +-0.461064 0.199489 0.664111 0.682063 0.828969 -0.566705 0.345817 -0.474344 +0.342875 0.792451 0.974492 0.00326968 -0.0979298 0.364309 0.952433 -0.350622 +0.246868 0.420798 -0.77104 -0.686994 0.046457 -0.646043 0.0945476 0.3939 +0.713466 -0.197333 -0.956722 -0.318996 0.0542445 0.966028 0.926643 0.927768 +-0.956614 -0.150579 -0.778315 0.27839 0.340588 0.456458 0.64809 -0.862655 +0.93772 -0.0823584 0.645405 0.152695 -0.0893484 0.079338 -0.181385 -0.149401 +0.880062 -0.899808 0.67678 0.983115 -0.793427 -0.0992431 0.10006 0.674211 +-0.25547 0.809335 0.773695 -0.0525009 0.155048 -0.397669 0.244787 0.163812 +0.0814183 0.733641 0.123502 -0.341607 -0.744109 0.549434 -0.581446 -0.534397 +-0.545486 -0.598795 0.742333 -0.932709 0.964186 -0.437112 0.429452 0.55377 +-0.804624 -0.964547 -0.410035 -0.0545865 -0.751108 -0.239502 -0.441446 -0.861369 +0.110917 0.669109 0.836676 0.518027 -0.853143 0.0849209 0.103102 -0.925186 +-0.300751 0.0979728 0.608553 -0.586374 0.868477 -0.0524241 -0.649287 -0.950954 +0.370902 -0.654803 0.0152561 -0.497862 -0.849674 -0.164914 0.850231 0.258313 +0.491816 0.823417 0.219459 0.00673006 0.104549 -0.348766 -0.24244 0.556283 +-0.522479 0.509741 0.156232 -0.54768 0.774396 0.179653 -0.588555 -0.916058 +0.0815185 -0.575153 0.252636 0.166534 0.617775 -0.304252 -0.507862 -0.450254 +0.227304 -0.494694 -0.534251 0.274714 -0.845407 -0.0655565 -0.435776 -0.567606 +-0.981232 0.550524 -0.538458 0.696908 -0.636625 0.653841 0.612047 -0.417008 +0.887174 -0.340062 -0.847439 0.774232 0.283741 -0.409639 -0.440044 -0.432796 +-0.975221 -0.967874 0.286576 0.162995 -0.27583 0.155831 0.869568 -0.153391 +-0.411653 0.267808 -0.587389 0.914526 0.34149 0.654458 -0.893734 -0.234464 +0.772245 0.271029 -0.202365 -0.860186 0.00942087 -0.40884 -0.723717 -0.864783 +0.276351 -0.529273 -0.494314 0.666065 -0.806368 0.220149 0.478168 0.0328102 +-0.250285 0.600581 0.614246 -0.681106 -0.843817 0.944788 0.518175 -0.141106 +0.213816 -0.191986 -0.00334154 -0.423007 0.040556 -0.66452 -0.204187 -0.234212 +-0.0915631 0.424535 0.287596 0.764726 0.266142 0.02135 -0.179428 0.445019 +-0.306792 -0.317645 0.798546 -0.481469 -0.437666 0.541224 0.742633 0.141972 +-0.259233 0.735648 0.18293 0.226327 0.815834 -0.169555 -0.891832 0.965041 +0.817583 -0.306246 -0.727388 0.836307 -0.0567295 -0.359821 -0.0623004 0.0146595 +-0.982549 0.470623 0.224901 0.320201 -0.422177 0.0846818 0.877561 -0.0348397 +-0.599939 0.32302 -0.696371 0.408123 -0.0737024 -0.637588 -0.98979 -0.996502 +-0.883334 0.19633 -0.89659 -0.215099 -0.550339 0.384832 -0.740544 -0.549133 +0.0599547 0.690338 -0.91832 0.938188 0.305775 0.0802236 -0.201966 0.478655 +0.550545 0.07251 0.719926 -0.048884 0.366542 -0.351833 -0.211951 0.613254 +-0.794952 0.048904 0.638651 -0.784534 0.130564 0.0426809 -0.580999 0.626428 +0.798411 0.505826 0.818592 -0.174041 0.38094 -0.272236 0.720355 0.709383 +0.857351 0.100727 -0.613272 -0.410095 0.567996 -0.00762872 0.926644 0.640707 +-0.0424957 -0.161533 0.81314 -0.246815 -0.130873 0.310154 0.402256 0.159093 +-0.389781 0.223039 -0.683524 -0.395225 -0.497549 0.791054 -0.751099 -0.724181 +-0.661612 0.891685 0.62511 -0.399175 -0.681625 0.613913 0.0347462 0.0741704 +0.92973 0.777514 0.523026 -0.188668 -0.518442 -0.154507 0.876129 -0.0304955 +0.359611 0.437814 0.215449 0.679015 -0.385793 0.244239 0.0285141 0.377071 +-0.0901188 0.861664 0.592853 -0.0103729 0.634642 0.0399738 0.375644 -0.942805 +-0.878677 -0.0977806 -0.581259 0.909113 -0.949485 0.539159 -0.269272 -0.644702 +0.396922 -0.901451 0.775878 0.743231 0.387978 0.902272 0.647426 0.204801 +-0.727022 0.221606 0.394251 0.138904 -0.0424268 0.910571 -0.508341 0.724071 +0.699054 -0.868596 0.542153 -0.840958 0.599846 -0.624429 -0.632413 -0.654074 +-0.665642 0.538683 -0.0799395 -0.896025 -0.706551 -0.786008 -0.672906 0.353977 +0.959652 -0.202836 -0.794991 -0.53457 0.781096 -0.101194 -0.171251 0.486897 +-0.859707 0.950463 -0.763817 -0.91514 -0.333851 0.936668 -0.216623 -0.0952078 +-0.894765 0.105362 -0.950423 0.562549 0.270471 -0.699869 0.315632 -0.91655 +0.882887 -0.00132108 0.980841 0.409653 -0.563253 0.885914 0.880727 0.964139 +0.823164 -0.920521 -0.649476 -0.626808 -0.285936 -0.248118 -0.361665 0.420277 +0.19636 0.0985554 0.150611 0.517697 -0.304759 0.122974 0.815924 -0.685767 +0.451288 0.321481 0.130937 0.116384 0.121141 -0.86833 0.639199 0.260986 +0.864675 0.681775 -0.218958 -0.769449 -0.677597 -0.971851 0.0532934 0.221523 +0.533964 0.15659 0.28682 -0.818857 -0.201443 -0.649906 0.542813 -0.00959073 +0.817783 0.165464 0.103392 -0.716906 0.962953 -0.202037 -0.0759537 0.186108 +0.562349 0.0929924 -0.666527 0.447057 -0.733005 -0.0808003 0.938691 0.94022 +0.377163 0.794003 0.878441 -0.585736 -0.216602 0.317632 -0.368325 0.960691 +0.35932 0.217905 -0.66962 0.757986 -0.0605952 0.369402 0.349153 0.375401 +0.128361 -0.759455 -0.454601 0.231159 0.182047 0.626316 -0.2662 0.970907 +0.417101 0.00294624 -0.31508 -0.81961 -0.645843 0.760031 -0.700553 -0.275863 +-0.643067 0.412063 0.268319 -0.878727 0.847759 -0.53539 -0.0379323 -0.756312 +0.31784 -0.727992 0.910541 0.947458 -0.616752 0.155985 -0.757064 0.0402706 +0.29477 0.486366 -0.195294 -0.44712 -0.730204 -0.224981 -0.573309 0.365301 +-0.640745 0.15997 -0.675915 -0.983852 0.582019 0.769503 -0.534825 0.822197 +0.730151 -0.652336 0.771257 -0.715613 -0.529114 -0.349577 0.334493 0.516408 +0.648553 0.539158 0.357103 -0.0156328 -0.427603 -0.911554 0.407488 0.392862 +0.879597 -0.0713534 -0.370896 0.695681 0.629233 -0.630578 -0.522855 0.574893 +0.84401 0.66487 -0.815655 -0.919033 0.258513 -0.873484 0.752816 -0.409359 +-0.62824 0.90338 0.339717 -0.61761 0.708712 0.962615 0.832122 0.00398013 +-0.885082 0.586661 -0.607857 0.0706468 0.343362 0.236728 -0.269383 -0.238784 +0.820654 0.911229 0.255108 -0.290276 0.363748 0.739205 0.626344 -0.791513 +0.157016 0.378835 0.249012 0.831632 -0.408016 0.483629 0.405754 0.547478 +0.015345 -0.932139 0.660487 0.521992 0.603381 0.245233 -0.274024 -0.335447 +0.887678 0.491729 -0.737601 -0.187352 -0.994706 0.889207 0.187995 -0.183223 +0.565283 0.82096 -0.138177 -0.527245 -0.400863 0.554744 0.761942 -0.335533 +0.309582 0.00424392 0.218933 0.0392123 0.274676 0.806379 -0.305205 0.0880121 +-0.676519 0.820172 0.265933 -0.807138 -0.155751 -0.939377 -0.649055 -0.562359 +-0.0252011 -0.727199 0.342119 -0.622712 -0.692151 -0.535785 0.0109545 -0.354449 +0.594403 -0.620663 -0.501857 -0.531579 -0.286862 -0.493018 0.931711 0.897296 +-0.188629 0.836926 0.816477 -0.514478 0.70182 -0.150489 -0.656092 -0.223061 +-0.637774 0.922224 -0.366716 -0.853182 -0.165967 -0.47444 -0.15255 0.237983 +-0.959962 0.731896 0.677249 -0.947991 0.0474711 -0.464246 0.180211 0.4343 +0.471294 0.390443 0.688116 -0.0258603 0.253201 -0.524004 0.00343533 -0.197581 +0.498937 -0.79427 -0.387358 -0.200615 -0.781537 0.0654888 -0.0235635 0.910196 +-0.654484 0.841849 0.349937 0.278838 0.641925 0.914998 -0.901531 0.22933 +-0.283348 0.922009 -0.824676 -0.71865 -0.791757 -0.625036 -0.321023 0.854829 +0.0107176 -0.664931 0.239071 0.40789 -0.654548 -0.848005 -0.750935 -0.713981 +0.506206 0.495062 -0.304657 -0.643287 0.723505 0.241457 0.119593 0.371297 +0.180474 0.468024 0.988186 -0.48715 -0.991846 0.244942 0.0528599 0.0637469 +0.833889 -0.11873 -0.17861 -0.189427 -0.298778 0.55161 0.243032 0.545208 +0.722107 -0.0935925 0.516911 -0.487714 -0.745494 -0.379238 0.257987 -0.666524 +0.497401 0.842661 0.209398 0.760874 -0.923557 0.1712 0.0554442 0.195015 +-0.936423 -0.663775 -0.104996 0.00741343 -0.744289 -0.617282 0.594674 0.979071 +0.208138 0.782254 -0.158247 0.222795 0.579382 0.147957 -0.114167 0.960539 +-0.923005 -0.898775 -0.0621371 0.552772 -0.858906 -0.068227 0.865541 0.5706 +0.781961 0.640867 -0.809071 0.136981 -0.356763 -0.0792435 0.297144 -0.538134 +-0.221544 -0.354654 0.4786 0.333252 -0.174252 -0.244583 0.869017 -0.0716268 +0.848776 0.283365 0.868168 0.0538657 -0.532768 0.579825 -0.506475 0.345407 +-0.652467 0.0745767 -0.161587 0.0106741 -0.00559021 0.74463 0.533452 -0.450377 +-0.541299 -0.547479 0.713555 -0.706911 0.158814 -0.232027 -0.642914 -0.11275 +-0.345691 -0.477523 0.309209 -0.576494 -0.709177 0.254141 0.88782 -0.0494284 +0.00376162 0.476296 0.324455 -0.0231295 0.75273 -0.678247 -0.766696 0.992602 +-0.392655 0.221898 -0.996051 0.643405 -0.289373 0.555213 -0.966631 0.388454 +0.399735 -0.0782908 0.282509 0.809283 0.0621044 0.686929 -0.287878 0.146168 +0.468366 -0.599108 0.491734 0.415345 -0.597701 -0.188818 -0.321578 0.439873 +0.933667 0.912003 -0.689847 0.776399 0.132141 -0.0142812 0.841542 0.904968 +0.932671 -0.205578 0.107385 0.059832 0.510427 -0.0480776 -0.67251 0.621484 +-0.100876 0.549002 0.634983 -0.119785 -0.446428 -0.391563 0.403919 0.590761 +-0.0603544 0.45941 0.25589 0.579738 -0.983069 -0.459147 -0.0990035 0.0473122 +0.954596 0.633348 0.609027 -0.12728 -0.442261 -0.953808 -0.452732 0.578247 +0.0964376 0.993204 0.940248 0.510918 0.32833 -0.98558 -0.614856 -0.511803 +0.761979 -0.582177 0.478123 0.168238 0.191916 -0.600198 -0.60908 0.438701 +0.779942 0.212245 -0.551264 0.909407 0.112989 0.237651 0.659996 -0.871192 +0.0781793 0.62752 -0.608189 0.948704 -0.494867 0.79049 0.940317 -0.817677 +-0.87335 0.831035 0.457211 0.991613 -0.673819 0.715329 -0.923197 0.650651 +0.505027 0.455998 0.244774 0.620398 0.896838 -0.0624675 -0.294483 -0.714691 +-0.807255 -0.184722 -0.606469 0.0510232 0.179566 -0.0579363 -0.174412 -0.863459 +0.710181 -0.587959 -0.998859 -0.779537 0.221212 -0.918746 -0.626431 0.0818739 +-0.881738 -0.0697553 0.506168 -0.434019 -0.935939 -0.120315 0.219988 -0.846367 +0.375305 -0.854521 0.182392 -0.314735 0.30013 -0.474127 -0.841578 -0.627124 +0.52294 0.382034 0.54439 0.0941296 -0.679883 -0.380568 0.572685 0.711513 +-0.316525 0.277625 0.983235 0.518219 0.241373 0.743714 0.0649138 -0.20638 +0.693347 0.403006 -0.464385 -0.823494 -0.321207 0.918251 0.647452 -0.502137 +0.441142 0.647581 0.632004 0.487662 0.731203 0.863621 0.463359 0.786659 +0.384 -0.0455528 0.481857 0.413089 -0.458782 -0.667023 0.522426 0.29537 +-0.82415 -0.550388 -0.255981 -0.735899 -0.380215 -0.627895 -0.234079 0.944972 +0.893836 0.735363 -0.769291 0.944714 0.285597 -0.0938004 -0.123621 0.755603 +-0.888358 0.278655 0.92245 -0.598397 -0.230367 0.748407 0.520847 0.348698 +-0.896829 -0.145125 0.962619 -0.92495 0.451189 -0.261137 -0.286005 -0.679152 +-0.539385 0.775541 -0.0944589 0.367213 0.542262 -0.346505 -0.532552 0.139301 +0.977876 0.734137 0.408733 0.485077 0.972942 -0.759233 0.735209 -0.552718 +-0.943534 0.544304 0.0340769 0.887574 0.901972 -0.674539 0.0974603 0.926637 +-0.330129 -0.703179 -0.577478 0.0477279 0.188415 0.855658 0.152493 -0.0639507 +-0.232286 0.224599 -0.370838 -0.712825 0.675681 0.00981678 0.389022 0.0244613 +-0.399395 0.894336 0.551905 0.89118 -0.444561 0.764462 -0.303071 0.141737 +0.786329 0.673323 0.477762 -0.167822 0.71861 0.664168 -0.268925 0.0828351 +0.863814 -0.929986 -0.434447 0.898087 -0.0612498 0.757239 -0.258106 -0.0494983 +0.392358 0.420596 0.134843 -0.944536 -0.672695 -0.387 -0.65693 0.562342 +0.881747 -0.842434 -0.0466943 -0.516486 -0.14465 -0.743237 0.874053 -0.0565631 +0.0330436 -0.311132 -0.173063 0.210661 -0.25813 0.318614 0.198463 -0.630609 +-0.166034 -0.966343 0.488652 -0.836782 0.809192 -0.263693 0.743423 -0.139854 +-0.448914 0.728159 -0.371649 0.183715 -0.382062 -0.611343 0.360754 -0.750939 +0.725689 -0.275327 0.566848 -0.258814 -0.89277 -0.198909 0.874353 -0.27228 +0.25559 -0.404302 -0.887753 0.832919 -0.60103 -0.480956 0.772441 0.973311 +0.814496 0.535915 0.530017 -0.528991 -0.287927 0.471753 0.607369 -0.930765 +0.255896 0.792492 -0.72809 -0.515453 -0.327744 -0.130237 -0.962123 -0.945513 +-0.791085 -0.155853 -0.759945 0.17272 0.012639 0.71853 -0.295496 -0.962142 +-0.738404 -0.942573 0.219774 -0.242158 -0.79843 0.567457 -0.269836 0.573959 +0.999862 -0.292232 0.296913 0.154585 -0.0319392 -0.101248 -0.0284865 0.566198 +-0.270317 0.0990491 0.800965 -0.972202 -0.758828 -0.524636 -0.795831 0.0511171 +0.74104 0.756612 -0.777225 0.890035 -0.0559034 -0.177004 0.0648665 0.159184 +0.722954 -0.44605 -0.930824 -0.892966 0.94335 -0.801206 -0.183307 0.882795 +0.071331 0.312503 -0.0158416 -0.384237 0.11333 0.190089 -0.532708 0.89314 +0.560323 0.165608 -0.487801 0.839083 0.777147 0.619958 -0.326733 -0.48473 +-0.959508 0.596919 -0.347908 -0.28008 0.708603 -0.00157721 0.895788 -0.556427 +-0.330629 0.710724 -0.820599 0.278355 -0.190401 0.0906331 0.498114 -0.751765 +-0.333808 0.420045 -0.497672 0.946621 0.0894518 -0.432735 -0.813018 0.373842 +0.426476 -0.225521 0.45047 0.819105 0.865342 -0.921414 -0.725207 -0.425674 +-0.281437 0.995249 -0.529129 -0.677178 -0.601884 0.0964011 0.361923 -0.301413 +-0.664911 0.927445 0.739841 -0.37735 -0.0321333 -0.925231 0.257107 0.0908388 +-0.176315 -0.843917 0.273098 0.716013 0.123057 0.70907 -0.217759 -0.686514 +0.733115 -0.0402991 0.0794695 0.546967 0.874903 0.170671 0.692598 0.649382 +0.116708 0.113768 0.641518 0.0478678 -0.137072 -0.241049 0.762593 0.292057 +-0.490503 -0.604258 0.0301591 -0.551319 0.302458 0.900232 0.561375 0.133538 +0.768615 0.121881 -0.720506 0.681753 -0.984649 -0.0141507 -0.930949 0.0295205 +-0.042986 -0.762953 -0.0271066 -0.0377672 0.199279 0.867505 0.494154 -0.93018 +0.990379 -0.300296 -0.549796 0.408229 -0.861129 -0.196474 0.457403 0.546383 +-0.390446 0.157214 -0.0581865 0.846007 -0.152204 0.591226 -0.703394 0.535103 +-0.332402 -0.532502 0.315163 0.111102 0.822611 0.735132 0.962867 0.336456 +0.808038 0.369777 0.0355726 -0.328323 0.362608 -0.635222 -0.31314 -0.477716 +0.810855 -0.941815 0.240262 0.999463 0.299438 -0.182634 0.168391 -0.956243 +-0.410342 -0.887757 -0.825826 0.476632 -0.633834 0.967322 0.287407 -0.803921 +-0.727006 -0.72843 0.216492 -0.807746 0.965501 0.845416 -0.179987 0.172446 +0.496043 0.741301 -0.192255 0.0823884 0.260061 0.376388 0.895602 -0.492551 +-0.67124 0.524929 0.424585 -0.588839 -0.918418 0.833771 -0.666691 -0.395147 +0.70891 -0.546548 -0.494552 0.765338 0.351682 0.208478 0.309074 -0.783014 +-0.414118 0.216203 0.311043 -0.769911 0.25044 -0.914296 0.505495 -0.862396 +-0.661161 0.318837 -0.323545 -0.749562 0.238528 -0.864356 0.0969031 0.343573 +0.910163 -0.0435227 -0.306567 -0.91579 0.758843 -0.735411 -0.657015 0.067253 +0.0824448 -0.143139 0.000233853 -0.669545 0.979572 -0.171555 -0.00872194 -0.281785 +0.553714 -0.0448039 -0.297894 -0.269935 0.0816493 -0.817265 -0.25409 0.816555 +-0.910175 0.453318 0.0867426 0.65485 0.408334 -0.109336 0.461691 0.673779 +-0.53455 0.371076 -0.413704 -0.303239 -0.20085 0.627329 -0.142815 -0.277738 +-0.376888 -0.239065 0.720016 0.992076 -0.966696 -0.850758 -0.604795 0.39294 +-0.268847 0.142458 -0.491271 -0.25731 0.839292 -0.403519 0.276029 0.275732 +-0.272131 -0.649085 -0.397107 -0.473747 0.19504 -0.315186 -0.332551 0.953764 +0.829421 -0.277897 0.291972 -0.431647 0.319913 0.532588 -0.648084 0.792957 +0.32397 0.325757 -0.530295 0.875518 0.530823 -0.369587 0.977863 -0.806537 +0.5498 -0.512532 0.631372 -0.219018 -0.309337 -0.791233 0.126655 -0.668416 +-0.907103 -0.593879 -0.258768 -0.929844 0.31005 0.643959 0.199629 0.539163 +-0.157051 -0.0516952 -0.924173 -0.313176 -0.951263 0.925897 -0.487796 0.898177 +-0.856732 -0.994336 0.980966 -0.988833 0.120569 0.071028 -0.546373 0.314786 +0.445977 -0.957414 0.668461 -0.363623 -0.943982 0.283875 0.509337 0.141872 +-0.638478 0.152685 -0.0681733 0.038048 -0.773979 0.927497 0.659393 0.135351 +-0.940054 0.211372 0.528711 -0.50352 0.805783 -0.510394 -0.569456 -0.694606 +0.0995063 -0.891677 0.57187 -0.0835409 0.565456 -0.58246 0.992037 0.395467 +0.275065 0.529805 -0.155233 0.176407 -0.0336307 0.896007 -0.9481 -0.81459 +-0.237838 -0.994235 -0.109618 0.173412 -0.748352 -0.882013 0.387504 0.673715 +0.822711 0.0505035 -0.110435 -0.783284 0.166197 0.0547938 0.927833 0.147362 +-0.657396 0.340709 0.40621 0.679443 -0.0472974 0.883564 0.82865 0.495513 +-0.0387411 0.711403 0.235356 0.777087 0.303619 0.594127 0.0310233 -0.757835 +-0.109776 -0.193426 -0.497913 0.853871 0.123684 0.176588 0.0694529 -0.201389 +-0.0402764 0.83056 0.175167 -0.107285 -0.739853 -0.232708 0.541223 0.677185 +0.501453 0.569484 -0.510039 -0.34945 0.0179517 0.943833 -0.158113 -0.919172 +-0.493293 -0.971963 -0.212403 -0.643734 0.443588 -0.641623 -0.211297 -0.466253 +-0.0285846 0.0773716 0.0650886 0.980142 -0.458166 0.0895902 0.789982 0.714124 +0.255996 -0.769745 -0.0267572 -0.166986 -0.530757 -0.915754 0.720455 -0.116985 +0.782805 -0.949967 -0.99872 0.61993 0.255601 0.802841 0.552145 0.315338 +0.084646 0.0161256 -0.0109366 0.443328 0.748397 0.30841 -0.415378 0.618193 +-0.507773 0.272894 0.858081 0.257301 -0.119435 -0.306529 -0.497836 0.704057 +0.661695 0.386045 0.397397 -0.532988 0.505115 0.188356 0.425434 -0.406217 +-0.0724046 -0.0522931 0.618651 -0.746365 0.585327 -0.164312 0.388168 -0.829286 +0.327152 -0.611959 -0.104688 -0.439687 -0.989773 0.593231 -0.359783 -0.100241 +0.395388 0.228014 -0.361063 -0.592886 0.237209 -0.85933 -0.952566 -0.567496 +-0.425794 0.707947 -0.217454 -0.948841 -0.951188 0.427717 0.649977 0.451391 +-0.0809486 0.762827 -0.208069 0.761946 0.195246 0.330323 -0.712674 0.385718 +-0.713438 -0.0104818 0.373325 -0.158264 -0.558272 -0.935253 -0.180376 0.257992 +0.963579 -0.467634 -0.991456 0.73661 0.420621 0.611541 0.129878 -0.139247 +0.121076 -0.232961 -0.685685 0.175954 0.636974 0.106251 0.771119 -0.486818 +0.0236844 0.845598 0.0274395 0.794204 -0.937526 0.593828 -0.677017 -0.46641 +-0.0135729 -0.615094 -0.398661 -0.833819 -0.523664 -0.0747468 0.2075 0.892752 +-0.846625 -0.545092 -0.043494 0.667598 -0.934632 -0.468268 -0.682847 0.355478 +0.137197 -0.336166 -0.205873 0.956068 -0.551939 -0.292111 0.62029 -0.690471 +-0.0719763 0.243208 0.906418 -0.861834 0.826217 -0.213284 0.0212987 -0.233671 +0.0813541 0.170654 0.403923 -0.187356 -0.816106 -0.151359 0.105874 -0.401042 +0.839184 0.347649 -0.0576062 0.760529 0.391581 0.9243 -0.352764 0.961582 +0.502812 0.134488 0.341987 0.788667 0.503163 0.692971 -0.780474 0.0476577 +0.0412754 -0.350309 0.454983 0.312676 0.135271 -0.523718 -0.418448 -0.362349 +-0.197467 -0.358567 -0.105724 -0.338137 0.461614 -0.0580483 0.303333 -0.0102347 +0.219552 0.908984 0.285955 -0.793621 0.608321 -0.35922 -0.554176 -0.939427 +0.549849 0.31185 0.952824 -0.612367 -0.0122756 -0.859247 -0.707739 0.599578 +0.755847 -0.487411 -0.746853 -0.356608 -0.491911 0.465175 -0.783563 0.508618 +0.747822 0.40923 -0.84765 0.00950605 -0.459484 0.215416 0.843092 -0.900749 +-0.332525 -0.528359 -0.896191 0.602761 -0.0746646 -0.976921 0.10818 -0.704926 +-0.476777 -0.739367 0.915101 0.256158 0.407109 0.512779 0.016504 -0.390586 +0.481183 -0.791426 -0.862797 -0.457648 0.183429 -0.921095 -0.586662 0.357809 +0.778921 0.753544 0.436628 0.964292 0.391287 -0.9507 0.180487 0.87763 +-0.915636 -0.357254 -0.0276632 0.0985259 0.365129 0.632246 0.0456464 0.826809 +0.162956 -0.551402 -0.100095 0.375576 0.929266 -0.768643 0.453956 -0.558734 +0.387555 0.00583336 0.0956637 0.150533 0.535709 0.224147 0.459317 -0.328455 +-0.302872 0.997435 0.693767 -0.580299 -0.923281 0.38768 0.910991 -0.944723 +0.263872 -0.00554942 0.922022 0.966055 -0.916112 0.953158 -0.0659692 0.67065 +0.771442 0.564864 -0.0156295 0.887604 0.702961 -0.705951 -0.818255 -0.528323 +-0.310714 -0.288474 -0.58712 0.717359 0.159609 0.551893 0.975287 0.827947 +0.65936 0.82215 0.939652 0.648182 0.252733 -0.17138 0.522031 -0.4215 +-0.706526 0.1775 -0.273366 -0.687876 0.854777 0.63618 0.398037 0.020683 +0.753955 0.0357367 0.332278 0.184082 -0.120687 -0.0202955 -0.494045 0.0165401 +0.563232 -0.762517 -0.758065 0.385607 0.0584629 0.0359835 0.564418 0.658008 +-0.814176 0.193863 0.340561 -0.467972 0.730094 -0.590777 0.266266 0.898681 +0.42032 -0.158488 0.0773322 0.629157 0.148051 0.788621 -0.0995409 -0.51202 +0.551366 -0.174213 0.211137 0.44097 0.627692 0.487515 -0.110838 -0.259599 +0.660744 0.808913 0.431178 -0.743901 -0.70084 -0.614744 0.873532 0.947402 +0.657012 0.677467 -0.88745 -0.848636 0.488145 -0.70814 0.21825 0.146662 +-0.640812 0.575023 0.305682 -0.321175 -0.789839 0.669056 -0.265304 -0.460024 +0.0602146 0.623089 -0.118032 -0.258082 0.32257 -0.434977 -0.706771 -0.730281 +0.785421 0.949763 0.00173022 0.307924 0.913622 0.945387 -0.192498 -0.78929 +0.0812777 -0.1087 -0.902461 -0.439343 -0.0509033 0.493594 -0.91322 -0.911076 +0.664665 -0.345977 -0.122002 -0.148442 0.995442 0.948341 -0.474989 0.717596 +0.560131 0.514181 -0.436591 -0.0717882 0.487307 -0.670861 -0.0540871 0.73297 +-0.345602 0.578287 0.131515 -0.470945 0.13739 -0.263547 -0.158584 0.305424 +-0.484451 -0.718533 -0.885015 -0.280674 -0.918536 0.212214 -0.176913 0.517279 +0.988947 -0.76769 -0.749337 0.300556 -0.37006 0.164866 0.228126 -0.759785 +-0.174493 -0.924436 -0.506373 0.482527 -0.956326 0.165372 0.633601 0.177169 +-0.517201 0.00372408 0.415542 -0.350327 0.222067 0.225172 0.815001 -0.0865672 +0.197375 0.222817 -0.747992 -0.503789 0.468773 -0.439407 0.033173 -0.129953 +0.827224 -0.466374 -0.495222 -0.0898777 -0.680222 -0.585435 0.916833 0.0594001 +0.959447 -0.380616 0.975301 -0.367369 0.40445 -0.823556 0.0115204 0.84144 +-0.472505 0.360614 0.206951 -0.583504 -0.625714 -0.748102 0.330881 -0.562482 +-0.990271 -0.739283 -0.191383 -0.00171732 0.546829 0.295452 0.0531057 -0.383237 +-0.72186 -0.835512 -0.705172 0.381392 -0.606595 0.77036 0.123339 -0.249107 +0.888597 0.00179132 -0.78501 0.794097 -0.651798 -0.813885 0.78348 0.297299 +0.81999 0.15467 -0.14832 -0.458069 -0.404541 0.832797 -0.630262 0.480856 +0.314595 0.0334145 -0.135598 -0.202529 0.999964 -0.198896 -0.246905 -0.513281 +-0.884823 0.558152 0.314944 0.438152 0.426111 0.895771 0.404761 -0.743871 +-0.0142195 0.576544 0.263497 0.550393 -0.177705 -0.0444126 -0.493675 0.149114 +0.788509 -0.967804 0.0512684 -0.000240066 0.968937 0.177356 0.894977 -0.0332478 +0.920454 -0.684096 -0.00578537 0.343446 0.376961 -0.825182 0.973292 0.59011 +-0.815357 0.00406678 0.781357 -0.772359 0.270754 0.888258 0.359646 0.399655 +-0.113866 -0.884301 -0.958318 -0.32709 0.840044 -0.628694 0.628969 -0.204064 +-0.438121 -0.670837 0.590836 -0.805603 -0.007223 0.575179 -0.82525 0.826362 +-0.547629 -0.954535 -0.644461 -0.955827 -0.766725 -0.351031 0.903685 -0.599275 +0.854089 -0.314952 0.0995219 0.0699437 -0.669311 0.942229 0.149795 0.537265 +0.309702 -0.824829 -0.548082 0.206617 -0.725008 0.180603 0.580146 0.615781 +-0.854342 0.479803 -0.9838 -0.099605 -0.763394 0.237341 0.934116 -0.420095 +0.115805 -0.208419 -0.087311 0.129972 -0.563641 -0.421101 -0.970127 0.137739 +0.44262 -0.177393 0.167527 -0.692812 0.599586 -0.743865 -0.772632 -0.176744 +-0.549924 -0.368415 0.30554 0.353603 -0.123664 -0.352592 0.847888 0.423067 +-0.413168 -0.0570652 0.847956 -0.918095 -0.741655 0.462271 -0.679351 -0.111826 +0.287593 0.46235 -0.579968 0.335121 0.6549 0.460653 -0.167511 0.622548 +-0.672489 0.443283 -0.203378 -0.216303 0.0656424 0.964999 0.400008 0.477621 +0.207475 -0.961349 -0.262596 -0.731828 -0.506035 -0.999647 0.751166 -0.764657 +0.467351 -0.367681 -0.953751 0.359332 0.754394 -0.999689 -0.531382 -0.871787 +0.250477 -0.796916 0.423656 0.909619 0.553729 -0.122082 0.977349 -0.467007 +0.520121 0.95428 -0.410991 -0.409846 0.546661 0.840189 -0.915785 0.98718 +-0.18025 -0.607312 0.0637037 0.37189 -0.847285 -0.180727 0.508935 -0.30391 +0.643897 0.352201 -0.662156 -0.883445 -0.235406 0.303709 -0.568661 -0.853786 +0.555629 -0.404865 -0.93202 0.41341 -0.61751 -0.304193 0.857318 0.10947 +0.712673 -0.808243 -0.0434287 0.0282617 0.200517 -0.420758 -0.663233 -0.804838 +-0.477177 0.173882 -0.980349 -0.973668 0.196806 -0.165048 0.889967 -0.527342 +-0.189642 0.0841829 -0.158568 0.690367 -0.68358 0.333694 0.835314 -0.687871 +-0.711753 -0.443409 0.998708 0.174378 0.91963 -0.664183 -0.811339 -0.656113 +0.0287801 0.0142831 0.551603 0.962091 -0.00350028 -0.531681 0.525424 0.25806 +-0.458069 0.485684 -0.0619558 0.833071 0.0482247 0.535973 -0.236037 0.867441 +-0.023838 -0.0643108 -0.996132 -0.567693 0.440262 -0.103496 -0.527486 0.464781 +-0.698311 -0.296613 0.0111023 -0.488601 -0.659732 -0.738163 -0.963845 0.230247 +-0.908222 -0.299702 -0.642994 -0.55212 0.260429 -0.226378 0.913648 -0.365756 +0.437429 0.162903 -0.195237 0.531475 0.091433 0.282727 0.203729 0.00381281 +0.0990043 0.819328 -0.611776 0.123238 0.6737 0.398916 -0.234533 -0.337256 +0.814935 -0.153293 -0.76881 0.169639 -0.338824 -0.85024 -0.273738 -0.613287 +-0.210824 -0.627221 -0.541288 -0.0872546 0.389206 0.701921 -0.782778 0.79226 +-0.909832 -0.215319 0.660727 0.775423 -0.372287 0.624207 -0.637745 0.932302 +0.842689 -0.874822 0.0611899 0.730969 -0.580852 -0.337593 0.67403 -0.244609 +0.22271 0.545747 -0.321391 0.866144 -0.615409 -0.860523 -0.670567 -0.749662 +-0.726717 0.681525 -0.87862 -0.620928 -0.606091 0.0870114 0.752608 0.857461 +-0.0590785 0.818145 -0.332715 0.360067 0.841109 0.216229 0.0631998 -0.885411 +0.955158 -0.937858 0.360506 -0.519713 -0.420515 -0.412394 0.668483 0.306322 +0.00551993 -0.873231 0.567241 -0.0486603 0.887307 0.0875648 0.479888 -0.155571 +0.904497 -0.342693 0.382679 -0.19778 0.53716 0.508197 -0.269558 -0.792825 +0.52473 -0.304597 -0.224985 0.751555 0.353214 -0.999656 0.783507 0.413489 +0.80228 0.66089 -0.584213 -0.968646 0.498895 0.162749 -0.338572 0.816104 +-0.557026 0.883686 0.343095 0.334774 0.344759 0.755417 0.136652 -0.945347 +-0.416951 -0.878276 -0.971276 -0.830583 0.798158 -0.499066 0.237057 0.266891 +-0.760204 0.386817 0.558751 0.27612 -0.285203 -0.0346366 -0.97617 0.0346681 +-0.146884 0.400747 -0.0775784 0.900523 0.017959 0.649192 -0.478388 0.674617 +0.74203 0.950873 0.685794 -0.64869 0.540257 0.513511 0.138377 0.322264 +-0.727548 0.706718 -0.000295323 0.629921 0.396159 -0.73155 -0.172958 0.0498129 +-0.878049 -0.118984 -0.213529 0.759694 0.833882 0.731587 0.97162 -0.613445 +-0.491061 0.196977 0.356361 -0.742985 -0.945365 0.274974 -0.489835 0.625618 +-0.630478 -0.36574 0.463239 -0.116383 0.783928 0.979597 -0.947382 0.560773 +-0.33433 0.104791 0.744223 -0.622755 0.0544037 0.687749 -0.376238 -0.977356 +0.530733 -0.95224 -0.583356 -0.262283 -0.837691 -0.114288 -0.498621 0.398882 +-0.85912 0.775853 0.96867 0.873247 -0.597385 -0.258265 -0.469445 -0.541538 +-0.657603 0.994144 -0.518487 0.717148 0.357168 0.781278 0.366237 -0.91158 +0.66088 0.979942 -0.0887133 -0.708632 0.394368 0.691787 -0.0560976 0.0170481 +0.421953 0.0205685 -0.456769 0.384411 -0.558128 -0.0706432 -0.337617 0.425415 +0.825493 -0.570805 -0.197645 0.826435 -0.975019 0.0510593 0.31627 -0.0646259 +-0.341256 -0.966377 -0.388371 -0.530386 -0.940404 -0.291 0.621017 0.938019 +0.207462 -0.835385 -0.933832 0.802338 0.576419 0.876296 -0.0189136 -0.62584 +0.566295 -0.204288 0.381545 -0.957756 0.229146 0.911575 -0.273125 -0.86176 +-0.159784 0.118258 -0.0928733 0.908685 -0.75321 0.17539 0.9311 0.919689 +-0.895679 -0.869722 -0.305613 0.978413 -0.260642 -0.22097 0.0108463 0.464738 +-0.921535 0.531013 -0.89864 -0.181785 -0.987569 -0.301404 -0.462394 0.0737861 +0.275929 -0.76026 0.881128 -0.806603 -0.375909 -0.117435 -0.324399 0.734031 +0.199174 0.951772 -0.786122 -0.469441 -0.660992 -0.839116 0.227365 -0.330594 +0.490465 -0.898334 0.179136 -0.984101 0.140673 0.909234 0.331808 0.915265 +0.0119734 0.416263 0.976076 0.496574 0.495028 0.0999223 0.712925 -0.870446 +0.00638765 0.296281 0.926079 -0.487033 0.584958 -0.50556 -0.439026 0.833546 +0.630958 -0.596538 0.605977 0.0390853 0.720553 0.89873 -0.543126 -0.975361 +-0.748472 0.0475716 -0.529878 -0.430742 -0.397697 -0.0979335 -0.674655 0.399633 +-0.48724 0.549792 0.658135 -0.309457 -0.883989 -0.732573 0.226791 0.930981 +0.332137 0.11424 -0.839425 -0.51136 -0.177398 0.102265 0.13192 -0.0157651 +-0.0631248 -0.227487 0.380461 -0.0747341 -0.61549 -0.529484 0.299037 0.690554 +-0.682568 0.532712 -0.0527239 -0.420051 0.867505 -0.599011 -0.0133785 -0.554751 +-0.859661 -0.463941 0.418014 -0.706624 0.611324 -0.157146 -0.279821 0.827332 +0.409209 -0.439493 0.0758388 -0.201192 -0.989339 -0.671252 0.649598 -0.763886 +-0.914459 -0.531413 0.484629 -0.590613 0.333156 -0.369144 -0.667669 0.831709 +-0.0354539 -0.354733 -0.36816 -0.664978 -0.657856 0.397374 0.136192 0.849048 +-0.187504 0.806837 -0.606356 0.617539 -0.66631 0.475744 -0.214508 0.0036764 +0.217461 0.652098 0.448925 -0.427721 0.0810363 0.467725 -0.360456 -0.857412 +-0.574992 -0.526611 -0.635704 -0.546381 -0.0412227 -0.340441 0.649255 -0.361588 +-0.674937 0.380113 -0.0846294 -0.94479 0.798474 0.402347 0.19684 0.536886 +-0.675463 -0.145289 -0.374791 0.953359 0.81581 0.498523 0.309522 0.0254998 +0.959249 0.559139 0.0918515 -0.367284 -0.10403 -0.586723 0.628689 -0.179668 +-0.513358 -0.496821 -0.293347 -0.909988 -0.880276 -0.776228 -0.615681 0.497814 +-0.319152 0.116039 0.912388 -0.241796 -0.301361 -0.514832 -0.856162 -0.247559 +-0.925836 -0.392175 0.176942 0.595711 -0.172777 -0.787395 0.183967 0.739094 +0.0525105 -0.0792188 0.350732 0.3928 -0.712205 0.207856 -0.768793 0.254312 +-0.141179 -0.219261 -0.260389 -0.16628 0.726619 0.475262 0.264393 -0.873328 +-0.850199 -0.00897556 -0.188208 -0.269785 0.461309 0.815468 0.420283 -0.807427 +-0.203922 0.784878 -0.0223819 0.962732 0.933451 0.441232 -0.0194445 -0.0915435 +-0.305227 -0.065699 0.800444 0.588996 -0.981894 -0.325637 -0.900863 0.437637 +-0.932576 -0.402177 -0.17346 0.634145 -0.0238627 0.963023 -0.697048 -0.351221 +-0.287877 -0.79217 0.760758 0.751295 0.660071 0.252603 -0.976328 -0.0297105 +-0.0206815 0.53749 -0.924362 0.92181 -0.442592 -0.605057 -0.450468 0.572781 +0.872323 -0.262186 -0.471666 -0.801154 -0.109649 0.101526 0.593327 -0.357968 +-0.426648 -0.874541 0.306597 -0.978336 0.149578 -0.158159 -0.398312 0.0457713 +-0.835031 0.381016 0.301201 0.472713 -0.147695 0.233435 0.72058 -0.178571 +0.38076 -0.0232382 -0.0441087 0.293799 -0.503988 0.688588 -0.275395 -0.476685 +0.529689 -0.941966 -0.669545 0.614952 0.318608 0.0132478 0.140862 -0.212678 +-0.423667 -0.677594 0.59492 -0.305622 -0.237802 -0.470778 0.0884266 0.535806 +0.797109 -0.145284 0.136003 0.334246 0.848925 0.900752 0.585877 -0.112343 +-0.192336 -0.908105 -0.334296 -0.715652 0.879834 -0.402718 -0.872987 0.296066 +-0.653681 -0.184739 0.940983 0.209873 0.544847 0.282653 0.339019 -0.428972 +-0.194294 -0.0596286 -0.810739 0.726835 0.451793 -0.707472 -0.950164 -0.236336 +0.637462 -0.256761 -0.670492 -0.193041 -0.915003 -0.731883 0.0366833 -0.245979 +-0.105886 0.743982 -0.740773 -0.865156 -0.87489 0.848912 0.523122 0.946026 +0.943791 0.325707 -0.671541 0.375961 -0.77914 0.430596 -0.032457 0.605194 +-0.416813 0.324276 0.131722 -0.258272 0.233975 -0.837174 0.594033 -0.505245 +0.817084 0.530562 -0.549989 0.444467 0.369909 -0.963979 0.301724 -0.0409435 +0.291737 0.278037 -0.110433 -0.692999 0.195792 0.158968 0.153503 0.196956 +0.0469962 0.823191 0.500532 0.255422 -0.840759 -0.393582 0.875076 0.992727 +-0.87556 0.237767 -0.912181 0.542862 0.163611 -0.453662 0.668599 -0.0388426 +0.509496 0.187931 0.693408 0.267075 0.047769 0.67806 0.273793 -0.90513 +0.941115 0.58601 -0.337077 -0.9097 0.450873 0.0433947 0.742621 0.913492 +-0.351252 -0.270526 -0.017284 0.292235 0.708252 -0.35782 0.313049 -0.47276 +-0.541737 0.477614 0.914302 0.187172 0.94786 -0.782811 -0.590241 0.803465 +0.435025 -0.298838 0.966699 0.491255 0.315439 0.61704 -0.395228 -0.392824 +0.0618606 0.597891 0.787649 -0.20335 0.281462 -0.341359 0.857565 -0.417426 +0.612807 0.878532 0.54191 -0.91607 0.910597 0.944217 0.28692 -0.872627 +-0.252343 0.483845 0.558156 0.837132 -0.354361 -0.824163 -0.0468551 0.598785 +0.458753 0.509112 -0.107625 0.358408 -0.773761 0.920507 0.5133 0.0146401 +0.509639 -0.86449 -0.980457 0.734108 0.190015 0.447651 -0.797752 -0.151256 +0.360296 0.0602842 -0.158694 0.522549 0.5189 0.105209 -0.804607 0.086694 +-0.652952 -0.91206 0.793921 -0.820705 -0.486369 0.0957001 0.426589 0.868367 +0.53759 -0.900937 -0.408052 0.440422 0.931243 -0.939854 0.697158 0.11263 +0.477773 0.598425 0.387298 -0.300583 0.593027 0.204957 0.279418 0.654208 +0.97629 -0.725834 -0.961116 0.794761 -0.262701 -0.494546 0.105579 -0.491426 +0.492469 0.610988 -0.318709 -0.0778782 -0.844701 0.345592 -0.564935 0.97157 +-0.572702 0.185061 0.297169 -0.0994182 -0.00171426 -0.524556 0.89236 -0.18742 +-0.920791 0.840442 -0.438821 0.255716 0.491834 -0.915584 -0.0704714 -0.0883544 +0.189995 -0.134067 0.97846 -0.787238 -0.106828 0.518955 -0.0981396 0.8735 +0.307827 -0.141964 -0.618969 0.390996 -0.845153 0.720349 -0.585495 -0.470719 +0.860287 0.957916 0.716103 0.645734 -0.443912 0.728765 -0.969215 -0.632284 +-0.630021 0.101462 0.505277 -0.31435 0.668509 0.262507 0.604366 -0.172558 +0.772381 0.101686 -0.207645 -0.649582 0.0250132 0.734477 0.646272 0.88122 +-0.97247 -0.124273 0.376311 0.202495 0.241541 -0.249191 0.274259 0.865586 +-0.488333 0.124564 -0.0907398 0.851215 -0.817624 -0.456055 0.178095 0.490173 +0.423917 0.385585 -0.351425 0.518931 0.852271 0.457764 0.622485 -0.757424 +0.429632 -0.0673521 -0.986684 -0.915105 -0.18279 -0.0054937 0.369554 -0.0413534 +-0.259525 -0.900449 0.869191 0.383346 -0.588504 0.0464366 -0.331381 -0.603107 +-0.0421066 0.521706 -0.457787 -0.859707 0.121332 -0.688289 -0.627297 0.147912 +-0.728273 -0.327037 -0.797175 0.124753 0.607685 0.515823 0.467392 0.624953 +0.64195 -0.921966 0.923367 -0.0103251 0.274991 -0.719075 0.666047 0.609565 +0.418002 0.0575557 0.185757 -0.440775 0.916628 -0.329855 0.139507 -0.459667 +-0.304674 0.664609 -0.687229 0.254551 -0.12832 0.225946 0.336273 -0.859519 +-0.746536 -0.479471 -0.48817 -0.720331 0.466456 -0.533169 0.349399 0.599752 +-0.0693433 -0.66859 -0.879882 -0.599289 0.237562 0.877683 -0.689928 0.312201 +-0.0717741 0.936356 0.287193 0.598347 0.280962 -0.415179 -0.631889 -0.759308 +-0.476299 0.500561 -0.389283 0.0752255 -0.823881 -0.629974 -0.777593 0.589724 +0.16367 -0.901747 0.137909 -0.200179 -0.310539 -0.730002 -0.753454 0.221545 +-0.823618 0.71099 0.120062 0.94313 -0.540315 -0.174294 0.0997371 -0.303804 +0.229812 0.166168 0.0178043 0.381846 -0.180521 0.73516 0.403749 -0.395635 +0.0992278 0.330474 -0.581984 -0.138663 -0.617203 -0.135819 0.600691 0.0268797 +-0.867314 -0.584255 0.809209 0.329158 0.90545 0.1753 -0.400219 -0.820276 +0.889715 -0.615202 0.422693 -0.512655 -0.28159 0.688616 0.16942 0.915295 +-0.161029 -0.515813 0.783674 -0.0141777 -0.208935 0.24286 -0.581803 0.900997 +-0.293134 -0.926263 0.11065 0.889701 -0.196972 0.240469 0.0977642 -0.269138 +0.947799 -0.692088 -0.0539804 0.98837 -0.0416007 0.883438 -0.574093 0.762027 +-0.753382 -0.476178 -0.120212 -0.250303 0.819984 -0.35557 -0.724674 -0.062026 +0.172574 -0.24731 0.490383 0.534608 -0.507587 -0.114624 0.343643 0.664548 +0.495146 -0.904574 -0.595895 0.768859 0.559969 0.467195 -0.774944 -0.95477 +-0.496379 -0.641125 0.517243 -0.275505 0.684218 -0.632928 0.711154 -0.404151 +0.384641 0.584677 -0.0372261 -0.243059 -0.511208 0.586556 -0.907605 -0.916789 +-0.765877 0.416646 -0.193778 0.299936 0.0225621 -0.559503 -0.502178 -0.568158 +-0.172914 -0.717633 -0.802751 0.0825455 0.629485 0.0559055 0.603573 -0.372429 +-0.433832 0.562259 0.441644 0.0365981 0.571727 -0.35747 -0.903666 0.170439 +-0.0182899 0.582303 0.396927 0.490243 0.428688 0.826028 -0.769244 0.131322 +-0.0649736 -0.486877 0.307647 -0.282122 0.00321377 -0.278147 0.188783 -0.79282 +-0.461419 0.0587373 0.00863312 -0.836072 0.982549 -0.9016 0.212936 0.769096 +-0.145638 0.854439 -0.722917 -0.676676 0.549161 0.770368 0.173006 -0.11283 +-0.285712 0.358843 0.35235 -0.10454 0.691551 -0.251248 0.720999 -0.941685 +-0.298927 -0.697801 -0.450239 0.780919 -0.708458 -0.815036 -0.271314 0.457595 +0.791149 -0.843316 0.986323 -0.546781 -0.255032 -0.426204 -0.280213 0.992756 +0.409801 -0.670451 0.40012 -0.39183 -0.345477 -0.42522 -0.966631 0.786546 +-0.312445 -0.0309838 -0.554719 0.140774 0.273426 0.832503 -0.157708 -0.171821 +0.876955 0.827097 0.328969 0.488356 -0.144097 -0.996807 -0.356181 -0.611194 +0.58955 -0.0291045 -0.332825 -0.197394 0.425674 -0.699252 0.642559 -0.794596 +-0.529947 -0.0193539 0.98977 -0.353262 -0.42003 -0.0451023 0.746347 -0.644907 +0.626559 0.780302 -0.308995 0.229609 -0.366871 -0.362754 -0.0219739 0.366236 +-0.820737 0.242969 0.358432 -0.452546 -0.731564 0.431045 -0.976861 0.198892 +-0.376432 0.77431 0.649057 0.319377 -0.850052 -0.58928 0.0156763 -0.812998 +-0.493896 0.41896 -0.517035 -0.811271 0.40643 -0.23912 -0.356455 0.6641 +-0.41023 0.700385 0.737752 -0.644895 -0.0700061 0.171841 -0.712709 0.679685 +0.538251 -0.777821 -0.00789328 0.261929 -0.679857 0.744825 -0.789269 -0.806872 +-0.232583 -0.195067 0.392618 -0.953142 -0.0904066 0.264567 0.543454 0.863769 +0.290802 -0.0484524 0.212338 0.70878 0.594766 -0.970906 0.383978 -0.11893 +0.857453 -0.598519 0.700796 -0.637398 -0.947281 -0.287379 -0.68622 -0.578451 +0.61569 -0.0413152 0.189581 -0.025467 0.591727 -0.384784 0.507341 -0.200527 +-0.327361 0.216689 0.278828 -0.610616 -0.924084 0.571235 0.658218 -0.0680971 +0.369076 -0.508041 0.07053 0.444586 0.423478 -0.771579 -0.973658 -0.133692 +0.689909 0.288778 -0.00930822 -0.40316 0.0746928 -0.730177 -0.455322 0.308062 +-0.75867 -0.902211 -0.767175 -0.50214 0.067032 -0.196716 -0.721929 -0.217908 +-0.418515 -0.0892808 0.334449 -0.530416 0.275294 0.628504 -0.519566 -0.494369 +-0.805554 -0.36026 0.697411 0.742628 0.980818 -0.986554 0.618374 -0.362962 +-0.781809 0.252234 -0.938689 0.307694 0.114816 0.43207 0.371939 -0.700677 +0.530469 -0.880949 -0.927973 -0.948703 0.888111 0.513933 0.541723 -0.232608 +-0.634947 0.83015 -0.854609 -0.868864 -0.741456 0.315889 0.372722 -0.512462 +-0.526706 -0.967388 -0.395551 0.967151 0.180373 -0.285083 -0.712694 -0.527483 +0.826659 0.197001 0.168898 0.802458 0.683358 0.603025 0.696586 0.786815 +-0.399333 0.491316 0.156492 0.155273 -0.664144 -0.0482588 0.715768 -0.964983 +-0.347052 0.276578 -0.427049 -0.665851 0.376211 -0.133866 0.833013 0.84972 +-0.550404 0.293952 -0.652923 0.263592 -0.66903 0.908735 0.13017 -0.207125 +0.558522 0.0243762 -0.252566 0.425635 0.970293 0.201025 -0.933472 0.485181 +0.418512 0.973218 0.934906 -0.851058 -0.923213 -0.00528692 0.663163 0.336733 +0.300305 -0.449919 -0.917818 0.56312 -0.846321 -0.209079 0.420273 0.414711 +-0.534024 0.782551 -0.195787 0.633653 -0.618581 -0.0647479 -0.559319 -0.689941 +0.118928 0.136822 -0.0326385 -0.767448 -0.983201 -0.608737 -0.538138 -0.771818 +0.0642788 -0.23575 -0.955825 0.531643 0.896696 -0.93714 -0.743735 0.83404 +-0.759699 -0.307215 0.897355 -0.912848 -0.202901 -0.503434 -0.127725 0.657111 +0.588039 0.642811 0.798735 -0.357405 0.429553 -0.8095 0.142669 0.281876 +0.731616 -0.745817 0.687116 -0.963179 -0.202882 -0.560052 0.219008 -0.577207 +0.171463 -0.789992 -0.26166 0.148791 -0.461787 -0.620984 0.800754 -0.533135 +0.146333 0.133831 0.129373 -0.38419 -0.852851 -0.963873 -0.754177 0.450762 +-0.0854603 0.463209 0.162718 0.14919 -0.398727 0.0412205 -0.741961 0.344254 +0.648451 0.533531 -0.305557 0.943382 0.259429 0.35427 -0.170163 -0.687101 +-0.384459 0.862088 -0.538926 -0.0551781 -0.162722 -0.610804 -0.342109 0.922671 +-0.707937 0.290735 0.500182 -0.917945 0.0717458 0.131323 -0.568289 -0.723669 +-0.821583 0.919702 -0.380865 -0.0226084 -0.0980169 -0.397053 -0.563419 0.710794 +0.933331 -0.210902 0.145008 -0.830874 0.545921 -0.766231 0.70935 0.380556 +-0.118949 0.833075 -0.138143 0.388361 0.294505 0.307174 -0.122785 0.242586 +-0.989216 0.278074 0.944563 -0.887136 -0.495663 0.0860985 -0.365618 0.539404 +0.327773 -0.00732701 -0.453755 0.49406 0.660355 -0.33187 0.600803 0.460809 +-0.823785 0.387044 0.260448 0.539937 -0.544437 -0.772416 0.882615 0.984641 +0.374367 0.764354 -0.356019 -0.124537 0.879582 -0.492949 -0.0903574 0.798317 +0.995688 0.216409 0.996199 0.896376 -0.227497 0.438396 -0.629191 0.420907 +-0.653814 0.570553 0.109743 -0.133596 -0.481663 0.863684 0.35997 -0.985733 +0.877632 -0.193981 0.700456 -0.519204 -0.0232916 0.408009 0.420762 0.891245 +0.32699 -0.195468 -0.745174 0.669308 0.567984 0.125155 0.369705 0.586686 +0.350518 0.857318 0.235782 -0.0613923 0.930641 0.442481 -0.0804044 -0.710929 +-0.160918 -0.982138 -0.358503 -0.523143 0.300813 -0.429542 -0.209023 0.313505 +-0.96121 -0.735214 0.238155 0.770734 -0.797954 0.685873 -0.435539 -0.481711 +0.226573 -0.947087 0.483706 0.88208 -0.280183 0.838936 -0.29229 0.391445 +-0.908792 0.486889 0.217232 -0.822105 0.414924 -0.482778 0.676449 0.183816 +0.0442115 0.623602 -0.65238 0.278868 -0.0683481 -0.255748 -0.937132 -0.459009 +0.863573 0.615655 -0.315832 0.0756595 -0.984566 -0.196992 -0.69228 0.814119 +-0.349865 -0.339028 -0.898581 0.673827 -0.976803 -0.226884 -0.38377 0.208712 +-0.399204 0.283016 0.270532 -0.602491 0.505236 0.957699 -0.688275 0.0937528 +-0.362006 -0.180131 -0.00592082 -0.640728 0.261582 0.991148 -0.900273 -0.806972 +0.583159 0.246894 -0.333407 -0.949928 0.864219 -0.751779 0.691914 0.384194 +0.519467 0.975468 0.330569 -0.90671 0.876544 0.528413 -0.257303 -0.443693 +0.975573 0.761322 0.906247 -0.379877 -0.301486 0.88182 -0.270344 -0.0292251 +0.133132 0.527226 0.684918 0.763549 -0.154507 0.694995 0.568294 -0.583042 +0.703709 0.335868 -0.598098 0.939269 -0.985655 -0.51328 0.666223 -0.134206 +-0.993873 -0.0213064 0.558352 0.758266 0.0838586 0.83138 -0.29162 -0.224693 +-0.0316652 -0.193959 -0.22978 0.317311 0.36578 0.515929 -0.0359695 -0.285163 +0.912247 -0.53452 0.973823 0.231653 -0.736281 -0.0860418 -0.834986 -0.790922 +-0.577686 -0.576915 -0.0706287 0.202458 0.782071 -0.625289 -0.776728 0.0224522 +-0.707905 0.50783 -0.061236 -0.617065 -0.618228 -0.131832 -0.153148 0.942724 +0.360483 -0.871978 0.993859 0.114053 0.757332 0.386036 -0.361646 0.207122 +0.908065 0.830837 0.869343 -0.73375 0.928219 -0.464749 -0.571267 0.586814 +-0.341393 -0.627896 -0.264869 -0.585668 0.700693 0.094233 0.20721 0.479512 +-0.457757 -0.473789 0.576526 0.301305 0.574675 -0.883921 0.449592 0.0104652 +0.138251 0.49342 -0.17178 -0.56035 -0.762154 -0.121695 -0.563466 -0.339857 +0.406129 -0.857286 -0.290089 0.12217 -0.820902 -0.73995 -0.321759 -0.956618 +-0.0963213 -0.5873 0.645211 -0.0321442 0.133028 0.918141 -0.628066 -0.916372 +0.0722743 -0.914343 0.414923 0.546207 -0.107927 -0.494056 -0.643561 0.900971 +-0.249978 -0.145655 -0.814521 0.0326581 0.231742 0.836964 -0.941829 -0.804002 +0.574748 0.744282 -0.485392 -0.812953 -0.441999 -0.373936 0.301269 -0.338922 +0.219447 0.0117936 -0.441458 0.803417 -0.335385 -0.690639 -0.478367 0.307749 +0.132945 0.488976 0.135689 0.0114681 -0.025846 -0.599261 0.326764 -0.935265 +-0.363688 0.695589 -0.5346 -0.407649 0.981315 0.0246431 -0.527814 0.230187 +-0.875594 0.456132 -0.888954 -0.698443 -0.217489 -0.475568 0.0283053 0.889665 +-0.0128877 0.291354 0.546735 0.0149985 0.383543 -0.842329 0.701909 -0.570953 +-0.571183 0.999504 -0.122796 -0.961091 -0.891756 0.71844 -0.0322515 -0.0286555 +0.82554 0.507298 -0.134212 -0.0271159 -0.977184 0.319353 0.531244 0.676701 +0.459324 -0.53799 0.985868 -0.836446 -0.0763077 -0.135364 0.450683 0.898561 +0.648359 0.841209 -0.551843 -0.860345 0.270765 0.326527 -0.879455 0.606743 +-0.402212 0.427867 0.314495 0.436551 -0.918564 -0.38591 0.796554 0.613382 +0.302905 -0.495404 -0.523858 -0.104942 -0.363109 -0.583927 -0.972001 0.0532944 +0.57196 0.904289 0.0753444 0.932419 -0.375329 -0.864336 0.610242 0.694952 +-0.0443916 0.933443 0.92164 0.496693 0.104307 0.0601594 -0.965775 -0.0209767 +0.898485 -0.622735 -0.780745 0.850789 -0.766448 0.29336 -0.335751 0.598825 +0.185243 -0.417636 0.618871 -0.00301566 -0.522258 0.593437 0.548895 0.895387 +-0.717995 0.370277 0.364839 -0.995687 -0.34362 0.16334 0.0853892 -0.909615 +-0.664666 -0.751413 -0.577684 -0.726584 0.560147 0.913928 0.906507 0.918903 +-0.784676 0.796495 0.24843 0.758365 0.648675 0.446033 -0.661835 0.229135 +-0.218507 -0.842401 -0.94384 -0.340522 -0.567136 -0.0856874 0.249805 0.851357 +-0.419823 0.868567 0.316477 0.601669 0.182882 0.744039 0.381101 -0.264542 +0.20937 -0.216538 0.995052 0.398241 -0.835791 0.128067 0.835295 0.871096 +0.68631 -0.67594 0.499961 0.819347 0.0212814 0.424364 0.225614 0.337487 +0.455317 -0.873514 -0.57145 -0.689051 0.94138 0.449968 -0.647846 -0.764756 +0.947225 0.408823 -0.923999 -0.326329 -0.724871 -0.818855 -0.691498 0.0741818 +0.324278 -0.937081 -0.887451 0.609746 -0.796141 -0.0630527 -0.475713 -0.148614 +-0.218216 0.577573 -0.328165 -0.74413 0.539602 -0.320021 0.16646 0.732442 +0.914569 -0.247973 0.322736 -0.646617 -0.465801 -0.225577 0.343479 -0.18574 +-0.622274 0.509186 0.16363 0.474264 0.247911 -0.0491472 -0.337898 -0.773024 +-0.455746 0.925947 0.271179 0.157244 0.918011 0.816703 0.723029 -0.407765 +0.135431 0.207946 0.454171 0.150807 0.39808 -0.181156 0.662142 0.998837 +-0.170967 -0.262359 -0.352112 -0.862965 -0.722295 0.0390601 -0.383904 -0.561961 +-0.500291 -0.300887 -0.140161 0.443431 0.973627 -0.793971 0.31385 -0.409709 +-0.437718 0.280706 0.0449257 0.581218 0.0743008 -0.506769 -0.858017 0.947134 +-0.162883 0.12211 0.58106 -0.967633 0.00458991 0.879703 -0.186182 0.447892 +0.49764 -0.700122 -0.0962428 -0.345036 0.12346 -0.431724 -0.186435 -0.522608 +-0.916139 0.0949659 -0.0479898 -0.178232 -0.838173 0.496476 -0.827512 -0.224191 +0.847845 -0.909976 -0.778024 0.428089 0.224087 0.0605156 0.825071 -0.676221 +-0.336896 -0.495372 -0.848476 0.650922 -0.65299 -0.0757912 0.131118 0.18207 +0.418753 0.124491 -0.185776 -0.428969 -0.305312 0.527287 -0.701612 0.600852 +0.568295 -0.835178 -0.839875 0.585269 0.659516 0.675947 -0.870419 -0.405351 +-0.0963861 0.0854124 0.0702742 0.0915023 -0.728222 0.508501 -0.429693 0.42044 +-0.76163 0.699498 -0.394918 0.609276 0.849858 -0.225132 -0.535513 -0.601581 +0.443189 0.845143 0.129504 0.899637 -0.495319 -0.521681 0.333595 0.313646 +0.197139 -0.5217 0.542349 0.00545544 -0.983832 -0.280804 -0.278377 0.772221 +0.375314 -0.336739 0.659778 0.613643 -0.98438 0.0728006 0.439172 0.412867 +0.0230588 -0.932134 0.73279 -0.349458 0.68099 -0.138023 -0.507766 -0.789176 +-0.503146 0.0273425 -0.555536 -0.519163 -0.058158 0.402099 -0.0639556 0.272505 +0.549357 0.364673 -0.956001 0.21719 -0.669472 -0.0098492 -0.258739 0.660656 +0.620616 0.407279 -0.113876 -0.52831 0.178259 0.162639 0.868408 -0.0754357 +-0.362482 0.159049 0.517145 -0.45285 -0.445442 0.289062 -0.253505 0.674218 +-0.357427 0.573968 0.310438 -0.313141 -0.405675 -0.611489 -0.0276639 -0.429119 +-0.668139 0.635528 0.593448 -0.183699 -0.156371 -0.437839 0.390206 -0.294725 +0.129772 -0.211686 -0.492115 -0.84819 0.387332 0.938125 0.218802 -0.830251 +0.474645 -0.988604 0.910576 -0.992808 -0.88129 0.312076 -0.106249 0.108644 +-0.345939 -0.385284 -0.300995 0.887221 -0.488168 -0.120372 0.086807 0.952477 +-0.531646 0.545158 0.997297 0.209956 0.127618 0.882957 0.522523 0.942717 +-0.652333 -0.376931 -0.353511 0.229265 -0.824008 0.188566 0.924286 0.360831 +0.863307 -0.518797 0.179152 -0.749976 0.411346 0.971809 -0.650945 0.569322 +0.407134 0.599725 0.559955 0.0969481 0.617985 0.634583 0.42873 -0.569662 +-0.800046 -0.00313865 -0.728843 0.36328 0.289795 -0.115441 0.792551 -0.518129 +0.777594 -0.612453 -0.240238 0.344502 -0.542242 0.221281 -0.888601 0.00326914 +0.360732 -0.682803 -0.107311 -0.928915 0.129344 -0.616168 -0.538422 -0.288398 +0.33447 -0.176508 -0.741403 0.372003 -0.879242 0.606991 -0.504806 0.724598 +0.311839 0.822131 -0.686503 0.253273 0.346116 -0.336598 0.363425 -0.774734 +-0.94456 0.141385 0.696468 -0.508014 0.474444 -0.206303 0.024932 0.730156 +-0.555203 -0.937368 -0.736873 -0.940357 0.41468 -0.317797 0.505206 -0.744362 +-0.047413 -0.168765 0.699887 -0.011384 -0.712655 -0.569805 0.509026 -0.527639 +0.0921165 -0.0872709 -0.63125 0.913504 -0.522371 -0.873718 0.774925 0.8211 +-0.835514 0.807243 -0.451478 0.562789 -0.648487 0.600922 -0.185889 0.443629 +0.138278 0.140251 -0.433804 0.911148 -0.986832 -0.643513 -0.73119 0.346114 +-0.14968 -0.870077 0.155331 0.432867 -0.245532 0.585842 -0.17101 -0.467997 +-0.174975 -0.191355 0.0111016 0.206618 -0.0788315 0.206557 0.700146 0.26407 +-0.599876 0.367874 0.554409 -0.678359 -0.434445 -0.0627907 0.866011 -0.631266 +0.40957 0.101284 -0.593199 -0.497476 0.734292 -0.048336 0.488333 -0.971627 +0.267436 0.860481 -0.110975 -0.547661 0.84888 -0.978113 0.177378 0.646281 +0.264242 -0.20734 -0.404393 -0.706742 -0.245965 -0.0312825 -0.177695 -0.590433 +-0.88398 -0.292129 0.652842 0.679528 0.714599 -0.31054 -0.955297 -0.180481 +0.108656 0.826234 0.574338 -0.666069 -0.0100122 0.0803361 0.162848 0.692929 +0.274484 0.683277 -0.938547 -0.490008 0.165304 0.269299 0.823205 -0.373988 +0.135267 0.963689 0.717366 -0.515998 -0.840342 -0.704418 0.248176 -0.920035 +0.658957 -0.859143 0.970355 -0.329009 -0.0468982 0.204005 -0.170679 0.540487 +-0.527316 0.520957 -0.358999 -0.925968 -0.945894 -0.997646 -0.991608 0.55757 +-0.817878 -0.503903 -0.487906 -0.0567896 0.193223 0.892943 -0.45561 0.700621 +-0.759023 0.0254688 -0.855266 0.874996 -0.645042 -0.551461 0.761377 -0.818556 +0.291934 0.905122 0.66748 -0.661038 -0.908079 -0.753333 -0.513899 -0.200027 +-0.962323 0.27371 0.895297 0.81511 -0.258531 -0.648807 0.979072 -0.884441 +-0.82089 -0.681966 -0.228665 0.51323 0.270095 0.87616 -0.638903 -0.951388 +-0.261658 0.43373 0.287688 -0.948697 0.549712 -0.438453 0.882343 0.107756 +-0.143884 0.941573 -0.733211 0.0388048 -0.227978 0.025673 -0.069112 -0.699991 +0.0481841 -0.986915 -0.0591436 -0.579039 -0.00163794 0.448317 -0.88231 -0.274336 +-0.0520785 -0.520813 0.587888 -0.0927612 0.564898 0.914219 -0.469238 -0.868434 +-0.689648 0.248501 -0.830505 -0.00817715 0.57733 -0.193782 0.640914 -0.770624 +0.604876 -0.600517 0.369522 -0.0248955 -0.803796 0.736926 0.235804 -0.114192 +-0.314167 0.029882 -0.0550515 0.902548 0.00129659 0.0887846 0.468247 -0.973941 +-0.125029 -0.822576 0.898125 0.149557 0.932975 0.299965 -0.825157 -0.881807 +-0.019497 0.520082 0.830331 0.613313 -0.712255 -0.293715 0.290778 0.910808 +-0.612102 0.442327 -0.826731 -0.586718 -0.745161 0.35706 0.496725 -0.337971 +-0.177036 0.143153 0.442151 0.315148 -0.0962316 -0.534935 0.251563 -0.573321 +-0.795171 0.356316 -0.110224 -0.772718 0.609462 -0.916863 0.156313 0.00807432 +0.51919 -0.688593 0.174565 0.330887 0.937521 0.119489 -0.029361 0.330447 +0.267624 0.0636108 -0.766347 0.0368321 -0.178892 0.754918 -0.584797 0.646224 +0.0543071 -0.244817 -0.133002 0.418942 0.156912 0.401098 -0.457923 -0.0086396 +0.31796 0.274109 -0.591155 -0.588633 0.53215 -0.803649 0.917343 -0.0162614 +-0.748638 0.358657 0.0837448 0.412766 0.628267 0.987513 -0.393735 -0.0351636 +0.340234 0.160149 -0.422025 0.929521 0.150872 -0.185484 0.644958 0.399877 +0.369833 0.622548 -0.746154 0.576763 -0.24731 -0.221174 0.990903 0.196575 +-0.374449 -0.308648 0.572227 -0.51462 -0.993824 0.528717 0.864524 -0.982967 +0.375885 0.907404 0.759051 -0.413531 -0.569807 -0.301615 -0.487152 0.0736406 +-0.0547878 -0.567737 0.868215 0.726428 0.939528 -0.613973 -0.151486 -0.143228 +0.774938 -0.315413 -0.592695 -0.55891 0.740951 -0.956491 -0.0730064 -0.0338408 +-0.337309 -0.0691164 0.338541 0.999386 -0.0193022 0.677588 0.734364 -0.856655 +-0.028869 -0.752533 -0.453042 0.274491 -0.637134 -0.398187 -0.272979 -0.430847 +-0.673989 -0.286274 -0.562854 0.12427 0.0936976 0.965523 -0.82514 -0.49618 +0.770816 0.680283 -0.897072 0.501658 -0.617746 -0.586719 -0.798991 -0.136963 +0.236992 -0.614045 0.173716 -0.0687633 -0.446663 -0.79013 -0.328581 0.215918 +0.493988 -0.932995 -0.30012 -0.678104 -0.818305 -0.251725 0.0404109 0.767502 +0.92366 0.596716 0.529179 0.69413 -0.228518 0.821449 0.382839 -0.0813092 +-0.381741 0.980686 -0.408197 0.108125 -0.707274 -0.134126 -0.610366 -0.228834 +0.78183 -0.91614 0.500856 0.750621 0.544451 0.905196 -0.32836 -0.978336 +0.421739 -0.272365 -0.537244 0.79915 0.673203 -0.529353 0.328073 -0.6235 +-0.312532 -0.708554 -0.077073 0.70549 -0.0736282 -0.933252 -0.768467 -0.795785 +-0.605335 0.722372 -0.143753 -0.83284 -0.787781 -0.474113 -0.484129 -0.957288 +-0.29693 0.879444 0.245028 -0.304153 0.861379 0.416688 -0.231506 0.595379 +-0.819934 0.0964443 -0.702166 0.279822 0.6926 0.64321 -0.00340714 -0.504682 +-0.623415 0.140376 0.517706 0.813064 -0.0192871 -0.225431 0.851822 -0.311111 +0.906409 -0.463039 -0.125906 -0.326015 0.461082 -0.345953 -0.711728 0.454559 +-0.463604 -0.506316 -0.95116 -0.773319 0.288355 0.75944 -0.606086 -0.826483 +0.25271 -0.9609 0.945414 0.329588 0.374626 -0.145722 0.355244 0.951757 +-0.0978388 0.0883752 0.819972 -0.346529 -0.701948 0.493288 -0.484703 -0.277412 +0.752528 0.81242 -0.91897 0.369705 -0.87697 -0.705945 -0.149767 0.801977 +0.220821 -0.327548 -0.875952 0.101745 0.179896 -0.161492 -0.536122 0.681313 +-0.49327 0.614592 0.670578 -0.884864 0.518873 -0.634202 0.632039 -0.132086 +0.606229 -0.487425 0.290243 0.890012 0.20712 0.648662 0.68404 -0.837515 +0.571455 0.935079 -0.366354 -0.815684 0.142722 -0.033437 -0.672339 0.38266 +0.302957 -0.546423 0.826827 -0.648203 -0.067578 -0.0800815 0.933293 -0.585709 +-0.880886 0.413273 0.500182 0.490237 -0.448977 0.505172 -0.712596 -0.649271 +-0.349604 0.104807 -0.559456 0.81238 0.0240454 -0.134857 -0.231669 0.714498 +0.121195 0.511282 -0.764937 0.3487 -0.230063 0.306971 0.721399 0.910368 +-0.164307 -0.964873 0.255116 0.18614 -0.0710032 0.847507 0.13844 -0.425006 +-0.0294202 -0.663732 0.391538 0.125527 0.865593 0.744081 0.983922 -0.196187 +-0.592124 0.761828 -0.993756 -0.0473521 -0.201354 0.819108 0.566071 -0.97679 +0.132186 -0.938286 -0.845578 0.509997 0.337286 -0.952651 0.205407 0.526075 +-0.805208 0.0574104 0.400985 0.838457 0.273258 -0.357216 -0.7291 -0.0218883 +-0.798725 0.293082 -0.83925 -0.405219 0.772495 -0.162703 0.776866 -0.0616743 +-0.718476 0.490894 0.922168 -0.234468 -0.864068 -0.726702 0.125183 -0.739661 +0.224734 -0.449467 0.860439 0.548208 -0.219997 0.413782 -0.0719829 -0.89865 +0.668905 0.140998 -0.237877 -0.245798 0.191338 0.624373 -0.514573 -0.610171 +-0.852263 -0.702425 -0.839297 -0.988417 0.616082 -0.317768 -0.490215 -0.964163 +-0.845807 0.818447 -0.0769468 0.149338 0.644181 0.775342 -0.986283 -0.842497 +0.461963 -0.751987 -0.186809 0.128579 0.567975 -0.00383664 -0.100185 -0.23146 +-0.676349 0.539082 -0.0532405 0.0730482 0.135735 -0.985184 -0.171993 -0.712114 +0.750988 -0.183431 -0.936489 0.809974 0.796974 -0.648548 0.928596 -0.0290144 +-0.764139 -0.574596 0.13775 0.163946 -0.0185631 -0.50541 -0.505162 0.337413 +0.169893 0.80255 0.0326267 -0.64676 0.591884 -0.931843 0.333031 -0.28657 +0.711617 0.566115 -0.873711 -0.447148 -0.837245 0.937222 -0.443066 0.916289 +0.857331 0.209462 -0.746399 -0.962531 -0.794518 -0.353599 0.333256 -0.399661 +0.124117 0.673644 -0.395684 -0.754722 -0.178277 0.200462 0.831671 0.229839 +-0.0436045 -0.130365 0.0559433 -0.238672 -0.741023 -0.314417 0.832164 0.49558 +0.629799 -0.019173 0.363436 -0.479682 -0.308177 -0.71409 0.175529 -0.0225631 +0.73007 -0.840835 0.0629785 0.685571 -0.902139 0.616732 0.0802994 0.758177 +-0.85408 -0.0471578 0.590884 -0.0601573 0.983901 0.99031 -0.123045 0.882654 +-0.0816098 0.619264 0.334403 0.588455 -0.603777 0.955431 -0.729233 0.541021 +-0.518286 0.739772 0.271152 -0.965414 0.0938647 0.138862 -0.490594 -0.741147 +0.560105 -0.41576 -0.805391 0.423555 -0.91956 0.677451 -0.203752 -0.711401 +0.0538332 0.745948 -0.903786 -0.804641 0.806175 0.803283 0.770014 0.614073 +0.363265 0.0423812 -0.612926 0.623838 0.544472 -0.480674 0.933129 -0.139225 +0.451303 0.349994 -0.559412 -0.153014 -0.489767 -0.777127 0.249253 -0.492274 +0.984653 0.891803 -0.532161 0.583266 0.500533 0.71927 0.372692 -0.356016 +0.242516 -0.323755 -0.0772472 0.774458 0.187239 -0.73274 0.00992747 0.136559 +-0.280286 0.720583 0.00711111 -0.800192 -0.18599 0.435274 0.867915 -0.938762 +-0.839105 0.432264 -0.0551969 -0.132463 0.677694 -0.152299 0.666318 -0.775609 +-0.696103 -0.207586 0.481987 0.718709 0.0788425 0.0415259 -0.719586 -0.264512 +0.685926 -0.93111 0.303224 0.964486 0.601764 0.334563 -0.00143469 -0.867682 +0.47876 0.917552 -0.187515 0.0117107 -0.0857956 -0.918814 -0.45574 0.323111 +-0.875695 0.550742 0.672556 -0.856563 -0.826559 -0.484963 0.657209 0.851605 +0.574605 0.575943 0.887362 -0.51758 -0.0200551 -0.347917 0.267176 -0.547546 +-0.918976 -0.591552 0.649176 -0.12985 -0.805604 0.173736 0.374882 -0.68857 +-0.21926 0.724924 0.195898 0.787601 -0.344664 -0.129131 0.322424 -0.535366 +0.525124 -0.603729 0.46486 0.203147 0.0071692 0.17777 0.195174 0.00580404 +-0.410431 0.968821 0.338612 0.419906 0.463063 -0.970917 0.57079 -0.498508 +-0.489366 0.477389 -0.578136 -0.823802 0.346119 0.264939 0.540363 0.530289 +-0.865168 -0.757669 -0.21785 -0.299619 -0.409155 0.507296 -0.774418 -0.658391 +0.313145 0.924497 0.310088 0.868992 0.68397 -0.340971 -0.993908 -0.521261 +-0.728798 -0.536925 -0.820468 0.34252 -0.285503 0.643448 -0.787477 0.456246 +-0.93774 0.415129 -0.76223 0.142001 0.839158 0.211896 0.571701 0.111681 +0.637235 0.74066 0.878211 -0.592206 -0.921065 0.0648644 0.937055 0.87811 +0.736866 0.564391 0.962762 0.191391 -0.216403 0.376728 -0.126834 -0.73718 +0.363034 -0.382508 -0.952172 0.0407933 -0.771018 0.0679968 0.193112 0.955135 +0.249875 -0.114678 -0.653656 0.630404 -0.655171 0.56021 -0.417841 0.404821 +0.516553 0.790057 -0.0447277 0.0893541 -0.61616 -0.120965 0.0667103 0.701047 +-0.138791 0.383357 -0.428867 -0.50136 0.753356 0.281848 0.329351 -0.251867 +-0.469273 0.932868 0.380054 -0.698884 0.865777 -0.541439 0.683625 -0.116086 +0.744073 0.0712213 -0.103272 0.290377 0.169962 0.390293 -0.421272 -0.132716 +-0.458002 0.255651 0.2176 -0.189844 -0.275522 0.269161 0.672978 -0.357882 +0.985702 -0.727281 0.177093 0.998714 -0.575635 -0.200188 -0.432139 -0.176382 +-0.782175 -0.283259 0.972121 0.682 0.0863075 0.673289 -0.364885 -0.969685 +-0.711504 0.909925 -0.665869 -0.730461 -0.0691128 -0.292889 -0.111506 -0.0508709 +-0.635981 -0.124585 0.275619 0.845636 0.189531 0.0483202 -0.726763 0.887665 +0.223439 -0.0510921 -0.636781 -0.596858 0.749651 -0.164003 0.382015 0.816413 +-0.74869 0.744953 0.121052 0.418714 -0.385632 -0.0246765 -0.269526 0.827996 +-0.568231 0.0798874 -0.342219 -0.845772 -0.790258 0.310717 0.202105 0.202828 +-0.323885 0.914455 -0.873757 0.270622 -0.418957 0.719904 0.597644 0.907295 +0.257158 -0.916077 0.603025 0.131385 0.0668849 -0.797673 0.589164 0.158948 +-0.0432224 0.433686 0.764993 0.19622 0.482428 0.324204 -0.360954 0.177113 +0.957828 0.780848 -0.39585 -0.302662 0.276713 -0.250807 0.497336 0.330121 +0.0917771 -0.239933 0.755576 -0.0689747 0.942656 0.851844 -0.768862 -0.284016 +-0.680781 -0.207689 0.687366 -0.27144 -0.839248 -0.687103 0.336797 -0.677944 +0.497782 -0.586443 -0.629759 -0.997223 -0.0645083 0.937243 0.623351 -0.70684 +-0.138731 -0.673768 0.649323 -0.592869 -0.342837 0.51589 -0.681159 0.892454 +-0.617808 0.797262 0.280719 0.105536 -0.539847 0.769287 0.071249 -0.74514 +-0.990808 -0.95357 -0.0156943 -0.756002 -0.560972 -0.126089 -0.887808 0.634765 +-0.338516 -0.208635 0.597976 0.0854396 0.012734 -0.785142 0.0792855 -0.880097 +-0.0764062 -0.745109 -0.992707 -0.36499 0.335626 0.855709 0.324398 0.586782 +0.19424 -0.233436 -0.629849 0.356724 0.239352 0.532618 0.414879 -0.333027 +-0.758608 0.274271 0.53069 0.404052 -0.866642 0.713566 -0.901068 0.134162 +0.779362 -0.148483 0.543867 0.352114 -0.873935 0.186967 0.455569 0.725477 +-0.724292 -0.614634 0.202163 0.707401 -0.131517 0.454659 -0.95477 0.599232 +-0.20645 -0.719682 0.910262 -0.498215 -0.105908 0.163284 -0.735948 -0.488258 +0.549961 -0.24555 -0.872877 0.247513 0.442833 -0.847675 -0.36074 0.64803 +-0.252879 -0.0200819 0.59895 -0.920402 0.354448 0.528694 0.548263 -0.92867 +-0.25331 0.499176 0.650107 -0.41606 -0.0754911 0.498998 0.38674 0.882336 +-0.339236 -0.922157 0.543701 0.385575 0.725525 -0.253489 0.021898 -0.0273315 +-0.765082 0.00328447 -0.523069 -0.608791 0.636323 0.811651 -0.532138 -0.329503 +0.829887 0.628225 -0.187006 0.225173 0.577276 -0.211055 -0.892871 -0.483464 +-0.854714 0.858207 -0.0122937 -0.658461 -0.400685 0.0794606 0.850258 -0.797366 +0.0412844 0.667351 0.0407451 0.470619 -0.603677 0.0745575 0.539431 -0.254839 +-0.627035 -0.391491 -0.93397 0.931188 -0.307649 -0.0688708 0.878511 0.195199 +0.39852 0.737091 0.968778 -0.913558 -0.152581 0.64097 0.516574 0.0750405 +-0.719413 -0.496848 -0.0895111 0.0880705 -0.868255 0.0107875 -0.35242 -0.313344 +0.968694 -0.355047 0.0447438 0.633007 -0.656497 0.730452 -0.729791 0.0827981 +0.148828 0.428359 0.255626 0.258297 0.732308 -0.766279 0.352883 0.633439 +-0.497561 0.313801 -0.320826 0.0157509 -0.212151 0.255642 -0.647177 -0.782837 +0.606544 0.340345 -0.711952 0.899099 -0.794337 0.895916 -0.52872 -0.57984 +-0.213266 0.276505 0.797944 -0.713508 0.50813 0.499895 0.326735 0.807792 +-0.709922 0.730355 -0.852953 -0.357618 -0.322249 0.847351 -0.0743483 0.862197 +-0.260705 0.591657 -0.338952 -0.736816 0.627804 0.760506 0.0370344 -0.935321 +-0.99483 0.591093 -0.214169 0.230625 -0.845151 0.67705 -0.587658 -0.956223 +-0.714011 -0.811036 0.328978 0.0862574 -0.102706 0.907204 0.51428 -0.950143 +0.825537 -0.47859 -0.832021 -0.371021 0.147028 0.829249 -0.460161 -0.579437 +0.78764 -0.443974 -0.875969 -0.146768 0.489363 -0.810822 -0.505045 0.0578246 +0.18689 -0.509896 0.599836 -0.957962 -0.222421 -0.594202 -0.795124 0.227071 +-0.582764 -0.481441 0.65536 0.670812 -0.853464 -0.405088 0.645927 -0.484566 +0.852138 0.965099 -0.541339 0.838131 -0.910702 0.331916 -0.985499 0.0882578 +-0.900796 0.546121 -0.917633 -0.205875 -0.691595 -0.906553 -0.736063 -0.825395 +0.200625 0.893539 -0.447126 0.992227 0.620585 -0.866923 -0.306836 -0.676149 +0.396613 -0.814164 0.689558 0.428812 0.904269 0.100758 0.428217 0.480116 +0.740828 -0.670401 0.470159 0.184116 0.269109 0.902811 0.0948181 0.105362 +-0.470444 0.704059 0.497044 -0.460645 0.28168 -0.401993 0.682203 -0.101029 +-0.315868 -0.794748 -0.33912 0.868196 0.321008 -0.72829 -0.950654 0.864021 +0.94353 -0.773946 -0.640697 -0.321068 -0.16959 0.120698 -0.34633 -0.576954 +-0.25532 0.396661 -0.324702 -0.20864 -0.196708 0.0595977 0.627613 -0.274521 +-0.1019 -0.0184179 0.813906 0.879106 -0.524246 -0.839458 -0.195182 0.762441 +-0.452872 -0.80778 -0.10844 -0.422918 0.117921 -0.157016 0.418023 -0.899701 +0.381207 0.770573 -0.160566 -0.803347 0.828906 -0.860895 -0.0287614 -0.120912 +-0.375971 -0.196977 0.99154 0.848828 0.709757 -0.941375 0.413689 0.129763 +-0.135432 0.058013 -0.481544 -0.956331 0.43369 -0.175228 0.352469 -0.45887 +-0.271131 -0.964791 0.493779 -0.688609 -0.0275484 0.857738 -0.461904 0.0176501 +-0.452812 0.21217 0.541749 -0.0785204 -0.0615199 -0.57467 0.930401 0.455529 +0.701331 -0.634906 -0.981788 -0.771684 -0.175897 -0.00150364 0.658368 -0.544372 +-0.852321 0.837309 -0.811165 0.927336 0.684412 0.60988 -0.432303 -0.408333 +-0.566062 0.0970141 0.508099 0.97831 0.407016 -0.775956 -0.68734 -0.34894 +0.975476 -0.685599 -0.423073 -0.739336 -0.569095 -0.9524 0.934161 0.243014 +0.347246 -0.226405 -0.692922 -0.851449 -0.0457676 0.0100628 -0.497241 0.344657 +-0.391049 -0.257704 0.815436 0.99096 -0.134007 0.806396 -0.772571 -0.740668 +-0.774868 0.767908 0.147976 0.620459 0.00462954 -0.830532 0.41766 -0.390938 +-0.669933 -0.0416615 0.0964868 0.869981 -0.260919 0.786493 -0.0750642 0.878016 +-0.983086 -0.721285 0.0356617 -0.466093 -0.0409097 -0.0963076 -0.217036 -0.406273 +0.904678 0.12219 -0.0578239 0.892585 0.571189 0.146081 0.00117287 -0.323423 +0.9889 -0.551748 -0.438811 -0.625866 0.938955 0.696542 0.894238 -0.69931 +-0.0320403 0.00533449 -0.0125391 0.753212 -0.0913314 0.867907 0.159279 -0.660979 +-0.65511 0.657473 0.201508 -0.435361 0.59615 -0.955151 -0.941454 -0.812843 +-0.768966 -0.64707 -0.449595 0.887056 -0.269047 -0.0377617 0.0294012 -0.737474 +-0.313229 0.21805 -0.643576 0.899066 -0.824893 0.5781 -0.861668 0.327946 +0.862799 -0.0611898 0.783653 0.549268 0.493201 0.609317 -0.96656 0.556559 +0.0133684 -0.527867 -0.703127 0.911624 0.799844 0.554397 0.495858 0.721182 +0.43908 -0.711218 -0.72413 -0.164134 0.957587 0.566734 -0.608718 0.721829 +-0.473956 0.239482 -0.291373 0.758672 0.99164 0.0452519 -0.835765 -0.406954 +0.335401 0.223394 -0.931716 0.52907 -0.810138 -0.0436743 -0.755524 -0.228909 +0.290202 0.439833 -0.709652 0.499486 -0.757529 0.487796 -0.750841 0.0809009 +-0.528943 0.567796 0.533682 0.991938 0.743309 -0.487622 -0.110081 0.0541543 +-0.548527 0.988634 -0.336844 0.56271 0.9076 0.286145 -0.505793 0.621384 +-0.222138 0.891092 -0.0905769 0.514477 -0.444262 0.257015 -0.790373 0.424378 +0.763666 -0.830123 -0.806007 0.386166 -0.13065 -0.874418 0.711468 0.977072 +-0.667453 0.774677 0.215033 -0.103045 -0.359772 -0.503882 -0.821811 -0.279899 +0.776916 -0.208781 0.846638 -0.839401 0.39327 0.574632 -0.789329 0.542864 +-0.228708 -0.734394 -0.224797 -0.509429 0.373326 -0.490687 -0.637614 -0.19727 +-0.238996 0.120953 -0.416065 0.242201 0.656018 0.727064 -0.980073 -0.857004 +-0.926125 -0.744431 0.0295663 -0.495074 0.878549 0.628895 -0.793609 -0.138656 +-0.687222 -0.23321 -0.664315 -0.715454 0.435467 0.0495123 0.488384 0.419708 +-0.470442 0.975884 0.0590026 -0.905845 -0.438891 -0.219989 -0.693973 0.177237 +-0.941501 -0.884588 0.69855 -0.874291 0.752482 -0.881729 0.708262 -0.93316 +-0.508954 0.0458766 -0.792059 -0.182322 0.984095 -0.582856 -0.185611 0.265929 +0.244162 -0.261541 -0.964351 -0.329159 -0.735968 0.51962 0.651772 0.467936 +-0.106126 -0.597183 -0.750275 0.482004 -0.280488 0.357224 -0.949281 -0.8064 +0.298672 0.657303 0.309271 -0.0669985 -0.217628 -0.200461 -0.894731 0.864302 +0.498891 -0.484504 0.237507 -0.516705 0.383922 -0.581693 -0.822732 -0.503028 +0.460454 -0.91012 0.923092 -0.684988 0.413275 0.658274 -0.0419288 -0.0735897 +-0.831778 0.507878 0.98194 -0.778413 0.35959 -0.329035 0.650998 -0.333126 +-0.756533 -0.845052 -0.314941 -0.76689 0.201538 0.722158 0.699828 0.414017 +-0.0437371 -0.12473 -0.860191 0.661535 -0.500183 0.706605 -0.769794 -0.976089 +0.466445 0.562851 -0.868875 -0.225531 -0.177627 0.927466 0.357603 -0.811161 +0.00656017 0.965209 -0.148819 -0.338462 -0.431935 -0.27027 0.274063 0.634862 +-0.347729 -0.0305922 0.0709034 -0.29585 -0.187039 -0.957732 -0.108768 -0.166879 +-0.674004 -0.844242 0.167912 0.562829 0.375394 -0.314415 -0.644618 -0.904611 +-0.0256775 0.43706 0.167703 -0.122045 0.702429 -0.717653 0.831582 0.293733 +-0.620773 0.406897 -0.0985464 -0.964972 0.775873 -0.220469 -0.787068 0.493256 +0.651429 -0.688814 -0.243897 -0.40135 0.00912411 -0.675226 0.139356 -0.863417 +0.931631 -0.193099 0.478894 0.256669 0.472224 -0.192646 -0.34663 0.883549 +0.882007 0.820255 0.0359719 0.569316 -0.138325 -0.784179 -0.684112 0.0195816 +-0.844701 -0.190503 -0.558551 -0.612184 0.918313 0.829079 0.830881 -0.854826 +-0.578573 0.39969 0.22331 -0.391696 0.208646 0.250025 -0.0790775 0.789384 +0.96743 0.354552 -0.997684 0.797462 0.754953 0.419684 0.251792 0.294725 +-0.302599 -0.104254 0.211014 -0.756029 -0.982209 -0.00602782 -0.806971 -0.277436 +-0.284363 0.133574 0.394061 0.224389 0.51931 0.517874 -0.223655 -0.707307 +-0.971639 0.516331 0.670884 -0.881815 0.686452 0.538432 -0.316087 -0.905712 +-0.651487 0.346597 0.234044 -0.991198 -0.379236 -0.802704 -0.198115 -0.917887 +0.899136 0.905529 0.347404 -0.793734 0.169635 -0.438555 0.598018 -0.218781 +-0.680534 0.0772033 -0.554705 0.829286 -0.760164 -0.51107 0.873015 -0.793705 +0.968168 0.948096 0.743962 0.408089 -0.736592 -0.357396 0.269436 0.0816785 +-0.558592 0.196167 -0.937529 -0.436037 0.854778 0.488349 0.850979 -0.955412 +0.0536734 -0.176532 -0.711782 -0.436239 -0.964954 -0.104726 0.451129 -0.326247 +-0.486387 0.102119 0.234256 -0.421192 0.679901 0.133501 -0.368829 -0.530326 +-0.0808063 -0.57331 0.284529 0.682669 0.736315 -0.853189 -0.689337 -0.514051 +0.515633 0.838775 -0.400992 0.477558 0.549116 0.858222 0.323168 -0.729244 +0.36016 0.0528929 -0.922323 -0.0994507 -0.62948 0.634095 -0.200443 -0.442672 +0.83715 0.192852 0.32838 -0.266968 0.0421914 -0.866337 -0.0508683 0.0878756 +-0.97411 0.506679 0.296452 0.578632 -0.620198 -0.611143 0.364563 0.0918438 +-0.938963 0.391992 0.431048 0.565726 -0.34927 0.359105 0.289028 -0.672549 +-0.707697 -0.939126 0.812606 0.497211 0.457878 0.0245149 -0.687045 -0.38471 +0.0381184 -0.378653 0.931786 -0.419089 -0.0757799 0.439691 -0.997946 -0.12534 +-0.686592 -0.432369 0.27564 0.569506 0.647944 0.590072 0.0103596 -0.800668 +0.896275 -0.992825 -0.0750274 -0.100862 -0.204293 -0.211665 -0.677872 0.559411 +-0.536664 0.0907233 -0.338986 0.992628 0.352235 -0.264914 0.547069 0.150407 +0.775416 -0.92695 -0.434443 0.252423 0.317467 -0.331904 -0.557603 0.565371 +0.602662 0.408342 -0.512091 0.0030728 0.139674 -0.108054 -0.57626 -0.921403 +-0.692144 -0.171722 -0.433231 0.755881 0.675493 -0.733586 -0.173277 0.638359 +0.872178 0.637127 -0.924613 0.0491817 -0.757412 -0.887708 0.139245 0.951704 +-0.138399 -0.605358 -0.986579 0.587042 -0.076026 -0.85188 0.148138 -0.496719 +-0.188072 0.651901 0.729753 -0.958166 0.7573 0.628388 -0.823715 -0.319704 +-0.319146 0.212294 -0.851686 -0.528566 0.0971639 -0.779318 0.00756588 0.805455 +0.410997 -0.456638 -0.444694 0.38088 -0.348983 0.326262 -0.80014 0.684784 +-0.0217769 -0.728861 -0.271593 0.0100282 -0.139043 -0.569559 0.490239 0.291991 +0.191743 -0.956743 -0.0334999 -0.362208 -0.232509 0.187365 -0.267504 -0.98481 +-0.314604 0.807347 -0.0374692 0.457703 0.347372 -0.350642 0.503465 0.149619 +0.291539 -0.508797 -0.865771 -0.868354 0.657237 0.425768 0.342987 0.266782 +-0.242675 -0.0154465 0.336309 0.0771463 -0.549974 0.786037 0.777519 -0.661664 +0.199167 0.488603 0.925073 -0.294805 0.427892 0.976814 0.354408 -0.730521 +0.00497342 -0.723675 -0.157526 -0.221206 0.997355 -0.555464 0.591398 0.933278 +-0.798625 -0.680423 0.0390295 0.611335 -0.831012 -0.984318 0.804702 -0.591644 +-0.740838 -0.488049 -0.126706 0.10938 -0.999446 0.447424 -0.0374583 -0.409728 +-0.136065 0.476407 0.34104 0.968761 -0.469901 0.046042 0.177945 0.473385 +0.84876 0.810754 -0.282497 -0.835941 -0.920369 -0.480077 -0.621141 -0.380246 +0.877481 0.0974775 0.323491 0.188718 -0.294873 0.522551 -0.783575 -0.141574 +0.982167 -0.989738 -0.755443 -0.76878 0.636702 0.221192 0.254922 -0.323343 +-0.548756 0.730088 -0.321251 0.819124 0.262294 -0.0876072 -0.0599837 0.787316 +-0.0506024 0.647385 0.836957 0.103114 0.133693 -0.42191 -0.588739 -0.832526 +0.185687 0.468747 0.317314 0.650843 0.576084 -0.918716 -0.75977 0.142646 +0.346399 -0.424681 0.472921 0.880896 -0.71694 -0.440967 -0.489734 0.906221 +-0.380201 -0.530744 -0.21443 0.339864 -0.725634 0.794353 -0.489858 -0.268242 +-0.671276 0.208873 -0.833296 0.70882 -0.627373 0.955747 -0.991261 -0.73811 +0.732094 0.437701 0.880486 -0.0873656 -0.613097 -0.218302 -0.794763 -0.770974 +-0.126436 -0.374331 -0.403368 -0.154457 -0.686789 0.619502 0.80511 0.267929 +-0.326694 0.681777 0.933906 -0.157628 0.805015 0.426671 0.931648 -0.786719 +0.636221 -0.648427 -0.536288 -0.586465 0.306729 0.177567 0.979236 0.862653 +-0.0380231 -0.102955 0.719217 -0.870774 -0.664426 -0.676106 -0.65329 -0.745433 +-0.239066 -0.0182126 -0.715331 -0.199561 -0.561092 0.132848 0.42576 0.25964 +-0.0566575 -0.170979 -0.32052 0.879041 0.321288 0.269939 0.128845 -0.114174 +-0.294883 -0.418883 -0.266252 0.697484 0.0452615 -0.45592 -0.426135 -0.532594 +0.798272 0.133508 -0.362077 0.879304 0.884913 0.00422937 -0.061545 -0.248595 +-0.984744 -0.245919 -0.653422 0.0505498 -0.0114522 0.784298 0.77642 -0.986146 +0.536832 0.965122 -0.261572 0.951519 -0.55871 0.249804 0.553907 0.210255 +0.936155 -0.623036 -0.254564 0.423069 0.305309 0.653012 -0.439647 0.0252214 +0.584988 -0.127235 0.974026 0.723807 0.170148 0.759473 0.144984 0.770854 +-0.356029 0.451229 0.575067 0.576722 0.258416 -0.814711 -0.165241 0.51859 +-0.00813152 0.752535 -0.677814 -0.864048 0.229436 0.284087 -0.167891 0.436235 +0.00788004 -0.102295 -0.940285 0.828367 0.511707 -0.490535 0.0463589 -0.213364 +-0.638034 0.211723 0.306107 -0.073834 0.19495 -0.447647 -0.310053 -0.0380121 +-0.515999 -0.501062 0.472227 -0.0865003 0.589588 0.551636 -0.7153 0.459155 +-0.036833 0.334123 -0.22177 -0.805148 -0.0341958 0.527742 0.532444 -0.688905 +-0.179861 0.0147959 0.675828 0.865579 0.975198 -0.319942 0.808325 -0.250338 +-0.643869 -0.34536 -0.93296 -0.186212 -0.219868 -0.801813 0.492328 -0.592899 +0.606531 -0.506318 -0.447056 0.589777 0.565654 0.146293 -0.745378 -0.0403156 +0.964409 0.940273 -0.689325 0.305467 0.335155 -0.140431 -0.500529 0.319785 +0.960005 0.964473 -0.439225 -0.519572 -0.549881 0.909096 -0.0727993 0.529965 +0.476247 0.710058 0.0500236 0.943053 0.648911 0.195795 0.267082 -0.0229792 +-0.691105 0.306259 0.928882 -0.980668 0.0603002 -0.906808 0.0815965 -0.541805 +0.472548 -0.17892 0.405938 -0.920382 -0.815499 0.173898 -0.0650522 0.963914 +-0.192959 -0.605192 0.535509 -0.538357 0.474006 -0.749047 0.450723 0.391387 +0.689136 0.572692 -0.624065 -0.763781 0.821114 -0.732775 -0.354682 0.392788 +-0.428872 0.370659 -0.689162 -0.383518 0.158126 -0.362763 -0.298015 0.397011 +0.761692 -0.52822 0.767065 -0.411002 -0.563805 -0.677213 -0.584136 0.977493 +0.0483114 0.867581 -0.369478 -0.80581 -0.754131 0.452109 -0.771292 -0.680477 +0.710463 0.280461 0.10484 0.137275 0.104904 0.697411 -0.321435 0.515745 +0.85039 -0.110204 -0.530962 -0.495014 0.234349 0.964586 -0.413498 0.0765348 +0.778326 0.915482 0.428292 0.983919 -0.101911 0.560052 0.596412 -0.940664 +-0.00820141 0.341059 0.0756779 -0.65676 -0.291455 0.102098 -0.557903 0.142224 +0.382496 -0.451592 0.0654742 0.509533 -0.439345 -0.881442 -0.877415 0.66565 +0.381352 0.695412 -0.758496 -0.646606 -0.861144 -0.1932 0.444279 -0.417724 +-0.21722 -0.0174348 0.0919835 0.0670942 -0.478538 0.0741871 0.364884 0.225702 +0.754242 -0.240633 -0.405087 -0.57317 -0.875154 -0.369001 -0.646432 -0.0200557 +-0.257041 0.823314 -0.296069 -0.5396 -0.811253 0.782266 0.795831 -0.942367 +0.284828 -0.271832 -0.0547863 -0.048904 0.124154 -0.80463 -0.445958 0.481062 +0.750048 -0.618551 -0.625226 -0.102515 0.25261 0.583137 -0.903711 -0.397957 +0.628092 0.465506 -0.519213 -0.498953 -0.765629 0.893854 -0.668678 0.538349 +0.549358 0.544621 -0.197553 0.427111 0.419775 0.402888 -0.714201 -0.96057 +-0.789757 -0.24699 -0.690532 -0.754698 -0.507021 0.782456 0.134618 0.138965 +-0.145837 -0.907271 -0.380181 -0.171594 -0.887093 0.151408 0.0399608 -0.967782 +-0.239428 -0.868745 0.243802 0.786926 0.398945 -0.851344 0.113376 0.420488 +-0.474001 -0.71242 0.371567 -0.243781 -0.562235 0.783651 -0.0692558 -0.240311 +-0.573088 0.227966 0.506406 -0.409247 0.0447546 -0.362153 -0.846627 -0.0100686 +0.218826 0.0538275 0.471391 0.664573 0.659483 -0.246342 0.205041 -0.376889 +-0.56742 -0.297886 0.983211 -0.0619457 0.187484 -0.392358 -0.445509 0.532601 +0.151181 -0.226808 -0.781219 -0.88863 0.514738 0.578417 -0.291603 -0.377932 +0.320535 -0.259863 0.585372 0.367507 0.199292 -0.199893 -0.165519 -0.916644 +-0.193659 -0.323366 0.144188 -0.447858 -0.932131 -0.789041 -0.819976 -0.512463 +-0.785872 0.654538 -0.117231 0.182413 0.611999 -0.468289 -0.858888 -0.579697 +0.890708 -0.850613 0.956204 0.803646 0.691517 0.340154 -0.578665 -0.486647 +0.775513 -0.429141 0.722566 0.908044 0.542147 0.753112 -0.232435 0.267161 +0.339155 0.0100213 -0.250798 0.470405 -0.167442 0.62331 0.96121 0.290845 +-0.525227 0.816981 -0.111607 0.113413 -0.737994 0.713929 -0.515309 -0.511189 +-0.0366259 0.105772 0.733191 -0.174168 -0.0891108 0.0959599 0.12254 -0.549979 +0.0936712 0.983153 -0.748721 -0.0702506 -0.539602 -0.967965 -0.953551 0.779744 +0.439294 0.591822 0.524557 0.83802 0.936916 0.15132 -0.145569 -0.70357 +0.0577606 -0.890423 0.645814 0.52633 -0.140477 0.629657 -0.0911898 -0.867438 +0.641718 0.872184 0.674205 0.925779 0.969978 -0.692878 -0.541211 0.932084 +0.127287 0.339392 -0.436132 0.446942 0.323184 -0.427856 0.0450793 -0.547228 +0.571856 0.456378 -0.212494 0.412581 0.60747 0.457908 -0.730449 -0.432328 +0.716379 -0.282181 -0.149145 0.423577 0.531272 -0.192534 0.522158 -0.0139067 +0.392458 -0.43031 0.440483 -0.420511 -0.0837572 0.349625 0.878125 0.612409 +-0.48793 0.610584 -0.878666 -0.294242 -0.488136 0.777345 -0.504048 0.782072 +-0.807702 -0.917127 -0.899227 0.823244 -0.415499 -0.734847 0.873002 0.342213 +0.205201 -0.138148 -0.752051 0.703676 0.189249 0.888606 0.0206145 -0.531954 +-0.300858 -0.938632 -0.328701 -0.544132 -0.749591 -0.9912 -0.345828 -0.455907 +-0.595073 -0.678245 0.866344 0.465099 -0.509859 -0.457841 0.466966 0.383943 +-0.060213 -0.710382 0.0313389 0.283458 0.187496 0.310622 -0.595371 0.601871 +0.562767 0.0377798 0.76085 -0.892 -0.0911599 0.265912 -0.618319 0.952178 +-0.840834 0.821741 -0.975384 -0.725079 0.603053 -0.639858 -0.633069 -0.808539 +-0.538151 -0.948088 -0.51558 0.274384 -0.0619097 -0.0826329 0.180303 -0.855399 +0.42251 0.144264 0.293215 0.190766 -0.715834 0.112131 0.430095 -0.493941 +0.0027466 0.256351 0.821961 0.0155914 0.978361 0.325366 -0.152935 0.713048 +0.155912 -0.702545 -0.559075 -0.621663 -0.499971 -0.790038 -0.723394 0.270965 +-0.452068 0.0941228 -0.507194 0.537582 -0.615952 -0.473029 -0.654752 0.16797 +0.975202 -0.278628 -0.37559 -0.459865 -0.494414 -0.522035 -0.700555 -0.713496 +-0.31939 -0.214 -0.179502 0.597574 -0.448232 0.899591 -0.698854 -0.890447 +-0.75038 0.689621 0.691946 -0.400412 0.98447 0.824083 -0.540418 0.273547 +0.751513 0.992589 0.44151 -0.176448 -0.258649 -0.570728 0.990564 0.825067 +-0.288471 -0.175124 0.728809 -0.856118 0.963137 -0.371374 -0.121704 -0.722621 +-0.560635 0.256014 0.783282 -0.0436413 -0.46044 0.528746 -0.729818 0.505957 +-0.457373 0.502338 -0.259939 -0.591323 -0.379924 0.0464475 -0.371124 0.390725 +0.736234 -0.0702791 0.764597 -0.0402704 0.144329 -0.954984 -0.329526 -0.484438 +-0.41639 -0.726601 -0.351723 -0.826754 0.725462 -0.0631057 0.275125 0.947095 +0.966303 -0.979173 -0.981785 0.536177 -0.937156 0.926273 -0.244539 -0.213392 +-0.430865 -0.765427 -0.626624 -0.903924 -0.899377 -0.169289 -0.681021 0.0820862 +-0.110559 0.0761014 -0.110221 0.520959 -0.201519 -0.922766 -0.592008 0.110752 +-0.781808 0.835112 -0.557839 0.615583 -0.934306 -0.409004 0.105904 -0.609772 +0.187986 -0.536589 0.525622 0.965509 0.994878 0.440683 -0.782722 -0.10285 +0.221736 0.238921 -0.507302 0.701848 -0.969081 -0.654852 -0.0478535 -0.668043 +0.513093 0.149467 -0.55545 0.51696 -0.989508 -0.887487 0.503948 -0.320804 +0.36926 -0.125893 0.751347 0.923279 -0.23921 -0.704303 -0.649616 0.9348 +-0.882768 -0.695332 -0.652699 0.769483 0.346243 0.429311 0.445164 -0.549846 +0.900309 0.00963954 0.121683 -0.144578 -0.731711 -0.693846 -0.0810501 0.877884 +-0.448573 0.669242 0.976741 -0.0972122 0.531226 0.497216 0.685044 0.606398 +-0.793498 -0.0199782 0.378773 -0.54014 0.33045 -0.0403891 -0.830269 0.126731 +0.957517 -0.0318155 -0.20254 0.284324 0.87273 -0.908624 -0.0335001 0.314938 +0.225949 -0.686549 0.151156 0.391466 -0.679554 -0.284395 0.994301 -0.90876 +-0.395586 0.774109 0.712459 0.352602 -0.635886 -0.420902 -0.850352 -0.318036 +0.48513 -0.834401 -0.434297 0.439986 0.729257 0.862742 0.0441958 -0.901788 +-0.638434 0.273707 -0.367312 0.0578474 0.877717 0.185739 -0.505204 -0.638063 +0.241206 -0.831992 -0.965704 -0.586159 0.169424 -0.585115 -0.0547658 0.50218 +0.753684 0.768991 -0.501 0.317682 -0.0585389 0.3068 0.772707 0.169542 +0.977906 -0.519445 0.226863 -0.733432 0.296144 -0.919477 0.657372 -0.853784 +0.00631976 0.662154 -0.86129 0.311983 -0.275507 -0.42741 0.360565 -0.904424 +-0.451835 0.518714 0.294816 0.70085 0.279951 0.201791 -0.78446 0.367603 +0.0279764 -0.698014 -0.872753 0.227458 -0.222103 -0.598081 -0.595641 0.59122 +-0.0892559 -0.754093 -0.131712 0.202004 -0.491409 0.718173 -0.168244 -0.754166 +0.0358621 0.146345 0.252568 -0.897618 -0.743443 0.590545 0.735712 0.129365 +0.535206 -0.549116 -0.322435 -0.120387 0.326257 0.857455 0.926268 0.846448 +-0.844808 -0.0579436 0.413073 -0.681191 -0.157148 -0.991291 0.982462 -0.372447 +-0.371312 0.474717 -0.659698 -0.250764 0.351652 -0.248735 0.376753 0.404496 +0.122821 -0.375758 -0.583352 0.390892 0.441815 0.611139 -0.750248 0.690489 +-0.619211 0.652251 -0.232602 -0.023077 0.510154 0.514604 0.707036 -0.088341 +0.365802 -0.288358 0.498475 0.622598 0.0884513 -0.502601 -0.0398956 -0.241912 +-0.449921 -0.0662473 -0.482305 -0.56115 0.844889 -0.968386 -0.236661 0.958662 +0.716409 0.464967 -0.63852 0.321524 -0.64652 0.754909 -0.585983 -0.554646 +-0.447716 -0.274164 -0.845825 -0.677412 0.299511 0.429741 -0.00783276 -0.625215 +-0.0666598 0.941849 -0.721826 0.175247 0.166758 0.946796 -0.441443 -0.545678 +-0.280745 -0.558744 0.0782417 0.822043 0.0373034 -0.767634 0.334889 -0.204475 +0.304197 -0.923993 0.924242 0.340491 0.826447 0.652876 0.636878 -0.00527523 +0.229423 0.0912072 -0.798967 -0.846361 -0.634938 -0.855099 -0.602047 -0.742035 +-0.899023 -0.613459 0.892855 0.0549564 -0.714598 0.818618 0.541846 0.0304994 +0.678134 -0.977333 -0.672914 0.1998 0.0666526 -0.0546959 -0.875247 0.177203 +0.386777 0.476735 0.0564501 0.607217 0.515895 0.299154 0.86858 -0.929842 +0.685959 0.19825 0.326267 0.93105 -0.2731 -0.223146 -0.388904 0.644691 +0.0917231 0.456785 0.300217 -0.418998 -0.756469 -0.18787 0.0257972 -0.510528 +0.774582 0.108108 0.217937 -0.678055 -0.857652 0.257642 -0.23537 -0.459661 +0.492765 0.329134 -0.750469 0.265036 -0.549458 0.800931 0.45043 0.654937 +0.545092 -0.405946 0.97829 -0.241211 -0.761309 0.0522561 0.489279 -0.181044 +0.595806 0.301203 0.00175219 0.0346104 -0.871983 -0.316493 -0.35869 0.750833 +-0.356902 -0.83915 0.463834 -0.799833 -0.765589 -0.00996312 0.618092 0.925763 +0.17807 0.475797 0.984541 0.0352228 0.910344 0.897265 0.64628 -0.943552 +-0.213075 0.931375 0.390993 0.759357 0.855887 -0.664187 -0.45863 -0.557136 +0.544188 -0.349897 -0.304036 -0.914146 -0.977609 -0.204913 -0.610554 -0.890574 +0.677751 -0.962213 -0.276768 -0.965943 -0.742092 0.744066 0.72906 0.803358 +-0.920121 0.851578 -0.508072 -0.749494 0.458986 0.72717 0.883557 0.211832 +-0.429776 -0.814513 -0.520569 0.331702 -0.0368137 0.40048 -0.0194574 0.286821 +-0.0945039 0.501176 -0.259392 -0.201334 -0.817095 0.110605 -0.38989 -0.556894 +-0.888289 0.419195 -0.941187 -0.703618 -0.74757 0.83368 0.397319 -0.648898 +0.140283 0.236167 0.576773 0.174286 -0.0770867 -0.970377 -0.507436 0.331816 +0.926226 -0.949527 -0.344011 -0.362622 0.476272 0.5664 -0.0610025 -0.926603 +-0.812599 0.379471 0.816848 -0.460453 0.0192854 -0.532238 0.64875 0.290428 +-0.704732 0.344577 -0.986519 0.380786 -0.963709 -0.298283 0.160948 0.725572 +-0.37787 -0.355922 0.520489 0.529633 0.463511 0.562887 0.558426 -0.21356 +0.711711 0.382962 -0.0321731 -0.168244 -0.891085 0.885591 -0.869937 0.338166 +0.594262 -0.141912 -0.688893 0.99811 0.739581 -0.379 -0.838501 0.737623 +-0.240775 -0.31584 -0.977945 0.220277 -0.700471 0.121494 0.786246 -0.609107 +-0.469262 0.615444 0.822334 -0.938985 0.00972204 0.201078 0.952333 0.219098 +0.161819 -0.58996 -0.709192 0.0850985 -0.350235 -0.0183066 -0.962063 0.552786 +-0.322579 0.535901 0.0831581 -0.0385795 -0.86019 0.506289 0.108535 0.627683 +0.653316 0.581975 -0.428346 -0.327397 -0.533502 0.191921 -0.835736 -0.671013 +0.23607 -0.764082 -0.427963 0.936417 0.812322 0.62325 -0.225402 0.473908 +0.360824 -0.31927 0.223129 -0.865486 -0.166944 0.156986 0.205085 0.00717569 +-0.560244 -0.836575 0.121307 0.962825 -0.239955 0.941542 -0.87634 0.756335 +0.379483 0.672066 0.920528 -0.425731 -0.8055 0.618419 -0.681839 0.566572 +-0.541926 -0.377947 0.260811 -0.651411 0.721151 0.796162 -0.541762 -0.576999 +-0.181808 0.639802 -0.975259 -0.663825 -0.118761 0.935995 0.850632 0.623139 +-0.0280611 -0.100807 -0.0115205 0.769508 0.975921 0.36622 -0.439825 0.182228 +-0.518802 0.677906 -0.922765 -0.650697 0.38278 -0.802091 -0.441567 -0.0682614 +-0.0606541 -0.82269 -0.757103 0.451062 0.68341 -0.21763 -0.189813 -0.719505 +0.328524 0.374754 -0.829575 -0.233745 0.603112 0.115447 -0.205495 0.495732 +-0.940007 -0.372071 -0.0567001 0.0815177 0.237495 -0.165586 0.102285 0.106442 +0.0587672 0.203151 -0.617669 0.246597 0.766063 -0.0441826 0.225723 -0.375256 +0.595638 -0.8969 -0.859182 0.924258 -0.850319 0.619827 -0.336612 0.87471 +0.253623 -0.703156 0.392904 0.754309 -0.413597 -0.550302 -0.466837 -0.0554813 +-0.171574 0.760164 -0.746511 -0.449427 0.861316 0.908235 0.939748 0.900948 +-0.866745 -0.989101 -0.105858 0.746067 0.880719 0.0791559 -0.148423 0.567304 +-0.340772 0.342627 -0.418369 0.0183479 0.663974 -0.210388 0.566031 -0.307053 +-0.796909 -0.861782 -0.41856 0.904874 0.257222 -0.849611 0.135816 -0.837315 +0.573607 0.976107 0.647015 0.169306 -0.0390818 -0.681147 -0.2512 0.186309 +-0.79281 -0.465743 -0.873903 0.415853 0.929572 0.928767 -0.917676 0.389418 +-0.189122 -0.81393 -0.482353 -0.945896 0.204562 -0.551815 -0.623091 -0.180186 +-0.601643 -0.736529 0.0744873 -0.971781 0.767349 -0.0454771 -0.0333532 0.370712 +0.953419 0.752331 0.167843 0.242817 0.792761 -0.455219 0.738609 0.422799 +0.683497 -0.156342 0.972546 -0.166608 0.434767 -0.492561 -0.635644 -0.262027 +0.0969455 -0.986278 -0.427855 0.499039 0.872608 -0.285313 0.861969 -0.00726473 +0.568782 -0.47187 -0.660013 -0.193908 -0.924188 -0.304503 0.194021 0.548087 +-0.395025 0.130907 0.458495 -0.657022 0.507126 0.566483 0.343297 -0.153337 +-0.164236 -0.93546 0.139193 0.758905 0.657126 0.0436321 0.708452 0.318435 +0.74236 -0.281163 0.462817 -0.485953 0.922327 0.551694 0.232885 -0.525846 +-0.455437 0.928112 0.328556 -0.227581 -0.097357 0.554065 0.944684 -0.795896 +-0.399629 -0.151192 -0.272881 0.384818 0.643247 0.503916 -0.919137 0.262122 +0.267216 -0.389761 -0.716136 0.124153 -0.183209 0.203462 0.558165 0.467073 +0.663323 0.184449 0.388718 0.0287672 -0.30326 0.426009 -0.0135387 -0.970393 +-0.846424 0.765307 0.654113 0.169023 0.428073 -0.972336 0.838171 -0.048438 +0.918883 -0.599371 -0.639186 0.707787 0.0389316 -0.500555 0.539954 0.572245 +0.546336 -0.851287 -0.571707 0.843092 -0.0696237 -0.77709 0.828392 -0.670245 +0.256247 0.170751 -0.74507 -0.916481 -0.198322 -0.0422062 0.201764 0.303284 +0.707147 0.538474 -0.46604 0.768481 0.450826 0.78801 -0.320954 0.0529201 +-0.457465 0.713165 0.261461 0.500716 -0.761406 0.0585499 0.266564 -0.194963 +0.0469887 0.372271 -0.814744 -0.493067 0.986417 -0.220578 -0.147642 -0.290298 +0.865739 -0.843325 -0.586935 0.558152 -0.607688 0.133677 -0.314835 -0.874994 +-0.28407 -0.0310837 -0.244577 -0.499961 0.0831651 0.611807 -0.803031 -0.324554 +-0.674089 -0.114628 -0.869776 -0.68684 -0.680338 -0.13748 0.968537 0.226829 +-0.106497 0.826638 0.175156 -0.690683 -0.20081 -0.663019 0.527855 -0.215508 +-0.569968 0.224708 -0.833994 -0.342232 0.560923 -0.520778 -0.75234 0.382951 +0.134161 -0.208342 -0.427726 -0.173193 -0.332348 0.299537 -0.234726 0.832925 +-0.402892 0.44751 0.670677 0.982216 -0.161869 -0.224028 -0.924491 0.755886 +0.124148 0.31867 0.241076 -0.869214 0.756065 -0.1096 0.973246 0.939339 +-0.804345 0.0404028 0.366816 -0.112333 0.48207 0.594207 0.0851084 -0.78472 +0.950464 0.0877894 0.237575 0.701777 -0.793751 -0.181089 0.0768191 0.438248 +-0.0821008 -0.0783405 0.501966 -0.543472 -0.125108 0.84544 0.580949 -0.127013 +-0.437705 -0.799327 -0.51293 -0.704008 0.559853 -0.676329 -0.188623 0.670392 +0.371978 0.763898 -0.481408 0.020204 -0.502421 0.773839 0.95058 0.179744 +-0.819678 0.051496 0.962227 -0.0892686 0.250977 0.594883 -0.246833 0.437308 +0.76584 -0.625579 -0.36399 0.667921 -0.30947 0.244496 -0.975459 -0.113815 +-0.52928 -0.580881 -0.430803 0.00414179 0.35355 -0.964707 0.839863 0.703258 +0.369541 0.682136 -0.0195639 0.372471 0.778789 0.0287528 0.940356 -0.240733 +-0.0878356 0.146325 -0.439308 -0.206156 -0.573423 -0.350959 -0.323891 -0.810204 +0.0112959 -0.249291 0.0271747 0.649374 0.942587 0.21371 -0.906037 -0.744209 +-0.010731 0.991442 0.885706 -0.109002 -0.189258 -0.389477 -0.452456 0.0842571 +0.878999 -0.117072 0.271111 0.329515 -0.921645 -0.948288 0.441989 0.526507 +0.780293 -0.439826 -0.826501 -0.532999 -0.733558 -0.876879 0.532704 0.378396 +-0.0936228 0.4803 -0.741781 0.00110437 -0.240193 -0.398467 -0.376829 0.945627 +0.856679 -0.857759 -0.661542 0.217709 0.00500074 0.621913 0.763219 -0.193151 +0.385666 -0.573166 -0.553545 -0.0550383 0.716349 -0.443558 0.531387 0.874882 +0.735574 -0.452782 0.862433 0.816191 -0.490542 0.127588 0.908425 0.535995 +-0.742564 -0.433178 0.915441 0.429457 0.741941 0.777874 -0.824876 -0.492205 +0.928933 0.595887 0.555872 -0.506634 -0.190822 0.405726 -0.280609 -0.896837 +0.163702 0.249171 0.255146 -0.533572 -0.378421 0.745034 0.750554 -0.783449 +-0.320676 -0.344093 0.0856638 0.164454 0.249587 0.959115 0.676873 0.531421 +0.694168 -0.948914 0.284541 0.549565 -0.392633 0.754276 -0.714306 -0.735648 +-0.190019 -0.52543 -0.05979 -0.120959 0.522829 -0.255097 -0.0403621 -0.7353 +-0.328844 -0.0182174 0.11135 -0.477302 0.791178 0.0611149 -0.0462498 -0.175987 +0.269369 -0.929168 -0.726463 0.54813 -0.937998 0.745038 -0.293154 -0.654064 +0.551288 -0.502471 0.486128 0.651546 0.369143 -0.349521 0.144616 -0.109417 +0.765235 0.877474 -0.845408 0.351489 -0.63105 -0.769469 -0.457141 -0.234768 +0.311318 0.300883 0.299567 -0.327209 -0.576271 -0.643474 -0.360074 0.981788 +0.981298 0.608698 0.0826749 -0.114287 0.743939 0.49706 -0.566342 -0.879508 +0.0800737 -0.893772 -0.912034 0.187454 -0.692667 0.522734 0.0485591 -0.645851 +-0.324429 -0.700755 0.267917 0.0402615 -0.699743 0.992684 -0.579391 -0.431563 +0.996279 -0.924962 -0.939793 0.920964 0.689077 -0.395117 -0.017921 -0.216873 +0.0636556 0.895646 -0.317375 -0.733031 -0.701854 -0.490877 -0.198355 0.129399 +-0.687348 0.719909 0.641067 0.916343 0.316081 0.816246 -0.221022 -0.14204 +0.0855796 0.67265 -0.562649 -0.147528 -0.39122 -0.611359 -0.43629 0.80869 +-0.922597 0.76178 -0.862715 -0.372038 -0.671139 0.477378 -0.502672 -0.808751 +0.253303 0.457268 0.831574 -0.773127 -0.483561 -0.24741 0.957302 -0.929012 +0.197971 -0.53769 -0.109346 0.948488 -0.686124 0.0339448 -0.118122 -0.519184 +-0.844502 0.692427 -0.688552 -0.532634 -0.759507 -0.260971 -0.796699 -0.404532 +0.0865159 -0.780443 -0.893265 0.286129 -0.963133 0.404368 -0.106939 -0.754019 +0.856322 -0.56223 0.490658 -0.128994 -0.070527 0.611366 0.172883 -0.0892844 +0.104858 0.1888 -0.648231 0.405203 0.182899 -0.215067 -0.680568 0.415602 +-0.197065 0.405019 -0.680563 0.489857 0.7812 -0.000321634 0.251133 -0.163168 +-0.0828464 -0.845147 0.138025 0.0712586 0.561523 0.418024 -0.0945405 -0.772312 +0.0421709 -0.603521 -0.893089 -0.310384 0.338777 -0.285234 -0.235222 -0.849502 +0.425383 0.769619 -0.354696 -0.719294 -0.107823 0.440272 0.985391 -0.252171 +0.146365 0.0889267 -0.401725 -0.183417 0.981461 0.486241 0.681473 -0.258455 +0.952971 -0.679307 -0.725955 0.166804 -0.461048 0.483991 0.805641 0.564412 +-0.391718 -0.885734 -0.338494 -0.758048 0.62324 -0.904924 -0.511931 -0.313077 +-0.427775 -0.462631 0.571049 0.309519 -0.633172 -0.524454 0.774625 -0.141569 +-0.27132 0.746114 -0.330058 -0.485489 -0.506717 0.00733686 0.793065 0.48465 +-0.149967 0.0249565 -0.377554 0.635322 0.926616 0.316265 0.0518561 -0.601899 +0.221472 0.121239 0.574847 0.521096 0.559327 0.942286 -0.724584 -0.855785 +-0.119323 0.0382661 -0.628763 0.436192 0.94491 -0.501119 -0.679026 -0.745567 +-0.768534 -0.877493 0.168443 -0.116303 -0.271442 -0.232377 -0.272922 -0.438878 +-0.555787 0.0546222 0.667032 -0.599897 -0.398251 -0.194041 0.7088 -0.579869 +0.945534 -0.464931 -0.976692 -0.794661 0.51902 0.652344 -0.560435 0.902057 +-0.254705 -0.567206 -0.817415 0.840607 0.740243 0.598916 0.391895 -0.394496 +-0.100858 -0.392356 -0.0955732 0.744395 -0.098339 0.356142 0.185845 0.181413 +0.0203355 -0.788697 -0.600303 0.697847 -0.700404 0.902197 -0.74871 0.302692 +-0.885 -0.338142 -0.266243 0.17608 -0.576465 -0.502188 -0.596151 -0.878618 +0.44483 0.832059 -0.173066 0.456706 0.642328 0.724746 -0.1925 -0.893404 +0.443883 -0.456011 -0.770323 -0.997234 -0.952226 -0.892065 0.20022 0.953866 +-0.711862 -0.993364 0.907505 -0.579022 -0.925414 0.500686 -0.275635 0.565904 +0.423131 -0.0968551 -0.478523 0.0238519 0.316365 0.854634 0.904365 -0.131348 +-0.548285 0.578612 -0.275744 0.407103 0.316615 -0.882478 -0.473928 0.285793 +0.63222 0.455825 0.386028 0.207057 -0.66896 -0.628345 -0.0808006 -0.807238 +0.711269 -0.784493 0.4599 0.0397161 0.527732 -0.732751 -0.601908 0.218853 +0.283443 -0.692185 0.566496 -0.68177 0.928101 0.79579 -0.493063 0.144516 +-0.149631 -0.846303 0.652118 0.841565 -0.495354 0.36171 -0.320881 -0.766979 +0.505737 0.522733 0.76624 0.202624 0.89359 0.0311913 0.872182 0.0149582 +0.574351 -0.633518 -0.825413 0.154435 -0.141215 0.140963 -0.487547 0.417802 +-0.666241 0.565788 0.756247 0.868203 -0.116211 0.75985 0.585547 0.830323 +-0.626712 -0.45364 -0.195443 0.448415 0.104229 -0.664431 0.669827 0.192545 +-0.0324374 -0.140675 -0.500651 -0.305651 -0.645708 0.988018 0.553351 -0.549405 +-0.122066 0.225076 -0.818105 -0.996791 -0.547578 -0.881317 0.752254 -0.694483 +0.476205 0.584487 -0.490537 0.5268 -0.31787 -0.482516 0.533979 0.00115596 +0.899264 0.0182342 -0.868973 0.867343 0.650678 -0.994781 -0.102045 -0.0269937 +-0.0750363 -0.453265 0.702007 -0.00121795 -0.972748 0.834929 -0.633961 -0.71164 +0.985972 -0.589411 -0.809588 0.55176 -0.351489 -0.544948 0.954608 -0.346856 +-0.699835 -0.484832 -0.834155 -0.368864 0.608062 0.0825367 0.760286 -0.0527428 +-0.799013 -0.765432 0.974613 -0.684831 0.60186 0.999952 0.79829 -0.225519 +0.690754 -0.501941 0.324644 0.316548 -0.078213 0.936501 0.980851 -0.816268 +0.0774005 -0.555405 -0.154659 0.348248 -0.467778 -0.324692 -0.629435 -0.656457 +-0.200646 0.82515 0.14657 -0.806379 -0.759421 0.0829597 -0.374377 -0.00215195 +-0.77514 0.415386 0.983687 -0.0142301 0.980576 0.600523 0.146038 -0.0822019 +-0.538879 0.116211 -0.818458 -0.740589 -0.488668 0.314551 0.649157 -0.443189 +-0.285181 0.200458 0.332028 0.3074 -0.523374 -0.551051 0.220338 -0.34828 +-0.923755 -0.1266 -0.601394 -0.0253203 -0.828103 0.490856 0.266744 -0.408953 +0.0542938 -0.215857 0.386484 -0.78468 0.0258582 0.795984 -0.183508 -0.571211 +0.552468 -0.356369 -0.196538 0.734811 -0.118357 -0.128739 0.840145 -0.93725 +-0.154347 0.873422 -0.194153 0.872663 -0.356444 0.363519 -0.273476 -0.696162 +0.583401 -0.53281 0.731566 -0.444695 -0.472582 -0.663451 0.91995 0.650943 +-0.404663 0.840018 -0.120633 -0.471824 -0.752747 -0.475972 0.646036 -0.547903 +-0.233779 0.0825393 0.942899 0.158798 0.623666 -0.631099 0.00203193 -0.235393 +-0.585184 0.883392 0.132245 -0.438164 -0.161598 -0.0969587 0.000618285 0.79207 +-0.932912 0.537109 0.367195 0.524085 -0.414115 0.494211 0.9536 -0.80306 +0.386435 -0.988085 -0.936921 0.714699 0.625112 -0.866318 -0.942141 0.336779 +0.764189 0.0251004 -0.848174 0.665548 0.147669 0.254436 -0.264234 -0.896245 +0.325485 0.754366 0.0447624 -0.585063 0.719863 -0.0696208 -0.622733 -0.387195 +-0.169277 -0.113223 0.421046 -0.0531837 -0.405825 -0.230418 -0.983003 -0.711747 +0.336613 0.164089 -0.745039 -0.807313 -0.736208 -0.10126 0.824618 -0.920568 +0.909828 -0.622685 0.332989 0.00830162 0.38507 -0.397409 0.648477 0.529428 +0.0101819 0.62799 0.33955 -0.789978 -0.969035 -0.0619933 -0.626062 -0.888456 +-0.920535 0.031577 0.209105 0.355139 -0.0742127 0.841699 0.0614381 -0.0995839 +0.985094 0.130549 0.317291 -0.966487 0.510734 0.961951 0.183114 -0.805229 +-0.652149 0.7594 -0.487267 -0.787221 0.851975 -0.873241 0.439256 0.499765 +0.541152 0.0770298 0.605506 -0.582985 -0.949134 0.0863542 0.518711 -0.496535 +0.399843 0.912941 0.268388 -0.865712 0.107298 -0.571469 0.534591 -0.976143 +-0.338867 -0.93816 0.979595 -0.325682 -0.945629 0.546945 0.828186 -0.897783 +0.241588 0.801397 0.266351 0.916368 -0.861289 0.520631 -0.350318 0.409777 +0.610429 -0.083441 0.83093 -0.670309 -0.164084 0.604357 0.0783674 -0.42118 +0.36577 -0.508371 0.416979 -0.139311 0.883315 0.362692 0.183672 0.69271 +-0.28885 0.696964 0.211831 0.489029 0.226392 0.953463 0.10962 -0.73453 +0.986815 0.600921 0.0449613 0.110881 0.578612 -0.604654 -0.810103 0.771854 +0.902732 -0.495443 -0.734904 -0.520157 0.62146 0.460401 -0.969393 -0.0602119 +-0.539116 -0.706347 -0.74457 0.971574 0.2893 0.484338 0.77608 0.282123 +0.547443 0.29363 -0.94728 -0.163755 0.388137 0.689701 0.165507 -0.452441 +0.209506 0.769668 -0.468422 0.0512967 -0.0155995 0.369681 -0.0416683 0.385239 +0.536443 -0.640138 0.0763071 0.705092 0.989851 0.828893 -0.60472 -0.28465 +-0.494723 0.921693 0.0495236 0.173518 0.741574 -0.959035 0.990642 0.353335 +0.651272 0.178445 -0.61107 0.500453 0.341522 -0.837734 -0.990673 -0.36227 +0.763702 -0.274026 0.195442 0.452955 0.676666 -0.0271457 0.441324 -0.609185 +0.423997 -0.701139 -0.410888 0.0778383 0.878795 0.15746 -0.994007 0.113326 +-0.334275 -0.442163 0.12964 -0.481628 -0.968939 -0.225538 -0.279952 -0.348539 +0.73095 0.933779 -0.804383 0.526414 0.479168 0.988399 -0.941287 0.394242 +-0.0340086 0.705096 -0.554178 -0.844025 0.165571 0.223001 0.283481 0.437085 +0.0834355 -0.563229 0.578883 0.0711771 0.619632 -0.0333454 0.186991 0.701669 +-0.321065 0.418618 -0.401531 0.405464 0.119774 -0.488364 -0.541451 0.298125 +-0.930117 -0.714498 0.96836 -0.544415 0.0404438 0.107046 -0.494357 -0.294113 +0.7649 0.891545 -0.952906 -0.0227346 0.406766 0.859156 0.300293 0.187083 +-0.391863 -0.0590129 -0.849673 0.888853 -0.925853 0.894784 0.774522 0.667416 +-0.788453 0.313785 0.0735782 -0.9446 0.0881703 -0.877804 0.115091 0.690123 +-0.298138 0.199317 -0.897659 -0.76291 -0.672211 0.439996 0.169136 -0.9143 +-0.0962146 -0.160769 0.261731 0.550875 0.97825 -0.837458 -0.890215 0.16264 +-0.655996 0.400844 -0.753987 0.144687 -0.640398 0.67667 -0.345467 0.181287 +-0.992709 0.0882317 -0.240251 0.369297 0.557474 0.425089 0.39905 0.542164 +-0.550886 -0.303266 0.414447 0.951891 -0.900641 -0.637662 -0.739914 0.599469 +0.129487 0.241247 0.196362 0.403789 0.21839 0.877744 -0.282078 0.132361 +-0.0054312 0.918197 0.188897 -0.902218 0.103391 0.139808 0.393467 -0.199445 +-0.923921 0.373623 -0.853978 0.340359 -0.57419 0.536 -0.926296 0.632232 +0.707454 0.338353 0.127895 -0.196444 -0.0319703 -0.305862 0.704341 0.618947 +0.919735 -0.750654 0.176572 -0.802977 -0.0707223 -0.320515 -0.110584 0.473198 +-0.645532 0.562394 -0.0586577 -0.265339 0.144387 0.85353 0.308196 -0.946138 +0.527819 0.914607 0.524667 0.94169 -0.185767 0.570622 0.605907 -0.423411 +-0.804722 -0.684955 -0.456404 0.365336 -0.040309 0.428063 -0.133152 0.178633 +-0.992572 0.386273 0.33409 0.865669 0.158053 -0.554986 -0.729363 0.969722 +-0.409773 -0.373148 -0.471849 0.602634 0.164685 0.783269 0.112875 0.581757 +-0.977761 -0.0302597 0.904442 0.950423 0.0675092 -0.897506 0.236307 -0.216288 +-0.277661 0.868341 0.540508 0.24097 0.443353 0.33287 -0.989548 -0.194153 +0.865029 -0.71969 0.251391 -0.806809 0.887908 0.434057 0.505243 0.37496 +0.315971 -0.163629 0.432174 0.383298 0.746031 -0.815984 -0.18584 -0.408601 +-0.555325 0.129052 -0.0885912 -0.190683 0.782567 -0.225434 -0.429651 0.483977 +0.710882 0.298927 0.713428 -0.976695 -0.275012 -0.970883 -0.47833 0.938195 +-0.409982 0.791796 -0.476071 0.11307 -0.584786 0.826539 0.869438 -0.499075 +-0.504735 -0.789846 0.837696 -0.718721 0.89905 -0.211661 0.700321 -0.263882 +-0.424087 -0.195272 0.104407 0.561988 0.315623 0.581878 0.720829 -0.253763 +0.625601 -0.577368 -0.371724 -0.80142 -0.715806 0.0741293 0.778703 0.244978 +-0.868092 -0.163168 -0.707758 -0.822344 0.501819 0.74799 0.0668078 0.812413 +0.729534 0.702338 -0.134075 0.449142 0.785552 -0.701911 0.179284 0.695407 +-0.570295 -0.551425 0.291994 0.821019 0.71508 -0.664581 -0.980156 0.888598 +0.0281019 0.283294 -0.741183 0.300605 0.703548 0.109526 -0.98041 -0.28747 +-0.97019 -0.365164 -0.0386638 -0.835926 0.114051 -0.429095 -0.374637 -0.710279 +0.321577 -0.245106 -0.560334 -0.106617 0.1186 -0.49623 -0.992678 0.110437 +0.882378 -0.636962 -0.713416 0.0834107 -0.925594 -0.352722 0.656507 -0.736961 +0.584289 -0.175682 0.247739 0.617296 -0.354663 0.629163 -0.902824 0.953023 +0.0768384 -0.717327 -0.083367 -0.618186 -0.818971 0.947659 0.653877 -0.354289 +-0.887622 0.432379 0.0866054 -0.280477 0.0676555 -0.842187 -0.0842995 -0.430422 +0.173128 -0.520141 -0.087196 -0.662103 0.961155 -0.930147 0.416494 0.584796 +0.303029 0.493141 0.374201 0.472777 -0.446954 -0.793685 -0.87863 0.619676 +0.0513011 -0.987674 0.196521 -0.998323 -0.408941 -0.466114 0.361032 0.238023 +0.319364 -0.744774 0.826224 -0.727136 0.134271 0.169153 -0.350912 0.910232 +0.62319 -0.639507 0.455339 0.958609 -0.133199 0.738603 -0.785951 0.35698 +-0.426425 0.0968416 -0.356231 -0.864742 0.319383 -0.493453 0.67159 0.332411 +0.602833 0.613828 -0.63591 0.514773 -0.645953 0.319409 -0.970493 0.541499 +0.0162915 -0.59027 -0.403851 0.45786 -0.385471 0.854787 -0.728109 0.0384164 +-0.508749 0.25453 0.0775355 0.997228 -0.957396 -0.198614 -0.945542 -0.695928 +-0.160811 0.659122 -0.937518 -0.974774 0.310763 -0.971708 -0.0595999 -0.0528106 +0.461159 -0.365737 -0.702777 -0.978425 0.0990154 -0.327472 -0.962762 0.350789 +0.795224 0.381523 -0.938263 0.479238 -0.632396 -0.0509792 0.0153148 -0.265597 +-0.0848166 0.379515 -0.291117 0.694128 0.748272 -0.493666 -0.815691 -0.6926 +-0.165031 -0.0891072 0.158474 0.10956 -0.19114 -0.77 -0.780464 0.434505 +-0.139721 -0.544348 -0.750748 -0.293889 0.757612 0.818742 -0.228336 -0.544192 +-0.858 0.358474 0.543263 0.455568 -0.598232 -0.917574 0.380048 0.780082 +-0.515837 -0.855985 0.82244 -0.477901 0.646268 -0.570199 -0.430683 0.717503 +0.717701 0.699 0.462546 0.752024 -0.981553 -0.201349 -0.761635 0.330898 +-0.479242 -0.289216 -0.0796746 -0.135831 -0.888534 -0.978519 -0.193643 0.963184 +-0.116307 0.539999 0.936034 0.531333 -0.407026 -0.506016 -0.307663 -0.91202 +-0.881043 0.537134 -0.0208986 0.790174 0.160322 0.86974 0.0347648 0.556077 +0.149292 0.89986 -0.451053 0.640971 -0.179916 -0.34306 -0.837172 0.193749 +-0.126208 -0.0227467 -0.0916505 0.872552 -0.451527 -0.225225 -0.536412 -0.484111 +0.85332 -0.370758 -0.219432 0.806461 -0.771842 0.299293 0.826374 -0.377133 +0.0974112 -0.294711 0.0150352 -0.0237784 0.723876 -0.0288437 0.787362 0.340541 +-0.358887 -0.925932 -0.0877449 0.149521 -0.941664 -0.822475 0.48412 0.420145 +0.891805 -0.435028 0.640123 -0.100903 -0.913005 -0.802434 0.221251 -0.926006 +-0.59743 -0.998152 -0.159239 -0.121085 0.0891031 -0.19614 0.71132 0.509863 +-0.766773 -0.965367 -0.66386 -0.934419 0.898039 0.44383 -0.595711 0.275202 +-0.733219 0.715742 0.559052 0.840434 -0.600565 -0.908047 0.498603 0.211169 +0.583786 -0.813278 -0.822209 -0.632192 0.929584 0.111599 -0.0819159 -0.483515 +0.0372694 0.0395407 0.61394 0.302753 -0.844206 0.851324 -0.426415 0.692142 +0.864924 -0.373763 -0.444911 -0.939984 -0.523362 -0.0627783 -0.398258 0.191987 +0.00846989 -0.0237791 -0.064829 0.429948 -0.635047 -0.657757 -0.93342 -0.525435 +0.0152487 0.89563 -0.908316 0.151498 0.534151 -0.23771 -0.247125 0.676604 +0.718967 -0.391562 -0.509936 0.0940794 -0.591401 -0.0237542 0.0989418 0.667505 +0.642065 -0.808021 -0.668695 0.825106 -0.89777 0.436322 0.0146317 -0.84359 +0.947917 0.247783 0.797738 0.904664 -0.304274 -0.860577 0.583235 -0.15636 +0.802703 -0.648104 -0.74956 -0.903054 0.298878 0.673866 0.32473 -0.0477731 +0.360735 0.617388 0.0941327 -0.469065 0.784298 0.627796 0.0719741 -0.468131 +0.831949 0.890218 0.302191 -0.024926 0.554097 -0.391123 0.543936 0.710791 +-0.13657 -0.858949 -0.565543 -0.202202 0.904933 -0.522611 -0.700196 -0.0706605 +0.68578 0.785019 -0.373929 0.320873 -0.22783 -0.983629 0.20534 0.0679298 +0.054554 -0.285939 0.0105797 0.00241309 -0.961614 0.760555 -0.712269 0.18321 +0.112195 -0.928513 -0.917439 0.447439 0.694376 0.0474544 -0.957016 0.415338 +0.565741 -0.179495 0.15515 -0.130722 0.309835 0.391258 0.300341 0.782176 diff --git a/external/ann_1.1.1/test/test2-query.pts b/external/ann_1.1.1/test/test2-query.pts new file mode 100644 index 0000000..9498e86 --- /dev/null +++ b/external/ann_1.1.1/test/test2-query.pts @@ -0,0 +1,100 @@ +0.0902484 -0.207129 -0.419567 0.485743 0.826225 -0.30962 0.694758 0.987088 +-0.410807 -0.465182 -0.836501 0.490184 0.588289 0.656408 0.325807 0.38721 +-0.532226 -0.727036 -0.52506 -0.853508 0.28637 0.938617 -0.864754 0.622397 +-0.408646 -0.522319 0.0388774 -0.893642 0.385806 0.890013 -0.38066 -0.524536 +0.916427 -0.941696 0.219294 -0.971436 -0.706532 0.566439 -0.0591963 0.27756 +0.692452 -0.210879 0.927987 0.587037 0.610211 0.895158 -0.228196 -0.314064 +-0.13253 0.711121 0.605841 0.771335 -0.945103 0.356652 0.00215608 -0.54444 +0.0611156 0.921316 0.245255 0.92896 0.562614 0.160313 -0.457179 -0.432326 +-0.813199 -0.0630237 0.149021 0.0301869 0.669399 0.984082 -0.304983 0.480589 +0.311004 0.515906 -0.667349 -0.464028 -0.554472 0.123471 -0.932191 0.153486 +0.488214 -0.456547 0.695901 -0.693933 -0.775879 -0.940794 0.710796 -0.79388 +-0.73914 -0.733084 0.300943 0.0726274 -0.722715 -0.414562 0.463033 -0.378469 +-0.178166 -0.846243 -0.319029 0.186783 -0.364517 0.915747 -0.300208 -0.599272 +-0.544192 0.173829 -0.0957917 0.889828 0.775796 0.148865 -0.430932 0.0342097 +-0.969596 -0.545995 -0.98045 -0.57569 0.465756 -0.166752 0.622912 -0.580526 +0.0918901 0.635361 -0.934228 -0.0273098 0.65055 0.227406 -0.628807 0.213824 +0.216987 -0.653221 -0.789576 0.6252 0.124467 0.477613 -0.259097 0.913287 +0.587512 0.377176 -0.393846 0.293478 0.275818 -0.298198 0.063539 -0.592623 +0.867649 0.64842 -0.929959 0.677208 -0.302289 -0.230779 0.267189 -0.140577 +-0.360362 0.910053 -0.26718 0.167234 -0.0203549 -0.190717 -0.291433 0.756657 +0.637052 0.538531 0.200832 0.420082 0.688092 0.500134 0.78368 -0.542742 +0.00257324 0.53221 -0.899835 0.503303 -0.46265 0.13425 -0.66756 0.125758 +-0.28673 -0.255891 0.0805643 0.154396 -0.304337 0.942248 0.404729 -0.530016 +0.330364 -0.469459 0.492101 0.923757 -0.0870035 0.114578 -0.321104 0.586945 +0.104922 -0.620678 -0.27497 0.905927 0.219188 -0.495436 -0.762684 0.557364 +-0.665582 -0.75013 -0.249321 0.667873 -0.288485 -0.765806 -0.45304 0.919665 +-0.493835 0.239472 -0.917625 0.418003 0.273087 0.54198 -0.836992 -0.842215 +-0.576808 -0.958153 0.73833 0.0770337 -0.82097 0.0731924 -0.192127 -0.369044 +-0.204979 -0.564608 -0.792166 0.356056 -0.50905 -0.217096 -0.45753 -0.998959 +0.735413 0.347442 -0.644887 0.178 0.935974 -0.630639 -0.624678 0.946812 +0.72101 -0.881322 -0.0914539 0.80997 0.619855 0.299585 -0.0544264 -0.932907 +-0.454196 0.903609 0.216595 -0.515838 0.650697 0.322145 -0.0598022 0.29879 +0.56218 0.548496 0.116056 -0.109011 0.35975 0.375862 -0.473017 0.179013 +0.790441 0.202804 0.370116 -0.299956 -0.789657 0.66881 -0.429629 -0.203547 +0.870951 -0.240769 0.472253 -0.874723 -0.67061 -0.434253 0.661868 -0.515051 +-0.45736 0.0815795 0.924138 0.0979838 -0.00884649 0.0643335 0.803118 -0.542487 +-0.177146 -0.625442 -0.840198 -0.158722 -0.596283 -0.673887 -0.738309 0.439504 +0.186587 -0.465294 0.81993 0.754213 -0.929469 0.5224 -0.567962 -0.0020964 +-0.727445 0.654887 0.237451 -0.81993 0.461061 -0.330429 -0.423304 -0.11565 +-0.638766 -0.623638 0.33871 -0.295169 -0.864833 0.715051 -0.443567 0.530583 +0.81889 0.288548 -0.558678 -0.588774 -0.961246 0.46669 0.585559 0.566684 +-0.336336 0.911721 -0.353767 -0.387489 -0.0397957 -0.544424 0.388611 -0.49438 +0.389995 -0.989308 0.0531768 -0.119235 0.8707 0.190555 -0.829453 -0.0377095 +-0.754985 0.722122 -0.486071 -0.0543854 -0.00514588 -0.0407811 -0.923871 0.768664 +-0.257839 -0.963332 0.27127 0.90108 0.2946 0.295975 0.133463 -0.203565 +0.128047 -0.0221978 0.565967 0.441817 -0.885341 -0.294394 0.752 0.655274 +0.455767 -0.659883 0.40248 0.600338 -0.83844 -0.844635 -0.436961 -0.694439 +0.494475 -0.85312 -0.703241 -0.0320226 -0.0312604 -0.804464 -0.967423 0.134369 +-0.823558 0.72077 0.692424 -0.331696 0.28281 0.956438 -0.512021 0.343271 +-0.120567 0.85007 -0.634148 0.479445 0.999095 -0.362764 -0.547786 0.0405272 +-0.759062 -0.595061 0.891393 -0.772615 0.699682 0.433783 0.496053 0.989183 +-0.830714 0.673363 -0.774558 -0.428386 -0.163786 -0.576139 0.870208 -0.403316 +-0.358526 -0.816022 -0.40667 0.888208 0.0927729 0.567724 -0.993948 -0.315037 +0.173889 0.324026 0.971654 0.445513 -0.836598 -0.335657 -0.193173 0.544429 +-0.383334 0.0514736 -0.667312 -0.650427 -0.173149 -0.785155 -0.427284 -0.773588 +-0.942451 -0.429928 -0.296064 0.478439 -0.21067 -0.583727 -0.172756 -0.867286 +0.0722371 0.969577 -0.667728 -0.673244 0.975295 -0.468511 0.283715 -0.838649 +-0.135551 0.0966441 -0.899046 -0.107455 -0.233247 -0.784231 -0.273956 -0.735285 +-0.0414323 0.633082 0.756714 -0.941008 0.7334 -0.558333 0.515249 -0.0495845 +0.151553 0.897797 0.535985 -0.435869 0.276652 0.950385 -0.588415 -0.908762 +0.836871 -0.309154 0.542942 -0.555574 0.296423 -0.852823 0.0586046 0.907905 +-0.037232 -0.50382 0.828129 0.852639 -0.187631 0.110954 -0.520551 0.2231 +-0.669727 -0.670437 -0.395765 0.938759 -0.71912 -0.299401 -0.857412 0.136054 +-0.426925 -0.323029 0.847521 -0.768077 -0.737279 -0.73427 0.409976 -0.424011 +-0.485806 -0.842531 0.425504 0.928987 0.885911 0.193509 -0.786534 -0.0521742 +0.477176 0.948246 -0.81151 -0.461006 0.140611 -0.0403634 0.904953 0.527849 +0.278327 -0.960566 -0.745472 0.449632 -0.221733 -0.67303 0.0901394 -0.365342 +0.350109 0.412389 0.22772 -0.743153 0.374894 -0.674853 -0.940435 0.284267 +0.0780486 0.00241877 -0.793647 -0.801883 -0.931572 -0.906159 -0.325908 0.129096 +0.251037 -0.32573 -0.0132674 0.16178 -0.391019 0.541115 0.186404 0.804935 +-0.457725 0.0676978 -0.679403 -0.287371 -0.0475436 -0.433919 -0.777655 -0.648854 +-0.0915583 -0.911684 -0.450737 0.330562 0.51434 -0.989688 -0.394102 0.621241 +-0.475504 -0.0645391 0.836504 0.636607 -0.294769 0.747648 -0.23722 0.750184 +-0.767895 -0.446372 0.758335 -0.407514 -0.304965 0.551426 0.467747 0.962403 +-0.550376 0.261992 0.65622 -0.274081 0.87838 0.931551 -0.329732 0.0551602 +0.911471 0.324545 0.0503461 -0.796273 0.150228 0.760694 -0.428716 -0.677338 +0.320243 0.908401 -0.406211 -0.0914938 -0.0383119 0.971036 -0.996626 -0.420682 +-0.632748 0.159697 0.350173 0.188661 -0.463423 -0.79209 -0.321071 -0.849934 +-0.493952 0.59222 -0.239915 0.0675535 -0.209439 -0.896104 0.215966 -0.804748 +0.470257 -0.814033 0.0936659 -0.279521 0.631632 -0.00510561 -0.694679 -0.554847 +0.0193325 -0.515019 -0.502347 -0.0691725 0.0823693 0.218677 0.484909 0.230698 +0.411173 -0.360974 -0.0687193 0.982974 -0.62282 -0.808528 0.391168 0.509953 +-0.123533 0.573365 0.918135 -0.570049 0.0766659 0.916687 -0.189227 0.105294 +-0.436078 0.565401 0.107861 -0.321394 -0.681098 0.372357 -0.911342 -0.836162 +0.20572 0.550261 -0.578777 -0.236365 -0.582914 0.473617 -0.745445 -0.401362 +-0.268776 -0.00963149 -0.870677 -0.315329 -0.327188 0.571639 -0.922104 -0.889744 +-0.653846 0.42571 0.484338 0.786735 -0.924095 -0.777902 0.424617 -0.11099 +0.314249 -0.488492 -0.09607 -0.285476 -0.257726 -0.803911 -0.806167 0.4756 +-0.41036 -0.669857 -0.36997 0.551767 -0.906633 0.189437 -0.684472 -0.449454 +-0.813612 -0.0906479 0.286132 0.680878 0.675851 0.0646878 -0.2403 -0.310925 +-0.685114 0.0677462 -0.95481 -0.179017 0.857301 -0.87579 -0.329674 0.562246 +0.0735071 -0.575949 0.50454 -0.686882 -0.0657996 0.874931 0.927272 -0.333088 +-0.245092 -0.109308 -0.713837 -0.613438 -0.0236157 0.140357 -0.512282 -0.518118 +0.184375 -0.865972 0.707001 -0.612003 0.67617 -0.709794 -0.885369 0.826005 +-0.157901 0.836454 0.245372 0.589479 -0.930075 0.106183 0.420879 -0.510301 +-0.466877 -0.115361 -0.736242 0.493482 -0.785855 -0.55306 0.617798 -0.904856 +-0.830296 0.557992 -0.204564 -0.500123 0.153565 -0.773108 0.287265 0.823092 +0.986858 -0.323913 -0.914362 0.535652 -0.535098 -0.945814 0.974316 0.434805 +0.732686 0.221111 0.559403 0.584674 -0.447866 0.508206 0.907212 -0.782827 +-0.970814 -0.13434 -0.550199 0.523038 -0.373701 -0.359454 0.0321578 0.840907 diff --git a/external/ann_1.1.1/test/test2.in b/external/ann_1.1.1/test/test2.in new file mode 100644 index 0000000..7b55854 --- /dev/null +++ b/external/ann_1.1.1/test/test2.in @@ -0,0 +1,21 @@ + validate on + stats query_stats + dim 8 + data_size 5000 +read_data_pts test2-data.pts + query_size 100 +read_query_pts test2-query.pts + bucket_size 1 + near_neigh 3 + split_rule suggest + shrink_rule none +build_ann + epsilon 0.0 +run_queries standard +run_queries priority + epsilon 0.10 +run_queries standard +run_queries priority + epsilon 0.50 +run_queries standard +run_queries priority diff --git a/external/ann_1.1.1/test/test2.save b/external/ann_1.1.1/test/test2.save new file mode 100644 index 0000000..9cffce1 --- /dev/null +++ b/external/ann_1.1.1/test/test2.save @@ -0,0 +1,156 @@ +------------------------------------------------------------ +ann_test: Version 1.0 + Copyright: David M. Mount and Sunil Arya. + Latest Revision: Mar 1, 2005. +------------------------------------------------------------ + +validate = on (Warning: this may slow execution time.) +stats = query_stats +[Read Data Points: + data_size = 5000 + file_name = test2-data.pts + dim = 8 +] +[Read Query Points: + query_size = 100 + file_name = test2-query.pts + dim = 8 +] +[Build ann-structure: + split_rule = suggest + shrink_rule = none + data_size = 5000 + dim = 8 + bucket_size = 1 + process_time = 0.18 sec + (Structure Statistics: + n_nodes = 9999 (opt = 10000, best if < 100000) + n_leaves = 5000 (0 contain no points) + n_splits = 4999 + n_shrinks = 0 + empty_leaves = 0 percent (best if < 50 percent) + depth = 17 (opt = 12, best if < 196) + avg_aspect_ratio = 2.03396 (best if < 20) + ) +] +(Computing true nearest neighbors for validation. This may take time.) +[Run Queries: + query_size = 100 + dim = 8 + search_method = standard + epsilon = 0 + near_neigh = 3 + true_nn = 13 + query_time = 0.0008 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 269.6 : 154.1 ]< 68 , 1046 > + splitting_nodes = [ 448.2 : 259.2 ]< 100 , 1858 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 717.8 : 412.6 ]< 168 , 2904 > + points_visited = [ 269.6 : 154.1 ]< 68 , 1046 > + coord_hits/pt = [ 0.1975 : 0.1075 ]< 0.0446 , 0.6974 > + floating_ops_(K) = [ 8.492 : 4.716 ]< 1.939 , 32.61 > + average_error = [ 0 : 0 ]< 0 , 0 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] +[Run Queries: + query_size = 100 + dim = 8 + search_method = priority + epsilon = 0 + near_neigh = 3 + true_nn = 13 + query_time = 0.0011 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 237.7 : 131.6 ]< 68 , 801 > + splitting_nodes = [ 408.1 : 227.7 ]< 100 , 1398 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 645.8 : 358.5 ]< 168 , 2149 > + points_visited = [ 237.7 : 131.6 ]< 68 , 801 > + coord_hits/pt = [ 0.1679 : 0.08993 ]< 0.0472 , 0.5492 > + floating_ops_(K) = [ 10.83 : 6.344 ]< 2.638 , 38.3 > + average_error = [ 0 : 0 ]< 0 , 0 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] +[Run Queries: + query_size = 100 + dim = 8 + search_method = standard + epsilon = 0.1 + near_neigh = 3 + true_nn = 13 + query_time = 0.0006 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 200.9 : 115.8 ]< 51 , 762 > + splitting_nodes = [ 344.9 : 202.4 ]< 77 , 1407 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 545.9 : 317.4 ]< 128 , 2169 > + points_visited = [ 200.9 : 115.8 ]< 51 , 762 > + coord_hits/pt = [ 0.1548 : 0.08517 ]< 0.0348 , 0.5494 > + floating_ops_(K) = [ 6.606 : 3.703 ]< 1.513 , 25.14 > + average_error = [ 0 : 0 ]< 0 , 0 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] +[Run Queries: + query_size = 100 + dim = 8 + search_method = priority + epsilon = 0.1 + near_neigh = 3 + true_nn = 13 + query_time = 0.0007 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 176.1 : 101.1 ]< 49 , 629 > + splitting_nodes = [ 314.3 : 186.9 ]< 77 , 1285 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 490.4 : 286.6 ]< 128 , 1914 > + points_visited = [ 176.1 : 101.1 ]< 49 , 629 > + coord_hits/pt = [ 0.1309 : 0.07112 ]< 0.0374 , 0.4332 > + floating_ops_(K) = [ 8.205 : 4.999 ]< 2.032 , 33.27 > + average_error = [ 0 : 0 ]< 0 , 0 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] +[Run Queries: + query_size = 100 + dim = 8 + search_method = standard + epsilon = 0.5 + near_neigh = 3 + true_nn = 13 + query_time = 0.0002 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 83.07 : 46.06 ]< 23 , 264 > + splitting_nodes = [ 163.4 : 94.86 ]< 42 , 512 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 246.5 : 140.2 ]< 67 , 776 > + points_visited = [ 83.07 : 46.06 ]< 23 , 264 > + coord_hits/pt = [ 0.0765 : 0.03992 ]< 0.0182 , 0.2192 > + floating_ops_(K) = [ 3.224 : 1.734 ]< 0.891 , 9.572 > + average_error = [ 0.0009039 : 0.009619 ]< 0 , 0.1516 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] +[Run Queries: + query_size = 100 + dim = 8 + search_method = priority + epsilon = 0.5 + near_neigh = 3 + true_nn = 13 + query_time = 0.0004 sec/query (biased by perf measurements) + (Performance stats: [ mean : stddev ]< min , max > + leaf_nodes = [ 69.72 : 38.29 ]< 21 , 246 > + splitting_nodes = [ 146.8 : 81.69 ]< 40 , 475 > + shrinking_nodes = [ 0 : 0 ]< 0 , 0 > + total_nodes = [ 216.5 : 118.8 ]< 65 , 721 > + points_visited = [ 69.72 : 38.29 ]< 21 , 246 > + coord_hits/pt = [ 0.06206 : 0.03155 ]< 0.0182 , 0.194 > + floating_ops_(K) = [ 3.608 : 1.989 ]< 1.126 , 12.28 > + average_error = [ 0.001425 : 0.011 ]< 0 , 0.1516 > + rank_error = [ 0 : 0 ]< 0 , 0 > + ) +] diff --git a/include/figtree.h b/include/figtree.h index 909a6cd..2ae263e 100644 --- a/include/figtree.h +++ b/include/figtree.h @@ -45,9 +45,52 @@ // maxRange parameter to figtreeChoose* functions. // // Modified: 01-22-08 by Vlad Morariu -// Rename library to FIGTree (and some -// other function remanimg) +// Rename library to FIGTree (and some other function renamimg) // +// Modified: 05-03-08 by Vlad Morariu +// Add initial version of method selection code. +// +// Modified: 05-27-08 by Vlad Morariu +// Change figtreeChooseParameters* and figtreeChooseTruncationNumber functions +// to return the predicted errorBound. This can then be used to check if +// the parameters chosen will satisfy the desired error bound (they may not +// since we enforce a limit on pMax (the truncation number). +// +// Modified: 05-29-08 to 06-10-08 by Vlad Morariu +// Make changes for 'Automatic online tuning for fast Gaussian summation,' by +// Morariu et al, NIPS 2008. Changes include automatic parameter selection +// improvements, point-wise and cluster-wise truncation number selection, and +// automatic method selection. These changes make this approach much easier +// to use since the user does not need to choose parameters. +// 1) Added code to choose individual truncation numbers for both targets and sources +// using pointwise error bounds. +// 2) Added code to choose individual truncation numbers for targets and sources +// using clusterwise error bounds. +// 3) Reuse K-center clustering computed during method selection if +// FIGTREE_EVAL_AUTO is chosen. +// 4) Changed ANN code to compute unordered nearest neighbors, saving time +// by not using a priority queue and also because now the fixed radius +// nearest neighbor computation and retrieval is done in one step, +// instead of first finding # of nn's and then doing the search again to +// retrieve the nn's. This really speeds up direct+tree since the ANN +// priority queue was implemented using insertion sort. +// +// Modified: 11-02-08, 12-01-08 to 12-05-08 by Vlad Morariu +// Made some revisions before posting new version online. +// 1) Changed interface of figtree so users can choose truncation method +// (also changed figtree() to automatically revert to the simplest +// truncation method in cases where the two more complex methods +// cannot give a speedup). +// 2) Revised some comments +// 3) Found all parameters used throughout code and defined constants for them +// so that users can change them and recompile. In future releases, +// these should only be defaults, and users should be able to modify them +// at runtime. +// 4) Removed most helper functions from figtree.h (all but figtree(), +// figtreeChooseEvaluationMethod(), and figtreeKCenterClustering() ) and +// placed them in figtree_internal.h. +// 5) Changed floating op estimation functions to reflect revised versions +// of code //------------------------------------------------------------------------------ // The code was written by Vlad Morariu, Vikas Raykar, and Changjiang Yang @@ -103,20 +146,46 @@ extern "C" { #endif + + + //------------------------------------------------------------------------------ +// // Some useful constants for the figtree() function call +// +//------------------------------------------------------------------------------ + +// Constants for choosing evaluation method #define FIGTREE_EVAL_DIRECT 0 // direct evaluation of gauss transform #define FIGTREE_EVAL_IFGT 1 // truncated taylor series evaluation -#define FIGTREE_EVAL_DIRECT_TREE 2 // direct evaluation, with tree on sources -#define FIGTREE_EVAL_IFGT_TREE 3 // truncated taylor series, with tree on - // cluster centers +#define FIGTREE_EVAL_DIRECT_TREE 2 // direct evaluation +#define FIGTREE_EVAL_IFGT_TREE 3 // ifgt+tree +#define FIGTREE_EVAL_AUTO 4 // automatically chooses one of the four +#define FIGTREE_EVAL_SIZE 5 // total number of eval methods +// Constants for choosing parameter selection method for IFGT #define FIGTREE_PARAM_UNIFORM 0 // estimate params assuming sources are - // uniformly distributed + // uniformly distributed (not recommended + // for non-uniform data) #define FIGTREE_PARAM_NON_UNIFORM 1 // estimate params by using actual source // distribution (runs k-center clustering // twice, but speedup during evaluation // more than makes up for it in general) +#define FIGTREE_PARAM_SIZE 2 // total number of param estimation methods + +// Constants for choosing truncation selection method for IFGT +#define FIGTREE_TRUNC_MAX 0 // use worst case truncation number for all pts +#define FIGTREE_TRUNC_POINT 1 // use point-wise error bounds for individual truncations +#define FIGTREE_TRUNC_CLUSTER 2 // use cluster-wise error bounds for individual truncations +#define FIGTREE_TRUNC_SIZE 3 // total number of truncation selection methods + +//------------------------------------------------------------------------------ +// +// Main functions exported by the library. For more control over internal +// workings of figtree, see figtree_internal.h and figtree.cpp. +// +//------------------------------------------------------------------------------ + // Note: All matrix pointers are assumed to point to a contiguous one // dimensional array containing the entries of the matrx in row major format. @@ -124,11 +193,7 @@ extern "C" { // ptr[0] ... ptr[N-1] contains the first row of the matrix, and so on. // Evaluates gauss transform in one shot (chooses parameters and does clustering -// if necessary, and evaluates). This is the main function since it calls all -// the functions provided below. If more flexibility is required than this -// function allows, use the functions provided below (eg. it is possible that -// clustering needs to be done only once for a set of sources and then multiple -// evaluations are done using same parameters and clustering). +// if necessary, and evaluates). // // Input // * d --> data dimensionality. @@ -151,12 +216,12 @@ extern "C" { // IFGT_TREE], defined above. epsilon is needed for all but // DIRECT method. Parameter selection is done only in the IFGT // or IFGT_TREE case. -// * paramMethod --> the method to use for determining parameters. -// Can be FIGTREE_PARAM_UNIFORM or FIGTREE_PARAM_NON_UNIFORM. +// * ifgtParamMethod --> the method to use for determining parameters. +// Can be FIGTREE_PARAM_UNIFORM or FIGTREE_PARAM_NON_UNIFORM. +// * ifgtTruncMethod --> the method to use for determining where to truncate +// Taylor series for each source and target point. Can be +// FIGTREE_TRUNC_MAX, FIGTREE_TRUNC_POINT, and FIGTREE_TRUNC_CLUSTER // * verbose --> if nonzero, prints parameters chosen for evaluation -// * forceK --> if zero, the number of clusters(K) is determined by parameter -// selection. If nonzero, forceK overrides the K chosen by -// parameter selection. // // Output // * g --> W x M vector of the Gauss Transform evaluated at each target point. @@ -165,85 +230,52 @@ extern "C" { FIGTREE_DLL_API int figtree( int d, int N, int M, int W, double * x, double h, double * q, double * y, double epsilon, double * g, - int evalMethod = FIGTREE_EVAL_IFGT, - int paramMethod = FIGTREE_PARAM_NON_UNIFORM, - int verbose = 0, int forceK = 0 ); - -// Given the maximum cluster radius, this function computes the maximum -// truncation number that guarantees results within the desired error bound. -//Input -// * d --> dimension of the points. -// * h --> the source bandwidth. -// * epsilon --> the desired error. -// * rx --> maximum cluster radius -// * maxRange --> max dimension range. The range along a dimension is -// the difference between the max and min values that can ever -// occur along that dimension. The max dimension range is the -// maximum range among all dimensions. For example, if all -// points lie in unit hypercube, then maxRange = 1. -// -//Output -// * pMax --> maximum truncation number for the Taylor series. -FIGTREE_DLL_API -int figtreeChooseTruncationNumber( int d, double h, double epsilon, - double rx, double maxRange, int * pMax ); + int evalMethod = FIGTREE_EVAL_AUTO, + int ifgtParamMethod = FIGTREE_PARAM_NON_UNIFORM, + int ifgtTruncMethod = FIGTREE_TRUNC_CLUSTER, + int verbose = 0 ); -// Chooses parameters for IFGT and FIGTree by assuming that sources are -// uniformly distributed in a unit cube. -//Input -// * d --> dimension of the points. -// * h --> the source bandwidth. -// * epsilon --> the desired error. -// * kLimit --> upper limit on the number of clusters, kLimit. -// * maxRange --> max dimension range. The range along a dimension is -// the difference between the max and min values that can ever -// occur along that dimension. The max dimension range is the -// maximum range among all dimensions. For example, if all -// points lie in unit hypercube, then maxRange = 1. -// -//Note : [ Use roughly kLimit=round(40*sqrt(d)/h) ] -//Output -// * K --> number of clusters. -// * pMax --> maximum truncation number for the Taylor series. -// * r --> source cutoff radius. -FIGTREE_DLL_API -int figtreeChooseParametersUniform( int d, double h, double epsilon, - int kLimit, double maxRange, - int * K, int * pMax, double * r ); - -// Chooses parameters for IFGT and FIGTree without assumption that sources are -// uniformly distributed. In this case, k-center clustering is done as part -// of the parameter selection so that the radius of each cluster is not -// estimated but computed directly for the sources. This results in an -// additional k-center clustering operation, but the speedup when sources are -// not uniformly distributed can be large because -// optimal parameters are much more accurately estimated. Even when sources are -// uniformly distributed, the slowdown is often small compared to -// figtreeChooseParametersUniform. -// +// Chooses between evaluation methods // Input -// * d --> dimension of the points. +// * d --> data dimensionality. // * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This is useful if one needs multiple gauss transforms that have +// the same sources, targets, and bandwidth, but different +// weights/strengths (q). By computing coefficients for all W weight +// sets at once, we avoid duplicating much of the overhead. However, +// more memory is needed to store a set of coefficients for each set +// of weights. // * x --> N x d matrix of N source points in d dimensions. -// * h --> the source bandwidth. -// * epsilon --> the desired error. -// * kLimit --> upper limit on the number of clusters, K. -// Note : Use kLimit=N to allow for optimal param estimation. -// * maxRange --> max dimension range. The range along a dimension is -// the difference between the max and min values that can ever -// occur along that dimension. The max dimension range is the -// maximum range among all dimensions. For example, if all -// points lie in unit hypercube, then maxRange = 1. +// * h --> the source scale or bandwidth. +// * y --> M x d matrix of M target points in d dimensions. +// * epsilon --> desired error +// * paramMethod --> the method to use for determining parameters. +// Can be FIGTREE_PARAM_UNIFORM or FIGTREE_PARAM_NON_UNIFORM. +// * verbose --> if nonzero, prints parameters chosen for evaluation +// // Output -// * K --> number of clusters. -// * pMax --> maximum truncation number for the Taylor series. -// * r --> source cutoff radius. -FIGTREE_DLL_API -int figtreeChooseParametersNonUniform( int d, int N, double * x, - double h, double epsilon, int kLimit, double maxRange, - int * K, int * pMax, double * r ); +// * bestEvalMethod --> if non-NULL, the evaluation method to use in evaluating gauss +// transform. Can be FIGTREE_EVAL_[DIRECT,IFGT,DIRECT_TREE, +// IFGT_TREE], defined above. +// +// * flops --> if non-NULL, a double array of size FIGTREE_EVAL_SIZE, indexed by eval method +// type where flops[evalMethod] = estimated number of flops if we use this method. +// For evalMethod=FIGTREE_EVAL_IFGT or evalMethod=FIGTREE_EVAL_IFGT_TREE, +// it is possible that flops[.] = -1 in the case that it is decided early (before +// finishing the estimation) that these two methods will be slower than +// FIGTREE_EVAL_DIRECT or FIGTREE_EVAL_DIRECT_TREE +// * data_struct --> a structure that keeps some structures (k-center clustering, other params) +// that were computed during method selection that can be reused +// +FIGTREE_DLL_API +int figtreeChooseEvaluationMethod( int d, int N, int M, int W, double * x, double h, + double * y, double epsilon, int paramMethod=FIGTREE_PARAM_NON_UNIFORM, int verbose=0, + int * bestEvalMethod=0, double * flops=0, void * data_struct=0 ); -// Gonzalez's farthest-point clustering algorithm. O(N log K) version. + +// Gonzalez's farthest-point clustering algorithm. // // Input // * d --> data dimensionality. @@ -267,149 +299,6 @@ int figtreeKCenterClustering( int d, int N, double * x, int kMax, int * K, double * rx, int * clusterIndex, double * clusterCenters, int * numPoints, double * clusterRadii ); -// Computes exact gauss transform (within machine precision) using direct -// evaluation. Provided for time/error comparison. -// -// Input -// * d --> data dimensionality. -// * N --> number of source points. -// * M --> number of target points. -// * x --> N x d matrix of N source points in d dimensions. -// * h --> the source scale or bandwidth. -// * q --> 1 x N or N x 1 vector of the source strengths. -// * y --> M x d matrix of M target points in d dimensions. -// -// Output -// * g --> 1 x M vector of the Gauss Transform evaluated at each target -// point. -FIGTREE_DLL_API -int figtreeEvaluateDirect( int d, int N, int M, double * x, double h, - double * q, double * y, double * g ); - -// Computes an approximation to Gauss Transform. Implementation based on: -// Fast computation of sums of Gaussians in high dimensions. Vikas C. Raykar, -// C. Yang, R. Duraiswami, and N. Gumerov, CS-TR-4767, Department of computer -// science, University of Maryland, College Park. -// -// Input -// * d --> data dimensionality. -// * N --> number of source points. -// * M --> number of target points. -// * W --> number of weights that will be used for each source point. -// This really does multiple transforms, with different weights each -// time but with same sources and targets. This saves a lot of time -// since most of the work is not duplicated. However, it requires -// more memory to store the coefficients for each set of weights. -// * x --> N x d matrix of N source points in d dimensions. -// * h --> the source scale or bandwidth. -// * q --> W x N vector of the source strengths. -// * y --> M x d matrix of M target points in d dimensions. -// * pMax --> maximum truncation number for the Taylor series. -// * K --> the number of clusters. -// * clusterIndex --> N x 1 vector the i th element is the cluster number -// to which the i th point belongs. [ ClusterIndex[i] varies between -// 0 to K-1. ] -// * clusterCenter --> K x d matrix of K cluster centers. -// * clusterRadii --> K x 1 matrix of the radius of each cluster. -// * r --> cutoff radius -// * epsilon --> desired error -// -//Output -// * g --> W x M vector of the Gauss Transform evaluated at each target -// point. Each row q is the result of the transform using the qth set -// of weights. -FIGTREE_DLL_API -int figtreeEvaluateIfgt( int d, int N, int M, int W, double * x, - double h, double * q, double * y, - int pMax, int K, int * clusterIndex, - double * clusterCenter, double * clusterRadii, - double r, double epsilon, double * g ); - -// Computes an approximation to Gauss Transform using approximate -// nearest-neighbors. Same as figtreeEvaluateIfgt() but uses Approximate -// Nearest-Neighbors library to find source clusters which influence each target -// (part of FIGTree). Parameters for this function can be computed using -// figtreeChooseParameters[Non]Uniform and figtreeKCenterClustering. -// -// Input -// * d --> data dimensionality. -// * N --> number of source points. -// * M --> number of target points. -// * W --> number of weights that will be used for each source point. -// This really does multiple transforms, with different weights each -// time but with same sources and targets. This saves a lot of time -// since most of the work is not duplicated. However, it requires -// more memory to store the coefficients for each set of weights. -// * x --> N x d matrix of N source points in d dimensions. -// * h --> the source scale or bandwidth. -// * q --> W x N vector of the source strengths. -// * y --> M x d matrix of M target points in d dimensions. -// * pMax --> maximum truncation number for the Taylor series. -// * K --> the number of clusters. -// * clusterIndex --> N x 1 vector the i th element is the cluster number -// to which the i th point belongs. [ ClusterIndex[i] varies between -// 0 to K-1. ] -// * clusterCenter --> K x d matrix of K cluster centers. -// * clusterRadii --> K x 1 matrix of the radius of each cluster. -// * r --> cutoff radius -// * epsilon --> desired error -// -// Output -// * g --> W x M vector of the Gauss Transform evaluated at each target -// point. Each row of g is the result of the transform using one set -// of weights. -FIGTREE_DLL_API -int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, - double h, double * q, double * y, - int pMax, int K, int * clusterIndex, - double * clusterCenter, double * clusterRadii, - double r, double epsilon, double * g ); - -// Computes an approximation to Gauss Transform using approximate -// nearest-neighbors. Direct method (no taylor expansion is done), with tree -// directly on samples (part of FIGTree). Requires Approximate -// Nearest-Neighbor(ANN) library. -// -// Input -// * d --> data dimensionality. -// * N --> number of source points. -// * M --> number of target points. -// * x --> N x d matrix of N source points in d dimensions. -// * h --> the source scale or bandwidth. -// * q --> 1 x N vector of the source strengths. -// * y --> M x d matrix of M target points in d dimensions. -// * epsilon --> desired error -// -// Output -// * g --> 1 x M vector of the Gauss Transform evaluated at each target -// point. -FIGTREE_DLL_API -int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, - double * q, double * y, double epsilon, double * g ); - -// Computes min and max values along each dimension. Used to determine -// the size of the hypercube (and the max distance R that any two pts -// can be from each other). -// -// Input -// * d --> data dimensionality. -// * n --> number of source points. -// * x --> n x d matrix of n source points in d dimensions. -// * mins --> d x 1 vector of minimum values; input values ignored if update == 0 -// * maxs --> d x 1 vector of maximum values; input values ignored if update == 0 -// * update --> if set to 1, then max[i] will contain -// max(max of values of all samples along dimension i, max[i] input value), and -// similarly for min[i]. -// -// Output -// * mins --> d x 1 vector of minimum values -// * maxs --> d x 1 vector of maximum values -FIGTREE_DLL_API -int figtreeCalcMinMax( int d, int n, double * x, double * mins, double * maxs, int update=0 ); - -FIGTREE_DLL_API -int figtreeCalcMaxRange( double d, double * mins, double * maxs, double * R ); - #if defined(__cplusplus) && !defined(FIGTREE_STATIC) } // extern "C" #endif diff --git a/matlab/CompileMexFilesUsingMatlab.m b/matlab/CompileMexFilesUsingMatlab.m index 662b69f..6a0c074 100644 --- a/matlab/CompileMexFilesUsingMatlab.m +++ b/matlab/CompileMexFilesUsingMatlab.m @@ -1,80 +1,14 @@ -function CompileMexFilesUsingMatlab( use_ann, ann_header_dir, ann_lib_dir ) -% Compiles the Mex files for using the FIGTree in Matlab. If no inputs -% are supplied, default values are assumed (see below). -% % Before running this file, run 'mex -setup' and make sure that gcc or g++ % are used for compiling mex files (code was only tested using gcc/g++). % -% If the ANN library is compiled as a static library (libANN.a), then it likely -% did not have -fpic or -fPIC as flags for the compiler, which can cause -% errors when linking the static library into a mex file (which is a -% dynamic library). To solve this problem, there are a couple of options: -% -% 1) compile the ANN library into a shared library (libANN.so) and -% make sure that it is in the library path or that LD_LIBRARY_PATH -% is set accordingly. (PREFERRED OPTION) -% -% 2) modify (ANNBASEDIRECTORY)/Make-config to ensure that -fpic or -fPIC -% flags are used even when compiling into a static library -% -% 3) use 'ld -G -z textoff' to link to libANN.a -% (Matlab uses 'g++ -shared') by default when using g++ compiler, which -% automatically sets '-z text' ld flag which does not allow for relocation) -% Can result in slow code. -% -% Inputs: -% use_ann - if nonzero, then the mex files will be compiled with ANN -% support, and will be linked against libANN.a or libANN.so. -% By default, mex files are compiled with ANN support. -% ann_header_dir - the directory in which ANN headers are located. -% By default ann_header_dir = '../../ann_1.1.1/include' -% ann_lib_dir - the directory in which the ANN library is located. -% By default, ann_lib_dir = '../../ann_1.1.1/lib' -% % Created: 09-12-07 by Vlad Morariu -% Modified: 10-05-07 +% Modified: 12-05-08 -if( ~exist('use_ann') || use_ann ~= 0 ) - use_ann = 1; -else - use_ann = 0; -end; if( ~isunix ) fprintf('To compile mex files in windows, you can use the VS8 projects provided.\n'); end; -if( use_ann == 0 ) - fprintf('Compiling mex files without ANN support\n'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtree.cpp','-output','figtree'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseParametersNonUniform.cpp','-output','figtreeChooseParametersNonUniform'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseParametersUniform.cpp','-output','figtreeChooseParametersUniform'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseTruncationNumber.cpp','-output','figtreeChooseTruncationNumber'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateDirect.cpp','-output','figtreeEvaluateDirect'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateDirectTree.cpp','-output','figtreeEvaluateDirectTree'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateIfgt.cpp','-output','figtreeEvaluateIfgt'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateIfgtTree.cpp','-output','figtreeEvaluateIfgtTree'); - mex('-v','-O','-I../include','-DFIGTREE_NO_ANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeKCenterClustering.cpp','-output','figtreeKCenterClustering'); -else - fprintf('Compiling mex files with ANN support\n'); - if( ~exist('ann_header_dir')) - ann_header_dir = '../../ann_1.1.1/include'; - fprintf('ann_header_dir not passed in as argument, assuming default value\n'); - fprintf('ann_header_dir=%s\n', ann_header_dir); - end; - if( ~exist('ann_lib_dir')) - ann_lib_dir = '../../ann_1.1.1/lib'; - fprintf('ann_lib_dir not passed in as argument, assuming default value\n'); - fprintf('ann_lib_dir=%s\n', ann_lib_dir); - end; - - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtree.cpp','-output','figtree'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseParametersNonUniform.cpp','-output','figtreeChooseParametersNonUniform'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseParametersUniform.cpp','-output','figtreeChooseParametersUniform'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseTruncationNumber.cpp','-output','figtreeChooseTruncationNumber'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateDirect.cpp','-output','figtreeEvaluateDirect'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateDirectTree.cpp','-output','figtreeEvaluateDirectTree'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateIfgt.cpp','-output','figtreeEvaluateIfgt'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeEvaluateIfgtTree.cpp','-output','figtreeEvaluateIfgtTree'); - mex('-v','-O','-I../include',sprintf('-I%s',ann_header_dir),sprintf('-L%s',ann_lib_dir),'-lANN','-DFIGTREE_USE_MATLAB_MEX','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeKCenterClustering.cpp','-output','figtreeKCenterClustering'); -end; \ No newline at end of file +mex('-v','-O','-I../include','-I../external/ann_1.1.1/include','-I../external/ann_1.1.1/src','-DFIGTREE_USE_MATLAB_MEX','../external/ann_1.1.1/src/ANN.cpp','../external/ann_1.1.1/src/bd_fix_rad_search.cpp','../external/ann_1.1.1/src/bd_pr_search.cpp','../external/ann_1.1.1/src/bd_search.cpp','../external/ann_1.1.1/src/bd_tree.cpp','../external/ann_1.1.1/src/brute.cpp','../external/ann_1.1.1/src/kd_dump.cpp','../external/ann_1.1.1/src/kd_fix_rad_search.cpp','../external/ann_1.1.1/src/kd_pr_search.cpp','../external/ann_1.1.1/src/kd_search.cpp','../external/ann_1.1.1/src/kd_split.cpp','../external/ann_1.1.1/src/kd_tree.cpp','../external/ann_1.1.1/src/kd_util.cpp','../external/ann_1.1.1/src/perf.cpp','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtree.cpp','-output','figtree'); +mex('-v','-O','-I../include','-I../external/ann_1.1.1/include','-I../external/ann_1.1.1/src','-DFIGTREE_USE_MATLAB_MEX','../external/ann_1.1.1/src/ANN.cpp','../external/ann_1.1.1/src/bd_fix_rad_search.cpp','../external/ann_1.1.1/src/bd_pr_search.cpp','../external/ann_1.1.1/src/bd_search.cpp','../external/ann_1.1.1/src/bd_tree.cpp','../external/ann_1.1.1/src/brute.cpp','../external/ann_1.1.1/src/kd_dump.cpp','../external/ann_1.1.1/src/kd_fix_rad_search.cpp','../external/ann_1.1.1/src/kd_pr_search.cpp','../external/ann_1.1.1/src/kd_search.cpp','../external/ann_1.1.1/src/kd_split.cpp','../external/ann_1.1.1/src/kd_tree.cpp','../external/ann_1.1.1/src/kd_util.cpp','../external/ann_1.1.1/src/perf.cpp','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeChooseEvaluationMethod.cpp','-output','figtreeChooseEvaluationMethod'); +mex('-v','-O','-I../include','-I../external/ann_1.1.1/include','-I../external/ann_1.1.1/src','-DFIGTREE_USE_MATLAB_MEX','../external/ann_1.1.1/src/ANN.cpp','../external/ann_1.1.1/src/bd_fix_rad_search.cpp','../external/ann_1.1.1/src/bd_pr_search.cpp','../external/ann_1.1.1/src/bd_search.cpp','../external/ann_1.1.1/src/bd_tree.cpp','../external/ann_1.1.1/src/brute.cpp','../external/ann_1.1.1/src/kd_dump.cpp','../external/ann_1.1.1/src/kd_fix_rad_search.cpp','../external/ann_1.1.1/src/kd_pr_search.cpp','../external/ann_1.1.1/src/kd_search.cpp','../external/ann_1.1.1/src/kd_split.cpp','../external/ann_1.1.1/src/kd_tree.cpp','../external/ann_1.1.1/src/kd_util.cpp','../external/ann_1.1.1/src/perf.cpp','../src/figtree.cpp','../src/KCenterClustering.cpp','../src/mex/mexFigtreeKCenterClustering.cpp','-output','figtreeKCenterClustering'); diff --git a/matlab/figtree.m b/matlab/figtree.m index 6ecf9dc..cb11ff6 100644 --- a/matlab/figtree.m +++ b/matlab/figtree.m @@ -1,60 +1,64 @@ -function [G] = figtree(d, N, M, W, x, h, q, y, epsilon, evalMethod, paramMethod, verbose, forceK) -% -% Fast computation of the Gauss Transform. -% -% Computes and approximation $$\hat{G}(y_j)$$ to $$G(y_j)=\sum_{i=1}^{N} q_i -% e^{\|x_i-y_j\|^2/h^2},\:\:j=1...M$$ such that -% $$|\hat{G}(y_j)-G(y_j)| \leq Q \epsilon$$ , where -% $$Q=\sum_{i=1}^{N}q_i$$. -% -% C++ Implementation. -% -% -%% Input -% -% * d --> data dimensionality. -% * N --> number of source points. -% * M --> number of target points. -% * W --> number of weights that will be used for each source point. -% This is useful if one needs multiple gauss transforms that have -% the same sources, targets, and bandwidth, but different -% weights/strengths (q). By computing coefficients for all W weight -% sets at once, we avoid duplicating much of the overhead. However, -% more memory is needed to store a set of coefficients for each set -% of weights. -% * x --> d x N matrix of N source points in d dimensions. -% * h --> the source scale or bandwidth. -% * q --> N x W matrix of the source strengths (one set of weights is a column vector). -% * y --> d x M matrix of M target points in d dimensions. -% * epsilon --> desired error -% * evalMethod --> (optional, default = 1) the evaluation method to use in evaluating gauss -% transform. Can be 0, 1, 2, or 3 for DIRECT, IFGT, DIRECT_TREE, -% IFGT_TREE evaluation, respectively. epsilon is needed for all but -% DIRECT method. Parameter selection is done only in the IFGT -% or IFGT_TREE case. -% * paramMethod --> (optional, default = 1) the method to use for determining parameters. -% Can be 0 (FIGTREE_PARAM_UNIFORM) or 1 (FIGTREE_PARAM_NON_UNIFORM). -% * verbose --> (optional, default = 0) if nonzero, prints parameters chosen for evaluation -% * forceK --> (optional, default = 0) if zero, the number of clusters(K) is determined by parameter -% selection. If nonzero, forceK overrides the K chosen by -% parameter selection. -% -%% Ouput -% -% * g --> W x M vector of the Gauss Transform evaluated at each target point. -% The ith column is the result of the transform using the ith set of -% weights (ith column of q). -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% -%% See also -% -% figtreeChooseParametersUniform, figtreeChooseParametersNonUniform, -% figtreeChooseTruncationNumber, figtreeEvaluateDirect, figtreeEvaluateDirectAnn, -% figtreeEvaluateTruncated, figtreeEvaluateTruncatedAnn, figtreeKCenterClustering +function [G] = figtree( x, h, q, y, epsilon, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ) +% +% Fast computation of the Gauss Transform. +% +% Computes and approximation $$\hat{G}(y_j)$$ to $$G(y_j)=\sum_{i=1}^{N} q_i +% e^{\|x_i-y_j\|^2/h^2},\:\:j=1...M$$ such that +% $$|\hat{G}(y_j)-G(y_j)| \leq Q \epsilon$$ , where +% $$Q=\sum_{i=1}^{N}q_i$$. +% +% C++ Implementation of algorithms described in the following publication: +% +% Vlad I. Morariu, Balaji Vasan Srinivasan, Vikas C. Raykar, Ramani Duraiswami, and Larry S. Davis. +% Automatic online tuning for fast Gaussian summation. Advances in Neural Information Processing +% Systems (NIPS), 2008. +% +%% Input +% +% +% * x --> d x N matrix of N source points in d dimensions. +% * h --> the source scale or bandwidth. +% * q --> N x W matrix of the source strengths (one set of weights is a column vector). +% Here W is the number of weights that will be used for each source point. +% This is useful if one needs multiple gauss transforms that have +% the same sources, targets, and bandwidth, but different +% weights/strengths (q). By computing coefficients for all W weight +% sets at once, we avoid duplicating much of the overhead. However, +% more memory is needed to store a set of coefficients for each set +% of weights. +% * y --> d x M matrix of M target points in d dimensions. +% * epsilon --> desired error +% * evalMethod --> (optional, default = 4) the evaluation method to use in evaluating gauss +% transform. Can be the following: +% 0 - DIRECT +% 1 - IFGT +% 2 - DIRECT_TREE +% 3 - IFGT_TREE +% 4 - AUTO (automatically chooses between 0-3 based on data and parameters) +% epsilon is needed for all but 'direct' method. Parameter selection is done only +% in the ifgt-based methods. Setting to 4 (AUTO) allows figtree to estimate which +% method is likely to be faster based on source and target distributions (NOTE: the +% best method to run changes with bandwidth, epsilon and source/target distributions). +% * ifgtParamMethod --> (optional, default = 1) the method to use for determining parameters. +% Can be 0 (UNIFORM) or 1 (NON_UNIFORM). The first assumes that points are +% uniformly distributed, and the second adapts to whatever distribution is given when +% choosing IFGT parameters K (number of clusters) and p_max (max truncation number). +% NOTE: NON_UNIFORM is recommended if data is not uniformly distributed. +% * ifgtTruncMethod -> (optional, default = 2) the method to use for computing truncation numbers. +% 0 - MAX, use max truncation number for all points +% 1 - POINT, point-wise truncation +% 2 - CLUSTER, cluster-wise truncation +% * verbose --> (optional, default = 0) if nonzero, prints parameters chosen for evaluation +% +%% Ouput +% +% * g --> M x W vector of the Gauss Transform evaluated at each target point. +% The ith column is the result of the transform using the ith set of +% weights (ith column of q). +% +%% Signature +% +% Author: Vlad I Morariu +% E-Mail: morariu@cs.umd.edu +% Date: 2008-12-05 % \ No newline at end of file diff --git a/matlab/figtreeChooseEvaluationMethod.m b/matlab/figtreeChooseEvaluationMethod.m new file mode 100644 index 0000000..31ff579 --- /dev/null +++ b/matlab/figtreeChooseEvaluationMethod.m @@ -0,0 +1,46 @@ +function [bestMethod, estCost] = figtreeChooseEvaluationMethod( x, h, W, y, epsilon, ifgtParamMethod, verbose ) +% +% This function chooses the best evaluation method given the source and target points as well as the parameters +% such as bandwidth and epsilon. This function analyzes the source and target distributions and estimates +% the cost of each method. In the interest of saving time, some estimates are not done if it is obvious +% that the corresponding methods are slower, in which case an entry of -1 will be returned for est_cost. +% +% +%% Input +% +% * x --> d x N matrix of N source points in d dimensions. +% * h --> the source scale or bandwidth. +% * W --> number of weights that will be used for each source point. +% This is useful if one needs multiple gauss transforms that have +% the same sources, targets, and bandwidth, but different +% weights/strengths (q). By computing coefficients for all W weight +% sets at once, we avoid duplicating much of the overhead. However, +% more memory is needed to store a set of coefficients for each set +% of weights. +% * y --> d x M matrix of M target points in d dimensions. +% * epsilon --> desired error +% * ifgtParamMethod --> (optional, default = 1) the method to use for determining parameters. +% Can be 0 (UNIFORM) or 1 (NON_UNIFORM). The first assumes that points are +% uniformly distributed, and the second adapts to whatever distribution is given when +% choosing IFGT parameters K (number of clusters) and p_max (max truncation number). +% NOTE: NON_UNIFORM is recommended if data is not uniformly distributed. +% * verbose --> (optional, default = 0) if nonzero, prints parameters chosen for evaluation +% +%% Ouput +% +% * bestMethod --> the evaluation method to use in evaluating gauss +% transform. Can be 0, 1, 2, or 3 for DIRECT, IFGT, DIRECT_TREE, +% IFGT_TREE evaluation, respectively. +% * estCost --> the estimated cost of each method. If in the interest of time the cost +% was not estimate for some method that was determined to be too slow, a -1 is returned. +% +%% Signature +% +% Author: Vlad I Morariu +% E-Mail: morariu@cs.umd.edu +% Date: 2008-12-05 +% +%% See also +% +% figtree +% \ No newline at end of file diff --git a/matlab/figtreeChooseParametersNonUniform.m b/matlab/figtreeChooseParametersNonUniform.m deleted file mode 100644 index 6a6be7e..0000000 --- a/matlab/figtreeChooseParametersNonUniform.m +++ /dev/null @@ -1,42 +0,0 @@ -function [K, pMax, r] = figtreeChooseParametersNonUniform(d, h, epsilon, Klimit, maxRange) -% -% Choose the parameters for the Improved Fast Gauss Transform. -% -% Chooses parameters for IFGT and FIGTree without assumption that sources are -% uniformly distributed. In this case, k-center clustering is done as part -% of the parameter selection so that the radius of each cluster is not -% estimated but computed directly for the sources. This results in an -% additional k-center clustering operation, but the speedup when sources are -% not uniformly distributed can be large (as much as 10 times faster) because -% optimal parameters are much more accurately estimated. Even when sources are -% uniformly distributed, the slowdown is often small compared to -% figtreeChooseParametersUniform (however, there are cases where this is slower). -% -% -%% Input -% -% * d --> dimension of the points. -% * N --> number of source points. -% * x --> d x N matrix of N source points in d dimensions. -% * h --> the source bandwidth. -% * epsilon --> the desired error. -% * kLimit --> upper limit on the number of clusters, K. -% Note : Use kLimit=N to allow for optimal param estimation. -% * maxRange --> max dimension range. The range along a dimension is -% the difference between the max and min values that can ever -% occur along that dimension. The max dimension range is the -% maximum range among all dimensions. For example, if all -% points lie in unit hypercube, then maxRange = 1.% -%% Ouput -% -% * K -->number of clusters. -% * pMax --> maximum truncation number for the Taylor series. -% * r --> source cutoff radius. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% diff --git a/matlab/figtreeChooseParametersUniform.m b/matlab/figtreeChooseParametersUniform.m deleted file mode 100644 index 56e5e14..0000000 --- a/matlab/figtreeChooseParametersUniform.m +++ /dev/null @@ -1,39 +0,0 @@ -function [K, pMax, r] = figtreeChooseParametersUniform(d, h, epsilon, Klimit) -% -% Choose the parameters for the Improved Fast Gauss Transform. -% -% Chooses parameters for IFGT and FIGTree by assuming that sources are -% uniformly distributed in a unit cube. -% -% Implementation based on: -% -% Fast computation of sums of Gaussians in high dimensions. -% Vikas C. Raykar, C. Yang, R. Duraiswami, and N. Gumerov, -% CS-TR-4767, Department of computer science, -% University of Maryland, Collegepark. -% -%% Input -% -% * d --> dimension of the points. -% * h --> the source bandwidth. -% * epsilon --> the desired error. -% * kLimit --> upper limit on the number of clusters, K. -% Note : Use kLimit=N to allow for optimal param estimation. -% * maxRange --> max dimension range. The range along a dimension is -% the difference between the max and min values that can ever -% occur along that dimension. The max dimension range is the -% maximum range among all dimensions. For example, if all -% points lie in unit hypercube, then maxRange = 1.% -%% Ouput -% -% * K --> number of clusters. -% * pMax --> maximum truncation number for the Taylor series. -% * r --> source cutoff radius. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% diff --git a/matlab/figtreeChooseTruncationNumber.m b/matlab/figtreeChooseTruncationNumber.m deleted file mode 100644 index acae539..0000000 --- a/matlab/figtreeChooseTruncationNumber.m +++ /dev/null @@ -1,37 +0,0 @@ -function [pMax] = figtreeChooseTruncationNumber(d, h, epsilon, rx) -% -% Choose the parameters for the Improved Fast Gauss Transform. -% -% Given the maximum cluster radius, this function computes the maximum -% truncation number that guarantees results within the desired error bound. -% -% Implementation based on: -% -% Fast computation of sums of Gaussians in high dimensions. -% Vikas C. Raykar, C. Yang, R. Duraiswami, and N. Gumerov, -% CS-TR-4767, Department of computer science, -% University of Maryland, Collegepark. -% -%% Input -% -% * d --> dimension of the points. -% * h --> the source bandwidth. -% * epsilon --> the desired error. -% * rx --> maximum cluster radius -% * maxRange --> max dimension range. The range along a dimension is -% the difference between the max and min values that can ever -% occur along that dimension. The max dimension range is the -% maximum range among all dimensions. For example, if all -% points lie in unit hypercube, then maxRange = 1.% -% -%% Ouput -% -% * pMax --> maximum truncation number for the Taylor series.% -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% diff --git a/matlab/figtreeEvaluateDirect.m b/matlab/figtreeEvaluateDirect.m deleted file mode 100644 index 9ecc411..0000000 --- a/matlab/figtreeEvaluateDirect.m +++ /dev/null @@ -1,30 +0,0 @@ -function [ g ] = figtreeEvaluateDirect(d, N, M, x, h, q, y) -% -% Direct computation of the Gauss Transform. -% -% $$G(y_j)=\sum_{i=1}^{N} q_i e^{\|x_i-y_j\|^2/h^2},\:\:j=1...M$$ -% -% -%% Input -% -% * d --> data dimensionality. -% * N --> number of source points. -% * M --> number of target points. -% * x --> d x N matrix of N source points in d dimensions. -% * h --> source bandwidth or scale. -% * q --> N x 1 or 1 x N vector of the source strengths. -% * y --> d x M matrix of M target points in d dimensions. -% -%% Ouput -% -% * g --> M x 1 vector of the Gauss Transform evaluated at each target point. -% Note that unlike GaussTransform from the original IFGT library, -% the output is a column vector. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% \ No newline at end of file diff --git a/matlab/figtreeEvaluateDirectTree.m b/matlab/figtreeEvaluateDirectTree.m deleted file mode 100644 index 772557e..0000000 --- a/matlab/figtreeEvaluateDirectTree.m +++ /dev/null @@ -1,43 +0,0 @@ -function [ g ] = figtreeEvaluateDirectTree(d, N, M, x, h, q, y, epsilon) -% -% Gauss Transform with fast nearest neighbor searching. -% -% Given a specified epsilon, the code computes the Gauss transform by -% summing the sources only within a certain radius--whos contribution -% is alteast epsilon. -% -% The neighbors are found using the ANN library -% http://www.cs.umd.edu/~mount/ANN/. -% -% Computes and approximation $$\hat{G}(y_j)$$ to $$G(y_j)=\sum_{i=1}^{N} q_i -% e^{\|x_i-y_j\|^2/h^2},\:\:j=1...M$$ such that -% $$|\hat{G}(y_j)-G(y_j)| \leq Q \epsilon$$ , where -% $$Q=\sum_{i=1}^{N}q_i$$. -% -% This method is extremely fast for small bandwidths and different source -% and target distributions. -% -%% Input -% -% * d --> data dimensionality. -% * N --> number of source points. -% * M --> number of target points. -% * x --> d x N matrix of N source points in d dimensions. -% * h --> source bandwidth or scale. -% * q --> N x 1 or 1 x N vector of the source strengths. -% * y --> d x M matrix of M target points in d dimensions. -% * epsilon --> desired error. -% -%% Ouput -% -% * g --> M x 1 vector of the Gauss Transform evaluated at each target point. -% Note that unlike GaussTransform from the original IFGT library, -% the output is a column vector. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% \ No newline at end of file diff --git a/matlab/figtreeEvaluateIfgt.m b/matlab/figtreeEvaluateIfgt.m deleted file mode 100644 index b4092d7..0000000 --- a/matlab/figtreeEvaluateIfgt.m +++ /dev/null @@ -1,50 +0,0 @@ -function [g]=figtreeEvaluateIfgt(d, N, M, W, h, q, y, pMax, K, clusterIndex, clusterCenter, clusterRadii, r, epsilon) -% Computes Gauss Transform by evaluating truncated Taylor series (IFGT). -% -% Computes and approximation $$\hat{G}(y_j)$$ to $$G(y_j)=\sum_{i=1}^{N} q_i -% e^{\|x_i-y_j\|^2/h^2},\:\:j=1...M$$ such that -% $$|\hat{G}(y_j)-G(y_j)| \leq Q \epsilon$$ , where -% $$Q=\sum_{i=1}^{N}q_i$$. -% -% Implementation based on: -% Fast computation of sums of Gaussians in high dimensions. Vikas C. Raykar, -% C. Yang, R. Duraiswami, and N. Gumerov, CS-TR-4767, Department of computer -% science, University of Maryland, College Park.% -% -%% Input -% -% * d --> data dimensionality. -% * N --> number of source points. -% * M --> number of target points. -% * W --> number of weights that will be used for each source point. -% This really does multiple transforms, with different weights each -% time but with same sources and targets. This saves a lot of time -% since most of the work is not duplicated. However, it requires -% more memory to store the coefficients for each set of weights. -% * x --> d x N matrix of N source points in d dimensions. -% * h --> the source scale or bandwidth. -% * q --> N x W vector of the source strengths. -% * y --> d x M matrix of M target points in d dimensions. -% * pMax --> maximum truncation number for the Taylor series. -% * K --> the number of clusters. -% * clusterIndex --> 1 x N vector the i th element is the cluster number -% to which the i th point belongs. [ ClusterIndex[i] varies between -% 0 to K-1. ] -% * clusterCenter --> d x K matrix of K cluster centers. -% * clusterRadii --> 1 x K matrix of the radius of each cluster. -% * r --> cutoff radius -% * epsilon --> desired error -% -%% Ouput -% -% * g --> W x M vector of the Gauss Transform evaluated at each target -% point. Each row q is the result of the transform using the qth set -% of weights. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% diff --git a/matlab/figtreeEvaluateIfgtTree.m b/matlab/figtreeEvaluateIfgtTree.m deleted file mode 100644 index 10d044a..0000000 --- a/matlab/figtreeEvaluateIfgtTree.m +++ /dev/null @@ -1,41 +0,0 @@ -function [g] = figtreeEvaluateIfgtTree(d, N, M, W, h, q, y, pMax, K, clusterIndex, clusterCenter, clusterRadii, r, epsilon) -% Computes Gauss Transform by evaluating truncated Taylor series and -% using approximate nearest-neighbors. -% -%% Input -% -% * d --> data dimensionality. -% * N --> number of source points. -% * M --> number of target points. -% * W --> number of weights that will be used for each source point. -% This really does multiple transforms, with different weights each -% time but with same sources and targets. This saves a lot of time -% since most of the work is not duplicated. However, it requires -% more memory to store the coefficients for each set of weights. -% * x --> d x N matrix of N source points in d dimensions. -% * h --> the source scale or bandwidth. -% * q --> N x W vector of the source strengths. -% * y --> d x M matrix of M target points in d dimensions. -% * pMax --> maximum truncation number for the Taylor series. -% * K --> the number of clusters. -% * clusterIndex --> 1 x N vector the i th element is the cluster number -% to which the i th point belongs. [ ClusterIndex[i] varies between -% 0 to K-1. ] -% * clusterCenter --> d x K matrix of K cluster centers. -% * clusterRadii --> 1 x K matrix of the radius of each cluster. -% * r --> cutoff radius -% * epsilon --> desired error -% -%% Ouput -% -% * g --> W x M vector of the Gauss Transform evaluated at each target -% point. Each row q is the result of the transform using the qth set -% of weights. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% diff --git a/matlab/figtreeKCenterClustering.m b/matlab/figtreeKCenterClustering.m index 5a91823..1ec4730 100644 --- a/matlab/figtreeKCenterClustering.m +++ b/matlab/figtreeKCenterClustering.m @@ -1,29 +1,29 @@ -function [K, rx, clusterIndex, clusterCenter, numPoints, clusterRadii] = figtreeKCenterClustering(d, N, x, K) -% -% Gonzalez's farthest-point clustering algorithm. O(N log K) version. -% -%% Input -% -% * d --> data dimensionality. -% * N --> number of source points. -% * x --> d x N matrix of N source points in d dimensions -% * kMax --> maximum number of clusters. -% -%% Ouput -% -% * K --> actual number of clusters (less than kMax if duplicate pts exist) -% * rx --> maximum radius of the clusters. -% * clusterIndex --> vector of length N where the i th element is the -% cluster number to which the i th point belongs. -% ClusterIndex[i] varies between 0 to K-1. -% * clusterCenters --> d x K matrix of K cluster centers -% * numPoints --> number of points in each cluster. -% * clusterRadii --> radius of each cluster. -% -%% Signature -% -% Author: Vlad I Morariu -% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) -% E-Mail: morariu@cs.umd.edu -% Date: 2007-06-26 -% +function [K, rx, clusterIndex, clusterCenter, numPoints, clusterRadii] = figtreeKCenterClustering(d, N, x, K) +% +% Gonzalez's farthest-point clustering algorithm. +% +%% Input +% +% * d --> data dimensionality. +% * N --> number of source points. +% * x --> d x N matrix of N source points in d dimensions +% * kMax --> maximum number of clusters. +% +%% Ouput +% +% * K --> actual number of clusters (less than kMax if duplicate pts exist) +% * rx --> maximum radius of the clusters. +% * clusterIndex --> vector of length N where the i th element is the +% cluster number to which the i th point belongs. +% ClusterIndex[i] varies between 0 to K-1. +% * clusterCenters --> d x K matrix of K cluster centers +% * numPoints --> number of points in each cluster. +% * clusterRadii --> radius of each cluster. +% +%% Signature +% +% Author: Vlad I Morariu +% (original implementation by Vikas C. Raykar, vikas@cs.umd.edu) +% E-Mail: morariu@cs.umd.edu +% Date: 2007-06-26 +% diff --git a/readme.txt b/readme.txt index 3e9ae53..8ca2f36 100644 --- a/readme.txt +++ b/readme.txt @@ -1,19 +1,45 @@ Author: Vlad I. Morariu E-mail: morariu(at)umd(.)edu Date: 2007-06-26 -Modified: 2008-01-29 +Modified: 2008-12-05 -FIGTree is based on the original IFGT library and FIGTree code by -Vikas C. Raykar and Changjiang Yang. Improvements include bug fixes, -a new parameter selection algorithm, the addition of the tree-based -data structure, and a C/C++ interface. +FIGTree is a library that provides a C/C++ and MATLAB interface +for speeding up the computation of the Gauss Transform. Its +authors are Vlad Morariu, Vikas Raykar, and Changjiang Yang. The +authors worked under the supervision of Professor Ramani Duraiswami +and Professor Larry Davis, at the University of Maryland. -The library can be compiled both as a set MEX DLL files to provide a -Matlab interface and also as a DLL that provides a C interface. The -original code from the IFGT and FIGTree libraries has been repackaged -into figtree.cpp with some modifications (bug fixes, extensions, and -style changes). See figtree.h and figtree.cpp for a more detailed list of -changes. +The current version of the library is based on the following paper: + +Vlad I. Morariu, Balaji Vasan Srinivasan, Vikas C. Raykar, +Ramani Duraiswami, and Larry S. Davis. Automatic online tuning for +fast Gaussian summation. Advances in Neural Information Processing +Systems (NIPS), 2008. + +For more up-to-date information on this library, please go to the +FIGTree homepage: + +http://www.umiacs.umd.edu/~morariu/figtree/ + +or the SourceForge download page: + +http://sourceforge.net/projects/figtree + +This code makes use of the Approximate Nearest Neighbors (ANN) library +for the tree-based datastructure, but if the appropriate flags are +supplied (see below), the library can compile without ANN. A slightly +modified version of ANN (only makefiles are modified) is provided along +with the figtree code for convenience. For newer releases of ANN or for +any other information regarding ANN, please go to the authors' website: + +http://www.cs.umd.edu/~mount/ANN/ + + +----------------------------------------------------------------------- + +Samples and Documentation + +----------------------------------------------------------------------- Sample code for using the library in Matlab or C/C++ is provided in 'samples' directory. @@ -22,58 +48,101 @@ Documentation for the Matlab interface is available in the *.m stub files in the 'matlab' directory. The Windows MEX files have a *.dll extension since most Matlab versions accept *.dll files (whereas others accept *.mex and not *.mexw32 or vice versa). In case of -conflict with the figtree.dll that provides the C interface, the figtree.dll -MEX file can be renamed to have either a *.mex or *.mexw32 extension -(depending on the version of Matlab). +conflict with the figtree.dll that provides the C interface, the +figtree.dll MEX file can be renamed to have either a *.mex or *.mexw32 +extension (depending on the version of Matlab). -For description of available C functions, see 'include/figtree.h'. - -This code makes use of the Approximate Nearest Neighbors (ANN) library -by default to provide the tree-based datastructure, but if the -appropriate flags are supplied (see below), the library can compile -without ANN. A slightly modified version of ANN (only makefiles are -modified) is provided along with the figtree code for convenience. For newer -releases of ANN or for any other information regarding ANN, please go to -the authors' website: - -http://www.cs.umd.edu/~mount/ANN/ +For a description of available C/C++ functions, see 'include/figtree.h'. ----------------------------------------------------------------------- + Using Precompiled WIN32 binaries + ----------------------------------------------------------------------- The figtree precompiled binaries (.dll) and lib files are provided in figtree/bin and figtree/lib. -The ANN precompiled binaries and lib files are provided in -ann_1.1.1/MS_Win32/bin and ann_1.1.1/MS_Win32/lib. - To use the figtree library, you must add {BASE_PATH}/figtree/lib to the lib path, and add figtree.lib as a dependency. -To execute code linked against figtree (and ANN), you must make sure that -the locations of ANN.dll and figtree.dll are in the system path. +To execute code (not MATLAB) linked against figtree (and ANN), you must +make sure that the locations of ann_figtree_version.dll and figtree.dll +are in the system path. + +NOTE: See below for an example of how the PATH environment variable can +be used to add the paths of libraries without having to copy them in +the directory of each executable that uses them. + + + +----------------------------------------------------------------------- + +Compiling Library and Matlab MEX files in Windows using VS8 + +----------------------------------------------------------------------- + +You can compile the library using the Visual Studio Solution +(FIGTREE_DIR)/vs8/figtree.sln. Compiling the entire solution will +compile both the C/C++ library (figtree.dll will be in the bin +directory, and figtree.lib will be in the lib directory), and the mex +files, which will be placed in the matlab directory. + +Make sure you first switch to the 'Release' mode, or else figtree will +be very slow! + + + +----------------------------------------------------------------------- + +Compiling Matlab MEX files in Linux, Solaris, or Windows using Matlab mex + +----------------------------------------------------------------------- + +This has been tested on Matlab 7 with g++ as a compiler. Also, it works +in windows if the compiler is set up right. + +1. Set up matlab to use the gcc compiler by running 'mex -setup'. -NOTE: See below for an example of how the PATH environment variable can be -used to add the paths of libraries without having to copy them in the -directory of each executable that uses them. +2. In Matlab, set the working directory to (FIGTREE_DIR)/matlab/ and run + CompileMexFilesUsingMatlab.m. + +----------------------------------------------------------------------- + +Compiling Library in Linux or Solaris + ----------------------------------------------------------------------- -Using Precompiled WIN32 matlab MEX files + +1. Compile FIGTree library as a shared library by issuing command 'make' + + If you instead want to compile the FIGTree library as a static library, + then the command is 'make FIGTREE_LIB_TYPE=static'. + +2. If shared libraries are created, make sure that they are + in the library path. Assuming that FIGTree libraries are + in your home directory, one way to do this is to set LD_LIBRARY_PATH: + + setenv LD_LIBRARY_PATH ${HOME}/figtree/lib + + if LD_LIBRARY_PATH was not previously set, or + + setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${HOME}/figtree/lib + + if LD_LIBRARY_PATH was previously set. + + + ----------------------------------------------------------------------- -Because the MEX files are dynamically linked against ANN.dll, ANN.dll -needs to be present in the system executable path. If ANN.dll is not -in the path, then calling any of the MEX files in Matlab will give an -'Invalid MEX file' message. +Setting the PATH variable for programs that link against figtree.lib + +----------------------------------------------------------------------- -NOTE: using addpath() seems to work only for telling Matlab where to find -the MEX file, but not where to find its dependencies (in our case ANN.dll). -One way to fix this issue is to add the location of ANN.dll to the PATH -environment variable. For example, assume the ANN.dll is located in -C:\ann_1.1.1\MS_Win32\bin. To add it to the PATH environment variable (this +Assume the figtree.dll is located in +C:\figtree\bin. To add it to the PATH environment variable (this does not require admin privileges): 1. Right click on 'My Computer' @@ -86,121 +155,86 @@ does not require admin privileges): a) if PATH is not among the user variables (usually TEMP and TMP are present), then you must add it by clicking 'New', entering 'PATH' in the 'Variable name:' field, and then entering - '%PATH%; C:\ann_1.1.1\MS_Win32\bin' 'in the Variable value:' field. - The '%PATH%' is there so that the ANN.dll directory is APPENDED to the + '%PATH%; C:\figtree\bin' 'in the Variable value:' field. + The '%PATH%' is there so that the figtree directory is APPENDED to the System variables instance of 'PATH' (which you cannot change if you are not an administrator). b) if PATH is among the user variables, select it, and then append your path to the list, using ';' as delimiter. -6. If MATLAB was currently running, it must be restarted for the PATH - variable change to take effect (until then you will still get an - 'Invalid MEX file' error. ------------------------------------------------------------------------ -Compiling Library and Matlab MEX files in Windows using VS8 ------------------------------------------------------------------------ - -You can compile the library using the Visual Studio Solution -(FIGTREE_DIR)/vs8/figtree.sln. Compiling the entire solution will compile both the -C library (figtree.dll will be in the bin directory, and figtree.lib will be in -the lib directory), and the mex files, which will be placed in the -matlab directory. -To compile the library, the ANN library will be needed. -You must set the paths so that the *.h, *.lib, and *.dll are found -during the compilation process. ----------------------------------------------------------------------- -Compiling Library in Linux or Solaris ------------------------------------------------------------------------ - -1. (optional) Compile ANN library using g++ (see ANN compile instructions). - This Will generally require the command 'make linux-g++' or - 'make sunos5-g++' for a static library and 'make linux-g++-sl' or - 'make sunos5-g++-sl' for shared libraries. If there are errors about - unexpected end of line in the makefile and you are using Solaris, - try 'gmake' instead. - The option 'linux-g++-sl' does not exist in version 1.1.1 of ANN but - can be added with minimal work. The version of ANN provided with the - figtree code includes this change. See section 'Adding linux shared library - target to ANN Makefile' below for details on how to modify the original - version of the ANN source code if you wish to do so. +Todo List for Future versions -2. Compile FIGTree library as a shared library using the command 'make' - if you performed step 1 and compiled ANN as a shared library, or - 'make FIGTREE_NO_ANN=true' if you did not perform step 1 or wish to - compile the FIGTree library without ANN support (the 'tree' part of - FIGTree will not function). +----------------------------------------------------------------------- - If you instead want to compile the FIGTree library as a static library, - then the command is 'make FIGTREE_LIB_TYPE=static' if you also compiled - ANN as a static library in step 1. If you do not wish to use the ANN - library, then the command is - 'make FIGTREE_LIB_TYPE=static FIGTREE_NO_ANN=true'. - -Note: if you compile ANN as a static library but FIGTree as a shared library - you might have 'relocation' errors from the linker since the static library - is not compiled as position independent code (-fpic or -fPIC flags). If - linking succeeds, then the resulting code might be slow. - -3. If shared libraries are created, make sure that they are - in the library path. Assuming that both ANN and FIGTree libraries are - in your home directory, one way to do this is to set LD_LIBRARY_PATH: - - setenv LD_LIBRARY_PATH ${HOME}/ann_1.1.1/lib:${HOME}/figtree/lib +- TODO: Clean up makefiles for Unix/Linux/Solaris version. + +- TODO: estimate avg neighbors using approach of Faloutsos et + al (SIGMOD 2000) instead of querying kd-tree on subsampled + sources +- TODO: currently, k-center clustering is performed using an + N log(K) + K^2 (expected time) approach based on the Gonzales + K-center clustering. Use N log(K) approach instead. +- TODO: add function to improve cost prediction by tuning to actual + hardware (i.e. floating point operation times vary relative + to memory access times on different machines; also exp() + takes different number of float ops depending on machine) +- TODO: add memory allocation checks to avoid crashes +- TODO: allow kd-tree, clusters, and coefficients computed on sources + to persist between function calls in case user wants to reuse + them +- TODO: make some more of the internal parameters easier to modify by + users without requring code to be compiled again (such + parameters include: amt of subsampling to do for + estimating cost, truncation number limit, etc) +- TODO: modify ANN so that it no longer uses global variables (which + prevents figtree from being + called simultaneously in multiple threads) - if LD_LIBRARY_PATH was not previously set, or +----------------------------------------------------------------------- - setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH:${HOME}/ann_1.1.1/lib:${HOME}/figtree/lib +Change Log - if LD_LIBRARY_PATH was previously set. +----------------------------------------------------------------------- ----------------------------------------------------------------------- -Adding linux shared library target to ANN Makefile +figtree-0.9.2 2008-12-05 (Changes made by Vlad Morariu) ----------------------------------------------------------------------- -1. in ann_1.1.1/Make-config, add the following lines in the config - option list (be careful with tabs as they have special functions - in makefiles -- you can simply copy/paste following lines): - -# Linux using g++, make shared library -linux-g++-sl: - $(MAKE) targets \ - "ANNLIB = libANN.so" \ - "C++ = g++" \ - "CFLAGS = -fpic -O3" \ - "MAKELIB = g++ -shared -o" \ - "RANLIB = true" - -2. in ann_1.1.1/Makefile, after the comment 'main make entry point' - add, "linux-g++-sl" in the list of possible targets. For example - if the list is 'alpha-g++ macosx-g++ linux-g++' then make it - 'alpha-g++ macosx-g++ linux-g++ linux-g++-sl'. - -3. (optional) in ann_1.1.1/Makefile, add the following line under the 'default:' - target after the line containing '@echo " make linux-g++ ...': - - @echo " make linux-g++-sl for Linux and g++, make shared libs" - +- NEW: Added function that chooses fastest method between Direct, + DirectTree, Ifgt, and IfgtTree, making figtree a black-box approach +- Added point-wise and cluster-wise approaches to selecting + source/target truncation numbers +- Moved ann-1.1.1 library inside (figtree-dir)/external directory to + reduce confusion +- Change mex code to include ANN code (instead of linking to it) to + prevent issues with library paths +- Removed many of the mex files that were really just confusing people, + and left only figtree, method selection, and k-center clustering + mex files as they are most useful. +- Changed interface of the mex files to remove redundant arguments. +- Other improvements (see source files) ----------------------------------------------------------------------- -Compiling Matlab MEX files in Linux or Solaris +figtree-0.9.1 2008-02-26 (Changes made by Vlad Morariu) ----------------------------------------------------------------------- -This has been tested on Matlab 7 with g++ as a compiler. +- FIX: parameter selection gave bad params since K (number of + clusters) was not allowed to equal number of sources -1. If ANN support is desired, compile ANN library as a shared library as - described above. It is important that the library is compiled as - a shared library, since code might otherwise not link or run slowly. +----------------------------------------------------------------------- +figtree-0.9 2008-01-30 (Changes made by Vlad Morariu) +----------------------------------------------------------------------- -2. Set up matlab to use the gcc compiler by running 'mex -setup'. +- Initial adaptation from Vikas's initial code +- NEW: integrated Vikas's FIGTree code into library +- NEW: added parameter selection method that does not assume uniformly + distributed sources +- NEW: added C/C++ interface, with one function (figtree()) that does + most work +- Sources and targets no longer need to fit in unit hypercube -3. in Matlab, set the working directory to (FIGTREE_DIR)/matlab/ and run - CompileMexFilesUsingMatlab(use_ann, ann_header_dir, ann_lib_dir). - If no arguments are passed, use_ann is assumed to be 1 (so step 1 must - be performed, and the ANN header and library directories are assumed to be - the default locations. To compile the MEX files without ANN support you - can use command 'CompileMexFilesUsingMatlab(0)'. See - CompileMexFilesUsingMatlab.m for more details. diff --git a/samples/Makefile b/samples/Makefile index 19db8b8..02041b6 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -23,8 +23,8 @@ BINDIR = $(BASEDIR)/bin # make "FIGTREE_NO_ANN=true" # #----------------------------------------------------------------------------- -ANNLIBDIR = $(BASEDIR)/../ann_1.1.1/lib -ANNINCDIR = $(BASEDIR)/../ann_1.1.1/include +ANNLIBDIR = $(BASEDIR)/lib +ANNINCDIR = $(BASEDIR)/external/ann_1.1.1/include # uncomment this line to compile the library without ANN support #FIGTREE_NO_ANN=true @@ -40,7 +40,7 @@ LDFLAGS=-L$(LIBDIR) -lfigtree # (this is really necessary only if ANN and FIGTree are compiled as static libs, # but doesn't hurt in the other cases) ifneq ($(FIGTREE_NO_ANN),true) -LDFLAGS+= -L$(ANNLIBDIR) -lANN +LDFLAGS+= -L$(ANNLIBDIR) -lann_figtree_version endif SOURCES=sample.cpp diff --git a/samples/matlab_sample1_shift_scale.m b/samples/matlab_sample1_shift_scale.m deleted file mode 100644 index 1563343..0000000 --- a/samples/matlab_sample1_shift_scale.m +++ /dev/null @@ -1,281 +0,0 @@ -% Script the demonstrate the use of FIGTree. Note, only -% figtree/matlab/figtree.dll is needed for the figtree() function to -% function. All other mex files are provided in case users require -% advanced control over parameter selection and clustering processes. See -% sample2.m for example of how to use the additional mex files provided. -clear all; -close all; -clear functions; -clc; - -% the MEX binaries for the FIGTree library reside in ../matlab -% we assume that the script is run from the figtree/samples/ directory, -% otherwise the correct path for the mex files must be set. -addpath('../matlab'); - -disp('---------------------------------------------'); -disp(sprintf('Examples to demonstrate the use of FIGTree')); -disp('---------------------------------------------'); - -% the number of sources -N = 2500; -disp(sprintf('Number of source points N=%d',N)); - -% the number of targets -M = 2500; -disp(sprintf('Number of target points M=%d',M)); - -% the desired error -epsilon = 1e-3; -disp(sprintf('Target error epsilon=%e',epsilon)); - -% run all algorithms with all parameter selection methods with some -% different source/target distributions, dimensionality, and bandwidth, -% to show some cases where some methods perform better than others -for i = 1:4 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Generate sources and targets - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - clear X_shifted_scaled X_shifted X Y; - fprintf('\n\n'); - if( i == 1 ) - disp('----------------------------------------------------------------------'); - disp(sprintf('Sources drawn from multiple gaussians\nTargets uniformly distributed')); - - % the data dimensionality - d = 4; - disp(sprintf('Dimensionality d=%d',d)); - - % the bandwidth - h = .01; %sqrt(2)*0.2*sqrt(d); - disp(sprintf('Bandwidth h=%f',h)); - disp('----------------------------------------------------------------------'); - - % the source points - % d x N matrix of N source points in d dimensions. - % Scale the data - G = 25; - m = rand(d,G); - v = 0.02*ones(1,G); - [X] = generate_multiple_gaussians(N,G,m,v,d); - - for j = 1:d - shift = min(X(j,:)); - X_shifted(j,:) = X(j,:) - shift; - scale = 1/max(X_shifted(j,:)); - X_shifted_scaled(j,:) = X_shifted(j,:)*scale; - end - - X = X_shifted_scaled; - - % the target points - % d x M matrix of M source points in d dimensions. - Y = rand(d,M); - end; - - if( i == 2 ) - disp('----------------------------------------------------------------------'); - disp(sprintf('Sources and targets drawn from (same) multiple gaussians')); - - % the data dimensionality - d = 4; - disp(sprintf('Dimensionality d=%d',d)); - - % the bandwidth - h = .1; %sqrt(2)*0.2*sqrt(d); - disp(sprintf('Bandwidth h=%f',h)); - disp('----------------------------------------------------------------------'); - - % the source points - % d x N matrix of N source points in d dimensions. - % Scale the data - G = 25; - m = rand(d,G); - v = 0.02*ones(1,G); - [X] = generate_multiple_gaussians(N+M,G,m,v,d); - - for j = 1:d - shift = min(X(j,:)); - X_shifted(j,:) = X(j,:) - shift; - scale = 1/max(X_shifted(j,:)); - X_shifted_scaled(j,:) = X_shifted(j,:)*scale; - end - - inds = randperm(M+N); - X = X_shifted_scaled(:,inds(1:N)); - Y = X_shifted_scaled(:,inds(N+1:N+M)); - end; - - if( i == 3 ) - disp('----------------------------------------------------------------------'); - disp(sprintf('Sources and targets drawn from (same) multiple gaussians')); - - % the data dimensionality - d = 2; - disp(sprintf('Dimensionality d=%i',d)); - - % the bandwidth - h = .1; %sqrt(2)*0.2*sqrt(d); - disp(sprintf('Bandwidth h=%f',h)); - disp('----------------------------------------------------------------------'); - - % the source points - % d x N matrix of N source points in d dimensions. - % Scale the data - G = 25; - m = rand(d,G); - v = 0.02*ones(1,G); - [X] = generate_multiple_gaussians(N+M,G,m,v,d); - - for j = 1:d - shift = min(X(j,:)); - X_shifted(j,:) = X(j,:) - shift; - scale = 1/max(X_shifted(j,:)); - X_shifted_scaled(j,:) = X_shifted(j,:)*scale; - end - - X = X_shifted_scaled(:,1:N); - Y = X_shifted_scaled(:,N+1:N+M); - end; - - if( i == 4 ) - disp('----------------------------------------------------------------------'); - disp(sprintf('Sources and targets drawn from (same) multiple gaussians')); - - % the data dimensionality - d = 2; - disp(sprintf('Dimensionality d=%i',d)); - - % the bandwidth - h = .2; %sqrt(2)*0.2*sqrt(d); - disp(sprintf('Bandwidth h=%f',h)); - disp('----------------------------------------------------------------------'); - - % the source points - % d x N matrix of N source points in d dimensions. - % Scale the data - G = 25; - m = rand(d,G); - v = 0.02*ones(1,G); - [X] = generate_multiple_gaussians(N+M,G,m,v,d); - - for j=1:d - shift = min(X(j,:)); - X_shifted(j,:) = X(j,:)-shift; - scale = 1/max(X_shifted(j,:)); - X_shifted_scaled(j,:) = X_shifted(j,:)*scale; - end - - X = X_shifted_scaled(:,1:N); - Y = X_shifted_scaled(:,N+1:N+M); - end; - - % the source weights - % 1 x N row vector - q = rand(1,N); - - % scale and shift the data and bandwidth to make sure that such - % changes do not affect accuracy or speed. (Thus, sources - % and targets no longer have to lie in a unit hypercube). - new_scale = .01; - new_shift = 0; - X = new_scale*X+new_shift; - Y = new_scale*Y+new_shift; - h = new_scale*h; - - % try for various scales - for j = 1:9 - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Evaluate gauss transform - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % direct method (exact up to machine precision) - tic; - [ g_direct ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 0, 0 ); - t_direct(j) = toc; - fprintf('.'); - - % direct evaluation with approximate nearest neighbor structure - % (parameter selection not relevant, so it can be anything) - - % implemented as in the FIGTree paper (Raykar et al, submitted to - % Joural of Machine Learning). - tic; - [ g_direct_tree ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 2, 0 ); - t_direct_tree(j) = toc; - fprintf('.'); - - % truncated series, uniform parameter selection - implemented exactly - % as described in IFGT paper (Raykar et al, 2005). - tic; - [ g_ifgt_u ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 1, 0 ); - t_ifgt_u(j) = toc; - fprintf('.'); - - % truncated series, with nonuniform parameter selection - the - % default method when calling function without last two arguments - % that select the method: figtree( d, N, M, 1, X, h, q, Y, epsilon ); - % works well in general - tic; - [ g_ifgt_nu ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 1, 1 ); - t_ifgt_nu(j) = toc; - fprintf('.'); - - % truncated series with approximate nearest neighbor structure, - % with uniform parameter selection - implemented as in the FIGTree - % paper (Raykar et al, submitted to Joural of Machine Learning). - tic; - [ g_ifgt_tree_u ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 3, 0 ); - t_ifgt_tree_u(j) = toc; - fprintf('.'); - - % truncated series, with non-uniform parameter selection. Is faster - % than ifgt-nu if targets are not identically distributed to - % sources. - tic; - [ g_ifgt_tree_nu ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 3, 1 ); - t_ifgt_tree_nu(j) = toc; - fprintf('.'); - - % show errors - e_direct_tree(j) = max(abs(g_direct-g_direct_tree))/sum(q); - e_ifgt_u(j) = max(abs(g_direct-g_ifgt_u))/sum(q); - e_ifgt_nu(j) = max(abs(g_direct-g_ifgt_nu))/sum(q); - e_ifgt_tree_u(j) = max(abs(g_direct-g_ifgt_tree_u))/sum(q); - e_ifgt_tree_nu(j) = max(abs(g_direct-g_ifgt_tree_nu))/sum(q); - - new_scale = 4; - new_shift = 10^j; - X = new_scale*X+new_shift; - Y = new_scale*Y+new_shift; - h = new_scale*h; - - end; - fprintf('\n'); - - % show times and errors - fprintf('direct : %3.2e seconds\n', t_direct ); - fprintf('direct-tree : %3.2e seconds, speedup = %3.2f\n', [t_direct_tree; t_direct./t_direct_tree] ); - fprintf('ifgt-u : %3.2e seconds, speedup = %3.2f\n', [t_ifgt_u; t_direct./t_ifgt_u] ); - fprintf('ifgt-nu : %3.2e seconds, speedup = %3.2f\n', [t_ifgt_nu; t_direct./t_ifgt_nu] ); - fprintf('ifgt-tree-u : %3.2e seconds, speedup = %3.2f\n', [t_ifgt_tree_u; t_direct./t_ifgt_tree_u] ); - fprintf('ifgt-tree-nu : %3.2e seconds, speedup = %3.2f\n', [t_ifgt_tree_nu; t_direct./t_ifgt_tree_nu] ); - fprintf('\nMaximum absolute error from direct (exact) method:\n'); - fprintf('direct-tree : %3.2e\n', e_direct_tree ); - fprintf('ifgt-u : %3.2e\n', e_ifgt_u ); - fprintf('ifgt-nu : %3.2e\n', e_ifgt_nu ); - fprintf('ifgt-tree-u : %3.2e\n', e_ifgt_tree_u ); - fprintf('ifgt-tree-nu : %3.2e\n', e_ifgt_tree_nu ); - - if( (max(e_direct_tree(:)) < epsilon) && ... - (max(e_ifgt_u(:)) < epsilon) && ... - (max(e_ifgt_nu(:)) < epsilon) && ... - (max(e_ifgt_tree_u(:)) < epsilon) && ... - (max(e_ifgt_tree_nu(:)) < epsilon) ) - fprintf('\nDesired error (%e) satisfied.\n', epsilon); - else - fprintf('\nDesired error (%e) NOT satisfied!\n', epsilon); - end; - -end; diff --git a/samples/matlab_sample1_simple.m b/samples/matlab_sample1_simple.m new file mode 100644 index 0000000..b66ce66 --- /dev/null +++ b/samples/matlab_sample1_simple.m @@ -0,0 +1,94 @@ +% Script the demonstrate the use of FIGTree. Note, only +% (FIGTREE-DIRECTORY)/matlab/figtree.dll is needed for the figtree() function to +% function. +% +% Created by Vlad Morariu on 2008-12-03. +clear all; +close all; +clear functions; +clc; + +% the MEX binaries for the FIGTree library reside in ../matlab +% we assume that the script is run from the figtree/samples/ directory, +% otherwise the correct path for the mex files must be set. +addpath('../matlab'); + +disp('---------------------------------------------'); +disp(sprintf('Example to demonstrate the use of FIGTree')); +disp('---------------------------------------------'); + +% the distribution +disp(sprintf('Sources uniformly distributed\nTargets uniformly distributed')); + +% the number of sources +N = 10000; +disp(sprintf('Number of source points N=%d',N)); + +% the number of targets +M = 10000; +disp(sprintf('Number of target points M=%d',M)); + +% the desired error +epsilon = 1e-2; +disp(sprintf('Target error epsilon=%e',epsilon)); + +% the data dimensionality +d = 3; +disp(sprintf('Dimensionality d=%d',d)); + +% the bandwidth +h = .02; +disp(sprintf('Bandwidth h=%f',h)); + +% the source points +% d x N matrix of N source points in d dimensions. +X = rand(d,N); + +% the target points +% d x M matrix of M source points in d dimensions. +Y = rand(d,M); + +% the source weights +% 1 x N row vector +q = rand(1,N); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Evaluate gauss transform +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Call figtree, using default parameters. The default is to choose the +% fastest method automatically by predicting estimated evaluation cost of +% each method (evalMethod=4), to choose ifgt parameters (if an ifgt method +% is chosen) without assuming a uniform distribution (ifgtParamMethod=1), +% and to use cluster-wise truncations for ifgt (ifgtTruncMethod=2). These +% default parameters allow for the fastest evaluation and best parameter +% tuning to the actual distributions. +% +% If we wanted to, we could include these default parameters as follows: +% +% evalMethod = 4; ifgtParamMethod = 1; ifgtTruncMethod = 2; verbose=0; +% [ g_auto ] = figtree( X, h, q, Y, epsilon, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ); +% +% However, the function call below is equivalent to the two lines shown +% above, and is simpler to write out. +fprintf('Running figtree (automatic method + param selection) ... '); +tic; +[ g_auto ] = figtree( X, h, q, Y, epsilon ); +t_auto = toc; +fprintf('done.\n'); + +% +% To evaluate error and speedup, we will also call figtree with +% evalMethod=0 so that direct evaluation is performed. +% +fprintf('Running exact method, for error and time comparison ... '); +tic; +evalMethod=0; +[ g_exact ] = figtree( X, h, q, Y, epsilon, evalMethod ); +t_exact = toc; +fprintf('done.\n'); + +disp('---------------------------------------------'); +fprintf('exact : %3.2e seconds\n', t_exact ); +fprintf('auto : %3.2e seconds, speedup = %3.2f, error = %3.2e\n', ... + t_auto, t_exact/t_auto, max(abs(g_exact-g_auto))/sum(q) ); \ No newline at end of file diff --git a/samples/matlab_sample2.m b/samples/matlab_sample2.m deleted file mode 100644 index 3f2d76e..0000000 --- a/samples/matlab_sample2.m +++ /dev/null @@ -1,173 +0,0 @@ -% Script the demonstrate the use of FIGTree without the wrapper function 'figtree' -% (i.e. by manually calling figtreeChooseParameters*(), KCenterClustering(), -% etc). Manually calling these functions instead of letting figtree() do it -% allows the user to change parameters (such as number of clusters, -% truncation number, or even the clustering method itself). -clear all; -close all; -clear functions; -clc; - -% the MEX binaries for the FIGTree library reside in ../matlab -% we assume that the script is run from the figtree/samples/ directory, -% otherwise the correct path for the mex files must be set. -addpath('../matlab'); - -disp('---------------------------------------------'); -disp(sprintf('Example to demonstrate the use of FIGTree')); -disp('---------------------------------------------'); - -% the data dimensionality -d = 2; -disp(sprintf('Dimensionality d=%d\n',d)); - -% the number of sources -N = 5000; -disp(sprintf('Number of source points N=%d\n',N)); - -% the number of targets -M = 5000; -disp(sprintf('Number of target points M=%d\n',M)); - -% the source points -% d x N matrix of N source points in d dimensions. -% Scale the data -G = 25; -m = rand(d,G); -v = 0.02*ones(1,G); -[X] = generate_multiple_gaussians(N,G,m,v,d); - -for j = 1:d - shift = min(X(j,:)); - X_shifted(j,:) = X(j,:)-shift; - scale = 1/max(X_shifted(j,:)); - X_shifted_scaled(j,:) = X_shifted(j,:)*scale; -end -X= X_shifted_scaled; - -% the target points -% d x M matrix of M source points in d dimensions. -Y = rand(d,M); - -% the source weights -% 1 x N row vector -q=rand(1,N); - -% the bandwidth -h = sqrt(2)*0.2*sqrt(d); -disp(sprintf('Bandwidth h=%f\n',h)); - -% the desired error -epsilon=1e-3; -disp(sprintf('Target error epsilon=%e\n',epsilon)); - -% The upper limit on the number of clusters. -kLimit = N; % we'll let KCenterClustering stop whenever it reaches N clusters - % or when there are no more unique source pts -disp(sprintf('kLimit=%d\n',kLimit)); -disp(sprintf('Press any key to continue...\n')); -pause - -disp('---------------------------------------------'); -disp(sprintf('Choosing the FIGTree parameters\n')); -disp('---------------------------------------------'); - -% Choose the parameters -% -% K -- number of clusters -% p_max -- maximum truncation number -% r -- cutoff radius - -to=clock; -% you can uncomment the next line and comment the one after it to choose -% parameters assuming uniform source distribution -%[K,p_max,r]=figtreeChooseParametersUniform(d,h,epsilon,kLimit, 1); -[K,p_max,r]=figtreeChooseParametersNonUniform(d,N,X,h,epsilon,kLimit,1); -parameters_time=etime(clock,to); - -disp(sprintf('Number of clusters K=%d\n',K)); -disp(sprintf('Maximum truncation number p_max=%d\n', p_max)); -disp(sprintf('Cutoff radius r=%f\n',r)); -disp(sprintf('Time taken=%f secs\n',parameters_time)); -disp(sprintf('Press any key to continue...\n')); -pause - -disp('---------------------------------------------'); -disp(sprintf('Running the k-center clustering\n')); -disp('---------------------------------------------'); - -% k-center clustering -to=clock; -[K, rx, clusterIndex, clusterCenter, numPoints, clusterRadii] = figtreeKCenterClustering(d, N, X, K); -clustering_time=etime(clock,to); - -disp(sprintf('Actual clusters(K)=%f\n', K)); -disp(sprintf('Maximum cluster radius=%f\n', rx)); -disp(sprintf('Time taken=%f secs\n', clustering_time)); - -%Pretty plot of the results of the clustering procedure. -%Plots only for two and three dimensions. -plot_clusters(N, d, X, K, clusterIndex, clusterCenter); - -disp(sprintf('Press any key to continue...\n')); -pause - -disp('---------------------------------------------'); -disp(sprintf('Updating the truncation number\n')); -disp('---------------------------------------------'); - -to = clock; -[p_max] = figtreeChooseTruncationNumber(d, h, epsilon, rx, 1); -trunc_time = etime(clock,to); - -disp(sprintf('Updated Maximum Truncation Number=%d\n',p_max)); -disp(sprintf('Time taken=%f secs\n',trunc_time)); -disp(sprintf('Press any key to continue...\n')); -pause - -disp('---------------------------------------------'); -disp(sprintf('Running the FIGTree\n')); -disp('---------------------------------------------'); - -to=clock; -% you can use another evaluation method by uncommenting it and commenting -% the current one. Note that to use the last, the bandwidth should be set -% to some very small number (eg. .01) or else evaluation will take a very -% long time. -[G_FIGTREE]=figtreeEvaluateIfgt(d, N, M, 1, X, h, q, Y, p_max, K, ... - clusterIndex, clusterCenter, clusterRadii, r, epsilon); -%[G_FIGTREE]=figtreeEvaluateIfgtTree(d, N, M, 1, X, h, q, Y, p_max, K, ... -% clusterIndex, clusterCenter, clusterRadii, r, epsilon); -%[G_FIGTREE]=figtreeEvaluateDirectTree(d, N, M, X, h, q, Y, epsilon); % very slow if bandwidth is above h = .1 -FIGTREE_time=etime(clock,to); - -disp(sprintf('Time taken=%f secs\n',FIGTREE_time)); -disp(sprintf('Press any key to continue...\n')); - -pause - -disp('---------------------------------------------'); -disp(sprintf('Running the direct method.\n')); -disp('---------------------------------------------'); - -to=clock; -[G_direct]=figtreeEvaluateDirect(d,N,M,X,h,q,Y); -GT_time=etime(clock,to); - -disp(sprintf('Time taken=%f secs\n',GT_time)); - -disp('---------------------------------------------'); -disp(sprintf('Summary\n')); -disp('---------------------------------------------'); - -FIGTREE_total_time=parameters_time+clustering_time+trunc_time+FIGTREE_time; -FIGTREE_err=max(abs((G_direct-G_FIGTREE)))/sum(q); - -disp(sprintf('Direct computation takes %f secs\n',GT_time)); -disp('---------------------------------------------'); -disp(sprintf('FIGTree takes %f secs Speedup=%f\n',FIGTREE_total_time,GT_time/FIGTREE_total_time)); -disp(sprintf('Actual error for FIGTree is %e Target was %e \n',FIGTREE_err,epsilon)); -disp('---------------------------------------------'); - - - diff --git a/samples/matlab_sample1.m b/samples/matlab_sample2_diff_methods.m similarity index 72% rename from samples/matlab_sample1.m rename to samples/matlab_sample2_diff_methods.m index 3be08d5..13aa5b1 100644 --- a/samples/matlab_sample1.m +++ b/samples/matlab_sample2_diff_methods.m @@ -1,8 +1,6 @@ % Script the demonstrate the use of FIGTree. Note, only % (FIGTREE-DIRECTORY)/matlab/figtree.dll is needed for the figtree() function to -% function. All other mex files are provided in case users require -% advanced control over parameter selection and clustering processes. See -% sample2.m for example of how to use the additional mex files provided. +% function. clear all; close all; clear functions; @@ -13,6 +11,16 @@ % otherwise the correct path for the mex files must be set. addpath('../matlab'); +% This example runs all evaluation methods with both parameter selection +% methods with some different source/target distributions, dimensionality, +% and bandwidth, to show some cases where some methods perform better +% than others. +% +% As expected, the non-uniform parameter selection outperforms the +% uniform parameter selection method as it tunes parameters to the actual +% data. In addition, depending on the situation, different evaluation +% methods outperform, but the automatic method selection approach is always +% very close to the fastest method. disp('---------------------------------------------'); disp(sprintf('Examples to demonstrate the use of FIGTree')); disp('---------------------------------------------'); @@ -29,9 +37,6 @@ epsilon = 1e-3; disp(sprintf('Target error epsilon=%e',epsilon)); -% run all algorithms with all parameter selection methods with some -% different source/target distributions, dimensionality, and bandwidth, -% to show some cases where some methods perform better than others for i = 1:4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Generate sources and targets @@ -178,58 +183,70 @@ % Evaluate gauss transform %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % direct method (exact up to machine precision) + % direct method (exact up to machine precision) (evalMethod=0) tic; - [ g_direct ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 0, 0 ); + [ g_direct ] = figtree( X, h, q, Y, epsilon, 0 ); t_direct = toc; fprintf('direct : %3.2e seconds\n', t_direct ); - % direct evaluation with approximate nearest neighbor structure - % (parameter selection not relevant, so it can be anything) - - % implemented as in the FIGTree paper (Raykar et al, submitted to - % Joural of Machine Learning). + % direct evaluation with tree data structure (evalMethod=2) tic; - [ g_direct_tree ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 2, 0 ); + [ g_direct_tree ] = figtree( X, h, q, Y, epsilon, 2 ); t_direct_tree = toc; fprintf('direct-tree : %3.2e seconds, speedup = %3.2f\n', t_direct_tree, t_direct/t_direct_tree ); - % truncated series, uniform parameter selection - implemented exactly - % as described in IFGT paper (Raykar et al, 2005). + % ifgt (evalMethod=1) and parameter selection that assume + % uniform distribution (ifgtParamMethod=0) tic; - [ g_ifgt_u ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 1, 0 ); + [ g_ifgt_u ] = figtree( X, h, q, Y, epsilon, 1, 0 ); t_ifgt_u = toc; fprintf('ifgt-u : %3.2e seconds, speedup = %3.2f\n', t_ifgt_u, t_direct/t_ifgt_u ); - % truncated series, with nonuniform parameter selection - the - % default method when calling function without last two arguments - % that select the method: figtree( d, N, M, 1, X, h, q, Y, epsilon ); - % works well in general + % ifgt (evalMethod=1) and parameter selection that does not assume + % uniform distribution (ifgtParamMethod=1) tic; - [ g_ifgt_nu ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 1, 1 ); + [ g_ifgt_nu ] = figtree( X, h, q, Y, epsilon, 1, 1 ); t_ifgt_nu = toc; fprintf('ifgt-nu : %3.2e seconds, speedup = %3.2f\n', t_ifgt_nu, t_direct/t_ifgt_nu ); - % truncated series with approximate nearest neighbor structure, - % with uniform parameter selection - implemented as in the FIGTree - % paper (Raykar et al, submitted to Joural of Machine Learning). + % ifgt with tree data structure (evalMethod=3) and parameter selection + % that assumes uniform distribution (ifgtParamMethod=0) tic; - [ g_ifgt_tree_u ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 3, 0 ); + [ g_ifgt_tree_u ] = figtree( X, h, q, Y, epsilon, 3, 0 ); t_ifgt_tree_u = toc; fprintf('ifgt-tree-u : %3.2e seconds, speedup = %3.2f\n', t_ifgt_tree_u, t_direct/t_ifgt_tree_u ); - % truncated series, with non-uniform parameter selection. Is faster - % than ifgt-nu if targets are not identically distributed to - % sources. + % ifgt with tree data structure (evalMethod=3) and parameter selection + % that does NOT assume uniform distribution (ifgtParamMethod=1) tic; - [ g_ifgt_tree_nu ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 3, 1 ); + [ g_ifgt_tree_nu ] = figtree( X, h, q, Y, epsilon, 3, 1 ); t_ifgt_tree_nu = toc; fprintf('ifgt-tree-nu : %3.2e seconds, speedup = %3.2f\n', t_ifgt_tree_nu, t_direct/t_ifgt_tree_nu ); - + + % automatically select evaluation method (evalMethod=4) and use + % parameter selection that assumes uniform distribution + % (ifgtParamMethod=0). + tic; + [ g_auto_u ] = figtree( X, h, q, Y, epsilon, 4, 0 ); + t_auto_u = toc; + fprintf('auto-u : %3.2e seconds, speedup = %3.2f\n', t_auto_u, t_direct/t_auto_u ); + + % automatically select evaluation method (evalMethod=4) and use + % parameter selection that does NOT assume uniform distribution + % (ifgtParamMethod=1). + tic; + [ g_auto_nu ] = figtree( X, h, q, Y, epsilon, 4, 1 ); + t_auto_nu = toc; + fprintf('auto-nu : %3.2e seconds, speedup = %3.2f\n', t_auto_nu, t_direct/t_auto_nu ); + + err_direct_tree = max(abs(g_direct-g_direct_tree))/sum(q); err_ifgt_u = max(abs(g_direct-g_ifgt_u))/sum(q); err_ifgt_nu = max(abs(g_direct-g_ifgt_nu))/sum(q); err_ifgt_tree_u = max(abs(g_direct-g_ifgt_tree_u))/sum(q); err_ifgt_tree_nu = max(abs(g_direct-g_ifgt_tree_nu))/sum(q); + err_auto_u = max(abs(g_direct-g_auto_u))/sum(q); + err_auto_nu = max(abs(g_direct-g_auto_nu))/sum(q); % show errors fprintf('\nMaximum absolute error from direct (exact) method:\n'); @@ -238,12 +255,16 @@ fprintf('ifgt-nu : %3.2e\n', err_ifgt_nu); fprintf('ifgt-tree-u : %3.2e\n', err_ifgt_tree_u); fprintf('ifgt-tree-nu : %3.2e\n', err_ifgt_tree_nu); + fprintf('auto-u : %3.2e\n', err_auto_u); + fprintf('auto-nu : %3.2e\n', err_auto_nu); if( (err_direct_tree < epsilon) && ... (err_ifgt_u < epsilon) && ... (err_ifgt_nu < epsilon) && ... (err_ifgt_tree_u < epsilon) && ... - (err_ifgt_tree_nu < epsilon) ) + (err_ifgt_tree_nu < epsilon)&& ... + (err_auto_u < epsilon)&& ... + (err_auto_nu < epsilon) ) fprintf('\nDesired error (%e) satisfied.\n', epsilon); else fprintf('\nDesired error (%e) NOT satisfied!\n', epsilon); diff --git a/samples/matlab_sample3.m b/samples/matlab_sample3.m deleted file mode 100644 index b6010b9..0000000 --- a/samples/matlab_sample3.m +++ /dev/null @@ -1,159 +0,0 @@ -% Script the demonstrate the use of FIGTree. Note, only -% (FIGTREE-DIRECTORY)/matlab/figtree.dll is needed for the figtree() function to -% function. All other mex files are provided in case users require -% advanced control over parameter selection and clustering processes. See -% sample2.m for example of how to use the additional mex files provided. -clear all; -close all; -clear functions; -clc; - -% the MEX binaries for the FIGTree library reside in ../matlab -% we assume that the script is run from the figtree/samples/ directory, -% otherwise the correct path for the mex files must be set. -addpath('../matlab'); - -disp('---------------------------------------------'); -disp(sprintf('Examples to demonstrate the use of FIGTree')); -disp('---------------------------------------------'); - -% the number of sources -N = 2000; -disp(sprintf('Number of source points N=%d',N)); - -% the number of targets -M = 2000; -disp(sprintf('Number of target points M=%d',M)); - -% the desired error -epsilon = 1e-3; -disp(sprintf('Target error epsilon=%e',epsilon)); - -% verbosity -verbose = 0; - -ds = 1:6; -hs = [.01 .02 .04 .08 .16 .32 .64]; -ntrials = 1; - -timings_direct = zeros( ntrials, length(hs), length(ds) ); -timings_direct_tree = zeros( ntrials, length(hs), length(ds) ); -timings_ifgt = zeros( ntrials, length(hs), length(ds) ); -timings_ifgt_nu = zeros( ntrials, length(hs), length(ds) ); -timings_ifgt_tree = zeros( ntrials, length(hs), length(ds) ); -timings_ifgt_tree_nu = zeros( ntrials, length(hs), length(ds) ); - -for k = 1:length(ds) - d = ds(k); - for j = 1:length(hs) - h = hs(j); - for i = 1:ntrials - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Generate sources and targets - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('\n\n'); - disp('----------------------------------------------------------------------'); - disp(sprintf('Sources drawn from multiple gaussians\nTargets uniformly distributed')); - - % the data dimensionality - disp(sprintf('Dimensionality d=%d',d)); - - % the bandwidth - %h = rand(1); - disp(sprintf('Bandwidth h=%f',h)); - disp('----------------------------------------------------------------------'); - - % the source points - % d x N matrix of N source points in d dimensions. - X = rand(d,N); - - % the target points - % d x M matrix of M source points in d dimensions. - Y = rand(d,M); - - % the source weights - % 1 x N row vector - q = rand(1,N); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Evaluate gauss transform - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % direct method (exact up to machine precision) - tic; - [ g_direct ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 0, 0, verbose ); - t_direct = toc; - fprintf('direct : %3.2e seconds\n', t_direct ); - - % direct evaluation with approximate nearest neighbor structure - % (parameter selection not relevant, so it can be anything) - - % implemented as in the FIGTree paper (Raykar et al, submitted to - % Joural of Machine Learning). - tic; - [ g_direct_tree ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 2, 0, verbose ); - t_direct_tree = toc; - fprintf('direct-tree : %3.2e seconds, speedup = %3.2f\n', t_direct_tree, t_direct/t_direct_tree ); - - % truncated series, uniform parameter selection - implemented exactly - % as described in IFGT paper (Raykar et al, 2005). - tic; - [ g_ifgt_u ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 1, 0, verbose ); - t_ifgt_u = toc; - fprintf('ifgt-u : %3.2e seconds, speedup = %3.2f\n', t_ifgt_u, t_direct/t_ifgt_u ); - - % truncated series, with nonuniform parameter selection - the - % default method when calling function without last two arguments - % that select the method: figtree( d, N, M, 1, X, h, q, Y, epsilon ); - % works well in general - tic; - [ g_ifgt_nu ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 1, 1, verbose ); - t_ifgt_nu = toc; - fprintf('ifgt-nu : %3.2e seconds, speedup = %3.2f\n', t_ifgt_nu, t_direct/t_ifgt_nu ); - - % truncated series with approximate nearest neighbor structure, - % with uniform parameter selection - implemented as in the FIGTree - % paper (Raykar et al, submitted to Joural of Machine Learning). - tic; - [ g_ifgt_tree_u ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 3, 0, verbose ); - t_ifgt_tree_u = toc; - fprintf('ifgt-tree-u : %3.2e seconds, speedup = %3.2f\n', t_ifgt_tree_u, t_direct/t_ifgt_tree_u ); - - % truncated series, with non-uniform parameter selection. Is faster - % than ifgt-nu if targets are not identically distributed to - % sources. - tic; - [ g_ifgt_tree_nu ] = figtree( d, N, M, 1, X, h, q, Y, epsilon, 3, 1, verbose ); - t_ifgt_tree_nu = toc; - fprintf('ifgt-tree-nu : %3.2e seconds, speedup = %3.2f\n', t_ifgt_tree_nu, t_direct/t_ifgt_tree_nu ); - - % show errors - fprintf('\nMaximum absolute error from direct (exact) method:\n'); - fprintf('direct-tree : %3.2e\n', max(abs(g_direct-g_direct_tree))/sum(q)); - fprintf('ifgt-u : %3.2e\n', max(abs(g_direct-g_ifgt_u))/sum(q)); - fprintf('ifgt-nu : %3.2e\n', max(abs(g_direct-g_ifgt_nu))/sum(q)); - fprintf('ifgt-tree-u : %3.2e\n', max(abs(g_direct-g_ifgt_tree_u))/sum(q)); - fprintf('ifgt-tree-nu : %3.2e\n', max(abs(g_direct-g_ifgt_tree_nu))/sum(q)); - - timings_direct(i,j,k) = t_direct; - timings_direct_tree(i,j,k) = t_direct_tree; - timings_ifgt(i,j,k) = t_ifgt_u; - timings_ifgt_nu(i,j,k) = t_ifgt_nu; - timings_ifgt_tree(i,j,k) = t_ifgt_tree_u; - timings_ifgt_tree_nu(i,j,k) = t_ifgt_tree_nu; - end; - end; - - figure; - loglog( hs, sum(timings_direct(:,:,k), 1), 'r.-', ... - hs, sum(timings_direct_tree(:,:,k), 1), 'g.-', ... - hs, sum(timings_ifgt(:,:,k), 1), 'b.-', ... - hs, sum(timings_ifgt_nu(:,:,k), 1), 'c.-', ... - hs, sum(timings_ifgt_tree(:,:,k), 1), 'm.-', ... - hs, sum(timings_ifgt_tree_nu(:,:,k), 1), 'k.-' ... - ); - legend('direct', 'direct-tree', 'ifgt', 'ifgt-nu', 'ifgt-tree', 'ifgt-tree-nu'); - xlabel('bandwidth(h)'); - ylabel('CPU Time'); - title(sprintf('CPU Time vs h (d = %i, N = %i, M = %i)', d, N, M)); - %pause; -end; \ No newline at end of file diff --git a/samples/matlab_sample3_auto_selection.m b/samples/matlab_sample3_auto_selection.m new file mode 100644 index 0000000..c72210e --- /dev/null +++ b/samples/matlab_sample3_auto_selection.m @@ -0,0 +1,180 @@ +% Script the demonstrate the use of FIGTree. Note, only +% (FIGTREE-DIRECTORY)/matlab/figtree.dll is needed for the figtree() function to +% function. +clear all; +close all; +clear functions; +clc; + +% the MEX binaries for the FIGTree library reside in ../matlab +% we assume that the script is run from the figtree/samples/ directory, +% otherwise the correct path for the mex files must be set. +addpath('../matlab'); + +disp('---------------------------------------------'); +disp(sprintf('Examples to demonstrate the use of FIGTree')); +disp('---------------------------------------------'); + +% the number of sources +N = 4000; +disp(sprintf('Number of source points N=%d',N)); + +% the number of targets +M = 2000; +disp(sprintf('Number of target points M=%d',M)); + +% the desired error +epsilon = 1e-2; +disp(sprintf('Target error epsilon=%e',epsilon)); + +% verbosity +verbose = 0; + +ds = 1:4; +hs = [.01 .02 .04 .08 .16 .32 .64]; +ntrials = 1; + +timings_direct = zeros( ntrials, length(hs), length(ds) ); +timings_direct_tree = zeros( ntrials, length(hs), length(ds) ); +timings_ifgt = zeros( ntrials, length(hs), length(ds) ); +timings_ifgt_tree = zeros( ntrials, length(hs), length(ds) ); +timings_auto_method = zeros( ntrials, length(hs), length(ds) ); + +flops_direct = zeros( ntrials, length(hs), length(ds) ); +flops_direct_tree = zeros( ntrials, length(hs), length(ds) ); +flops_ifgt = zeros( ntrials, length(hs), length(ds) ); +flops_ifgt_tree = zeros( ntrials, length(hs), length(ds) ); + +for k = 1:length(ds) + d = ds(k); + for j = 1:length(hs) + h = hs(j); + for i = 1:ntrials + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Generate sources and targets + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + fprintf('\n\n'); + disp('----------------------------------------------------------------------'); + disp(sprintf('Sources drawn from multiple gaussians\nTargets uniformly distributed')); + + % the data dimensionality + disp(sprintf('Dimensionality d=%d',d)); + + % the bandwidth + %h = rand(1); + disp(sprintf('Bandwidth h=%f',h)); + disp('----------------------------------------------------------------------'); + + % the source points + % d x N matrix of N source points in d dimensions. + X = rand(d,N); + + % the target points + % d x M matrix of M source points in d dimensions. + Y = rand(d,M); + + % the source weights + % 1 x N row vector + q = rand(1,N); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Evaluate gauss transform + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % direct method (exact up to machine precision) + % the arguments 'ifgtParamMethod' and 'ifgtTruncMethod' are + % irrelevant since we are not evaluating using ifgt. + evalMethod = 0; ifgtParamMethod = 1; ifgtTruncMethod = 2; + tic; + [ g_direct ] = figtree( X, h, q, Y, epsilon, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ); + t_direct = toc; + fprintf('direct : %3.2e seconds\n', t_direct ); + + % direct evaluation with tree data structure + % the arguments 'ifgtParamMethod' and 'ifgtTruncMethod' are + % irrelevant since we are not evaluating using ifgt. + evalMethod = 2; ifgtParamMethod = 1; ifgtTruncMethod = 2; + tic; + [ g_direct_tree ] = figtree( X, h, q, Y, epsilon, 2, 0, 2, verbose ); + t_direct_tree = toc; + fprintf('direct+tree : %3.2e seconds, speedup = %3.2f\n', t_direct_tree, t_direct/t_direct_tree ); + + % ifgt evaluation, with non-uniform parameter selection (does + % not assume uniform distribution), with cluster-wise + % truncations + evalMethod = 1; ifgtParamMethod = 1; ifgtTruncMethod = 2; + tic; + [ g_ifgt ] = figtree( X, h, q, Y, epsilon, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ); + t_ifgt = toc; + fprintf('ifgt : %3.2e seconds, speedup = %3.2f\n', t_ifgt, t_direct/t_ifgt ); + + % ifgt evaluation, with non-uniform parameter selection (does + % not assume uniform distribution), with cluster-wise + % truncations + evalMethod = 3; ifgtParamMethod = 1; ifgtTruncMethod = 2; + tic; + [ g_ifgt_tree ] = figtree( X, h, q, Y, epsilon, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ); + t_ifgt_tree = toc; + fprintf('ifgt-tree : %3.2e seconds, speedup = %3.2f\n', t_ifgt_tree, t_direct/t_ifgt_tree ); + + % we run 'figtreeChooseEvaluationMethod' just so we can obtain + % the estimated flops and to time method selection + tic; + [ best_method, flops ] = figtreeChooseEvaluationMethod( X, h, 1, Y, epsilon, 1, verbose ); + t_auto_method = toc; + + flops_direct(i,j,k) = flops(1); + flops_ifgt(i,j,k) = flops(2); + flops_direct_tree(i,j,k) = flops(3); + flops_ifgt_tree(i,j,k) = flops(4); + + % ifgt evaluation, with non-uniform parameter selection (does + % not assume uniform distribution), with cluster-wise + % truncations + evalMethod = 4; ifgtParamMethod = 1; ifgtTruncMethod = 2; + tic; + [ g_auto ] = figtree( X, h, q, Y, epsilon, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ); + t_auto = toc; + fprintf('auto : %3.2e seconds, speedup = %3.2f (%3.2e seconds to choose method)\n', t_auto_method+t_auto, t_direct/(t_auto_method+t_auto), t_auto_method ); + + + % show errors + fprintf('\nMaximum absolute error from direct (exact) method:\n'); + fprintf('direct+tree : %3.2e\n', max(abs(g_direct-g_direct_tree))/sum(q)); + fprintf('ifgt : %3.2e\n', max(abs(g_direct-g_ifgt))/sum(q)); + fprintf('ifgt+tree : %3.2e\n', max(abs(g_direct-g_ifgt_tree))/sum(q)); + fprintf('auto(%i) : %3.2e\n', best_method, max(abs(g_direct-g_auto))/sum(q)); + + timings_direct(i,j,k) = t_direct; + timings_direct_tree(i,j,k) = t_direct_tree; + timings_ifgt(i,j,k) = t_ifgt; + timings_ifgt_tree(i,j,k) = t_ifgt_tree; + timings_auto_method(i,j,k) = t_auto_method + t_auto; + end; + end; + + figure; + loglog( hs, sum(timings_direct(:,:,k), 1), 'r.-', ... + hs, sum(timings_direct_tree(:,:,k), 1), 'g.-', ... + hs, sum(timings_ifgt(:,:,k), 1), 'c.-', ... + hs, sum(timings_ifgt_tree(:,:,k), 1), 'k.-', ... + hs, sum(timings_auto_method(:,:,k), 1), 'y.-' ... + ); + legend('direct', 'direct+tree', 'ifgt', 'ifgt+tree', 'auto'); + xlabel('bandwidth(h)'); + ylabel('CPU Time'); + title(sprintf('CPU Time vs h (d = %i, N = %i, M = %i)', d, N, M)); + + figure; + loglog( hs, sum(flops_direct(:,:,k), 1), 'r.-', ... + hs, sum(flops_direct_tree(:,:,k), 1), 'g.-', ... + hs, sum(flops_ifgt(:,:,k), 1), 'c.-', ... + hs, sum(flops_ifgt_tree(:,:,k), 1), 'k.-' ... + ); + legend('direct', 'direct+tree', 'ifgt', 'ifgt+tree'); + xlabel('bandwidth(h)'); + ylabel('Estimated Flops'); + title(sprintf('Estimated Flops vs h (d = %i, N = %i, M = %i)', d, N, M)); + + %pause; +end; \ No newline at end of file diff --git a/src/KCenterClustering.h b/src/KCenterClustering.h index daa7df5..8be3368 100644 --- a/src/KCenterClustering.h +++ b/src/KCenterClustering.h @@ -50,7 +50,6 @@ // Speed up using the doubly circular list. // The clusters far away are trimmed. The nodes inside the neighboring // clusters which are within half sphere are trimmed. -// The computational complexity is reduced to O(n log k). // //---------------------------------------------------------------------------- // diff --git a/src/Makefile b/src/Makefile index 977fbaf..a50e2e4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,13 +10,6 @@ LIBDIR = $(BASEDIR)/lib BINDIR = $(BASEDIR)/bin #----------------------------------------------------------------------------- -# Default locations for the Approximate Nearest Neighbor (ANN) library. -# For other locations, modify the paths in this makefile, or set them on the -# command line. For example, if the ANN library resides in your_ann_path, -# you can either modify the variables below, or call 'make' as below: -# -# make "ANNLIBDIR=your_ann_path/lib" "ANNINCDIR=your_ann_path/include" -# # If you do not have the ANN library on your system or wish to compile # the IFGT library without ANN support, either uncomment the line # that defines "FIGTREE_NO_ANN=true" or set it on the command line: @@ -24,8 +17,8 @@ BINDIR = $(BASEDIR)/bin # make "FIGTREE_NO_ANN=true" # #----------------------------------------------------------------------------- -ANNLIBDIR = $(BASEDIR)/../ann_1.1.1/lib -ANNINCDIR = $(BASEDIR)/../ann_1.1.1/include +ANNLIBDIR = $(BASEDIR)/lib +ANNINCDIR = $(BASEDIR)/external/ann_1.1.1/include # uncomment this line to compile the library without ANN support #FIGTREE_NO_ANN=true @@ -61,7 +54,7 @@ CFLAGS+= -DFIGTREE_NO_ANN else CFLAGS+= -I$(ANNINCDIR) ifneq ($(FIGTREE_LIB_TYPE),static) -LDFLAGS= -L$(ANNLIBDIR) -lANN +LDFLAGS= -L$(ANNLIBDIR) -lann_figtree_version endif endif diff --git a/src/figtree.cpp b/src/figtree.cpp index b18da6c..ca29821 100644 --- a/src/figtree.cpp +++ b/src/figtree.cpp @@ -62,7 +62,55 @@ // Also added FIGTREE_CHECK_POS_DOUBLE macro to allow rx to be zero when // checking input parameters. // - +// Modified: 05-03-08 by Vlad Morariu +// Add method selection code. This set of functions uses a tree data structure +// and k-center clustering to estimate number of source neighbors, target neighbors, +// and ifgt parameters, which then allows us to estimate how much it would cost +// to evaluate using any of direct, direct+tree, ifgt, or ifgt+tree. +// +// Modified: 05-27-08 by Vlad Morariu +// Change figtreeChooseParameters* and figtreeChooseTruncationNumber functions +// to return the predicted errorBound. This can then be used to check if +// the parameters chosen will satisfy the desired error bound (they may not +// since we enforce a limit on pMax (the truncation number). +// +// Modified: 05-29-08 by Vlad Morariu +// Fixed a small computational error in the error bound (when choosing truncation +// number). Because the bounds are loose, the desired error was still met even +// with the computation error. +// +// Modified: 05-29-08 to 06-10-08 by Vlad Morariu +// A few changes were made: +// 1) Added code to choose individual truncation numbers for both targets and sources +// using pointwise error bounds. +// 2) Added code to choose individual truncation numbers for targets and sources +// using clusterwise error bounds. +// 3) Reuse K-center clustering computed during method selection if +// FIGTREE_EVAL_AUTO is chosen. +// 4) Changed ANN code to compute unordered nearest neighbors, saving time +// by not using a priority queue and also because now the fixed radius +// nearest neighbor computation and retrieval is done in one step, +// instead of first finding # of nn's and then doing the search again to +// retrieve the nn's. This really speeds up direct+tree since the ANN +// priority queue was implemented using insertion sort. +// +// Modified: 11-02-08, 12-01-08 to 12-05-08 by Vlad Morariu +// Made some revisions before posting new version online. +// 1) Changed interface of figtree so users can choose truncation method +// (also changed figtree() to automatically revert to the simplest +// truncation method in cases where the two more complex methods +// cannot give a speedup). +// 2) Revised some comments +// 3) Found all parameters used throughout code and defined constants for them +// so that users can change them and recompile. In future releases, +// these should only be defaults, and users should be able to modify them +// at runtime. +// 4) Removed most helper functions from figtree.h (all but figtree(), +// figtreeChooseEvaluationMethod(), and figtreeKCenterClustering() ) and +// placed them in figtree_internal.h. +// 5) Changed floating op estimation functions to reflect revised versions +// of code +// //------------------------------------------------------------------------------ // The code was written by Vlad Morariu, Vikas Raykar, and Changjiang Yang // and is copyrighted under the Lesser GPL: @@ -85,11 +133,43 @@ // morariu(at)umd(.)edu, vikas(at)umiacs(.)umd(.)edu, cyang(at)sarnoff(.)com //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Parameters used by the algorithm +// +// Currently, the code must be recompiled when these parameters are changed. +// In future releases, users should be able to dynamically set these at runtime. +// +// FLOPS_EXP is especially important since each processor might have different +// values for this, which will affect prediction performance +//------------------------------------------------------------------------------ + +#define P_UPPER_LIMIT 100 // upper limit on truncation numbers +//#define C_UPPER_LIMIT 536870912 // upper limit for total amt of memory + // coefficients can use... NOT USED FOR NOW + +// these parameters are all for the method selection portion of the code +#define M_SAMPLE 50 // number of queries when querying tree +#define N_SS_MIN 100 // min number of source samples +#define N_SS_POW .75 // the exponent for determining size of + // subsampled set Nss = N^N_SS_POW +#define K_LIMIT_TO_AVG_NBR_RATIO 2 // the max K we allow as ratio of avg source neighbors +#define FLOPS_EXP 28 // how many floating point ops does exp() + // take (machine dependent) + +//------------------------------------------------------------------------------ +// headers +//------------------------------------------------------------------------------ +#define _SECURE_SCL 0 + #include "figtree.h" +#include "figtree_internal.h" -#include // for definition of NULL -#include // for rounding (floor) -#include // for printf +#include // for definition of NULL +#include // for rounding (floor) +#include // for printf + +#include // for lower_bound and random_sample +#include // for greater #include "KCenterClustering.h" // provides class for KCenterClustering @@ -105,9 +185,6 @@ #include #endif -// define the upper limit for the truncation number -#define P_UPPER_LIMIT 100 - // define MAX and MIN if not yet defined #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b) ) @@ -128,16 +205,24 @@ #undef printf #define printf mexPrintf +/* +//Commented this out because when ANN is compiled as part of the same DLL +//it uses the 'new()' definition below, which significantly slows it down. +//I am not sure why the code in the ANN source files uses the 'new()' +//definition in figtree.cpp. +inline void * operator new (size_t size) { void *p=mxMalloc(size); return p; } +inline void operator delete (void *p) { mxFree(p); } +*/ #endif //------------------------------------------------------------------------------ @@ -172,6 +257,121 @@ void operator delete (void *p) return -1; \ } +#ifndef ANN_H +#define ANNpointArray void* +#define ANNkd_tree void* +#endif + +typedef struct _FigtreeData +{ +// // general params - not used yet, but will be used when saving data-structured for multiple calls +// int d; +// int N; +// int M; +// int W; +// double epsilon; +// double * x; +// double h; +// double * q; +// double * y; + + // params for IFGT + int pMax; + int pMaxTotal; + int K; + int * clusterIndex; + double * clusterCenters; + double * clusterRadii; + int * numPoints; + double r; + double rx; + + // params for IFGT + Tree + ANNpointArray annClusters; + ANNkd_tree * annClustersKdTree; + + // params for Direct + Tree + ANNpointArray annSources; + ANNkd_tree * annSourcesKdTree; + +} FigtreeData; + +FigtreeData figtreeCreateData() +{ + FigtreeData data; + + data.pMax = 0; + data.pMaxTotal = 0; + data.K = 0; + data.clusterIndex = NULL; + data.clusterCenters = NULL; + data.clusterRadii = NULL; + data.numPoints = NULL; + data.r = 0; + data.rx = 0; + + data.annClusters = NULL; + data.annClustersKdTree = NULL; + + data.annSources = NULL; + data.annSourcesKdTree = NULL; + + return data; +} + +void figtreeReleaseData( FigtreeData * data ) +{ + data->pMax = 0; + data->pMaxTotal = 0; + data->K = 0; + if( data->clusterIndex != NULL ) + { + delete [] data->clusterIndex; + data->clusterIndex = NULL; + } + if( data->clusterCenters != NULL ) + { + delete [] data->clusterCenters; + data->clusterCenters = NULL; + } + if( data->clusterRadii != NULL ) + { + delete [] data->clusterRadii; + data->clusterRadii = NULL; + } + if( data->numPoints != NULL ) + { + delete [] data->numPoints; + data->numPoints = NULL; + } + data->r = 0; + data->rx = 0; + +#ifndef FIGTREE_NO_ANN + if( data->annClusters != NULL ) + { + annDeallocPts(data->annClusters); + data->annClusters = NULL; + } + if( data->annClustersKdTree != NULL ) + { + delete data->annClustersKdTree; + data->annClustersKdTree = NULL; + } + + if( data->annSources != NULL ) + { + annDeallocPts(data->annSources); + data->annSources = NULL; + } + if( data->annSourcesKdTree != NULL ) + { + delete data->annSourcesKdTree; + data->annSourcesKdTree = NULL; + } +#endif +} + //////////////////////////////////////////////////////////////////////////////// // Helper functions (their prototpyes do not appear in the header file). //////////////////////////////////////////////////////////////////////////////// @@ -331,6 +531,190 @@ void computeTargetCenterMonomials( int d, double h, double * dy, delete [] heads; } +//------------------------------------------------------------------------------ +// Given error(a,b,p) = (2^p/p!) * (a/h)^p * (b/h)^p * e^(-(a-b)^2/h^2), +// calculates the maximum error given only a and the maximum possible b value +// a - radius of source (target) point +// b_max - maximum radius of target (source) point +// c - constant term (2^p/p!) +// h2 - bandwidth, squared +// p - truncation number +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +inline +double figtreeOneSidedErrorBound( double a, double b_max, double c, double h2, int p ) +{ + double b = MIN( b_max, .5*(a + sqrt(a*a + 2*p*h2)) ); // this is the value of at which error(a,b,p) reaches maximum for a given 'a' and 'p' + double d_ab = a-b; + return c * pow(a*b/h2,p) * exp( -d_ab*d_ab/h2 ); +} + + +//------------------------------------------------------------------------------ +// Let error(a,b_max,p) = (2^p/p!) * (a/h)^p * (b/h)^p * e^(-(a-b)^2/h^2). This function +// finds radius values of lo_out and hi_out such that error(a_lo,b_max,p) <= epsilon < error(a_hi,b_max,p) +// We assume that the input arguments a_hi and a_lo initially satisfy this property. +// a - radius of source (target) point +// b_max - maximum radius of target (source) point +// c - constant term (2^p/p!) +// h2 - bandwidth, squared +// p - truncation number +// epsilon - desired error bound +// max_it - number of iterations of halving the interval [lo,hi] +// +// Created by Vlad Morariu on 2008-06-04 +//------------------------------------------------------------------------------ +void figtreeFindRadiusBounds( double a_lo, double a_hi, double b_max, + double c, double h2, int p, double epsilon, + int max_it, double * lo_out, double * hi_out ) +{ + // compute bounds at hi + bool sat_hi = (figtreeOneSidedErrorBound( a_hi, b_max, c, h2 ,p ) <= epsilon); + if( sat_hi ) + { + // the bounds are already satisfied even at a_hi, where error is highest + *hi_out = a_hi; + *lo_out = a_hi; + } + else + { + bool sat_lo = (figtreeOneSidedErrorBound( a_lo, b_max, c, h2 ,p ) <= epsilon); + if( !sat_lo ) + { + // the bounds are not satisfied at a_lo (and since we assume error to increase + // monotonically from a_lo to a_hi, it is not satisfied in this range) + *hi_out = a_hi; + *lo_out = 2*a_lo - a_hi; // go a little past a_lo to signal that not even a_lo satisfied error + } + else + { + for( int i = 0; i < max_it; i++ ) + { + double a_mid = .5*(a_lo + a_hi); + bool sat_mid = (figtreeOneSidedErrorBound( a_mid, b_max, c, h2 ,p ) <= epsilon); + if( sat_mid ) // move the lo or hi value to keep property that error is not satisfied at a_hi, but is satisfied at a_lo + a_lo = a_mid; + else + a_hi = a_mid; + } + *hi_out = a_hi; + *lo_out = a_lo; + } + } +} + + +//------------------------------------------------------------------------------ +// This function precomputes, for each truncation number, the range in the +// distance of a source from the cluster center so that error is still satisfied. +// This is used in the point-wise adaptive version of the IFGT. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void figtreeSourceTruncationRanges( double r, double rx, double h, double epsilon, int pMax, double * max_source_dists2 ) +{ + double h2 = h*h; + for( int i = 0; i < pMax-1; i++ ) + max_source_dists2[i] = -1; // negative numbers indicate no distance satisfies error bounds for the particular value of p + max_source_dists2[pMax-1] = rx; + + double c = 1; + for( int i = 0; i < pMax-1; i++ ) + { + c *= (2.0/(i+1)); + double a_lo = 0, a_hi = rx; + figtreeFindRadiusBounds( a_lo, a_hi, r + rx, c, h2, i+1, epsilon, 10, &a_lo, &a_hi ); + max_source_dists2[i] = a_lo*a_lo; + } +} + +//------------------------------------------------------------------------------ +// This function precomputes, for each truncation number, the range in the +// distance of a target from the cluster center so that error is still satisfied. +// This is used in the point-wise adaptive version of the IFGT. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void figtreeTargetTruncationRanges( double r, double rx, double h, double epsilon, int pMax, double * max_target_dists2, double * min_target_dists2 ) +{ + double h2 = h*h; + double ry = r + rx; + for( int i = 0; i < pMax-1; i++ ) + { + max_target_dists2[i] = -1; + min_target_dists2[i] = ry*ry+1; + } + + double c = 1; + for( int i = 0; i < pMax-1; i++ ) + { + c *= (2.0/(i+1)); + + double peak_dist = .5*(rx + sqrt( rx*rx + 2*h2*(i+1) )); + + // here we calculate for each value of p the maximum distance from a cluster center + // that a target can be to satisfy the error bounds, provided the distance is + // in the portion of the error bound that monotonically increases with distance + double a_lo = 0, a_hi = MIN(ry,peak_dist); + figtreeFindRadiusBounds( a_lo, a_hi, rx, c, h2, i+1, epsilon, 10, &a_lo, &a_hi ); + max_target_dists2[i] = a_lo*a_lo; + + // here we calculate for each value of p the minimum distance from a cluster center + // that a target can be to satisfy the error bounds, provided the radius is + // in the portion of the error bound that monotonically increases with distance + if( peak_dist <= ry ) + { + a_lo = ry, a_hi = peak_dist; + figtreeFindRadiusBounds( a_lo, a_hi, rx, c, h2, i+1, epsilon, 10, &a_lo, &a_hi ); + min_target_dists2[i] = a_lo*a_lo; + } // otherwise we leave it at ry*ry+1 (it should have been initialized to this + + if( i > 0 && min_target_dists2[i] > min_target_dists2[i-1] ) + { + min_target_dists2[i] = min_target_dists2[i-1]; + } + } + if( pMax > 1 && min_target_dists2[pMax-1] > min_target_dists2[pMax-2] ) + { + min_target_dists2[pMax-1] = min_target_dists2[pMax-2]; + } + +} + + +//------------------------------------------------------------------------------ +// Given the precomputed distances from the cluster center for which +// the error bound is satisfied for each truncation number, and the actual +// distance from the cluster center, this function finds the lowest truncation +// number so that error is still satisfied. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +inline +int figtreeSourceTruncationNumber( double dx2, int pMax, double * max_source_dists2 ) +{ + return (int)(std::lower_bound( max_source_dists2, max_source_dists2 + pMax - 1, dx2) - max_source_dists2) + 1; +} + +//------------------------------------------------------------------------------ +// Given the precomputed distances from the cluster center for which +// the error bound is satisfied for each truncation number, and the actual +// distance from the cluster center, this function finds the lowest truncation +// number so that error is still satisfied. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +inline +int figtreeTargetTruncationNumber( double dy2, int pMax, double * max_target_dists2, double * min_target_dists2 ) +{ + if( dy2 <= max_target_dists2[pMax-2] ) + return (int)(std::lower_bound( max_target_dists2, max_target_dists2 + pMax - 1, dy2) - max_target_dists2) + 1; + else if( dy2 >= min_target_dists2[pMax-2] ) + return (int)(std::lower_bound( min_target_dists2, min_target_dists2 + pMax - 1, dy2, std::greater() ) - min_target_dists2) + 1; + else + return pMax; +} //------------------------------------------------------------------------------ // This function computes the coefficients C_k for all clusters. @@ -395,173 +779,534 @@ void computeC( int d, int N, int W, int K, int pMaxTotal, int pMax, delete [] dx; } - -/////////////////////////////////////////////////////////////////////////////////// -// Implementations of functions whose prototypes appear in figtree.h. -/////////////////////////////////////////////////////////////////////////////////// - //------------------------------------------------------------------------------ -// This function provides a simple interface for evaluation of gauss transforms -// in several ways (direct, direct with approximate nearest-neighbors -// structure on sources, ifgt, and ifgt with approximate nearest-neighbors) and -// using different parameter selection methods (can assume uniform distribution -// or use the actual distribution in estimating parameters). +// This function computes a separate truncation number for each cluster that +// satisfies the total allowed cluster-wise error. This means that some +// sources are allowed to contribute more error as long as others contribute +// less. The speedup is observed mostly in higher dimensions since finding +// the cluster-wise truncation numbers adds to the overhead cost. The +// truncations for each cluster are found by doing a binary search over +// the truncation number, p. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. // -// Created by Vlad Morariu on 2006-11-03. -// Modified by Vlad Morariu on 2007-06-21. +// NOTES: 1) This function currently only works when only one set of weights 'q' +// are used (i.e. W=1). It can be extended to W>1, but I have not had +// time to clean up that part of the code for release yet. +// +// 2) Also, this function does not currently compute multiple 'regions' +// for targets where different cluster-wise truncation numbers are used +// depending on what region targets are in. +// +// Created by Vlad Morariu on 2008-06-04. //------------------------------------------------------------------------------ -int figtree( int d, int N, int M, int W, double * x, double h, - double * q, double * y, double epsilon, double * g, - int evalMethod, int paramMethod, - int verbose, int forceK ) +void figtreeFindClusterTruncations( int d, int N, double * x, double * q, double h, double epsilon, double r, int pMax, int K, int * clusterIndex, int * numPoints, double * clusterCenters, double * clusterRadii, int * clusterTruncations ) { - int ret = 0; - - // for FIGTREE_EVAL_DIRECT and FIGTREE_EVAL_DIRECT_TREE, we don't need to compute - // parameters, so we just run the fcns directly, once for each set of weights - if( evalMethod == FIGTREE_EVAL_DIRECT ) + double * clusterWeights = new double[K]; + double * pointClusterDists = new double[N]; + double h2 = h*h; + + double * q_reordered = new double[N]; + + memset(clusterTruncations,0,sizeof(int)*K); + memset(clusterWeights,0,sizeof(double)*K); + memset(pointClusterDists,0,sizeof(double)*N); + + // find out total sum of weights for each cluster + for( int i = 0; i < N; i++ ) + clusterWeights[ clusterIndex[i] ] += q[i]; + + // precompute a list of points for each cluster so that we can reorganize + // some frequently used data in memory to make memory is accessed + // sequentially. + int * clusterMembers = new int[N]; + int * clusterStart = new int[K], * clusterEnd = new int[K]; + clusterStart[0] = 0; + clusterEnd[0] = clusterStart[0]; + for( int i = 1; i < K; i++ ) { - for( int i = 0; i < W; i++ ) - figtreeEvaluateDirect( d, N, M, x, h, q+i*N, y, g+i*M ); + clusterStart[i] = clusterStart[i-1] + numPoints[i-1]; + clusterEnd[i] = clusterStart[i]; } - - if( evalMethod == FIGTREE_EVAL_DIRECT_TREE ) + + for( int i = 0; i < N; i++ ) + clusterMembers[clusterEnd[clusterIndex[i]]++] = i; + + // compute the distance from points to clusters, and + // reorder them so that the weights 'q_reordered' and cluster + // distances 'pointClusterDists' for points that belong to the + // same cluster are contiguous in memory (reduces memory access overhead). + for( int k = 0; k < K; k++ ) { - for( int i = 0; i < W; i++ ) - figtreeEvaluateDirectTree( d, N, M, x, h, q+i*N, y, epsilon, g+i*M ); + int start = clusterStart[k], end = clusterEnd[k]; + for( int i = start; i < end; i++ ) + { + q_reordered[i] = q[ clusterMembers[i] ] / clusterWeights[k]; + for( int j = 0; j < d; j++ ) + { + double dx = clusterCenters[k*d+j] - x[clusterMembers[i]*d+j]; + pointClusterDists[i] += dx*dx; + } + pointClusterDists[i] = sqrt(pointClusterDists[i]); + } } - // for FIGTREE_EVAL_IFGT and FIGTREE_EVAL_IFGT_TREE, we must first compute - // parameters - if( evalMethod == FIGTREE_EVAL_IFGT || evalMethod == FIGTREE_EVAL_IFGT_TREE ) + // precompute constant in front of error term that depends only on p + double * constants = new double[pMax]; + constants[0] = 2; + for( int p = 2; p <= pMax; p++ ) + constants[p-1] = constants[p-2]*2.0/p; + + // find the lowest p for each cluster such that the total error per cluster meets the error bound using + // a binary search based algorithm. If for some reason, there exists a p_i > p_j such that + // error is met for p_j but not for p_i, (i.e. the p's are not ordered), the resulting p is still guaranteed + // to satisfy error, though it may not be the lowest p that satisfies error. + for( int k = 0; k < K; k++ ) { - int kLimit = N, K, pMax, kMax; - double r, maxRange=0; - - // calculate R, the diameter of the hypercube that encompasses sources and targets - double * mins = new double[d]; - double * maxs = new double[d]; - figtreeCalcMinMax( d, N, x, mins, maxs, 0 ); - figtreeCalcMinMax( d, M, y, mins, maxs, 1 ); - figtreeCalcMaxRange( d, mins, maxs, &maxRange ); - delete [] mins; - delete [] maxs; - - // choose parameters for IFGT - if( paramMethod == FIGTREE_PARAM_NON_UNIFORM ) - ret = figtreeChooseParametersNonUniform( d, N, x, h, epsilon, kLimit, maxRange, &kMax, &pMax, &r ); - else - ret = figtreeChooseParametersUniform( d, h, epsilon, kLimit, maxRange, &kMax, &pMax, &r ); - if( ret < 0 ) + int start = clusterStart[k], end = clusterEnd[k]; + + int p_lo = 1, p_hi = pMax; + while( p_lo < p_hi ) { - printf("figtree: figtreeChooseParameters%sUniform() failed.\n", - ((paramMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : "")); - return ret; + int p_mid = (p_hi + p_lo)/2; + double clusterBound = 0; + for( int i = start; i < end && clusterBound <= epsilon; i++ ) + { + double error = q_reordered[i]*figtreeOneSidedErrorBound( pointClusterDists[i], clusterRadii[k]+r, constants[p_mid-1], h2 , p_mid ); + clusterBound += error; + } + + if( clusterBound > epsilon ) + p_lo = p_mid + 1; + else + p_hi = p_mid; } + + clusterTruncations[k] = p_hi; + } - verbose && printf("figtreeChooseParameters%sUniform() chose p=%i, k=%i.\n", - ((paramMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : ""), pMax, kMax ); + delete [] constants; + delete [] clusterWeights; + delete [] pointClusterDists; + delete [] clusterMembers; + delete [] clusterStart; + delete [] clusterEnd; + delete [] q_reordered; +} - // if forceK is set to nonzero value, then we set K to that value. - if (forceK > 0) - K = forceK; +//------------------------------------------------------------------------------ +// This function computes the cluster coefficients using a separate truncation +// number for each cluster that satisfies the total allowed cluster-wise error. +// The clusterwise truncation numbers are returned by the function +// figtreeFindClusterTruncations(). +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Because figtreeFindClusterTruncations() only takes one set of weights +// into account when computing cluster-wise truncations, this function +// will not give accurate results for multiple sets of weights (W>1). +// When figtreeFindClusterTruncations is modified to consider all W sets +// of weights, this function should work properly. Thus, W=1 is assumed +// for now even though it is part of the input arguments. +// +// 2) Also, this function does not currently use multiple 'regions' +// for targets where different cluster-wise truncation numbers are used +// depending on what region targets are in. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void computeCAdaptiveCluster( int d, int N, int W, int K, int pMaxTotal, int pMax, + double h, int * clusterIndex, double * x, double * q, + double * clusterCenter, int * clusterTruncations, int * pMaxTotals, double * C ) +{ + double * sourceCenterMonomials = new double[pMaxTotal]; + double * constantSeries = new double[pMaxTotal]; + double hSquare = h*h; + double * dx = new double[d]; - // do k-center clustering - double rx; - int * clusterIndex = new int[N]; - int * numPoints = new int[kMax]; - double * clusterCenters = new double[d*kMax]; - double * clusterRadii = new double[kMax]; - - ret = figtreeKCenterClustering( d, N, x, kMax, &K, &rx, clusterIndex, - clusterCenters, numPoints, clusterRadii ); - if( ret >= 0 ) - { - // choose truncation number again now that clustering is done - ret = figtreeChooseTruncationNumber( d, h, epsilon, rx, maxRange, &pMax ); - if( ret >= 0 ) - { - // evaluate IFGT - verbose && printf( "Eval IFGT(h= %f, pMax= %i, K= %i, r= %f, rx= %e, epsilon= %f)\n", - h, pMax, K, r, rx, epsilon); - if( evalMethod == FIGTREE_EVAL_IFGT_TREE ) - { - ret = figtreeEvaluateIfgtTree( d, N, M, W, x, h, q, y, pMax, K, clusterIndex, - clusterCenters, clusterRadii, r, epsilon, g ); - } - else // evalMethod == FIGTREE_EVAL_IFGT - { - ret = figtreeEvaluateIfgt( d, N, M, W, x, h, q, y, pMax, K, clusterIndex, - clusterCenters, clusterRadii, r, epsilon, g ); - } + memset( C, 0, sizeof(double)*W*K*pMaxTotal ); - if( ret < 0 ) - { - printf("figtree: figtreeEvaluateIfgt%s() failed.\n", - ((evalMethod == FIGTREE_EVAL_IFGT_TREE) ? "Tree" : "")); - } - } - else // if figtreeChooseTruncationNumber fails... + for(int i = 0; i < N; i++) + { + int k = clusterIndex[i]; + int sourceBase = i*d; + int centerBase = k*d; + double sourceCenterDistanceSquare = 0.0; + + for (int j = 0; j < d; j++) + { + dx[j] = (x[sourceBase+j] - clusterCenter[centerBase+j]); + sourceCenterDistanceSquare += (dx[j]*dx[j]); + } + + int p = clusterTruncations[k]; + int pTotal = pMaxTotals[p-1]; + computeSourceCenterMonomials( d, h, dx, p, sourceCenterMonomials ); + + for(int w = 0; w < W; w++ ) + { + double f = q[N*w + i]*exp(-sourceCenterDistanceSquare/hSquare); + for(int alpha = 0; alpha < pTotal; alpha++) { - printf("figtree: figtreeChooseTruncationNumber() failed.\n"); + C[(K*w + k)*pMaxTotal + alpha] += (f*sourceCenterMonomials[alpha]); } - } // if figtreeKCenterClustering fails... - else + } + } + + computeConstantSeries( d, pMaxTotal, pMax, constantSeries ); + + for(int w = 0; w < W; w++) + { + for(int k = 0; k < K; k++) { - printf("figtree: figtreeKCenterClustering() failed.\n"); + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] *= constantSeries[alpha]; + } } - - delete [] clusterIndex; - delete [] clusterCenters; - delete [] numPoints; - delete [] clusterRadii; } - return ret; + delete [] sourceCenterMonomials; + delete [] constantSeries; + delete [] dx; } //------------------------------------------------------------------------------ -// Chooses minimum truncation number that satisfies desired error, given -// the maximum radius of any cluster (rx). +// This function computes the cluster coefficients allowing each source point +// to have a variable truncation number that still satisfies the desired error +// assuming the worst-case target point. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. // -// Originally constructor from -// ImprovedFastGaussTransformChooseTruncationNumber.cpp (IFGT source code) by -// Vikas C. Raykar. +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. // -// Modified by Vlad Morariu on 2007-06-20 -// Modified by Vlad Morariu on 2007-10-03 - pass R (the max distance between -// any source and target) as argument instead of assuming that data fits -// in unit hypercube +// Created by Vlad Morariu on 2008-06-04. //------------------------------------------------------------------------------ -int figtreeChooseTruncationNumber( int d, double h, double epsilon, - double rx, double maxRange, int * pMax ) +void computeCAdaptivePoint( int d, int N, int W, int K, int pMaxTotal, int pMax, + double h, int * clusterIndex, double * x, double * q, + double * clusterCenter, double * maxSourceDists2, int * pMaxTotals, double * C ) { - // check input arguments - FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseTruncationNumber ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeChooseTruncationNumber ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeChooseTruncationNumber ); - FIGTREE_CHECK_POS_DOUBLE( rx, figtreeChooseTruncationNumber ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( maxRange, figtreeChooseTruncationNumber ); - FIGTREE_CHECK_NONNULL_PTR( pMax, figtreeChooseTruncationNumber ); - - double R = maxRange*sqrt((double)d); - double hSquare = h*h; + double * sourceCenterMonomials = new double[pMaxTotal]; + double * constantSeries = new double[pMaxTotal]; + double hSquare = h*h; + double * dx = new double[d]; + + memset( C, 0, sizeof(double)*W*K*pMaxTotal ); + + //int * pHistogram = new int[pMax]; + //memset(pHistogram,0,sizeof(int)*pMax); + + for(int i = 0; i < N; i++) + { + int k = clusterIndex[i]; + int sourceBase = i*d; + int centerBase = k*d; + double sourceCenterDistanceSquare = 0.0; + + for (int j = 0; j < d; j++) + { + dx[j] = (x[sourceBase+j] - clusterCenter[centerBase+j]); + sourceCenterDistanceSquare += (dx[j]*dx[j]); + } + + int p = figtreeSourceTruncationNumber( sourceCenterDistanceSquare, pMax, maxSourceDists2 ); + int pTotal = pMaxTotals[p-1]; + //pHistogram[p-1]++; + computeSourceCenterMonomials( d, h, dx, p, sourceCenterMonomials ); + + for(int w = 0; w < W; w++ ) + { + double f = q[N*w + i]*exp(-sourceCenterDistanceSquare/hSquare); + for(int alpha = 0; alpha < pTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] += (f*sourceCenterMonomials[alpha]); + } + } + } + + computeConstantSeries( d, pMaxTotal, pMax, constantSeries ); + + for(int w = 0; w < W; w++) + { + for(int k = 0; k < K; k++) + { + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] *= constantSeries[alpha]; + } + } + } + + //printf( "source p histogram: "); + //for( int i = 0; i < pMax; i++ ) + // printf( " %i", pHistogram[i] ); + //printf( "\n" ); + //delete [] pHistogram; + + delete [] sourceCenterMonomials; + delete [] constantSeries; + delete [] dx; +} + +//------------------------------------------------------------------------------ +// This function provides a simple interface for evaluation of gauss transforms +// in several ways (direct, direct with approximate nearest-neighbors +// structure on sources, ifgt, and ifgt with approximate nearest-neighbors) and +// using different parameter selection methods (can assume uniform distribution +// or use the actual distribution in estimating parameters). +// +// Created by Vlad Morariu on 2006-11-03. +// +// Modified by Vlad Morariu on 2007-06-21. +// +// Modified by Vlad Morariu on 2008-06-04. +// +// - Added changes described in 'Automatic online tuning for fast Gaussian +// summation,' by Morariu et al, NIPS 2008 for details). +// - added FIGTREE_EVAL_AUTO eval method which allows FIGTREE to pick +// the evaluation method that is predicted to be the fastest, making +// FIGTREE a black box apprach +// - added point-wise and cluster-wise adaptive versions of the IFGT (instead +// of using the max truncation number for all sources, clusters, and targets, +// the truncation number is varied either point-wise or cluster-wise to improve +// performance while still satisfying the desired error bound). +// +// Modified by Vlad Morariu on 2008-12-01 +// - add a third parameter ifgtTruncMethod to reduce the number of evalMethod +// possibilities, separating evaluation method from truncation number choices +// - removed 'forceK' option, since it was used only for debugging +//------------------------------------------------------------------------------ +int figtree( int d, int N, int M, int W, double * x, double h, + double * q, double * y, double epsilon, double * g, + int evalMethod, int ifgtParamMethod, int ifgtTruncMethod, int verbose ) +{ + int ret = 0; + + FigtreeData data = figtreeCreateData(); + + // if the evalMethod is FIGTREE_EVAL_AUTO, choose the method that is estimated to be the fastest + if( evalMethod == FIGTREE_EVAL_AUTO ) + { + ret = figtreeChooseEvaluationMethod( d, N, M, W, x, h, y, epsilon, ifgtParamMethod, verbose, &evalMethod, NULL, &data ); + } + + // for FIGTREE_EVAL_DIRECT and FIGTREE_EVAL_DIRECT_TREE, we don't need to compute + // parameters, so we just run the fcns directly, once for each set of weights + if( evalMethod == FIGTREE_EVAL_DIRECT ) + { + for( int i = 0; i < W; i++ ) + ret = figtreeEvaluateDirect( d, N, M, x, h, q+i*N, y, g+i*M ); + } + + if( evalMethod == FIGTREE_EVAL_DIRECT_TREE ) + { + for( int i = 0; i < W; i++ ) + ret = figtreeEvaluateDirectTree( d, N, M, x, h, q+i*N, y, epsilon, g+i*M ); + } + + // for FIGTREE_EVAL_IFGT and FIGTREE_EVAL_IFGT_TREE, we must first compute + // parameters + if( evalMethod == FIGTREE_EVAL_IFGT || + evalMethod == FIGTREE_EVAL_IFGT_TREE ) + { + bool alreadyHaveClustering = (data.clusterCenters != NULL); // quick and dirty test + double maxRange = 0; + if( !alreadyHaveClustering ) + { + int kLimit = N, kMax; + + // + // calculate R, the diameter of the hypercube that encompasses sources and targets + // + double * mins = new double[d]; + double * maxs = new double[d]; + figtreeCalcMinMax( d, N, x, mins, maxs, 0 ); + figtreeCalcMinMax( d, M, y, mins, maxs, 1 ); + figtreeCalcMaxRange( d, mins, maxs, &maxRange ); + delete [] mins; + delete [] maxs; + + // + // choose parameters for IFGT + // + if( ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM ) + ret = figtreeChooseParametersNonUniform( d, N, x, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + else + ret = figtreeChooseParametersUniform( d, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + if( ret < 0 ) + { + printf("figtree: figtreeChooseParameters%sUniform() failed.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : "")); + return ret; + } + + verbose && printf("figtreeChooseParameters%sUniform() chose p=%i, k=%i.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : ""), data.pMax, kMax ); + + // + // do k-center clustering + // + data.clusterIndex = new int[N]; + data.numPoints = new int[kMax]; + data.clusterCenters = new double[d*kMax]; + data.clusterRadii = new double[kMax]; + + ret = figtreeKCenterClustering( d, N, x, kMax, &data.K, &data.rx, data.clusterIndex, + data.clusterCenters, data.numPoints, data.clusterRadii ); + if( ret < 0 ) + printf("figtree: figtreeKCenterClustering() failed.\n"); + } + + double errorBound = epsilon + 1; + if( ret >= 0 && !alreadyHaveClustering ) + { + // choose truncation number again now that clustering is done + ret = figtreeChooseTruncationNumber( d, h, epsilon, data.rx, maxRange, &data.pMax, &errorBound ); + if( ret < 0 ) + printf("figtreeChooseTruncatoinNumber() failed.\n"); + else + { + if( verbose && errorBound > epsilon ) + printf("figtreeChooseTruncationNumber(): could not find p within limit that satisfies error bound!\n" ); + } + } + + if( ret >= 0 ) + { + // evaluate IFGT + verbose && printf( "Eval IFGT(h= %3.2e, pMax= %i, K= %i, r= %3.2e, rx= %3.2e, eps= %3.2e)\n", + h, data.pMax, data.K, data.r, data.rx, epsilon); + + // if maximum truncation is 1, then nothing can be gained by doing individual truncations + if( data.pMax == 1 && (ifgtTruncMethod != FIGTREE_TRUNC_MAX) ) + { + evalMethod = FIGTREE_EVAL_IFGT; + verbose && printf("figtree(): max truncation is 1, so adaptive truncations are unnecessary.\n Switching to FIGTREE_TRUNC_MAX...\n"); + } + + // if W>1, and we want to use adaptive truncations, we cannot use cluster-wise truncations yet + if( W > 1 && (ifgtTruncMethod == FIGTREE_TRUNC_CLUSTER ) ) + { + ifgtTruncMethod = FIGTREE_TRUNC_POINT; + verbose && printf( "figtree(): FIGTREE_TRUNC_CLUSTER is not yet implemented\n to handle W > 1. Switching to FIGTREE_TRUNC_POINT...\n"); + } + + if( evalMethod == FIGTREE_EVAL_IFGT && ifgtTruncMethod == FIGTREE_TRUNC_POINT ) + { + ret = figtreeEvaluateIfgtAdaptivePoint( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( evalMethod == FIGTREE_EVAL_IFGT_TREE && ifgtTruncMethod == FIGTREE_TRUNC_POINT ) + { + ret = figtreeEvaluateIfgtTreeAdaptivePoint( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( ifgtTruncMethod == FIGTREE_TRUNC_CLUSTER ) + { + int * clusterTruncations = new int[data.K]; + figtreeFindClusterTruncations( d, N, x, q, h, epsilon, data.r, data.pMax, data.K, data.clusterIndex, data.numPoints, data.clusterCenters, data.clusterRadii, clusterTruncations ); + int pMaxNew = 0; + for( int i = 0; i < data.K; i++ ) + pMaxNew = MAX(pMaxNew, clusterTruncations[i]); + if( evalMethod == FIGTREE_EVAL_IFGT ) + { + ret = figtreeEvaluateIfgtAdaptiveCluster( d, N, M, W, x, h, q, y, pMaxNew, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, clusterTruncations, g ); + } + else // evalMethod == FIGTREE_EVAL_IFGT_TREE + { + ret = figtreeEvaluateIfgtTreeAdaptiveCluster( d, N, M, W, x, h, q, y, pMaxNew, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, clusterTruncations, g ); + } + + delete [] clusterTruncations; + } + + if( evalMethod == FIGTREE_EVAL_IFGT && ifgtTruncMethod == FIGTREE_TRUNC_MAX ) + { + ret = figtreeEvaluateIfgt( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( evalMethod == FIGTREE_EVAL_IFGT_TREE && ifgtTruncMethod == FIGTREE_TRUNC_MAX ) + { + ret = figtreeEvaluateIfgtTree( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( ret < 0 ) + { + printf("figtree: figtreeEvaluateIfgt%s*() failed.\n", + ((evalMethod == FIGTREE_EVAL_IFGT_TREE) ? "Tree" : "")); + } + } + } // if we are doing IFGT + + // release data if any was allocated + figtreeReleaseData( &data ); + + return ret; +} + +//------------------------------------------------------------------------------ +// Chooses minimum truncation number that satisfies desired error, given +// the maximum radius of any cluster (rx). +// +// Originally constructor from +// ImprovedFastGaussTransformChooseTruncationNumber.cpp (IFGT source code) by +// Vikas C. Raykar. +// +// Modified by Vlad Morariu on 2007-06-20 +// Modified by Vlad Morariu on 2007-10-03 - pass R (the max distance between +// any source and target) as argument instead of assuming that data fits +// in unit hypercube +//------------------------------------------------------------------------------ +int figtreeChooseTruncationNumber( int d, double h, double epsilon, + double rx, double maxRange, int * pMax, double * errorBound ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_DOUBLE( rx, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( maxRange, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_NONNULL_PTR( pMax, figtreeChooseTruncationNumber ); + + double R = maxRange*sqrt((double)d); + double hSquare = h*h; double r = MIN(R, h*sqrt(log(1/epsilon))); double rxSquare = rx*rx; - double error = 1; + double error = epsilon + 1; double temp = 1; int p = 0; + /* while((error > epsilon) & (p <= P_UPPER_LIMIT)){ p++; double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + r); double c = rx - b; temp = temp*(((2*rx*b)/hSquare)/p); error = temp*(exp(-(c*c)/hSquare)); + } */ + while((error > epsilon) & (p <= P_UPPER_LIMIT)) + { + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + r); + double c = rx - b; + temp = 1; + for( int i = 1; i <= p; i++ ) + temp = temp*((2.0*rx*b/hSquare)/i); + error = temp*(exp(-(c*c)/hSquare)); } - if( pMax != NULL ) - *pMax = p; + *pMax = p; + if( errorBound != NULL ) + *errorBound = error; return 0; } @@ -583,9 +1328,11 @@ int figtreeChooseTruncationNumber( int d, double h, double epsilon, // Modified by Vlad Morariu on 2007-10-03 - pass R (the max distance between // any source and target) as argument instead of assuming that data fits // in unit hypercube +// Modified by Vlad Morariu on 2008-06-04 - change the way bound is computed to +// be more precise //------------------------------------------------------------------------------ int figtreeChooseParametersUniform( int d, double h, double epsilon, - int kLimit, double maxRange, int * K, int * pMax, double * r ) + int kLimit, double maxRange, int * K, int * pMax, double * r, double * errorBound ) { // check input arguments FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseParametersUniform ); @@ -604,11 +1351,11 @@ int figtreeChooseParametersUniform( int d, double h, double epsilon, int kTemp = 1; int pMaxTemp = P_UPPER_LIMIT + 1; double rTemp = MIN(R,h*sqrt(log(1/epsilon))); - + double errorTemp = epsilon + 1; + for(int i = 0; i < kLimit; i++) { double rx = maxRange*pow((double)i + 1,-1.0/(double)d); - //double rx = pow((double)i + 1,-1.0/(double)d); // assumes unit hypercube double rxSquare = rx*rx; double n = MIN(i + 1, pow(rTemp/rx,(double)d)); double error = epsilon + 1; @@ -619,25 +1366,25 @@ int figtreeChooseParametersUniform( int d, double h, double epsilon, p++; double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + rTemp); double c = rx - b; - temp = temp*(((2*rx*b)/hSquare)/p); + temp = 1; + for( int j = 1; j <= p; j++ ) + temp = temp*((2.0*rx*b/hSquare)/j); error = temp*(exp(-(c*c)/hSquare)); } double complexity = (i + 1) + log((double)i + 1) + ((1 + n)*nchoosek_double(p - 1 + d, d)); - - //printf("d=%d r=%f K=%d rx=%f n=%f p=%d terms=%d c=%f\n",d,r,i+1,rx,n,p,nchoosek(p-1+d,d),complexity); - if (complexity < complexityMin ) { complexityMin = complexity; kTemp = i + 1; pMaxTemp = p; + errorTemp = error; } } // added this to catch case where desired error is never reached. // The best thing is to have as many clusters and terms in the taylor // series as possible (which will give lowest error) - if( kTemp == 1 && pMaxTemp == P_UPPER_LIMIT + 1 ) + if( errorTemp > epsilon ) { kTemp = kLimit; } @@ -649,6 +1396,8 @@ int figtreeChooseParametersUniform( int d, double h, double epsilon, *pMax = pMaxTemp; if( r != NULL ) *r = rTemp; + if( errorBound != NULL ) + *errorBound = errorTemp; return 0; } @@ -656,7 +1405,7 @@ int figtreeChooseParametersUniform( int d, double h, double epsilon, //------------------------------------------------------------------------------ // Parameter selection scheme that does not assume uniform distribution. // In cases where sources are not uniformly distribution, this can lead to -// very large performance increases(observed as much as 10x speedup) +// very large performance increases // because as the number of clusters increases, the max radius of any cluster // decreases MUCH faster than it would if the sources were uniformly distributed. // This function is based on ImprovedFastGaussTransformChooseParameters.cpp from @@ -670,10 +1419,14 @@ int figtreeChooseParametersUniform( int d, double h, double epsilon, // Modified by Vlad Morariu on 2008-02-21 - allow rx to be zero. In some cases, // if there isn't a center at each source pt to give rx=0, an excessively // large pMax is needed, and it is faster to just have a center at each pt. +// Modified by Vlad Morariu on 2008-06-04 - change the way bound is computed to +// be more precise +// Modified by Vlad Morariu on 2008-12-05 - began changing function to incorporate +// memory limit for coefficient storage... not done yet //------------------------------------------------------------------------------ int figtreeChooseParametersNonUniform( int d, int N, double * x, double h, double epsilon, int kLimit, double maxRange, - int * K, int * pMax, double * r ) + int * K, int * pMax, double * r, double * errorBound ) { // check input arguments FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseParametersNonUniform ); @@ -691,10 +1444,12 @@ int figtreeChooseParametersNonUniform( int d, int N, double * x, double R = maxRange*sqrt((double)d); double hSquare = h*h; double complexityMin = DBL_MAX; + double complexityLast = DBL_MAX; double rTemp = MIN(R,h*sqrt(log(1/epsilon))); int kTemp = 1; int pMaxTemp = P_UPPER_LIMIT + 1; + double errorTemp = epsilon + 1; int numClusters; double rx; @@ -705,12 +1460,12 @@ int figtreeChooseParametersNonUniform( int d, int N, double * x, // evaluate complexity for increasing values of K for(int i = 0; i < kLimit; i++) { - //rx=pow((double)i+1,-1.0/(double)d); // Vlad 01/24/07 - not needed since we're using the real rx double rxSquare = rx*rx; double n = MIN(i + 1, pow(rTemp/rx,(double)d)); - double error = 1; + double error = epsilon + 1; double temp = 1; int p = 0; + /* while((error > epsilon) & (p <= P_UPPER_LIMIT)) { p++; @@ -718,30 +1473,56 @@ int figtreeChooseParametersNonUniform( int d, int N, double * x, double c = rx - b; temp = temp*(((2*rx*b)/hSquare)/p); error = temp*(exp(-(c*c)/hSquare)); - } - double complexity = (i + 1) + log((double)i + 1) + ((1 + n)*nchoosek_double(p - 1 + d, d)); - //printf("d=%d r=%f K=%d rx=%f n=%f p=%d terms=%d c=%f\n",d,r,i+1,rx,n,p,nchoosek(p-1+d,d),complexity); - + }*/ + //double memTotalC = 8*(i+1); // 8 is number of bytes, i+1 is K + while((error > epsilon) && (p <= P_UPPER_LIMIT) ) //&& (memTotalC <= C_UPPER_LIMIT) ) + { + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + rTemp); + double c = rx - b; + temp = 1; + for( int j = 1; j <= p; j++ ) + temp = temp*((2.0*rx*b/hSquare)/j); + error = temp*(exp(-(c*c)/hSquare)); + + //memTotalC *= (d+p); + //memTotalC /= p; + } + double complexity = d*(i + 1) + d*log((double)i + 1) + ((1 + n)*nchoosek_double(p - 1 + d, d)); if ( (complexity < complexityMin) && (error <= epsilon)) { complexityMin = complexity; kTemp = i + 1; - pMaxTemp = p; + pMaxTemp = p; + errorTemp = error; } // try to guess if we have gone past the minimum (the complexity function - // zigzags as we try different number of clusters, but if it goes up enough, + // zigzags as we increase number of clusters, but if it goes up enough, // we'll assume we've passed the global minimum). // Also stop if truncation number is only 1 or if the max number of unique // clusters are reached (rx = 0). - if( (p == 1) || (rx <= 0) || (complexity > 1.5*complexityMin ) ) + double nextComplexityEstimate = d*(i + 1) + d*log((double)i + 1) + ((1 + n)*nchoosek_double(p - 2 + d, d)); + if( (p == 1) || (rx <= 0) || ( nextComplexityEstimate > 2*complexityMin || complexity > 2*complexityMin ) ) + { break; + } // add another cluster center, and get new max cluster radius - double rxOld = rx; kcc->ClusterIncrement( &numClusters, &rx ); + complexityLast = complexity; } + // added this to catch case where desired error is never reached. + // The best thing is to have as many clusters and terms in the taylor + // series as possible (which will give lowest error) + if( errorTemp > epsilon ) + { + kTemp = kLimit; + } + + //printf("memLimit = %e, memTotalC = %e\n", (double)C_UPPER_LIMIT, kTemp*8*nchoosek_double(pMaxTemp-1+d,d)); + // copy results if( K != NULL ) *K = kTemp; @@ -749,6 +1530,9 @@ int figtreeChooseParametersNonUniform( int d, int N, double * x, *pMax = pMaxTemp; if( r != NULL ) *r = rTemp; + if( errorBound != NULL ) + *errorBound = errorTemp; + delete [] pClusterIndex; delete kcc; @@ -924,70 +1708,323 @@ int figtreeEvaluateIfgt( int d, int N, int M, int W, double * x, return 0; } + //------------------------------------------------------------------------------ -// This function approximates Gauss Transform using Approximate Nearest -// Neighbors. -// Originally constructor, Evaluate(), and destructor from -// ImprovedFastGaussTransform.cpp of FIGTree code, by Vikas C. Raykar. +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. // -// Modified by Vlad Morariu on 2007-06-19. +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. //------------------------------------------------------------------------------ -int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, - double h, double * q, double * y, - int pMax, int K, int * clusterIndex, - double * clusterCenter, double * clusterRadii, - double r, double epsilon, double * g ) +int figtreeEvaluateIfgtAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ) { -#ifdef FIGTREE_NO_ANN - printf("This code was not compiled with support for ANN. Please recompile\n"); - printf("with 'FIGTREE_NO_ANN' not defined to enable ANN support.\n"); - return -1; -#else // check input arguments - FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTree ); - FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtAdaptive ); //Memory allocation - int pMaxTotal = nchoosek(pMax-1+d,d); + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; double * targetCenterMonomials = new double[pMaxTotal]; double * dy = new double[d]; - double * C = new double[W*K*pMaxTotal]; - double hSquare = h*h; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; - //Find the maximum cluster radius - double pcr_max = clusterRadii[0]; + double rx = clusterRadii[0]; for(int i = 0; i < K; i++) { - if (clusterRadii[i] > pcr_max) - { - pcr_max = clusterRadii[i]; - } - } - double rSquare=(r+pcr_max)*(r+pcr_max); + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } - //Allocate storage using ANN procedures - ANNpointArray dataPts = annAllocPts(K,d); // allocate data points - ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices - ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists - - // Copy the cluster centers to the ANN data structure - for (int k = 0; k < K; k++) + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + double * maxSourceDists2 = new double[pMax]; + figtreeSourceTruncationRanges( r, rx, h, epsilon, pMax, maxSourceDists2 ); + computeCAdaptivePoint( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, maxSourceDists2, pMaxTotals, C ); + delete [] maxSourceDists2; + + // for each cluster, compute distance ranges for each truncation number + double * targetDists2 = new double[2*pMax]; + figtreeTargetTruncationRanges( r, rx, h, epsilon, pMax, targetDists2, targetDists2+pMax ); + + //int * pHistogram = new int[pMax]; + //memset(pHistogram,0,sizeof(int)*pMax); + + memset( g, 0, sizeof(double)*M*W ); + //int targetBase = j*d; + for(int k = 0; k < K; k++) { - for ( int j = 0; j < d; j++ ) + for(int j = 0; j < M; j++) + { + //int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[j*d + i] - clusterCenter[k*d + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if(targetCenterDistanceSquare <= rySquare[k]) + { + int p = figtreeTargetTruncationNumber( targetCenterDistanceSquare, pMax, targetDists2, targetDists2+pMax ); + int pTotal = pMaxTotals[p-1]; + //pHistogram[p-1]++; + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + //printf( "target p histogram: "); + //for( int i = 0; i < pMax; i++ ) + // printf( " %i", pHistogram[i] ); + //printf( "\n" ); + //delete [] pHistogram; + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + delete [] targetDists2; + delete [] pMaxTotals; + + return 0; +} + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtAdaptive ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + computeCAdaptiveCluster( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, clusterTruncations, pMaxTotals, C ); + + memset( g, 0, sizeof(double)*M*W ); + //int targetBase = j*d; + for(int k = 0; k < K; k++) + { + int p = clusterTruncations[k]; + int pTotal = pMaxTotals[p-1]; + for(int j = 0; j < M; j++) + { + //int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[j*d + i] - clusterCenter[k*d + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if(targetCenterDistanceSquare <= rySquare[k]) + { + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + delete [] pMaxTotals; + + return 0; +} + +//------------------------------------------------------------------------------ +// This function approximates Gauss Transform using Approximate Nearest +// Neighbors. +// Originally constructor, Evaluate(), and destructor from +// ImprovedFastGaussTransform.cpp of FIGTree code, by Vikas C. Raykar. +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ) +{ +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with 'FIGTREE_NO_ANN' not defined to enable ANN support.\n"); + return -1; +#else + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTree ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax-1+d,d); + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double hSquare = h*h; + + //Find the maximum cluster radius + double pcr_max = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + if (clusterRadii[i] > pcr_max) + { + pcr_max = clusterRadii[i]; + } + } + double rSquare=(r+pcr_max)*(r+pcr_max); + + //Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(K,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists + + // Copy the cluster centers to the ANN data structure + for (int k = 0; k < K; k++) + { + for ( int j = 0; j < d; j++ ) dataPts[k][j]= clusterCenter[k*d + j]; } @@ -1015,23 +2052,16 @@ int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, ANNpoint queryPt=&(y[targetBase]); - int NN = kdTree->annkFRSearch( // search + int NN = kdTree->annkFRSearchUnordered( // search queryPt, // query point rSquare, // squared radius - 0, // number of near neighbors - NULL, // nearest neighbors (returned) - NULL, // distance (returned) + N, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) 0.0 ); + if (NN>0) { - kdTree->annkFRSearch( // search - queryPt, // query point - rSquare, // squared radius - NN, // number of near neighbors - nnIdx, // nearest neighbors (returned) - dists, // distance (returned) - 0.0); - for(int l = 0; l < NN; l++) { int k = nnIdx[l]; @@ -1081,9 +2111,12 @@ int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, // of FIGTree code, by Vikas C. Raykar. // // Modified by Vlad Morariu on 2007-06-20 +// Modified by Vlad Morariu on 2008-06-10 to use ANN fixed radius search with +// nearest neighbors unordered (saves a significant amt of time), and with +// one call instead of two, as a result. //------------------------------------------------------------------------------ int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, - double * q, double * y, double epsilon, double * g ) + double * q, double * y, double epsilon, double * g ) { #ifdef FIGTREE_NO_ANN printf("This code was not compiled with support for ANN. Please recompile\n"); @@ -1091,15 +2124,15 @@ int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, return -1; #else // check input arguments - FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateDirectTree ); - FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateDirectTree ); + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateDirectTreeUnordered ); double hSquare = h*h; double epsANN = 0.0; @@ -1137,30 +2170,19 @@ int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, int targetBase = j*d; ANNpoint queryPt = &(y[targetBase]); - int NN = kdTree->annkFRSearch( // fixed radius search - queryPt, // query point - rSquare, // squared radius - 0, // number of near neighbors - NULL, // nearest neighbors (returned) - NULL, // distance (returned) - epsANN ); - if (NN > 0) - { - kdTree->annkFRSearch( // fixed radius search - queryPt, // query point - rSquare, // squared radius - NN, // number of near neighbors - nnIdx, // nearest neighbors (returned) - dists, // distance (returned) + int NN = kdTree->annkFRSearchUnordered( // fixed radius search + queryPt, // query point + rSquare, // squared radius + N, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) epsANN ); - - for(int l = 0; l < NN; l++) - { - int i = nnIdx[l]; - double sourceTargetDistanceSquare = dists[l]; - g[j] += (q[i]*exp(-sourceTargetDistanceSquare/hSquare)); - } - } + for(int l = 0; l < NN; l++) + { + int i = nnIdx[l]; + double sourceTargetDistanceSquare = dists[l]; + g[j] += (q[i]*exp(-sourceTargetDistanceSquare/hSquare)); + } } ////////////////////////////////////////////////////////////////////////////// @@ -1176,49 +2198,834 @@ int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, #endif } -int figtreeCalcMinMax( int d, int n, double * x, double * mins, double * maxs, int update ) + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ) { +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with compiler flag 'FIGTREE_NO_ANN' not set to enable ANN support.\n"); + return -1; +#else // check input arguments - FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeCalcMinMax ); - FIGTREE_CHECK_POS_NONZERO_INT( n, figtreeCalcMinMax ); - FIGTREE_CHECK_NONNULL_PTR( x, figtreeCalcMinMax ); - FIGTREE_CHECK_NONNULL_PTR( mins, figtreeCalcMinMax ); - FIGTREE_CHECK_NONNULL_PTR( maxs, figtreeCalcMinMax ); + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTreeAdaptivePoint ); - // use first sample values as current min and max if we're not updating - // some previously computed min and max values. - if( update != 1 && n > 0 ) + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) { - for( int i = 0; i < d; i++ ) - { - mins[i] = x[i]; - maxs[i] = x[i]; - } - } + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } - // go through each sample in x and update mins and maxs for each dimension - for( int i = 0; i < n; i++ ) + // + // Build tree on cluster centers + // + double rSquare = (r+rx)*(r+rx); + //Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(K,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists + + // Copy the cluster centers to the ANN data structure + for (int k = 0; k < K; k++) { - for( int j = 0; j < d; j++ ) - { - mins[j] = MIN( mins[j], x[i*d+j] ); - maxs[j] = MAX( maxs[j], x[i*d+j] ); - } + for ( int j = 0; j < d; j++ ) + dataPts[k][j]= clusterCenter[k*d + j]; } - return 0; -} + // build search structure + ANNkd_tree * kdTree = new ANNkd_tree( + dataPts, // the data points + K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST); -int figtreeCalcMaxRange( double d, double * mins, double * maxs, double * maxRange ) -{ - FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeCalcMaxRange ); - FIGTREE_CHECK_NONNULL_PTR( mins, figtreeCalcMaxRange ); - FIGTREE_CHECK_NONNULL_PTR( maxs, figtreeCalcMaxRange ); - FIGTREE_CHECK_NONNULL_PTR( maxRange, figtreeCalcMaxRange ); - double maxRangeTemp = maxs[0] - mins[0]; - for( int i = 0; i < d; i++ ) - maxRangeTemp = MAX( maxRangeTemp, maxs[i] - mins[i] ); - *maxRange = maxRangeTemp; - return 0; -} + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + double * maxSourceDists2 = new double[pMax]; + figtreeSourceTruncationRanges( r, rx, h, epsilon, pMax, maxSourceDists2 ); + computeCAdaptivePoint( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, maxSourceDists2, pMaxTotals, C ); + delete [] maxSourceDists2; + + // for each cluster, compute distance ranges for each truncation number + double * targetDists2 = new double[2*pMax]; + figtreeTargetTruncationRanges( r, rx, h, epsilon, pMax, targetDists2, targetDists2+pMax ); + + //int * pHistogram = new int[pMax]; + //memset(pHistogram,0,sizeof(int)*pMax); + + memset( g, 0, sizeof(double)*M*W ); + + for(int j = 0; j < M; j++) + { + int targetBase = j*d; + ANNpoint queryPt=&(y[targetBase]); + + int NN = kdTree->annkFRSearchUnordered( // search + queryPt, // query point + rSquare, // squared radius + K, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + 0.0 ); + for(int l = 0; l < NN; l++) + { + int k = nnIdx[l]; + + int centerBase = k*d; + double targetCenterDistanceSquare = dists[l]; + if(targetCenterDistanceSquare <= rySquare[k]) + { + int p = figtreeTargetTruncationNumber( targetCenterDistanceSquare, pMax, targetDists2, targetDists2+pMax ); + int pTotal = pMaxTotals[p-1]; + //pHistogram[p-1]++; + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + } + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + //printf( "target p histogram: "); + //for( int i = 0; i < pMax; i++ ) + // printf( " %i", pHistogram[i] ); + //printf( "\n" ); + //delete [] pHistogram; + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + delete [] targetDists2; + delete [] pMaxTotals; + + annDeallocPts(dataPts); + delete [] nnIdx; + delete [] dists; + delete kdTree; + annClose(); + return 0; +#endif +} + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ) +{ +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with compiler flag 'FIGTREE_NO_ANN' not set to enable ANN support.\n"); + return -1; +#else + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTreeAdaptiveCluster ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } + + // + // Build tree on cluster centers + // + double rSquare = (r+rx)*(r+rx); + //Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(K,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists + + // Copy the cluster centers to the ANN data structure + for (int k = 0; k < K; k++) + { + for ( int j = 0; j < d; j++ ) + dataPts[k][j]= clusterCenter[k*d + j]; + } + + // build search structure + ANNkd_tree * kdTree = new ANNkd_tree( + dataPts, // the data points + K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST); + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + computeCAdaptiveCluster( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, clusterTruncations, pMaxTotals, C ); + + memset( g, 0, sizeof(double)*M*W ); + + for(int j = 0; j < M; j++) + { + int targetBase = j*d; + ANNpoint queryPt=&(y[targetBase]); + + int NN = kdTree->annkFRSearchUnordered( // search + queryPt, // query point + rSquare, // squared radius + K, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + 0.0 ); + for(int l = 0; l < NN; l++) + { + int k = nnIdx[l]; + int centerBase = k*d; + int p = clusterTruncations[k]; + int pTotal = pMaxTotals[p-1]; + + double targetCenterDistanceSquare = dists[l]; + if(targetCenterDistanceSquare <= rySquare[k]) + { + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + } + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + delete [] pMaxTotals; + + annDeallocPts(dataPts); + delete [] nnIdx; + delete [] dists; + delete kdTree; + annClose(); + return 0; +#endif +} + +int figtreeCalcMinMax( int d, int n, double * x, double * mins, double * maxs, int update ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeCalcMinMax ); + FIGTREE_CHECK_POS_NONZERO_INT( n, figtreeCalcMinMax ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeCalcMinMax ); + FIGTREE_CHECK_NONNULL_PTR( mins, figtreeCalcMinMax ); + FIGTREE_CHECK_NONNULL_PTR( maxs, figtreeCalcMinMax ); + + // use first sample values as current min and max if we're not updating + // some previously computed min and max values. + if( update != 1 && n > 0 ) + { + for( int i = 0; i < d; i++ ) + { + mins[i] = x[i]; + maxs[i] = x[i]; + } + } + + // go through each sample in x and update mins and maxs for each dimension + for( int i = 0; i < n; i++ ) + { + for( int j = 0; j < d; j++ ) + { + mins[j] = MIN( mins[j], x[i*d+j] ); + maxs[j] = MAX( maxs[j], x[i*d+j] ); + } + } + + return 0; +} + +int figtreeCalcMaxRange( double d, double * mins, double * maxs, double * maxRange ) +{ + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeCalcMaxRange ); + FIGTREE_CHECK_NONNULL_PTR( mins, figtreeCalcMaxRange ); + FIGTREE_CHECK_NONNULL_PTR( maxs, figtreeCalcMaxRange ); + FIGTREE_CHECK_NONNULL_PTR( maxRange, figtreeCalcMaxRange ); + + double maxRangeTemp = maxs[0] - mins[0]; + for( int i = 0; i < d; i++ ) + maxRangeTemp = MAX( maxRangeTemp, maxs[i] - mins[i] ); + *maxRange = maxRangeTemp; + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////// +// +// +// Methods for automatic selection of evaluation method. +// Functions created by Vlad Morariu 05-02-2008. +// Functions modified by Vlad Morariu 06-06-2008. +// Functions modified by Vlad Morariu 11-02-2008. +// - Added code to perform sub-sampling w/o replacement, and cleaned up code a +// little for release. +// +/////////////////////////////////////////////////////////////////////////////////// + +//------------------------------------------------------------------------------ +// The functions below are used to estimate avg number of neighbors in the source set +// given a query point from the target set. +// +// Created by Vlad Morariu 2008-06-04. +//------------------------------------------------------------------------------ +#ifndef FIGTREE_NO_ANN +inline void figtreeGetAverageNumNeighbors( ANNkd_tree * kdTree, int d, int M, double * y, double r, int Msample, double * avgNbrs, double * avgAnnFlops ) +{ + int numNbrs = 0; + int flopsAccum = 0, flops =0; + double rSquare = r*r; + double epsANN = 0.0; + + for(int i = 0; i < Msample; i++) + { + int idx = rand() % M; + ANNpoint queryPt = &(y[ idx*d ]); + + int NN = kdTree->annkFRSearchUnorderedFlops( // fixed radius search + queryPt, // query point + rSquare, // squared radius + 0, // number of near neighbors + NULL, // nearest neighbors (returned) + NULL, // distance (returned) + epsANN, + &flops ); + numNbrs += NN; + flopsAccum += flops; + } + + *avgNbrs = numNbrs / (double)Msample; + *avgAnnFlops = flopsAccum / (double)Msample; +} + +inline void figtreeEstimatedNeighborSources( int d, int M, double * y, double h, double epsilon, ANNkd_tree * sourcesKdTree, int Msample, double * avgNbrSources, double * avgAnnFlopsSources ) +{ + // Compute the cutoff radius + double r = h*sqrt(log(1/epsilon)); + + // estimate avg number of neighbors + figtreeGetAverageNumNeighbors( sourcesKdTree, d, M, y, r, Msample, avgNbrSources, avgAnnFlopsSources ); +} + +inline void figtreeEstimatedNeighborClusters( int d, int M, double * y, int K, double * clusterRadii, double r, ANNkd_tree * clustersKdTree, int Msample, double * avgNbrClusters, double * avgAnnFlopsClusters ) +{ + //Find the maximum cluster radius + double pcrMax = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + if (clusterRadii[i] > pcrMax) + { + pcrMax = clusterRadii[i]; + } + } + double rMax =(r+pcrMax); + + // estimate numbers of pts with more than 1 neighbor and avg number of neighbors + figtreeGetAverageNumNeighbors( clustersKdTree, d, M, y, rMax, Msample, avgNbrClusters, avgAnnFlopsClusters ); +} +#endif +inline void figtreeEstimatedNeighborClustersNoAnn( int d, int N, int M, double h, double * y, + int K, double * clusterCenter, double * clusterRadii, double r, int Msample, + double * avgNbrClustersNoAnn, double * avgFindCentersFlops ) +{ + double flops = 0; + double avgNbrClusters = 0; + double * dy = new double[d]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + } + + for(int j = 0; j < Msample; j++) + { + int targetBase = (rand()%M)*d; + for(int k = 0; k < K; k++) + { + int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + flops += 3; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if( targetCenterDistanceSquare <= rySquare[k] ) + avgNbrClusters++; + } + } + + *avgFindCentersFlops = flops/Msample; + *avgNbrClustersNoAnn = avgNbrClusters/Msample; + + delete [] dy; + delete [] ry; + delete [] rySquare; +} + + +//------------------------------------------------------------------------------ +// +// The functions below estimate the number of floating point operations (flops) +// for different parts of the figtree code. +// Where possible the estimates are made directly by counting the number of +// floating point operations in the code itself, but for things such as +// building the kd-Tree and clustering, we use the theoretical complexity. +// +// Created by Vlad Morariu 2008-05-03 to 2008-06-04. +// Modified by Vlad Morariu 2008-12-05 +// Changed floating op estimation functions to reflect revised versions of code. +//------------------------------------------------------------------------------ +inline double figtreeEstimatedFlopsComputeSourceCenterMonomials( int d, int pMaxTotal ) +{ + return (d + (double)pMaxTotal); +} + +inline double figtreeEstimatedFlopsComputeTargetCenterMonomials( int d, int pMaxTotal ) +{ + return (d + (double)pMaxTotal); +} + +inline double figtreeEstimatedFlopsComputeConstantSeries( int pMaxTotal ) +{ + return (2.0*pMaxTotal); +} + +inline double figtreeEstimatedFlopsComputeC( int d, int N, int W, int K, int pMaxTotal, double flopsExp ) +{ + double computeSourceCenterMonomials = figtreeEstimatedFlopsComputeSourceCenterMonomials( d, pMaxTotal ); + double computeConstantSeries = figtreeEstimatedFlopsComputeConstantSeries( pMaxTotal ); + return N*(3*d + computeSourceCenterMonomials + W*(2+flopsExp+2*pMaxTotal)) + computeConstantSeries + W*K*pMaxTotal; +} + +inline double figtreeEstimatedFlopsBuildTree( int d, int N ) +{ + return d*N*log((double)N); +} + +inline double figtreeEstimatedFlopsKCenterClustering( int d, int N, int K ) +{ + return 3*d*(N*log((double)K) + K*(double)K); // not using the NlogK version yet +} + +inline double figtreeEstimatedFlopsDirect( int d, int N, int M, int W, double flopsExp ) +{ + return W*(1 + ((double)M)*((double)N)*(d*3 + 3 + flopsExp)); +} + +inline double figtreeEstimatedFlopsDirectTree( int d, int N, int M, int W, double avgNbrSources, double avgAnnFlopsSources, double flopsExp ) +{ + return W*(7 + ((double)M)*( avgAnnFlopsSources + avgNbrSources*(3+flopsExp) )); +} + +inline double figtreeEstimatedFlopsIfgt( int d, int N, int M, int W, int K, int pMaxTotal, double avgNbrClustersNoAnn, double avgFindCentersFlops, double flopsExp ) +{ + // cost of computing coeffs from sources + double computeC = figtreeEstimatedFlopsComputeC( d, N, W, K, pMaxTotal, flopsExp ); + double source = 2*K + 1 + computeC; + + // cost of computing target monomials and evaluating + double computeTargetCenterMonomials = figtreeEstimatedFlopsComputeTargetCenterMonomials( d, pMaxTotal ); + double target = ((double)M)*(avgFindCentersFlops + avgNbrClustersNoAnn*(computeTargetCenterMonomials + 1 + flopsExp + W*3*((double)pMaxTotal))); + + return source + target; +} + +inline double figtreeEstimatedFlopsIfgtTree( int d, int N, int M, int W, int K, int pMaxTotal, double avgNbrClusters, double avgAnnFlopsClusters, double flopsExp ) +{ + // cost of computing coeffs from sources + double computeC = figtreeEstimatedFlopsComputeC( d, N, W, K, pMaxTotal, flopsExp ); + double source = 4 + computeC; + + // cost of computing target monomials and evaluating + double computeTargetCenterMonomials = figtreeEstimatedFlopsComputeTargetCenterMonomials( d, pMaxTotal ); + double target = ((double)M)*( avgAnnFlopsClusters + avgNbrClusters*(d + computeTargetCenterMonomials + 1 + flopsExp + W*3*((double)pMaxTotal) ) ); + + return source + target; +} + +//------------------------------------------------------------------------------ +// This function chooses the evaluation method for figtree, given the input +// parameters and data. +// +// Created by Vlad Morariu 2008-05-03 to 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeChooseEvaluationMethod( int d, int N, int M, int W, double * x, double h, + double * y, double epsilon, int ifgtParamMethod, int verbose, + int * bestMethod, double * flops, void * data_struct ) +{ + int ret = 0; // return value (0 is no error, -1 is error) + + // + // Parameters for estimating avg number of neighbors, flops needed to find neighbors using tree, + // and setting k limit. + // + // In future releases of the code, users should be able to choose these parameters as they affect the + // quality of method selection. For now, users will have to recompileif they want to change these + // parameters. + // + int Msample = M_SAMPLE; // how many of the target points do we sample to estimate avg number of neighbors and flops? + int Nss = MAX( MIN(N,N_SS_MIN), (int)pow(N,N_SS_POW) ); // number of subsampled sources + double kLimitToAvgNbrRatio = K_LIMIT_TO_AVG_NBR_RATIO; // set k limit to this times avg number of source neighbors + double flopsExp = FLOPS_EXP; // floating point ops per exp() call + + // other values computed fromthe parameters above + double ss = N/(double)Nss; // how much subsampling to do for building kd-Tree + int kLimit = N, kMax; // kLimit is the highest K that we allow, kMax is the max K-value chosen by param selection + + // initialize flop estimates; -1 indicates flop estimation was not completed + double flopsDirect = figtreeEstimatedFlopsDirect( d, N, M, W, flopsExp ); + double flopsDirectTree = -1; + double flopsIfgt = -1; + double flopsIfgtTree = -1; + + // avg number of neighboring clusters for IFGT (no tree), and avg flops spent finding + // the neighboring clusters + double avgNbrClustersNoAnn, avgFindCentersFlops; + + // this datastructure will hold the kd-Trees, cluster centers, etc + FigtreeData data = figtreeCreateData(); // obtain data structure filled with 0's + +#ifndef FIGTREE_NO_ANN + + // these variables will represent statistics of source distribution (avg neighbors) + double avgNbrSources, avgNbrClusters; + + // these variables contain avg cost of each kd-Tree query for finding neighbors + double avgAnnFlopsSources, avgAnnFlopsClusters; + + // get a random sampling of Nss points, w/o replacement + int * shuffled_indexes = new int[N]; + for( int i = 0; i < N; i++ ) + shuffled_indexes[i] = i; + std::random_shuffle( shuffled_indexes, shuffled_indexes+N ); // could also use random_sample, if available + + // Allocate storage using ANN procedures + data.annSources = annAllocPts(Nss,d); // allocate data points + + // Copy the source points to the ANN data structure + for (int i = 0; i < Nss; i++) + { + for ( int j = 0; j < d; j++ ) + data.annSources[i][j]= x[shuffled_indexes[i]*d + j]; + } + + delete [] shuffled_indexes; + + // Build search structure + data.annSourcesKdTree = new ANNkd_tree( + data.annSources, // the data points + Nss, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST ); + + figtreeEstimatedNeighborSources( d, M, y, h, epsilon, data.annSourcesKdTree, Msample, &avgNbrSources, &avgAnnFlopsSources); + flopsDirectTree = figtreeEstimatedFlopsBuildTree( d, N ) + figtreeEstimatedFlopsDirectTree( d, N, M, W, ss*avgNbrSources, ss*avgAnnFlopsSources*(log((double)N)/log((double)Nss)), flopsExp ); + + // set kLimit based on how many source points, on average, are within radius of each query pt + kLimit = MIN((int)(kLimitToAvgNbrRatio*ss*avgNbrSources),N); + +#endif // #ifndef FIGTREE_NO_ANN + + if( kLimit > 0 ) + { + double maxRange=0; + + // calculate R, the diameter of the hypercube that encompasses sources and targets + double * mins = new double[d]; + double * maxs = new double[d]; + figtreeCalcMinMax( d, N, x, mins, maxs, 0 ); + figtreeCalcMinMax( d, M, y, mins, maxs, 1 ); + figtreeCalcMaxRange( d, mins, maxs, &maxRange ); + delete [] mins; + delete [] maxs; + + if( ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM ) + ret = figtreeChooseParametersNonUniform( d, N, x, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + else + ret = figtreeChooseParametersUniform( d, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + if( ret < 0 ) + { + printf("figtree: figtreeChooseParameters%sUniform() failed.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : "")); + return ret; + } + + verbose && printf("figtreeChooseParameters%sUniform() chose p=%i, k=%i.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : ""), data.pMax, kMax ); + + // do k-center clustering + data.clusterIndex = new int[N]; + data.numPoints = new int[kMax]; + data.clusterCenters = new double[d*kMax]; + data.clusterRadii = new double[kMax]; + + ret = figtreeKCenterClustering( d, N, x, kMax, &data.K, &data.rx, data.clusterIndex, + data.clusterCenters, data.numPoints, data.clusterRadii ); + if( ret >= 0 ) + { + double errorBound = epsilon + 1; + // choose truncation number again now that clustering is done + ret = figtreeChooseTruncationNumber( d, h, epsilon, data.rx, maxRange, &data.pMax, &errorBound ); + if( ret >= 0 ) + { + // these are the params we would evaluate IFGT with + verbose && printf( "Eval IFGT(h= %3.2e, pMax= %i, K= %i, r= %3.2e, rx= %3.2e, epsilon= %3.2e, bound = %3.2e)\n", + h, data.pMax, data.K, data.r, data.rx, epsilon, errorBound); + + double pMaxTotalDouble = nchoosek_double(data.pMax-1+d,d); + if( errorBound <= epsilon && pMaxTotalDouble < INT_MAX ) + { + data.pMaxTotal = (int)pMaxTotalDouble; + + // + // Estimate number of flops for performing IFGT + // + figtreeEstimatedNeighborClustersNoAnn( d, N, M, h, y, data.K, data.clusterCenters, data.clusterRadii, data.r, Msample, &avgNbrClustersNoAnn, &avgFindCentersFlops ); + flopsIfgt = figtreeEstimatedFlopsIfgt( d, N, M, W, data.K, data.pMaxTotal, avgNbrClustersNoAnn, avgFindCentersFlops, flopsExp ); + +#ifndef FIGTREE_NO_ANN + // + // Estimate number of flops for performing IFGT with kd-Tree + // + + // Allocate storage using ANN procedures + data.annClusters = annAllocPts(data.K,d); // allocate data points + + // Copy the source points to the ANN data structure + for (int i = 0; i < data.K; i++) + { + for ( int j = 0; j < d; j++ ) + data.annClusters[i][j]= data.clusterCenters[i*d + j]; + } + + // build search structure + data.annClustersKdTree = new ANNkd_tree( + data.annClusters, // the data points + data.K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST ); + + figtreeEstimatedNeighborClusters( d, M, y, data.K, data.clusterRadii, data.r, data.annClustersKdTree, Msample, &avgNbrClusters, &avgAnnFlopsClusters ); + flopsIfgtTree = figtreeEstimatedFlopsIfgtTree( d, N, M, W, data.K, data.pMaxTotal, avgNbrClusters, avgAnnFlopsClusters, flopsExp ); +#endif + } + } + else // if figtreeChooseTruncationNumber fails... + { + printf("figtree: figtreeChooseTruncationNumber() failed.\n"); + } + } // if figtreeKCenterClustering fails... + else + { + printf("figtree: figtreeKCenterClustering() failed.\n"); + } + } + + // save clustering and parameter selection data if desired + if( data_struct != NULL ) + { + FigtreeData * data_out = (FigtreeData*)data_struct; + // copy all data except for ANN data structures + *data_out = data; + data_out->annClusters = NULL; + data_out->annClustersKdTree = NULL; + data_out->annSources = NULL; + data_out->annSourcesKdTree = NULL; + + // set copied data to NULL, or else it will be deallocated + data.clusterCenters = NULL; + data.clusterIndex = NULL; + data.clusterRadii = NULL; + data.numPoints = NULL; + } + + figtreeReleaseData( &data ); + + // return flops per method if user supplies non-NULL pointer + if( flops != NULL ) + { + flops[ FIGTREE_EVAL_DIRECT ] = flopsDirect; + flops[ FIGTREE_EVAL_DIRECT_TREE ] = flopsDirectTree; + flops[ FIGTREE_EVAL_IFGT ] = flopsIfgt; + flops[ FIGTREE_EVAL_IFGT_TREE ] = flopsIfgtTree; + } + + // choose best method if user supplies non-NULL pointer + if( bestMethod!= NULL ) + { + double bestFlops = flopsDirect; + *bestMethod = FIGTREE_EVAL_DIRECT; + + if( flopsDirectTree != -1 && flopsDirectTree < bestFlops ) + { + *bestMethod = FIGTREE_EVAL_DIRECT_TREE; + bestFlops = flopsDirectTree; + } + + if( flopsIfgt!= -1 && flopsIfgt < bestFlops ) + { + *bestMethod = FIGTREE_EVAL_IFGT; + bestFlops = flopsIfgt; + } + + if( flopsIfgtTree != -1 && flopsIfgtTree < bestFlops ) + { + *bestMethod = FIGTREE_EVAL_IFGT_TREE; + bestFlops = flopsIfgtTree; + } + } + +#ifndef FIGTREE_NO_ANN + annClose(); +#endif + + return ret; +} \ No newline at end of file diff --git a/src/figtree_internal.h b/src/figtree_internal.h new file mode 100644 index 0000000..a7ed312 --- /dev/null +++ b/src/figtree_internal.h @@ -0,0 +1,341 @@ +#ifndef FIGTREE_INTERNAL_H +#define FIGTREE_INTERNAL_H + +#include "figtree.h" + +// we want to export C functions if using DLL +#if defined(__cplusplus) && !defined(FIGTREE_STATIC) +extern "C" { +#endif + +// Given the maximum cluster radius, this function computes the maximum +// truncation number that guarantees results within the desired error bound. +//Input +// * d --> dimension of the points. +// * h --> the source bandwidth. +// * epsilon --> the desired error. +// * rx --> maximum cluster radius +// * maxRange --> max dimension range. The range along a dimension is +// the difference between the max and min values that can ever +// occur along that dimension. The max dimension range is the +// maximum range among all dimensions. For example, if all +// points lie in unit hypercube, then maxRange = 1. +// +//Output +// * pMax --> maximum truncation number for the Taylor series. +// * errorBound --> the error bound (if desired error bound is not reached, then it will be epsilon+1) +FIGTREE_DLL_API +int figtreeChooseTruncationNumber( int d, double h, double epsilon, + double rx, double maxRange, int * pMax, double * errorBound ); + +// Chooses parameters for IFGT and FIGTree by assuming that sources are +// uniformly distributed in a unit cube. +//Input +// * d --> dimension of the points. +// * h --> the source bandwidth. +// * epsilon --> the desired error. +// * kLimit --> upper limit on the number of clusters, kLimit. +// * maxRange --> max dimension range. The range along a dimension is +// the difference between the max and min values that can ever +// occur along that dimension. The max dimension range is the +// maximum range among all dimensions. For example, if all +// points lie in unit hypercube, then maxRange = 1. +// +//Note : [ Use roughly kLimit=round(40*sqrt(d)/h) ] +//Output +// * K --> number of clusters. +// * pMax --> maximum truncation number for the Taylor series. +// * r --> source cutoff radius. +// * errorBound --> the expected error bound (if desired error bound is not reached, then it will be epsilon+1) +FIGTREE_DLL_API +int figtreeChooseParametersUniform( int d, double h, double epsilon, + int kLimit, double maxRange, + int * K, int * pMax, double * r, double * errorBound ); + +// Chooses parameters for IFGT and FIGTree without assumption that sources are +// uniformly distributed. In this case, k-center clustering is done as part +// of the parameter selection so that the radius of each cluster is not +// estimated but computed directly for the sources. This results in an +// additional k-center clustering operation, but the speedup when sources are +// not uniformly distributed can be large because +// optimal parameters are much more accurately estimated. Even when sources are +// uniformly distributed, the slowdown is often small compared to +// figtreeChooseParametersUniform. +// +// Input +// * d --> dimension of the points. +// * N --> number of source points. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source bandwidth. +// * epsilon --> the desired error. +// * kLimit --> upper limit on the number of clusters, K. +// Note : Use kLimit=N to allow for optimal param estimation. +// * maxRange --> max dimension range. The range along a dimension is +// the difference between the max and min values that can ever +// occur along that dimension. The max dimension range is the +// maximum range among all dimensions. For example, if all +// points lie in unit hypercube, then maxRange = 1. +// Output +// * K --> number of clusters. +// * pMax --> maximum truncation number for the Taylor series. +// * r --> source cutoff radius. +// * errorBound --> the expected error bound (if desired error bound is not reached, then it will be epsilon+1) +FIGTREE_DLL_API +int figtreeChooseParametersNonUniform( int d, int N, double * x, + double h, double epsilon, int kLimit, double maxRange, + int * K, int * pMax, double * r, double * errorBound ); + +// Computes exact gauss transform (within machine precision) using direct +// evaluation. Provided for time/error comparison. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> 1 x N or N x 1 vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// +// Output +// * g --> 1 x M vector of the Gauss Transform evaluated at each target +// point. +FIGTREE_DLL_API +int figtreeEvaluateDirect( int d, int N, int M, double * x, double h, + double * q, double * y, double * g ); + +// Computes an approximation to Gauss Transform. Implementation based on: +// Fast computation of sums of Gaussians in high dimensions. Vikas C. Raykar, +// C. Yang, R. Duraiswami, and N. Gumerov, CS-TR-4767, Department of computer +// science, University of Maryland, College Park. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This really does multiple transforms, with different weights each +// time but with same sources and targets. This saves a lot of time +// since most of the work is not duplicated. However, it requires +// more memory to store the coefficients for each set of weights. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> W x N vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * pMax --> maximum truncation number for the Taylor series. +// * K --> the number of clusters. +// * clusterIndex --> N x 1 vector the i th element is the cluster number +// to which the i th point belongs. [ ClusterIndex[i] varies between +// 0 to K-1. ] +// * clusterCenter --> K x d matrix of K cluster centers. +// * clusterRadii --> K x 1 matrix of the radius of each cluster. +// * r --> cutoff radius +// * epsilon --> desired error +// +//Output +// * g --> W x M vector of the Gauss Transform evaluated at each target +// point. Each row q is the result of the transform using the qth set +// of weights. +FIGTREE_DLL_API +int figtreeEvaluateIfgt( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ); + +// Computes an approximation to Gauss Transform using approximate +// nearest-neighbors. Same as figtreeEvaluateIfgt() but uses Approximate +// Nearest-Neighbors library to find source clusters which influence each target +// (part of FIGTree). Parameters for this function can be computed using +// figtreeChooseParameters[Non]Uniform and figtreeKCenterClustering. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This really does multiple transforms, with different weights each +// time but with same sources and targets. This saves a lot of time +// since most of the work is not duplicated. However, it requires +// more memory to store the coefficients for each set of weights. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> W x N vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * pMax --> maximum truncation number for the Taylor series. +// * K --> the number of clusters. +// * clusterIndex --> N x 1 vector the i th element is the cluster number +// to which the i th point belongs. [ ClusterIndex[i] varies between +// 0 to K-1. ] +// * clusterCenter --> K x d matrix of K cluster centers. +// * clusterRadii --> K x 1 matrix of the radius of each cluster. +// * r --> cutoff radius +// * epsilon --> desired error +// +// Output +// * g --> W x M vector of the Gauss Transform evaluated at each target +// point. Each row of g is the result of the transform using one set +// of weights. +FIGTREE_DLL_API +int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +FIGTREE_DLL_API +int figtreeEvaluateIfgtAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +FIGTREE_DLL_API +int figtreeEvaluateIfgtAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ); + +// Computes an approximation to Gauss Transform using approximate +// nearest-neighbors. Direct method (no taylor expansion is done), with tree +// directly on samples (part of FIGTree). Requires Approximate +// Nearest-Neighbor(ANN) library. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> 1 x N vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * epsilon --> desired error +// +// Output +// * g --> 1 x M vector of the Gauss Transform evaluated at each target +// point. +FIGTREE_DLL_API +int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, + double * q, double * y, double epsilon, double * g ); + +// Computes min and max values along each dimension. Used to determine +// the size of the hypercube (and the max distance R that any two pts +// can be from each other). +// +// Input +// * d --> data dimensionality. +// * n --> number of source points. +// * x --> n x d matrix of n source points in d dimensions. +// * mins --> d x 1 vector of minimum values; input values ignored if update == 0 +// * maxs --> d x 1 vector of maximum values; input values ignored if update == 0 +// * update --> if set to 1, then max[i] will contain +// max(max of values of all samples along dimension i, max[i] input value), and +// similarly for min[i]. +// +// Output +// * mins --> d x 1 vector of minimum values +// * maxs --> d x 1 vector of maximum values +FIGTREE_DLL_API +int figtreeCalcMinMax( int d, int n, double * x, double * mins, double * maxs, int update=0 ); + +FIGTREE_DLL_API +int figtreeCalcMaxRange( double d, double * mins, double * maxs, double * R ); + +#if defined(__cplusplus) && !defined(FIGTREE_STATIC) +} // extern "C" +#endif + +#endif // FIGTREE_INTERNAL_H \ No newline at end of file diff --git a/src/mex/mexFigtree.cpp b/src/mex/mexFigtree.cpp index dc800cb..134c35c 100644 --- a/src/mex/mexFigtree.cpp +++ b/src/mex/mexFigtree.cpp @@ -40,7 +40,6 @@ #include "mex.h" #include "figtree.h" - //The gateway function void mexFunction(int nlhs, // Number of left hand side (output) arguments @@ -50,57 +49,29 @@ void mexFunction(int nlhs, // Number of left hand side (output) a { //check for proper number of arguments - if(nrhs < 9) mexErrMsgTxt("at least 8 input arguments required."); + if(nrhs < 5) mexErrMsgTxt("at least 5 input arguments required."); if(nlhs != 1) mexErrMsgTxt("1 output argument required."); ////////////////////////////////////////////////////////////// // Input arguments ////////////////////////////////////////////////////////////// - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int) mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // N - argu = 1; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'N' must be a scalar."); - int N = (int) mxGetScalar(prhs[argu]); - if (N <= 0) - mexErrMsgTxt("Input 'N' must be a positive number."); - - // M - argu = 2; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'M' must be a scalar."); - int M = (int) mxGetScalar(prhs[argu]); - if (M <= 0) - mexErrMsgTxt("Input 'M' must be a positive number."); - - // W - argu = 3; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'W' must be a scalar."); - int W = (int) mxGetScalar(prhs[argu]); - if (W <= 0) - mexErrMsgTxt("Input 'W' must be a positive number."); - + int d, N, M, W; // x // The 2D array is column-major: each column represents a point. - argu = 4; + int argu = 0; double *x = mxGetPr(prhs[argu]); int mrows = (int) mxGetM(prhs[argu]); //mrows int ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix"); + d = mrows; + N = ncols; + //if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix"); + if( d <= 0 || N <= 0 ) + mexErrMsgTxt( "Input 'x' must be a d x N matrix, with d and N nonzero" ); // h - argu = 5; + argu = 1; if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) mexErrMsgTxt("Input 'h' must be a scalar."); double h = (double) mxGetScalar(prhs[argu]); @@ -108,23 +79,27 @@ void mexFunction(int nlhs, // Number of left hand side (output) a mexErrMsgTxt("Input 'h' must be a positive number."); // q - argu = 6; + argu = 2; double * q = mxGetPr(prhs[argu]); mrows =(int) mxGetM(prhs[argu]); //mrows ncols =(int) mxGetN(prhs[argu]); //ncols + W = mrows*ncols/N; if ( (W != 1 && mrows != N && ncols != W) || ( W == 1 && mrows*ncols != N ) ) - mexErrMsgTxt("Input 'q' must be a N x W matrix (or if W=1, then it can also be a 1 x N matrix)."); + mexErrMsgTxt("Input 'q' must be a N x W matrix (or if W=1, then it can also be a 1 x N matrix).\n Here N is the same as in the d x N matrix 'x'"); // y - argu = 7; + argu = 3; double * y = mxGetPr(prhs[argu]); mrows = (int)mxGetM(prhs[argu]); //mrows ncols = (int)mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != M) - mexErrMsgTxt("Input 'y' must be a d x M matrix"); + M = ncols; + if( mrows != d ) + mexErrMsgTxt("Input 'y' must be a d x M matrix, with d the same as the d x N matrix 'x'."); + if( M <= 0 ) + mexErrMsgTxt( "Input 'y' must be a d x M matrix, with d and M nonzero" ); // epsilon - argu = 8; + argu = 4; if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) mexErrMsgTxt("Input 'epsilon' must be a scalar."); double epsilon = (double) mxGetScalar(prhs[argu]); @@ -134,42 +109,49 @@ void mexFunction(int nlhs, // Number of left hand side (output) a ////////////////////////////////////////////////////////////// // Optional input arguments ////////////////////////////////////////////////////////////// - int evalMethod = FIGTREE_EVAL_IFGT; - int paramMethod = FIGTREE_PARAM_NON_UNIFORM; + int evalMethod = FIGTREE_EVAL_AUTO; + int ifgtParamMethod = FIGTREE_PARAM_NON_UNIFORM; + int ifgtTruncMethod = FIGTREE_TRUNC_CLUSTER; int verbose = 0; - int forceK = 0; // evalMethod - argu = 9; + argu = 5; if( nrhs >= argu+1 ) { if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'evalMethod' must be an integer."); + mexErrMsgTxt("Input 'evalMethod' must be an integer between 0 and 4" ); evalMethod = (int) mxGetScalar(prhs[argu]); + if( evalMethod < 0 || evalMethod >= FIGTREE_EVAL_SIZE ) + mexErrMsgTxt("Input 'evalMethod' must be an integer between 0 and 4" ); } - argu = 10; + argu = 6; if( nrhs >= argu+1 ) { if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'paramMethod' must be an integer."); - paramMethod = (int) mxGetScalar(prhs[argu]); + mexErrMsgTxt("Input 'ifgtParamMethod' must be an integer between 0 and 1" ); + ifgtParamMethod = (int) mxGetScalar(prhs[argu]); + if( ifgtParamMethod < 0 || ifgtParamMethod >= FIGTREE_TRUNC_SIZE ) + mexErrMsgTxt("Input 'ifgtParamMethod' must be an integer between 0 and 1" ); } - argu = 11; + argu = 7; if( nrhs >= argu+1 ) { if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'verbose' must be an integer."); - verbose = (int) mxGetScalar(prhs[argu]); + mexErrMsgTxt("Input 'ifgtTruncMethod' must be an integer between 0 and 2" ); + ifgtTruncMethod = (int) mxGetScalar(prhs[argu]); + if( ifgtTruncMethod < 0 || ifgtTruncMethod >= FIGTREE_TRUNC_SIZE ) + mexErrMsgTxt("Input 'ifgtTruncMethod' must be an integer between 0 and 2" ); + } - argu = 12; + argu = 8; if( nrhs >= argu+1 ) { if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'forceK' must be an integer."); - forceK = (int) mxGetScalar(prhs[argu]); + mexErrMsgTxt("Input 'verbose' must be an integer."); + verbose = (int) mxGetScalar(prhs[argu]); } ////////////////////////////////////////////////////////////// @@ -181,9 +163,7 @@ void mexFunction(int nlhs, // Number of left hand side (output) a double *g = mxGetPr(plhs[0]); // Function call - //mexPrintf("d = %i, N = %i, M = %i, W = %i, h = %3.2e, evalMethod = %i, paramMethod = %i, verbose = %i, forceK = %i\n", - // d, N, M, W, h, evalMethod, paramMethod, verbose, forceK ); - figtree( d, N, M, W, x, h, q, y, epsilon, g, evalMethod, paramMethod, verbose, forceK ); + figtree( d, N, M, W, x, h, q, y, epsilon, g, evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose ); return; } diff --git a/src/mex/mexFigtreeEvaluateDirectTree.cpp b/src/mex/mexFigtreeChooseEvaluationMethod.cpp similarity index 61% rename from src/mex/mexFigtreeEvaluateDirectTree.cpp rename to src/mex/mexFigtreeChooseEvaluationMethod.cpp index 180c93e..e273a29 100644 --- a/src/mex/mexFigtreeEvaluateDirectTree.cpp +++ b/src/mex/mexFigtreeChooseEvaluationMethod.cpp @@ -1,5 +1,5 @@ //------------------------------------------------------------------- -// File : MexIfgtEvaluateDirectTree.cpp +// File : MexFigtreeChooseEvaluateMethod.cpp // Purpose : Interface between MATLAB and C++ // Author : Vlad I. Morariu (morariu(at)umd(.)edu) // Date : 2007-06-25 @@ -37,11 +37,11 @@ // with mxPrintf and also causes memory operations such as new and delete to be managed // by matlab via mxMalloc and mxFree. - #include "mex.h" #include "figtree.h" //The gateway function + void mexFunction(int nlhs, // Number of left hand side (output) arguments mxArray *plhs[], // Array of left hand side arguments int nrhs, // Number of right hand side (input) arguments @@ -49,88 +49,105 @@ void mexFunction(int nlhs, // Number of left hand side (output) a { //check for proper number of arguments - if(nrhs != 8) mexErrMsgTxt("8 input arguments required."); - if(nlhs != 1) mexErrMsgTxt("1 output argument required."); + if(nrhs < 5) mexErrMsgTxt("at least 5 input arguments required."); + if(nlhs < 1) mexErrMsgTxt("at least 1 output argument required."); ////////////////////////////////////////////////////////////// // Input arguments ////////////////////////////////////////////////////////////// - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int) mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // N - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'N' must be a scalar."); - int N = (int) mxGetScalar(prhs[argu]); - if (N <= 0) - mexErrMsgTxt("Input 'N' must be a positive number."); - - // M - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'M' must be a scalar."); - int M = (int) mxGetScalar(prhs[argu]); - if (M <= 0) - mexErrMsgTxt("Input 'M' must be a positive number."); + int d, N, M, W; // x // The 2D array is column-major: each column represents a point. - argu++; + int argu = 0; double *x = mxGetPr(prhs[argu]); int mrows = (int) mxGetM(prhs[argu]); //mrows int ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix"); + d = mrows; + N = ncols; + //if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix"); + if( d <= 0 || N <= 0 ) + mexErrMsgTxt( "Input 'x' must be a d x N matrix, with d and N nonzero" ); // h - argu++; + argu = 1; if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) mexErrMsgTxt("Input 'h' must be a scalar."); double h = (double) mxGetScalar(prhs[argu]); if ( h <= 0.0) mexErrMsgTxt("Input 'h' must be a positive number."); - // q - argu++; - double * q = mxGetPr(prhs[argu]); - mrows =(int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( mrows*ncols != N ) - mexErrMsgTxt("Input 'q' must be a N x 1 or 1 x N matrix."); + // W + argu = 2; + if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) + mexErrMsgTxt("Input 'W' must be a scalar."); + W = (int) mxGetScalar(prhs[argu]); + if (W <= 0) + mexErrMsgTxt("Input 'W' must be a positive number."); // y - argu++; + argu = 3; double * y = mxGetPr(prhs[argu]); mrows = (int)mxGetM(prhs[argu]); //mrows ncols = (int)mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != M) - mexErrMsgTxt("Input 'y' must be a d x M matrix"); + M = ncols; + if( mrows != d ) + mexErrMsgTxt("Input 'y' must be a d x M matrix, with d the same as the d x N matrix 'x'."); + if( M <= 0 ) + mexErrMsgTxt( "Input 'y' must be a d x M matrix, with d and M nonzero" ); // epsilon - argu++; + argu = 4; if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) mexErrMsgTxt("Input 'epsilon' must be a scalar."); double epsilon = (double) mxGetScalar(prhs[argu]); if ( epsilon <= 0.0) mexErrMsgTxt("Input 'epsilon' must be a positive number."); + ////////////////////////////////////////////////////////////// + // Optional input arguments + ////////////////////////////////////////////////////////////// + int ifgtParamMethod = FIGTREE_PARAM_NON_UNIFORM; + int verbose = 0; + + argu++; + if( nrhs >= argu+1 ) + { + if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) + mexErrMsgTxt("Input 'ifgtParamMethod' must be an integer between 0 and 1" ); + ifgtParamMethod = (int) mxGetScalar(prhs[argu]); + if( ifgtParamMethod < 0 || ifgtParamMethod >= FIGTREE_TRUNC_SIZE ) + mexErrMsgTxt("Input 'ifgtParamMethod' must be an integer between 0 and 1" ); + } + + argu++; + if( nrhs >= argu+1 ) + { + if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) + mexErrMsgTxt("Input 'verbose' must be an integer."); + verbose = (int) mxGetScalar(prhs[argu]); + } + ////////////////////////////////////////////////////////////// // Output arguments ////////////////////////////////////////////////////////////// // g - plhs[0] = mxCreateDoubleMatrix(M,1,mxREAL); - double *g = mxGetPr(plhs[0]); + int bestEvalMethod = 0; + double * flops = NULL; + plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); + if( nlhs > 1 ) + { + plhs[1] = mxCreateDoubleMatrix(4,1,mxREAL); + flops = mxGetPr(plhs[1]); + } + + double * bestEvalMethodDouble = mxGetPr(plhs[0]); // Function call - figtreeEvaluateDirectTree( d, N, M, x, h, q, y, epsilon, g ); + figtreeChooseEvaluationMethod( d, N, M, W, x, h, y, epsilon, ifgtParamMethod, verbose, &bestEvalMethod, flops ); + *bestEvalMethodDouble = (double)bestEvalMethod; return; } diff --git a/src/mex/mexFigtreeChooseEvaluationMethod.def b/src/mex/mexFigtreeChooseEvaluationMethod.def new file mode 100644 index 0000000..6d1507b --- /dev/null +++ b/src/mex/mexFigtreeChooseEvaluationMethod.def @@ -0,0 +1,2 @@ +LIBRARY figtreeChooseEvaluationMethod.dll +EXPORTS mexFunction diff --git a/src/mex/mexFigtreeChooseParametersNonUniform.cpp b/src/mex/mexFigtreeChooseParametersNonUniform.cpp deleted file mode 100644 index 0b22e3f..0000000 --- a/src/mex/mexFigtreeChooseParametersNonUniform.cpp +++ /dev/null @@ -1,145 +0,0 @@ -//------------------------------------------------------------------- -// File : MexFigtreeChooseParametersNonUniform.cpp -// Purpose : Interface between MATLAB and C++ -// Author : Vlad I. Morariu (morariu(at)umd(.)edu) -// Date : 2007-06-25 -// -// This file has been derived by Vlad I. Morariu from Vikas C. -// Raykar's original IFGT code (source file mexmain.cpp). -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// The code was written by Vlad Morariu and Vikas C. Raykar -// and is copyrighted under the Lesser GPL: -// -// Copyright (C) 2007 Vlad Morariu and Vikas C. Raykar -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 or later. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, -// MA 02111-1307, USA. -// -// The author may be contacted via email at: -// morariu(at)umd(.)edu, vikas(at)cs(.)umd(.)edu -//------------------------------------------------------------------- - - -// preprocessor definitions used: FIGTREE_STATIC, FIGTREE_USE_MATLAB_MEX -// The first makes sure that the compiled code does not require figtree.dll, but instead -// compiles the code directly in the code. The second replaces all printf calls -// with mxPrintf and also causes memory operations such as new and delete to be managed -// by matlab via mxMalloc and mxFree. - -#include "mex.h" -#include "figtree.h" - - -//The gateway function - -void mexFunction(int nlhs, // Number of left hand side (output) arguments - mxArray *plhs[], // Array of left hand side arguments - int nrhs, // Number of right hand side (input) arguments - const mxArray *prhs[]) // Array of right hand side arguments -{ - // check for proper number of arguments - if(nrhs != 7) - mexErrMsgTxt("7 input arguments required."); - if(nlhs != 3) - mexErrMsgTxt("3 output arguments required."); - - ////////////////////////////////////////////////////////////// - // Input arguments - ////////////////////////////////////////////////////////////// - - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int)mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // N - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'N' must be a scalar."); - int N = (int) mxGetScalar(prhs[argu]); - if (N <= 0) - mexErrMsgTxt("Input 'N' must be a positive number."); - - // x - argu++; - double *x = mxGetPr(prhs[argu]); - int mrows = (int) mxGetM(prhs[argu]); //mrows - int ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != N) - mexErrMsgTxt("Input 'x' must be a d x N matrix"); - - // h - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'h' must be a scalar."); - double h = (double)mxGetScalar(prhs[argu]); - if ( h <= 0.0) - mexErrMsgTxt("Input 'h' must be a positive number."); - - // epsilon - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'epsilon' must be a scalar."); - double epsilon = (double)mxGetScalar(prhs[argu]); - if ( epsilon <= 0.0) - mexErrMsgTxt("Input 'epsilon' must be a positive number."); - - // kLimit - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'kLimit' must be a scalar."); - int kLimit = (int)mxGetScalar(prhs[argu]); - if (kLimit <= 0) - mexErrMsgTxt("Input 'kLimit' must be a positive number."); - - // maxRange - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'maxRange' must be a scalar."); - double maxRange = (double)mxGetScalar(prhs[argu]); - if ( maxRange <= 0.0) - mexErrMsgTxt("Input 'maxRange' must be a positive number."); - - - ////////////////////////////////////////////////////////////// - // Output arguments - ////////////////////////////////////////////////////////////// - - // K - argu = 0; - plhs[argu] = mxCreateDoubleMatrix(1,1,mxREAL); - double *K = mxGetPr(plhs[argu]); - - // pMax - argu++; - plhs[argu] = mxCreateDoubleMatrix(1,1,mxREAL); - double *pMax = mxGetPr(plhs[argu]); - - // r - argu++; - plhs[argu] = mxCreateDoubleMatrix(1,1,mxREAL); - double *r = mxGetPr(plhs[argu]); - - // Function call - int kTmp, pMaxTmp; - figtreeChooseParametersNonUniform( d, N, x, h, epsilon, kLimit, maxRange, &kTmp, &pMaxTmp, r ); - *K = kTmp; - *pMax = pMaxTmp; - - return; -} diff --git a/src/mex/mexFigtreeChooseParametersNonUniform.def b/src/mex/mexFigtreeChooseParametersNonUniform.def deleted file mode 100644 index d742f5c..0000000 --- a/src/mex/mexFigtreeChooseParametersNonUniform.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeChooseParametersNonUniform.dll -EXPORTS mexFunction diff --git a/src/mex/mexFigtreeChooseParametersUniform.cpp b/src/mex/mexFigtreeChooseParametersUniform.cpp deleted file mode 100644 index b54ff52..0000000 --- a/src/mex/mexFigtreeChooseParametersUniform.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//------------------------------------------------------------------- -// File : MexFigtreeChooseParametersUniform.cpp -// Purpose : Interface between MATLAB and C++ -// Author : Vlad I. Morariu (morariu(at)umd(.)edu) -// Date : 2007-06-25 -// -// This file has been derived by Vlad I. Morariu from Vikas C. -// Raykar's original IFGT code (source file mexmain.cpp). -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// The code was written by Vlad Morariu and Vikas C. Raykar -// and is copyrighted under the Lesser GPL: -// -// Copyright (C) 2007 Vlad Morariu and Vikas C. Raykar -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 or later. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, -// MA 02111-1307, USA. -// -// The author may be contacted via email at: -// morariu(at)umd(.)edu, vikas(at)cs(.)umd(.)edu -//------------------------------------------------------------------- - -// preprocessor definitions used: FIGTREE_STATIC, FIGTREE_USE_MATLAB_MEX -// The first makes sure that the compiled code does not require figtree.dll, but instead -// compiles the code directly in the code. The second replaces all printf calls -// with mxPrintf and also causes memory operations such as new and delete to be managed -// by matlab via mxMalloc and mxFree. - -#include "mex.h" -#include "figtree.h" - - -//The gateway function - -void mexFunction(int nlhs, // Number of left hand side (output) arguments - mxArray *plhs[], // Array of left hand side arguments - int nrhs, // Number of right hand side (input) arguments - const mxArray *prhs[]) // Array of right hand side arguments -{ - // check for proper number of arguments - if(nrhs != 5) - mexErrMsgTxt("5 input arguments required."); - if(nlhs != 3) - mexErrMsgTxt("3 output arguments required."); - - ////////////////////////////////////////////////////////////// - // Input arguments - ////////////////////////////////////////////////////////////// - - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int)mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // h - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'h' must be a scalar."); - double h = (double)mxGetScalar(prhs[argu]); - if ( h <= 0.0) - mexErrMsgTxt("Input 'h' must be a positive number."); - - // epsilon - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'epsilon' must be a scalar."); - double epsilon = (double)mxGetScalar(prhs[argu]); - if ( epsilon <= 0.0) - mexErrMsgTxt("Input 'epsilon' must be a positive number."); - - // kLimit - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'kLimit' must be a scalar."); - int kLimit = (int)mxGetScalar(prhs[argu]); - if (kLimit <= 0) - mexErrMsgTxt("Input 'kLimit' must be a positive number."); - - // maxRange - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'maxRange' must be a scalar."); - double maxRange = (double)mxGetScalar(prhs[argu]); - if ( maxRange <= 0.0) - mexErrMsgTxt("Input 'maxRange' must be a positive number."); - - ////////////////////////////////////////////////////////////// - // Output arguments - ////////////////////////////////////////////////////////////// - - // K - argu = 0; - plhs[argu] = mxCreateDoubleMatrix(1,1,mxREAL); - double *K = mxGetPr(plhs[argu]); - - // pMax - argu++; - plhs[argu] = mxCreateDoubleMatrix(1,1,mxREAL); - double *pMax = mxGetPr(plhs[argu]); - - // r - argu++; - plhs[argu] = mxCreateDoubleMatrix(1,1,mxREAL); - double *r = mxGetPr(plhs[argu]); - - // Function call - int kTmp, pMaxTmp; - figtreeChooseParametersUniform( d, h, epsilon, kLimit, maxRange, &kTmp, &pMaxTmp, r ); - *K = kTmp; - *pMax = pMaxTmp; - - return; -} diff --git a/src/mex/mexFigtreeChooseParametersUniform.def b/src/mex/mexFigtreeChooseParametersUniform.def deleted file mode 100644 index 22a3371..0000000 --- a/src/mex/mexFigtreeChooseParametersUniform.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeChooseParametersUniform.dll -EXPORTS mexFunction diff --git a/src/mex/mexFigtreeChooseTruncationNumber.cpp b/src/mex/mexFigtreeChooseTruncationNumber.cpp deleted file mode 100644 index c1672f6..0000000 --- a/src/mex/mexFigtreeChooseTruncationNumber.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//------------------------------------------------------------------- -// File : MexIfgt.cpp -// Purpose : Interface between MATLAB and C++ -// Author : Vlad I. Morariu (morariu(at)umd(.)edu) -// Date : 2007-06-25 -// -// This file has been derived by Vlad I. Morariu from Vikas C. -// Raykar's original IFGT code (source file mexmain.cpp). -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// The code was written by Vlad Morariu and Vikas C. Raykar -// and is copyrighted under the Lesser GPL: -// -// Copyright (C) 2007 Vlad Morariu and Vikas C. Raykar -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 or later. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, -// MA 02111-1307, USA. -// -// The author may be contacted via email at: -// morariu(at)umd(.)edu, vikas(at)cs(.)umd(.)edu -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// Automatic parameter selection for the -// Improved Fast Gauss Transform (IFGT). -// -// Given the maximum cluster radius this routine computes the -// required truncation number. -// -// Implementation based on: -// -// Fast computation of sums of Gaussians in high dimensions. -// Vikas C. Raykar, C. Yang, R. Duraiswami, and N. Gumerov, -// CS-TR-4767, Department of computer science, -// University of Maryland, Collegepark. -//-------------------------------------------------------------------- - -// preprocessor definitions used: FIGTREE_STATIC, USE_MATLAB_MEX -// The first makes sure that the compiled code does not require Ifgt.dll, but instead -// compiles the code directly in the code. The second replaces all printf calls -// with mxPrintf and also causes memory operations such as new and delete to be managed -// by matlab via mxMalloc and mxFree. - -#include "mex.h" -#include "figtree.h" - - -//The gateway function - -void mexFunction(int nlhs, // Number of left hand side (output) arguments - mxArray *plhs[], // Array of left hand side arguments - int nrhs, // Number of right hand side (input) arguments - const mxArray *prhs[]) // Array of right hand side arguments -{ - //check for proper number of arguments - - if(nrhs != 5) mexErrMsgTxt("5 inputs required."); - if(nlhs != 1) mexErrMsgTxt("1 outputs required."); - - ////////////////////////////////////////////////////////////// - // Input arguments - ////////////////////////////////////////////////////////////// - - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int) mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // h - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'h' must be a scalar."); - double h = (double) mxGetScalar(prhs[argu]); - if ( h <= 0.0) - mexErrMsgTxt("Input 'h' must be a positive number."); - - // epsilon - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'epsilon' must be a scalar."); - double epsilon = (double) mxGetScalar(prhs[argu]); - if ( epsilon <= 0.0) - mexErrMsgTxt("Input 'epsilon' must be a positive number."); - - // rx - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'rx' must be a scalar."); - double rx = (double) mxGetScalar(prhs[argu]); - if ( rx <= 0.0) - mexErrMsgTxt("Input 'rx' must be a positive number."); - - // maxRange - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu]) != 1 ) - mexErrMsgTxt("Input 'maxRange' must be a scalar."); - double maxRange = (double)mxGetScalar(prhs[argu]); - if ( maxRange <= 0.0) - mexErrMsgTxt("Input 'maxRange' must be a positive number."); - - // Output, pMax - plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); - double *pMax = mxGetPr(plhs[0]); - - // Function call - int pMaxTemp; - figtreeChooseTruncationNumber( d, h, epsilon, rx, maxRange, &pMaxTemp ); - *pMax = pMaxTemp; - - return; -} diff --git a/src/mex/mexFigtreeChooseTruncationNumber.def b/src/mex/mexFigtreeChooseTruncationNumber.def deleted file mode 100644 index 587502e..0000000 --- a/src/mex/mexFigtreeChooseTruncationNumber.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeChooseTruncationNumber.dll -EXPORTS mexFunction diff --git a/src/mex/mexFigtreeEvaluateDirect.cpp b/src/mex/mexFigtreeEvaluateDirect.cpp deleted file mode 100644 index 714ffb3..0000000 --- a/src/mex/mexFigtreeEvaluateDirect.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//------------------------------------------------------------------- -// File : MexIfgtEvaluateDirect.cpp -// Purpose : Interface between MATLAB and C++ -// Author : Vlad I. Morariu (morariu(at)umd(.)edu) -// Date : 2007-06-25 -// -// This file has been derived by Vlad I. Morariu from Vikas C. -// Raykar's original IFGT code (source file mexmain.cpp). -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// The code was written by Vlad Morariu and Vikas C. Raykar -// and is copyrighted under the Lesser GPL: -// -// Copyright (C) 2007 Vlad Morariu and Vikas C. Raykar -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 or later. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, -// MA 02111-1307, USA. -// -// The author may be contacted via email at: -// morariu(at)umd(.)edu, vikas(at)cs(.)umd(.)edu -//------------------------------------------------------------------- - - -// preprocessor definitions used: FIGTREE_STATIC, USE_MATLAB_MEX -// The first makes sure that the compiled code does not require Ifgt.dll, but instead -// compiles the code directly in the code. The second replaces all printf calls -// with mxPrintf and also causes memory operations such as new and delete to be managed -// by matlab via mxMalloc and mxFree. - -#include "mex.h" -#include "figtree.h" - - -//The gateway function - -void mexFunction(int nlhs, // Number of left hand side (output) arguments - mxArray *plhs[], // Array of left hand side arguments - int nrhs, // Number of right hand side (input) arguments - const mxArray *prhs[]) // Array of right hand side arguments -{ - //check for proper number of arguments - - if(nrhs != 7) mexErrMsgTxt("7 input arguments required."); - if(nlhs != 1) mexErrMsgTxt("1 output argument required."); - - ////////////////////////////////////////////////////////////// - // Input arguments - ////////////////////////////////////////////////////////////// - - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int) mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // N - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'N' must be a scalar."); - int N = (int) mxGetScalar(prhs[argu]); - if (N <= 0) - mexErrMsgTxt("Input 'N' must be a positive number."); - - // M - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'M' must be a scalar."); - int M = (int) mxGetScalar(prhs[argu]); - if (M <= 0) - mexErrMsgTxt("Input 'M' must be a positive number."); - - // x - // The 2D array is column-major: each column represents a point. - argu++; - double *x = mxGetPr(prhs[argu]); - int mrows = (int) mxGetM(prhs[argu]); //mrows - int ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix"); - - // h - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'h' must be a scalar."); - double h = (double) mxGetScalar(prhs[argu]); - if ( h <= 0.0) - mexErrMsgTxt("Input 'h' must be a positive number."); - - // q - argu++; - double * q = mxGetPr(prhs[argu]); - mrows =(int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( mrows*ncols != N ) - mexErrMsgTxt("Input 'q' must be a N x 1 or 1 x N matrix."); - - // y - argu++; - double * y = mxGetPr(prhs[argu]); - mrows = (int)mxGetM(prhs[argu]); //mrows - ncols = (int)mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != M) - mexErrMsgTxt("Input 'y' must be a d x M matrix"); - - ////////////////////////////////////////////////////////////// - // Output arguments - ////////////////////////////////////////////////////////////// - - // g - plhs[0] = mxCreateDoubleMatrix(M,1,mxREAL); - double *g = mxGetPr(plhs[0]); - - // Function call - figtreeEvaluateDirect( d, N, M, x, h, q, y, g ); - - return; -} diff --git a/src/mex/mexFigtreeEvaluateDirect.def b/src/mex/mexFigtreeEvaluateDirect.def deleted file mode 100644 index 17ed37d..0000000 --- a/src/mex/mexFigtreeEvaluateDirect.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeEvaluateDirect.dll -EXPORTS mexFunction diff --git a/src/mex/mexFigtreeEvaluateDirectTree.def b/src/mex/mexFigtreeEvaluateDirectTree.def deleted file mode 100644 index 0a66554..0000000 --- a/src/mex/mexFigtreeEvaluateDirectTree.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeEvaluateDirectTree.dll -EXPORTS mexFunction diff --git a/src/mex/mexFigtreeEvaluateIfgt.cpp b/src/mex/mexFigtreeEvaluateIfgt.cpp deleted file mode 100644 index b8bd762..0000000 --- a/src/mex/mexFigtreeEvaluateIfgt.cpp +++ /dev/null @@ -1,194 +0,0 @@ -//------------------------------------------------------------------- -// File : MexIfgtEvaluateDirectTree.cpp -// Purpose : Interface between MATLAB and C++ -// Author : Vlad I. Morariu (morariu(at)umd(.)edu) -// Date : 2007-06-25 -// -// This file has been derived by Vlad I. Morariu from Vikas C. -// Raykar's original IFGT code (source file mexmain.cpp). -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// The code was written by Vlad Morariu and Vikas C. Raykar -// and is copyrighted under the Lesser GPL: -// -// Copyright (C) 2007 Vlad Morariu and Vikas C. Raykar -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 or later. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, -// MA 02111-1307, USA. -// -// The author may be contacted via email at: -// morariu(at)umd(.)edu, vikas(at)cs(.)umd(.)edu -//------------------------------------------------------------------- - - -// preprocessor definitions used: FIGTREE_STATIC, USE_MATLAB_MEX -// The first makes sure that the compiled code does not require Ifgt.dll, but instead -// compiles the code directly in the code. The second replaces all printf calls -// with mxPrintf and also causes memory operations such as new and delete to be managed -// by matlab via mxMalloc and mxFree. - -#include "mex.h" -#include "figtree.h" - - -//The gateway function - -void mexFunction(int nlhs, // Number of left hand side (output) arguments - mxArray *plhs[], // Array of left hand side arguments - int nrhs, // Number of right hand side (input) arguments - const mxArray *prhs[]) // Array of right hand side arguments -{ - //check for proper number of arguments - - if(nrhs != 15) mexErrMsgTxt("15 input arguments required."); - if(nlhs != 1) mexErrMsgTxt("1 output argument required."); - - ////////////////////////////////////////////////////////////// - // Input arguments - ////////////////////////////////////////////////////////////// - - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int) mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // N - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'N' must be a scalar."); - int N = (int) mxGetScalar(prhs[argu]); - if (N <= 0) - mexErrMsgTxt("Input 'N' must be a positive number."); - - // M - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'M' must be a scalar."); - int M = (int) mxGetScalar(prhs[argu]); - if (M <= 0) - mexErrMsgTxt("Input 'M' must be a positive number."); - - // W - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'W' must be a scalar."); - int W = (int) mxGetScalar(prhs[argu]); - if (W <= 0) - mexErrMsgTxt("Input 'W' must be a positive number."); - - - // x - // The 2D array is column-major: each column represents a point. - argu++; - double *x = mxGetPr(prhs[argu]); - int mrows = (int) mxGetM(prhs[argu]); //mrows - int ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix."); - - // h - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'h' must be a scalar."); - double h = (double) mxGetScalar(prhs[argu]); - if ( h <= 0.0) - mexErrMsgTxt("Input 'h' must be a positive number."); - - // q - argu++; - double * q = mxGetPr(prhs[argu]); - mrows =(int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( (W != 1 && mrows != N && ncols != W) || ( W == 1 && mrows*ncols != N ) ) - mexErrMsgTxt("Input 'q' must be a N x W matrix (or if W=1, then it can also be a 1 x N matrix)."); - - // y - argu++; - double * y = mxGetPr(prhs[argu]); - mrows = (int)mxGetM(prhs[argu]); //mrows - ncols = (int)mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != M) - mexErrMsgTxt("Input 'y' must be a d x M matrix."); - - // pMax - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'pMax' must be a scalar."); - int pMax = (int) mxGetScalar(prhs[argu]); - if (pMax <= 0) - mexErrMsgTxt("Input 'pMax' must be a positive number."); - - // K - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'K' must be a scalar."); - int K = (int) mxGetScalar(prhs[argu]); - if (K <= 0) - mexErrMsgTxt("Input 'K' must be a positive number."); - - // clusterIndex - argu++; - int *clusterIndex =(int*) mxGetPr(prhs[argu]); - mrows = (int) mxGetM(prhs[argu]); //mrows - ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != 1 || ncols != N || !mxIsUint32(prhs[argu]) ) - mexErrMsgTxt("Input 'clusterIndex' must be a 1 x N matrix (of 32-bit uint values)."); - - // clusterCenter - argu++; - double * clusterCenter = mxGetPr(prhs[argu]); - mrows = (int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( mrows != d || ncols != K ) - mexErrMsgTxt("Input 'clusterCenter' must be a d x K matrix."); - - // clusterRadii - argu++; - double * clusterRadii = mxGetPr(prhs[argu]); - mrows = (int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( mrows != 1 || ncols != K ) mexErrMsgTxt("Input 'clusterRadii' must be a 1 x K matrix."); - - // r - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'r' must be a scalar."); - double r = (double) mxGetScalar(prhs[argu]); - if ( r <= 0.0) - mexErrMsgTxt("Input 'r' must be a positive number."); - - // epsilon - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'epsilon' must be a scalar."); - double epsilon = (double) mxGetScalar(prhs[argu]); - if ( epsilon <= 0.0) - mexErrMsgTxt("Input 'epsilon' must be a positive number."); - - ////////////////////////////////////////////////////////////// - // Output arguments - ////////////////////////////////////////////////////////////// - - // g - plhs[0] = mxCreateDoubleMatrix(M,W,mxREAL); - double *g = mxGetPr(plhs[0]); - - // Function call - figtreeEvaluateIfgt( d, N, M, W, x, h, q, y, pMax, K, clusterIndex, clusterCenter, clusterRadii, r, epsilon, g ); - - - return; -} diff --git a/src/mex/mexFigtreeEvaluateIfgt.def b/src/mex/mexFigtreeEvaluateIfgt.def deleted file mode 100644 index 8b78193..0000000 --- a/src/mex/mexFigtreeEvaluateIfgt.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeEvaluateIfgt.dll -EXPORTS mexFunction diff --git a/src/mex/mexFigtreeEvaluateIfgtTree.cpp b/src/mex/mexFigtreeEvaluateIfgtTree.cpp deleted file mode 100644 index 688af62..0000000 --- a/src/mex/mexFigtreeEvaluateIfgtTree.cpp +++ /dev/null @@ -1,194 +0,0 @@ -//------------------------------------------------------------------- -// File : MexFigtreeEvaluateIfgtTree.cpp -// Purpose : Interface between MATLAB and C++ -// Author : Vlad I. Morariu (morariu(at)umd(.)edu) -// Date : 2007-06-25 -// -// This file has been derived by Vlad I. Morariu from Vikas C. -// Raykar's original IFGT code (source file mexmain.cpp). -//------------------------------------------------------------------- - -//------------------------------------------------------------------- -// The code was written by Vlad Morariu and Vikas C. Raykar -// and is copyrighted under the Lesser GPL: -// -// Copyright (C) 2007 Vlad Morariu and Vikas C. Raykar -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 or later. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, -// MA 02111-1307, USA. -// -// The author may be contacted via email at: -// morariu(at)umd(.)edu, vikas(at)cs(.)umd(.)edu -//------------------------------------------------------------------- - - -// preprocessor definitions used: FIGTREE_STATIC, USE_MATLAB_MEX -// The first makes sure that the compiled code does not require Ifgt.dll, but instead -// compiles the code directly in the code. The second replaces all printf calls -// with mxPrintf and also causes memory operations such as new and delete to be managed -// by matlab via mxMalloc and mxFree. - -#include "mex.h" -#include "figtree.h" - - -//The gateway function - -void mexFunction(int nlhs, // Number of left hand side (output) arguments - mxArray *plhs[], // Array of left hand side arguments - int nrhs, // Number of right hand side (input) arguments - const mxArray *prhs[]) // Array of right hand side arguments -{ - //check for proper number of arguments - - if(nrhs != 15) mexErrMsgTxt("15 input arguments required."); - if(nlhs != 1) mexErrMsgTxt("1 output argument required."); - - ////////////////////////////////////////////////////////////// - // Input arguments - ////////////////////////////////////////////////////////////// - - // d - int argu = 0; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'd' must be a scalar."); - // get the scalar input d - int d = (int) mxGetScalar(prhs[argu]); - if (d <= 0) - mexErrMsgTxt("Input 'd' must be a positive number."); - - // N - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'N' must be a scalar."); - int N = (int) mxGetScalar(prhs[argu]); - if (N <= 0) - mexErrMsgTxt("Input 'N' must be a positive number."); - - // M - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'M' must be a scalar."); - int M = (int) mxGetScalar(prhs[argu]); - if (M <= 0) - mexErrMsgTxt("Input 'M' must be a positive number."); - - // W - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'W' must be a scalar."); - int W = (int) mxGetScalar(prhs[argu]); - if (W <= 0) - mexErrMsgTxt("Input 'W' must be a positive number."); - - - // x - // The 2D array is column-major: each column represents a point. - argu++; - double *x = mxGetPr(prhs[argu]); - int mrows = (int) mxGetM(prhs[argu]); //mrows - int ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != N) mexErrMsgTxt("Input 'x' must be a d x N matrix."); - - // h - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'h' must be a scalar."); - double h = (double) mxGetScalar(prhs[argu]); - if ( h <= 0.0) - mexErrMsgTxt("Input 'h' must be a positive number."); - - // q - argu++; - double * q = mxGetPr(prhs[argu]); - mrows =(int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( (W != 1 && mrows != N && ncols != W) || ( W == 1 && mrows*ncols != N ) ) - mexErrMsgTxt("Input 'q' must be a N x W matrix (or if W=1, then it can also be a 1 x N matrix)."); - - // y - argu++; - double * y = mxGetPr(prhs[argu]); - mrows = (int)mxGetM(prhs[argu]); //mrows - ncols = (int)mxGetN(prhs[argu]); //ncols - if ( mrows != d && ncols != M) - mexErrMsgTxt("Input 'y' must be a d x M matrix."); - - // pMax - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'pMax' must be a scalar."); - int pMax = (int) mxGetScalar(prhs[argu]); - if (pMax <= 0) - mexErrMsgTxt("Input 'pMax' must be a positive number."); - - // K - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'K' must be a scalar."); - int K = (int) mxGetScalar(prhs[argu]); - if (K <= 0) - mexErrMsgTxt("Input 'K' must be a positive number."); - - // clusterIndex - argu++; - int *clusterIndex =(int*) mxGetPr(prhs[argu]); - mrows = (int) mxGetM(prhs[argu]); //mrows - ncols = (int) mxGetN(prhs[argu]); //ncols - if ( mrows != 1 || ncols != N || !mxIsUint32(prhs[argu]) ) - mexErrMsgTxt("Input 'clusterIndex' must be a 1 x N matrix (of 32-bit uint values)."); - - // clusterCenter - argu++; - double * clusterCenter = mxGetPr(prhs[argu]); - mrows = (int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( mrows != d || ncols != K ) - mexErrMsgTxt("Input 'clusterCenter' must be a d x K matrix."); - - // clusterRadii - argu++; - double * clusterRadii = mxGetPr(prhs[argu]); - mrows = (int) mxGetM(prhs[argu]); //mrows - ncols =(int) mxGetN(prhs[argu]); //ncols - if ( mrows != 1 || ncols != K ) mexErrMsgTxt("Input 'clusterRadii' must be a 1 x K matrix."); - - // r - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'r' must be a scalar."); - double r = (double) mxGetScalar(prhs[argu]); - if ( r <= 0.0) - mexErrMsgTxt("Input 'r' must be a positive number."); - - // epsilon - argu++; - if( !mxIsDouble(prhs[argu]) || mxIsComplex(prhs[argu]) || mxGetN(prhs[argu])*mxGetM(prhs[argu])!=1 ) - mexErrMsgTxt("Input 'epsilon' must be a scalar."); - double epsilon = (double) mxGetScalar(prhs[argu]); - if ( epsilon <= 0.0) - mexErrMsgTxt("Input 'epsilon' must be a positive number."); - - ////////////////////////////////////////////////////////////// - // Output arguments - ////////////////////////////////////////////////////////////// - - // g - plhs[0] = mxCreateDoubleMatrix(M,W,mxREAL); - double *g = mxGetPr(plhs[0]); - - // Function call - figtreeEvaluateIfgtTree( d, N, M, W, x, h, q, y, pMax, K, clusterIndex, clusterCenter, clusterRadii, r, epsilon, g ); - - - return; -} diff --git a/src/mex/mexFigtreeEvaluateIfgtTree.def b/src/mex/mexFigtreeEvaluateIfgtTree.def deleted file mode 100644 index 4d2d7a8..0000000 --- a/src/mex/mexFigtreeEvaluateIfgtTree.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY figtreeEvaluateIfgtTree.dll -EXPORTS mexFunction diff --git a/test/Makefile b/test/Makefile index ef1cb92..479c16f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -23,8 +23,8 @@ BINDIR = $(BASEDIR)/bin # make "FIGTREE_NO_ANN=true" # #----------------------------------------------------------------------------- -ANNLIBDIR = $(BASEDIR)/../ann_1.1.1/lib -ANNINCDIR = $(BASEDIR)/../ann_1.1.1/include +ANNLIBDIR = $(BASEDIR)/lib +ANNINCDIR = $(BASEDIR)/external/ann_1.1.1/include # uncomment this line to compile the library without ANN support #FIGTREE_NO_ANN=true @@ -40,7 +40,7 @@ LDFLAGS=-L$(LIBDIR) -lfigtree # (this is really necessary only if ANN and FIGTree are compiled as static libs, # but doesn't hurt in the other cases) ifneq ($(FIGTREE_NO_ANN),true) -LDFLAGS+= -L$(ANNLIBDIR) -lANN +LDFLAGS+= -L$(ANNLIBDIR) -lann_figtree_version endif SOURCES=test.cpp diff --git a/test/test.cpp b/test/test.cpp index 1371339..3926b2f 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -38,9 +38,9 @@ #ifdef WIN32 // Link to figtree.dll if WIN32. If not, then we assume that // libfigtree.so or libfigtree.a are linked to from the Makefile. - // The locations of figtree.dll and ANN.dll must either be in the PATH - // environment variable, or in the same location from which sample.exe is - // is executed. + // The locations of figtree.dll and ann_figtree_version.dll must either be + // in the PATH environment variable, or in the same location from which + // sample.exe is is executed. #pragma comment(lib,"../lib/figtree.lib") #endif @@ -127,72 +127,101 @@ int main() // target sample. The first M elements will correspond to the Gauss Transform computed // with the first set of weights, second M elements will correspond to the G.T. computed // with the second set of weights, etc. - double * g_sf = new double[W*M]; - double * g_sf_tree = new double[W*M]; - double * g_ifgt_u = new double[W*M]; - double * g_ifgt_tree_u = new double[W*M]; - double * g_ifgt_nu = new double[W*M]; - double * g_ifgt_tree_nu = new double[W*M]; + double * g_direct = new double[W*M]; + double * g_direct_tree = new double[W*M]; + double * g_ifgt = new double[W*M]; + double * g_ifgt_point = new double[W*M]; + double * g_ifgt_cluster = new double[W*M]; + double * g_ifgt_tree_point = new double[W*M]; + double * g_ifgt_tree_cluster = new double[W*M]; + double * g_ifgt_tree = new double[W*M]; + double * g_auto = new double[W*M]; // initialize all output arrays to zero - memset( g_sf , 0, sizeof(double)*W*M ); - memset( g_sf_tree , 0, sizeof(double)*W*M ); - memset( g_ifgt_u , 0, sizeof(double)*W*M ); - memset( g_ifgt_tree_u , 0, sizeof(double)*W*M ); - memset( g_ifgt_nu , 0, sizeof(double)*W*M ); - memset( g_ifgt_tree_nu, 0, sizeof(double)*W*M ); + memset( g_direct , 0, sizeof(double)*W*M ); + memset( g_direct_tree , 0, sizeof(double)*W*M ); + memset( g_ifgt , 0, sizeof(double)*W*M ); + memset( g_ifgt_point , 0, sizeof(double)*W*M ); + memset( g_ifgt_cluster , 0, sizeof(double)*W*M ); + memset( g_ifgt_tree , 0, sizeof(double)*W*M ); + memset( g_ifgt_tree_point , 0, sizeof(double)*W*M ); + memset( g_ifgt_tree_cluster , 0, sizeof(double)*W*M ); + memset( g_auto , 0, sizeof(double)*W*M ); // evaluate gauss transform using direct (slow) method - figtree( d, N, M, W, x, h, q, y, epsilon, g_sf, FIGTREE_EVAL_DIRECT ); + figtree( d, N, M, W, x, h, q, y, epsilon, g_direct , FIGTREE_EVAL_DIRECT ); // evaluate gauss transform using direct method with approximate nearest neighbors - figtree( d, N, M, W, x, h, q, y, epsilon, g_sf_tree, FIGTREE_EVAL_DIRECT_TREE ); + figtree( d, N, M, W, x, h, q, y, epsilon, g_direct_tree , FIGTREE_EVAL_DIRECT_TREE ); - // evaluate gauss transform using FIGTREE (truncated series), estimating parameters with and without - // the assumption that sources are uniformly distributed - figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_u, FIGTREE_EVAL_IFGT, FIGTREE_PARAM_UNIFORM, 1 ); - figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_nu, FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, 1 ); + // evaluate gauss transform using ifgt + figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt , FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_MAX , 1 ); + figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_point , FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_POINT , 1 ); + figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_cluster , FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_CLUSTER, 1 ); - // evaluate gauss transform using FIGTREE (truncated series), estimating parameters with and without - // the assumption that sources are uniformly distributed - figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree_u, FIGTREE_EVAL_IFGT_TREE, FIGTREE_PARAM_UNIFORM, 1 ); - figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree_nu, FIGTREE_EVAL_IFGT_TREE, FIGTREE_PARAM_NON_UNIFORM, 1 ); + // evaluate gauss transform using ifgt + tree + figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree , FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_MAX , 1 ); + figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree_point , FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_POINT , 1 ); + figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree_cluster , FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_CLUSTER, 1 ); + + // evaluate gauss transform using automatically picked method + figtree( d, N, M, W, x, h, q, y, epsilon, g_auto , FIGTREE_EVAL_AUTO, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_CLUSTER, 1 ); // compute absolute error of the Gauss Transform at each target and for all sets of weights. - double err_sf_tree = fabs(g_sf_tree[0] - g_sf[0])/Q[0]; - double err_ifgt_u = fabs(g_ifgt_u[0] - g_sf[0])/Q[0]; - double err_ifgt_nu = fabs(g_ifgt_nu[0] - g_sf[0])/Q[0]; - double err_ifgt_tree_u = fabs(g_ifgt_tree_u[0] - g_sf[0])/Q[0]; - double err_ifgt_tree_nu = fabs(g_ifgt_tree_nu[0] - g_sf[0])/Q[0]; + double err_direct_tree = fabs(g_direct_tree[0] - g_direct[0])/Q[0]; + double err_ifgt = fabs(g_ifgt[0] - g_direct[0])/Q[0]; + double err_ifgt_point = fabs(g_ifgt_point[0] - g_direct[0])/Q[0]; + double err_ifgt_cluster = fabs(g_ifgt_cluster[0] - g_direct[0])/Q[0]; + double err_ifgt_tree = fabs(g_ifgt_tree[0] - g_direct[0])/Q[0]; + double err_ifgt_tree_point = fabs(g_ifgt_tree_point[0] - g_direct[0])/Q[0]; + double err_ifgt_tree_cluster = fabs(g_ifgt_tree_cluster[0] - g_direct[0])/Q[0]; + double err_auto = fabs(g_auto[0] - g_direct[0])/Q[0]; for( int i = 0; i < W; i++) for( int j = 0; j < M; j++ ) { - err_sf_tree = MAX(err_sf_tree, fabs(g_sf_tree[i*M+j] -g_sf[i*M+j])/Q[i]); - err_ifgt_u = MAX(err_ifgt_u, fabs(g_ifgt_u[i*M+j] -g_sf[i*M+j])/Q[i]); - err_ifgt_nu = MAX(err_ifgt_nu, fabs(g_ifgt_nu[i*M+j] -g_sf[i*M+j])/Q[i]); - err_ifgt_tree_u = MAX(err_ifgt_tree_u, fabs(g_ifgt_tree_u[i*M+j] -g_sf[i*M+j])/Q[i]); - err_ifgt_tree_nu = MAX(err_ifgt_tree_nu, fabs(g_ifgt_tree_nu[i*M+j]-g_sf[i*M+j])/Q[i]); + err_direct_tree = MAX(err_direct_tree , fabs(g_direct_tree[i*M+j] - g_direct[i*M+j])/Q[i]); + err_ifgt = MAX(err_ifgt , fabs(g_ifgt[i*M+j] - g_direct[i*M+j])/Q[i]); + err_ifgt_point = MAX(err_ifgt_point , fabs(g_ifgt_point[i*M+j] - g_direct[i*M+j])/Q[i]); + err_ifgt_cluster = MAX(err_ifgt_cluster , fabs(g_ifgt_cluster[i*M+j] - g_direct[i*M+j])/Q[i]); + err_ifgt_tree = MAX(err_ifgt_tree , fabs(g_ifgt_tree[i*M+j] - g_direct[i*M+j])/Q[i]); + err_ifgt_tree_point = MAX(err_ifgt_tree_point , fabs(g_ifgt_tree_point[i*M+j] - g_direct[i*M+j])/Q[i]); + err_ifgt_tree_cluster = MAX(err_ifgt_tree_cluster , fabs(g_ifgt_tree_cluster[i*M+j] - g_direct[i*M+j])/Q[i]); + err_auto = MAX(err_auto , fabs(g_auto[i*M+j] - g_direct[i*M+j])/Q[i]); } // deallocate memory - delete [] g_sf; - delete [] g_sf_tree; - delete [] g_ifgt_u; - delete [] g_ifgt_nu; - delete [] g_ifgt_tree_u; - delete [] g_ifgt_tree_nu; + delete [] g_direct; + delete [] g_direct_tree; + delete [] g_ifgt; + delete [] g_ifgt_point; + delete [] g_ifgt_cluster; + delete [] g_ifgt_tree; + delete [] g_ifgt_tree_point; + delete [] g_ifgt_tree_cluster; + delete [] g_auto; // print out results for all six ways to evaluate printf("\n\n\n"); - printf("Errors( d=%i, h=%e ):\n sf-tree: %6.4e\n ifgt-u: %6.4e\n ifgt-nu: %6.4e\n ifgt_tree_u: %6.4e\n ifgt_tree_nu: %6.4e\n", - d, h, err_sf_tree, err_ifgt_u, err_ifgt_nu, err_ifgt_tree_u, err_ifgt_tree_nu ); - if( (err_sf_tree < epsilon) && - (err_ifgt_u < epsilon) && - (err_ifgt_nu < epsilon) && - (err_ifgt_tree_u < epsilon) && - (err_ifgt_tree_nu < epsilon) ) - { + printf("Errors( d=%i, h=%e ):\n" + " direct-tree: %6.4e\n" + " ifgt: %6.4e\n" + " ifgt-point: %6.4e\n" + " ifgt-cluster: %6.4e\n" + " ifgt_tree: %6.4e\n" + " ifgt_tree_point: %6.4e\n" + " ifgt_tree_cluster: %6.4e\n" + " auto: %6.4e\n\n", + d, h, err_direct_tree, err_ifgt, err_ifgt_point, err_ifgt_cluster, err_ifgt_tree, err_ifgt_tree_point, err_ifgt_tree_cluster, err_auto ); + if( (err_direct_tree < epsilon) && + (err_ifgt < epsilon) && + (err_ifgt_point < epsilon) && + (err_ifgt_cluster < epsilon) && + (err_ifgt_tree < epsilon) && + (err_ifgt_tree_point < epsilon) && + (err_ifgt_tree_cluster < epsilon) && + (err_auto < epsilon) ) + { printf("\n\n\nTest Passed.\n\n\n\n"); } else diff --git a/vs8/figtree.sln b/vs8/figtree.sln index ffffc17..11315ed 100644 --- a/vs8/figtree.sln +++ b/vs8/figtree.sln @@ -10,20 +10,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "figtree", "figtree.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtree", "mexFigtree.vcproj", "{3106F69E-7161-44A2-ABD7-63889E215DAD}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeChooseParametersNonUniform", "mexFigtreeChooseParametersNonUniform.vcproj", "{302D063B-DEE0-4244-BE99-206B8A1314AE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeChooseParametersUniform", "mexFigtreeChooseParametersUniform.vcproj", "{705DC44F-FCB7-4C2E-8A74-03D89619C3DC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeChooseTruncationNumber", "mexFigtreeChooseTruncationNumber.vcproj", "{3AEEF507-6FCC-47DB-8D2D-423858F977E6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeEvaluateDirect", "mexFigtreeEvaluateDirect.vcproj", "{60723094-EA37-4A5F-9E63-3EEE54564F6E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeEvaluateDirectTree", "mexFigtreeEvaluateDirectAnn.vcproj", "{0552D563-5EDA-4BA0-894B-F694BC9D93E3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeEvaluateIfgt", "mexFigtreeEvaluateTruncated.vcproj", "{B0C622D9-EFC1-4D70-A6D0-745B10B3CCC5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeEvaluateIfgtTree", "mexFigtreeEvaluateTruncatedAnn.vcproj", "{0C87BC6A-B6A9-4A9C-BE0D-E77A1933FD63}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeKCenterClustering", "mexFigtreeKCenterClustering.vcproj", "{DDBFFD46-9534-4B93-A240-6A4F4F4D6583}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{B35FF5AD-7996-447E-A1AA-911E0B743253}" @@ -31,6 +17,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{B35 {408082FC-005E-4574-959E-CBBDA44A703C} = {408082FC-005E-4574-959E-CBBDA44A703C} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ann_figtree_version", "..\external\ann_1.1.1\MS_Win32\dll\dll.vcproj", "{A7D00B21-CB9C-4BBB-8DEE-51025104F867}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mexFigtreeChooseEvaluationMethod", "mexFigtreeChooseEvaluationMethod.vcproj", "{520B337B-7966-4095-8556-621B93806522}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -49,34 +39,6 @@ Global {3106F69E-7161-44A2-ABD7-63889E215DAD}.Debug|Win32.Build.0 = Debug|Win32 {3106F69E-7161-44A2-ABD7-63889E215DAD}.Release|Win32.ActiveCfg = Release|Win32 {3106F69E-7161-44A2-ABD7-63889E215DAD}.Release|Win32.Build.0 = Release|Win32 - {302D063B-DEE0-4244-BE99-206B8A1314AE}.Debug|Win32.ActiveCfg = Debug|Win32 - {302D063B-DEE0-4244-BE99-206B8A1314AE}.Debug|Win32.Build.0 = Debug|Win32 - {302D063B-DEE0-4244-BE99-206B8A1314AE}.Release|Win32.ActiveCfg = Release|Win32 - {302D063B-DEE0-4244-BE99-206B8A1314AE}.Release|Win32.Build.0 = Release|Win32 - {705DC44F-FCB7-4C2E-8A74-03D89619C3DC}.Debug|Win32.ActiveCfg = Debug|Win32 - {705DC44F-FCB7-4C2E-8A74-03D89619C3DC}.Debug|Win32.Build.0 = Debug|Win32 - {705DC44F-FCB7-4C2E-8A74-03D89619C3DC}.Release|Win32.ActiveCfg = Release|Win32 - {705DC44F-FCB7-4C2E-8A74-03D89619C3DC}.Release|Win32.Build.0 = Release|Win32 - {3AEEF507-6FCC-47DB-8D2D-423858F977E6}.Debug|Win32.ActiveCfg = Debug|Win32 - {3AEEF507-6FCC-47DB-8D2D-423858F977E6}.Debug|Win32.Build.0 = Debug|Win32 - {3AEEF507-6FCC-47DB-8D2D-423858F977E6}.Release|Win32.ActiveCfg = Release|Win32 - {3AEEF507-6FCC-47DB-8D2D-423858F977E6}.Release|Win32.Build.0 = Release|Win32 - {60723094-EA37-4A5F-9E63-3EEE54564F6E}.Debug|Win32.ActiveCfg = Debug|Win32 - {60723094-EA37-4A5F-9E63-3EEE54564F6E}.Debug|Win32.Build.0 = Debug|Win32 - {60723094-EA37-4A5F-9E63-3EEE54564F6E}.Release|Win32.ActiveCfg = Release|Win32 - {60723094-EA37-4A5F-9E63-3EEE54564F6E}.Release|Win32.Build.0 = Release|Win32 - {0552D563-5EDA-4BA0-894B-F694BC9D93E3}.Debug|Win32.ActiveCfg = Debug|Win32 - {0552D563-5EDA-4BA0-894B-F694BC9D93E3}.Debug|Win32.Build.0 = Debug|Win32 - {0552D563-5EDA-4BA0-894B-F694BC9D93E3}.Release|Win32.ActiveCfg = Release|Win32 - {0552D563-5EDA-4BA0-894B-F694BC9D93E3}.Release|Win32.Build.0 = Release|Win32 - {B0C622D9-EFC1-4D70-A6D0-745B10B3CCC5}.Debug|Win32.ActiveCfg = Debug|Win32 - {B0C622D9-EFC1-4D70-A6D0-745B10B3CCC5}.Debug|Win32.Build.0 = Debug|Win32 - {B0C622D9-EFC1-4D70-A6D0-745B10B3CCC5}.Release|Win32.ActiveCfg = Release|Win32 - {B0C622D9-EFC1-4D70-A6D0-745B10B3CCC5}.Release|Win32.Build.0 = Release|Win32 - {0C87BC6A-B6A9-4A9C-BE0D-E77A1933FD63}.Debug|Win32.ActiveCfg = Debug|Win32 - {0C87BC6A-B6A9-4A9C-BE0D-E77A1933FD63}.Debug|Win32.Build.0 = Debug|Win32 - {0C87BC6A-B6A9-4A9C-BE0D-E77A1933FD63}.Release|Win32.ActiveCfg = Release|Win32 - {0C87BC6A-B6A9-4A9C-BE0D-E77A1933FD63}.Release|Win32.Build.0 = Release|Win32 {DDBFFD46-9534-4B93-A240-6A4F4F4D6583}.Debug|Win32.ActiveCfg = Debug|Win32 {DDBFFD46-9534-4B93-A240-6A4F4F4D6583}.Debug|Win32.Build.0 = Debug|Win32 {DDBFFD46-9534-4B93-A240-6A4F4F4D6583}.Release|Win32.ActiveCfg = Release|Win32 @@ -85,6 +47,14 @@ Global {B35FF5AD-7996-447E-A1AA-911E0B743253}.Debug|Win32.Build.0 = Debug|Win32 {B35FF5AD-7996-447E-A1AA-911E0B743253}.Release|Win32.ActiveCfg = Release|Win32 {B35FF5AD-7996-447E-A1AA-911E0B743253}.Release|Win32.Build.0 = Release|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Debug|Win32.ActiveCfg = Debug|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Debug|Win32.Build.0 = Debug|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Release|Win32.ActiveCfg = Release|Win32 + {A7D00B21-CB9C-4BBB-8DEE-51025104F867}.Release|Win32.Build.0 = Release|Win32 + {520B337B-7966-4095-8556-621B93806522}.Debug|Win32.ActiveCfg = Debug|Win32 + {520B337B-7966-4095-8556-621B93806522}.Debug|Win32.Build.0 = Debug|Win32 + {520B337B-7966-4095-8556-621B93806522}.Release|Win32.ActiveCfg = Release|Win32 + {520B337B-7966-4095-8556-621B93806522}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs8/figtree.vcproj b/vs8/figtree.vcproj index e9b9f61..369d89d 100644 --- a/vs8/figtree.vcproj +++ b/vs8/figtree.vcproj @@ -38,7 +38,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vs8/mexFigtreeChooseParametersUniform.vcproj b/vs8/mexFigtreeChooseEvaluationMethod.vcproj similarity index 53% rename from vs8/mexFigtreeChooseParametersUniform.vcproj rename to vs8/mexFigtreeChooseEvaluationMethod.vcproj index c6f3665..0f3a8ac 100644 --- a/vs8/mexFigtreeChooseParametersUniform.vcproj +++ b/vs8/mexFigtreeChooseEvaluationMethod.vcproj @@ -2,8 +2,8 @@ @@ -40,8 +40,8 @@ @@ -209,7 +209,7 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vs8/mexFigtreeChooseParametersNonUniform.vcproj b/vs8/mexFigtreeChooseParametersNonUniform.vcproj deleted file mode 100644 index 93d2e81..0000000 --- a/vs8/mexFigtreeChooseParametersNonUniform.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vs8/mexFigtreeChooseTruncationNumber.vcproj b/vs8/mexFigtreeChooseTruncationNumber.vcproj deleted file mode 100644 index 7443a6d..0000000 --- a/vs8/mexFigtreeChooseTruncationNumber.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vs8/mexFigtreeEvaluateDirect.vcproj b/vs8/mexFigtreeEvaluateDirect.vcproj deleted file mode 100644 index 1df3b7c..0000000 --- a/vs8/mexFigtreeEvaluateDirect.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vs8/mexFigtreeEvaluateDirectAnn.vcproj b/vs8/mexFigtreeEvaluateDirectAnn.vcproj deleted file mode 100644 index 995371b..0000000 --- a/vs8/mexFigtreeEvaluateDirectAnn.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vs8/mexFigtreeEvaluateTruncatedAnn.vcproj b/vs8/mexFigtreeEvaluateTruncatedAnn.vcproj deleted file mode 100644 index 296a9ec..0000000 --- a/vs8/mexFigtreeEvaluateTruncatedAnn.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vs8/mexFigtreeKCenterClustering.vcproj b/vs8/mexFigtreeKCenterClustering.vcproj index 995aa35..9424b6b 100644 --- a/vs8/mexFigtreeKCenterClustering.vcproj +++ b/vs8/mexFigtreeKCenterClustering.vcproj @@ -40,8 +40,8 @@