[mlpack-svn] r14993 - in mlpack/branches/mlpack-1.x: . CMake doc/tutorials doc/tutorials/det doc/tutorials/emst doc/tutorials/linear_regression doc/tutorials/neighbor_search doc/tutorials/range_search src/mlpack src/mlpack/core/arma_extend src/mlpack/core/data src/mlpack/core/dists src/mlpack/core/kernels src/mlpack/core/math src/mlpack/core/metrics src/mlpack/core/tree src/mlpack/core/tree/binary_space_tree src/mlpack/core/tree/cover_tree src/mlpack/core/util src/mlpack/methods src/mlpack/methods/det src/mlpack/methods/emst src/mlpack/methods/fastmks src/mlpack/methods/gmm src/mlpack/methods/hmm src/mlpack/methods/kernel_pca src/mlpack/methods/kmeans src/mlpack/methods/lars src/mlpack/methods/local_coordinate_coding src/mlpack/methods/neighbor_search src/mlpack/methods/neighbor_search/sort_policies src/mlpack/methods/nmf src/mlpack/methods/sparse_coding src/mlpack/tests src/mlpack/tests/data

fastlab-svn at coffeetalk-1.cc.gatech.edu fastlab-svn at coffeetalk-1.cc.gatech.edu
Wed May 1 22:38:12 EDT 2013


Author: rcurtin
Date: 2013-05-01 22:38:08 -0400 (Wed, 01 May 2013)
New Revision: 14993

Added:
   mlpack/branches/mlpack-1.x/CMake/FindArmadillo.cmake
   mlpack/branches/mlpack-1.x/CMake/FindPackageHandleStandardArgs.cmake
   mlpack/branches/mlpack-1.x/README.txt
   mlpack/branches/mlpack-1.x/doc/tutorials/fastmks/
   mlpack/branches/mlpack-1.x/doc/tutorials/kmeans/
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/traits.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/traits.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/tree_traits.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/CMakeLists.txt
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_stat.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/rann/
   mlpack/branches/mlpack-1.x/src/mlpack/tests/allkrann_search_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_q_3_100.csv
   mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_qr_ranks.csv
   mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_r_3_900.csv
   mlpack/branches/mlpack-1.x/src/mlpack/tests/fastmks_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/lsh_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_traits_test.cpp
Modified:
   mlpack/branches/mlpack-1.x/
   mlpack/branches/mlpack-1.x/doc/tutorials/det/det.txt
   mlpack/branches/mlpack-1.x/doc/tutorials/emst/emst.txt
   mlpack/branches/mlpack-1.x/doc/tutorials/linear_regression/linear_regression.txt
   mlpack/branches/mlpack-1.x/doc/tutorials/neighbor_search/neighbor_search.txt
   mlpack/branches/mlpack-1.x/doc/tutorials/range_search/range_search.txt
   mlpack/branches/mlpack-1.x/doc/tutorials/tutorials.txt
   mlpack/branches/mlpack-1.x/src/mlpack/core.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/arma_extend/
   mlpack/branches/mlpack-1.x/src/mlpack/core/arma_extend/hdf5_misc.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/data/
   mlpack/branches/mlpack-1.x/src/mlpack/core/data/load_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/data/save_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/dists/
   mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/dists/gaussian_distribution.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/kernels/polynomial_kernel.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/math/
   mlpack/branches/mlpack-1.x/src/mlpack/core/math/random.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/metrics/lmetric.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/CMakeLists.txt
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/tree/statistic.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/util/
   mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/CMakeLists.txt
   mlpack/branches/mlpack-1.x/src/mlpack/methods/det/dt_utils.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/edge_pair.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/
   mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_train_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/CMakeLists.txt
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/random_partition.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/CMakeLists.txt
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allkfn_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allknn_main.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/furthest_neighbor_sort.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/nearest_neighbor_sort.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/typedef.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/nmf.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/random_init.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/CMakeLists.txt
   mlpack/branches/mlpack-1.x/src/mlpack/tests/allkfn_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/allknn_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/gmm_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/hmm_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/kernel_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/kmeans_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/nmf_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/sort_policy_test.cpp
   mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_test.cpp
Log:
Pull trunk in before 1.0.5 release.  Still a decent amount to do.



Property changes on: mlpack/branches/mlpack-1.x
___________________________________________________________________
Added: svn:mergeinfo
   + /mlpack/trunk:13978-14992

Copied: mlpack/branches/mlpack-1.x/CMake/FindArmadillo.cmake (from rev 14992, mlpack/trunk/CMake/FindArmadillo.cmake)
===================================================================
--- mlpack/branches/mlpack-1.x/CMake/FindArmadillo.cmake	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/CMake/FindArmadillo.cmake	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,113 @@
+# - Find Armadillo
+# Find the Armadillo C++ library
+#
+# Using Armadillo:
+#  find_package(Armadillo REQUIRED)
+#  include_directories(${ARMADILLO_INCLUDE_DIRS})
+#  add_executable(foo foo.cc)
+#  target_link_libraries(foo ${ARMADILLO_LIBRARIES})
+# This module sets the following variables:
+#  ARMADILLO_FOUND - set to true if the library is found
+#  ARMADILLO_INCLUDE_DIRS - list of required include directories
+#  ARMADILLO_LIBRARIES - list of libraries to be linked
+#  ARMADILLO_VERSION_MAJOR - major version number
+#  ARMADILLO_VERSION_MINOR - minor version number
+#  ARMADILLO_VERSION_PATCH - patch version number
+#  ARMADILLO_VERSION_STRING - version number as a string (ex: "1.0.4")
+#  ARMADILLO_VERSION_NAME - name of the version (ex: "Antipodean Antileech")
+
+#=============================================================================
+# Copyright 2011 Clement Creusot <creusot at cs.york.ac.uk>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+
+# UNIX paths are standard, no need to write.
+find_library(ARMADILLO_LIBRARY
+  NAMES armadillo
+  PATHS "$ENV{ProgramFiles}/Armadillo/lib"  "$ENV{ProgramFiles}/Armadillo/lib64" "$ENV{ProgramFiles}/Armadillo"
+  )
+find_path(ARMADILLO_INCLUDE_DIR
+  NAMES armadillo
+  PATHS "$ENV{ProgramFiles}/Armadillo/include"
+  )
+
+
+if(ARMADILLO_INCLUDE_DIR)
+
+  # ------------------------------------------------------------------------
+  #  Extract version information from <armadillo>
+  # ------------------------------------------------------------------------
+
+  # WARNING: Early releases of Armadillo didn't have the arma_version.hpp file.
+  # (e.g. v.0.9.8-1 in ubuntu maverick packages (2001-03-15))
+  # If the file is missing, set all values to 0
+  set(ARMADILLO_VERSION_MAJOR 0)
+  set(ARMADILLO_VERSION_MINOR 0)
+  set(ARMADILLO_VERSION_PATCH 0)
+  set(ARMADILLO_VERSION_NAME "EARLY RELEASE")
+
+  if(EXISTS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/arma_version.hpp")
+
+    # Read and parse armdillo version header file for version number
+    file(READ "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/arma_version.hpp" _armadillo_HEADER_CONTENTS)
+    string(REGEX REPLACE ".*#define ARMA_VERSION_MAJOR ([0-9]+).*" "\\1" ARMADILLO_VERSION_MAJOR "${_armadillo_HEADER_CONTENTS}")
+    string(REGEX REPLACE ".*#define ARMA_VERSION_MINOR ([0-9]+).*" "\\1" ARMADILLO_VERSION_MINOR "${_armadillo_HEADER_CONTENTS}")
+    string(REGEX REPLACE ".*#define ARMA_VERSION_PATCH ([0-9]+).*" "\\1" ARMADILLO_VERSION_PATCH "${_armadillo_HEADER_CONTENTS}")
+
+    # WARNING: The number of spaces before the version name is not one.
+    string(REGEX REPLACE ".*#define ARMA_VERSION_NAME\ +\"([0-9a-zA-Z\ _-]+)\".*" "\\1" ARMADILLO_VERSION_NAME "${_armadillo_HEADER_CONTENTS}")
+
+  endif(EXISTS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/arma_version.hpp")
+
+  set(ARMADILLO_VERSION_STRING "${ARMADILLO_VERSION_MAJOR}.${ARMADILLO_VERSION_MINOR}.${ARMADILLO_VERSION_PATCH}")
+endif (ARMADILLO_INCLUDE_DIR)
+
+
+#======================
+
+# Determine whether or not we need to link against HDF5.  We need to look in
+# config.hpp.
+if(EXISTS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp")
+  # Look for #define ARMA_USE_HDF5.
+  file(READ "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp" _armadillo_CONFIG_CONTENTS)
+  string(REGEX MATCH "[\r\n][\t ]*#define[ \t]+ARMA_USE_HDF5[ \t\r\n]" ARMA_USE_HDF5 "${_armadillo_CONFIG_CONTENTS}")
+
+  if(NOT "${ARMA_USE_HDF5}" STREQUAL "")
+    message(STATUS "Armadillo HDF5 support is enabled.")
+    # We have HDF5 support and need to link against HDF5.
+    find_package(HDF5 REQUIRED)
+  endif(NOT "${ARMA_USE_HDF5}" STREQUAL "")
+endif(EXISTS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp")
+
+#======================
+
+
+# Checks 'REQUIRED', 'QUIET' and versions.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Armadillo
+  REQUIRED_VARS ARMADILLO_LIBRARY ARMADILLO_INCLUDE_DIR
+  VERSION_VAR ARMADILLO_VERSION_STRING)
+# version_var fails with cmake < 2.8.4.
+
+if (ARMADILLO_FOUND)
+  set(ARMADILLO_INCLUDE_DIRS ${ARMADILLO_INCLUDE_DIR})
+  # HDF5 libraries are stored in HDF5_LIBRARIES, if they were necessary.
+  set(ARMADILLO_LIBRARIES ${ARMADILLO_LIBRARY} ${HDF5_LIBRARIES})
+endif (ARMADILLO_FOUND)
+
+
+# Hide internal variables
+mark_as_advanced(
+  ARMADILLO_INCLUDE_DIR
+  ARMADILLO_LIBRARY)
+
+#======================

Copied: mlpack/branches/mlpack-1.x/CMake/FindPackageHandleStandardArgs.cmake (from rev 14992, mlpack/trunk/CMake/FindPackageHandleStandardArgs.cmake)
===================================================================
--- mlpack/branches/mlpack-1.x/CMake/FindPackageHandleStandardArgs.cmake	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/CMake/FindPackageHandleStandardArgs.cmake	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,296 @@
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ... )
+#
+# This function is intended to be used in FindXXX.cmake modules files.
+# It handles the REQUIRED, QUIET and version-related arguments to FIND_PACKAGE().
+# It also sets the <UPPERCASED_NAME>_FOUND variable.
+# The package is considered found if all variables <var1>... listed contain
+# valid results, e.g. valid filepaths.
+#
+# There are two modes of this function. The first argument in both modes is
+# the name of the Find-module where it is called (in original casing).
+#
+# The first simple mode looks like this:
+#    FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> (DEFAULT_MSG|"Custom failure message") <var1>...<varN> )
+# If the variables <var1> to <varN> are all valid, then <UPPERCASED_NAME>_FOUND
+# will be set to TRUE.
+# If DEFAULT_MSG is given as second argument, then the function will generate
+# itself useful success and error messages. You can also supply a custom error message
+# for the failure case. This is not recommended.
+#
+# The second mode is more powerful and also supports version checking:
+#    FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS <var1>...<varN>]
+#                                           [VERSION_VAR   <versionvar>]
+#                                           [HANDLE_COMPONENTS]
+#                                           [CONFIG_MODE]
+#                                           [FAIL_MESSAGE "Custom failure message"] )
+#
+# As above, if <var1> through <varN> are all valid, <UPPERCASED_NAME>_FOUND
+# will be set to TRUE.
+# After REQUIRED_VARS the variables which are required for this package are listed.
+# Following VERSION_VAR the name of the variable can be specified which holds
+# the version of the package which has been found. If this is done, this version
+# will be checked against the (potentially) specified required version used
+# in the find_package() call. The EXACT keyword is also handled. The default
+# messages include information about the required version and the version
+# which has been actually found, both if the version is ok or not.
+# If the package supports components, use the HANDLE_COMPONENTS option to enable
+# handling them. In this case, find_package_handle_standard_args() will report
+# which components have been found and which are missing, and the <NAME>_FOUND
+# variable will be set to FALSE if any of the required components (i.e. not the
+# ones listed after OPTIONAL_COMPONENTS) are missing.
+# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for
+# a find_package(... NO_MODULE) call.  In this case VERSION_VAR will be set
+# to <NAME>_VERSION and the macro will automatically check whether the
+# Config module was found.
+# Via FAIL_MESSAGE a custom failure message can be specified, if this is not
+# used, the default message will be displayed.
+#
+# Example for mode 1:
+#
+#    FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2  DEFAULT_MSG  LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
+#
+# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
+# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE.
+# If it is not found and REQUIRED was used, it fails with FATAL_ERROR,
+# independent whether QUIET was used or not.
+# If it is found, success will be reported, including the content of <var1>.
+# On repeated Cmake runs, the same message won't be printed again.
+#
+# Example for mode 2:
+#
+#    FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON  REQUIRED_VARS BISON_EXECUTABLE
+#                                             VERSION_VAR BISON_VERSION)
+# In this case, BISON is considered to be found if the variable(s) listed
+# after REQUIRED_VAR are all valid, i.e. BISON_EXECUTABLE in this case.
+# Also the version of BISON will be checked by using the version contained
+# in BISON_VERSION.
+# Since no FAIL_MESSAGE is given, the default messages will be printed.
+#
+# Another example for mode 2:
+#
+#    FIND_PACKAGE(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
+#    FIND_PACKAGE_HANDLE_STANDARD_ARGS(Automoc4  CONFIG_MODE)
+# In this case, FindAutmoc4.cmake wraps a call to FIND_PACKAGE(Automoc4 NO_MODULE)
+# and adds an additional search directory for automoc4.
+# The following FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
+# success/error message.
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+INCLUDE(FindPackageMessage)
+INCLUDE(CMakeParseArguments)
+
+# internal helper macro
+MACRO(_FPHSA_FAILURE_MESSAGE _msg)
+  IF (${_NAME}_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "${_msg}")
+  ELSE (${_NAME}_FIND_REQUIRED)
+    IF (NOT ${_NAME}_FIND_QUIETLY)
+      MESSAGE(STATUS "${_msg}")
+    ENDIF (NOT ${_NAME}_FIND_QUIETLY)
+  ENDIF (${_NAME}_FIND_REQUIRED)
+ENDMACRO(_FPHSA_FAILURE_MESSAGE _msg)
+
+
+# internal helper macro to generate the failure message when used in CONFIG_MODE:
+MACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
+  # <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
+  IF(${_NAME}_CONFIG)
+    _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
+  ELSE(${_NAME}_CONFIG)
+    # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
+    # List them all in the error message:
+    IF(${_NAME}_CONSIDERED_CONFIGS)
+      SET(configsText "")
+      LIST(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
+      MATH(EXPR configsCount "${configsCount} - 1")
+      FOREACH(currentConfigIndex RANGE ${configsCount})
+        LIST(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
+        LIST(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
+        SET(configsText "${configsText}    ${filename} (version ${version})\n")
+      ENDFOREACH(currentConfigIndex)
+      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
+
+    ELSE(${_NAME}_CONSIDERED_CONFIGS)
+      # Simple case: No Config-file was found at all:
+      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
+    ENDIF(${_NAME}_CONSIDERED_CONFIGS)
+  ENDIF(${_NAME}_CONFIG)
+ENDMACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
+
+
+FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
+
+# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
+# new extended or in the "old" mode:
+  SET(options CONFIG_MODE HANDLE_COMPONENTS)
+  SET(oneValueArgs FAIL_MESSAGE VERSION_VAR)
+  SET(multiValueArgs REQUIRED_VARS)
+  SET(_KEYWORDS_FOR_EXTENDED_MODE  ${options} ${oneValueArgs} ${multiValueArgs} )
+  LIST(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
+
+  IF(${INDEX} EQUAL -1)
+    SET(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
+    SET(FPHSA_REQUIRED_VARS ${ARGN})
+    SET(FPHSA_VERSION_VAR)
+  ELSE(${INDEX} EQUAL -1)
+
+    CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${_FIRST_ARG} ${ARGN})
+
+    IF(FPHSA_UNPARSED_ARGUMENTS)
+      MESSAGE(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
+    ENDIF(FPHSA_UNPARSED_ARGUMENTS)
+
+    IF(NOT FPHSA_FAIL_MESSAGE)
+      SET(FPHSA_FAIL_MESSAGE  "DEFAULT_MSG")
+    ENDIF(NOT FPHSA_FAIL_MESSAGE)
+  ENDIF(${INDEX} EQUAL -1)
+
+# now that we collected all arguments, process them
+
+  IF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
+    SET(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
+  ENDIF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
+
+  # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
+  # when it successfully found the config-file, including version checking:
+  IF(FPHSA_CONFIG_MODE)
+    LIST(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
+    LIST(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
+    SET(FPHSA_VERSION_VAR ${_NAME}_VERSION)
+  ENDIF(FPHSA_CONFIG_MODE)
+
+  IF(NOT FPHSA_REQUIRED_VARS)
+    MESSAGE(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
+  ENDIF(NOT FPHSA_REQUIRED_VARS)
+
+  LIST(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
+
+  STRING(TOUPPER ${_NAME} _NAME_UPPER)
+  STRING(TOLOWER ${_NAME} _NAME_LOWER)
+
+  # collect all variables which were not found, so they can be printed, so the
+  # user knows better what went wrong (#6375)
+  SET(MISSING_VARS "")
+  SET(DETAILS "")
+  SET(${_NAME_UPPER}_FOUND TRUE)
+  # check if all passed variables are valid
+  FOREACH(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
+    IF(NOT ${_CURRENT_VAR})
+      SET(${_NAME_UPPER}_FOUND FALSE)
+      SET(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
+    ELSE(NOT ${_CURRENT_VAR})
+      SET(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
+    ENDIF(NOT ${_CURRENT_VAR})
+  ENDFOREACH(_CURRENT_VAR)
+
+  # component handling
+  UNSET(FOUND_COMPONENTS_MSG)
+  UNSET(MISSING_COMPONENTS_MSG)
+
+  IF(FPHSA_HANDLE_COMPONENTS)
+    FOREACH(comp ${${_NAME}_FIND_COMPONENTS})
+      IF(${_NAME}_${comp}_FOUND)
+
+        IF(NOT DEFINED FOUND_COMPONENTS_MSG)
+          SET(FOUND_COMPONENTS_MSG "found components: ")
+        ENDIF()
+        SET(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
+
+      ELSE()
+
+        IF(NOT DEFINED MISSING_COMPONENTS_MSG)
+          SET(MISSING_COMPONENTS_MSG "missing components: ")
+        ENDIF()
+        SET(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
+
+        IF(${_NAME}_FIND_REQUIRED_${comp})
+          SET(${_NAME_UPPER}_FOUND FALSE)
+          SET(MISSING_VARS "${MISSING_VARS} ${comp}")
+        ENDIF()
+
+      ENDIF()
+    ENDFOREACH(comp)
+    SET(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
+    SET(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
+  ENDIF(FPHSA_HANDLE_COMPONENTS)
+
+  # version handling:
+  SET(VERSION_MSG "")
+  SET(VERSION_OK TRUE)
+  SET(VERSION ${${FPHSA_VERSION_VAR}} )
+  IF (${_NAME}_FIND_VERSION)
+
+    IF(VERSION)
+
+      IF(${_NAME}_FIND_VERSION_EXACT)       # exact version required
+        IF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
+          SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+          SET(VERSION_OK FALSE)
+        ELSE (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
+          SET(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+        ENDIF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
+
+      ELSE(${_NAME}_FIND_VERSION_EXACT)     # minimum version specified:
+        IF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
+          SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
+          SET(VERSION_OK FALSE)
+        ELSE ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
+          SET(VERSION_MSG "(found suitable version \"${VERSION}\", required is \"${${_NAME}_FIND_VERSION}\")")
+        ENDIF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
+      ENDIF(${_NAME}_FIND_VERSION_EXACT)
+
+    ELSE(VERSION)
+
+      # if the package was not found, but a version was given, add that to the output:
+      IF(${_NAME}_FIND_VERSION_EXACT)
+         SET(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
+      ELSE(${_NAME}_FIND_VERSION_EXACT)
+         SET(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
+      ENDIF(${_NAME}_FIND_VERSION_EXACT)
+
+    ENDIF(VERSION)
+  ELSE (${_NAME}_FIND_VERSION)
+    IF(VERSION)
+      SET(VERSION_MSG "(found version \"${VERSION}\")")
+    ENDIF(VERSION)
+  ENDIF (${_NAME}_FIND_VERSION)
+
+  IF(VERSION_OK)
+    SET(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
+  ELSE(VERSION_OK)
+    SET(${_NAME_UPPER}_FOUND FALSE)
+  ENDIF(VERSION_OK)
+
+
+  # print the result:
+  IF (${_NAME_UPPER}_FOUND)
+    FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
+  ELSE (${_NAME_UPPER}_FOUND)
+
+    IF(FPHSA_CONFIG_MODE)
+      _FPHSA_HANDLE_FAILURE_CONFIG_MODE()
+    ELSE(FPHSA_CONFIG_MODE)
+      IF(NOT VERSION_OK)
+        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
+      ELSE(NOT VERSION_OK)
+        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
+      ENDIF(NOT VERSION_OK)
+    ENDIF(FPHSA_CONFIG_MODE)
+
+  ENDIF (${_NAME_UPPER}_FOUND)
+
+  SET(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE)
+
+ENDFUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _FIRST_ARG)

Copied: mlpack/branches/mlpack-1.x/README.txt (from rev 14992, mlpack/trunk/README.txt)
===================================================================
--- mlpack/branches/mlpack-1.x/README.txt	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/README.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,214 @@
+================================================================================
+
+           mlpack: open-source scalable c++ machine learning library
+
+================================================================================
+
+0. Contents
+
+  1. Introduction
+  2. Citation details
+  3. Dependencies
+  4. Building mlpack from source
+  5. Running mlpack programs
+  6. Further documentation
+  7. Bug reporting
+
+================================================================================
+
+1. Introduction
+
+mlpack is an intuitive, fast, scalable C++ machine learning library, meant to be
+a machine learning analog to LAPACK. It aims to implement a wide array of
+machine learning methods and function as a "swiss army knife" for machine
+learning researchers.
+
+The mlpack website can be found at http://mlpack.org and contains numerous
+tutorials and extensive documentation.  This README serves as a guide for what
+mlpack is, how to install it, how to run it, and where to find more
+documentation.  The website should be consulted for further information:
+
+  http://www.mlpack.org/
+
+  http://www.mlpack.org/tutorial.html  <-- tutorials
+  http://www.mlpack.org/trac/          <-- development site (Trac)
+  http://www.mlpack.org/doxygen.php    <-- API documentation
+
+================================================================================
+
+2. Citation details
+
+If you use mlpack in your research or software, please cite mlpack using the
+citation below (given in BiBTeX format):
+
+ at INPROCEEDINGS{mlpack2011,
+  author    = {Ryan R. Curtin and James R. Cline and Neil P. Slagle and Matthew
+      L. Amidon and Alexander G. Gray},
+  title     = {{MLPACK: A Scalable C++ Machine Learning Library}},
+  booktitle = {{BigLearning: Algorithms, Systems, and Tools for Learning at
+      Scale}},
+  year      = 2011
+}
+
+Citations are beneficial for the growth and improvement of mlpack.
+
+================================================================================
+
+3. Dependencies
+
+mlpack has the following dependencies:
+
+  Armadillo     >= 2.4.4
+  LibXml2       >= 2.6.0
+  Boost (program_options, math_c99, unit_test_framework, random)
+  CMake         >= 2.8.5
+
+All of those should be available in your distribution's package manager.  If
+not, you will have to compile each of them by hand.  See the documentation for
+each of those packages for more information.
+
+If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled.
+
+================================================================================
+
+4. Building mlpack from source
+   (see also http://www.mlpack.org/doxygen.php?doc=build.html )
+
+mlpack uses CMake as a build system and allows several flexible build
+configuration options. One can consult any of numerous CMake tutorials for
+further documentation, but this tutorial should be enough to get mlpack built
+and installed.
+
+First, unpack the mlpack source and change into the unpacked directory.  Here we
+use mlpack-x.y.z where x.y.z is the version.
+
+$ tar -xzf mlpack-x.y.z.tar.gz
+$ cd mlpack-x.y.z
+
+Then, make a build directory.  The directory can have any name, not just
+'build', but 'build' is sufficient.
+
+$ mkdir build
+$ cd build
+
+The next step is to run CMake to configure the project.  Running CMake is the
+equivalent to running `./configure` with autotools. If you run CMake with no
+options, it will configure the project to build with no debugging symbols and no
+profiling information:
+
+$ cmake ../
+
+You can specify options to compile with debugging information and profiling
+information:
+
+$ cmake -D DEBUG=ON -D PROFILE=ON ../
+
+Options are specified with the -D flag.  A list of options allowed:
+
+  DEBUG=(ON/OFF): compile with debugging symbols
+  PROFILE=(ON/OFF): compile with profiling symbols
+  ARMA_EXTRA_DEBUG=(ON/OFF): compile with extra Armadillo debugging symbols
+  BOOST_ROOT=(/path/to/boost/): path to root of boost installation
+  ARMADILLO_INCLUDE_DIR=(/path/to/armadillo/include/): path to Armadillo headers
+  ARMADILLO_LIBRARY=(/path/to/armadillo/libarmadillo.so): Armadillo library
+
+Other tools can also be used to configure CMake, but those are not documented
+here.
+
+Once CMake is configured, building the library is as simple as typing 'make'.
+This will build all library components as well as 'mlpack_test'.
+
+$ make
+
+You can specify individual components which you want to build, if you do not
+want to build everything in the library:
+
+$ make pca allknn allkfn
+
+If the build fails and you cannot figure out why, register an account on Trac
+and submit a ticket and the mlpack developers will quickly help you figure it
+out:
+
+http://mlpack.org/trac/
+
+Alternately, mlpack help can be found in IRC at #mlpack on irc.freenode.net.
+
+If you wish to install mlpack to /usr/include/mlpack/ and /usr/lib/ and
+/usr/bin/, once it has built, make sure you have root privileges (or write
+permissions to those two directories), and simply type
+
+# make install
+
+You can now run the executables by name; you can link against mlpack with
+-lmlpack, and the mlpack headers are found in /usr/include/mlpack/.
+
+================================================================================
+
+5. Running mlpack programs
+
+After building mlpack, the executables will reside in build/bin/.  You can call
+them from there, or you can install the library and (depending on system
+settings) they should be added to your PATH and you can call them directly.  The
+documentation below assumes the executables are in your PATH.
+
+We consider the 'allknn' program, which finds the k nearest neighbors in a
+reference dataset of all the points in a query set.  That is, we have a query
+and a reference dataset. For each point in the query dataset, we wish to know
+the k points in the reference dataset which are closest to the given query
+point.
+
+Alternately, if the query and reference datasets are the same, the problem can
+be stated more simply: for each point in the dataset, we wish to know the k
+nearest points to that point.
+
+Each mlpack program has extensive help documentation which details what the
+method does, what each of the parameters are, and how to use them:
+
+$ allknn --help
+
+Running allknn on one dataset (that is, the query and reference datasets are the
+same) and finding the 5 nearest neighbors is very simple:
+
+$ allknn -r dataset.csv -n neighbors_out.csv -d distances_out.csv -k 5 -v
+
+The -v (--verbose) flag is optional; it gives informational output.  It is not
+unique to allknn but is available in all mlpack programs.  Verbose output also
+gives timing output at the end of the program, which can be very useful.
+
+================================================================================
+
+6. Further documentation
+
+The documentation given here is only a fraction of the available documentation
+for mlpack.  If doxygen is installed, you can type 'make doc' to build the
+documentation locally.  Alternately, up-to-date documentation is available for
+older versions of mlpack:
+
+  http://www.mlpack.org/tutorial.html   <-- tutorials for mlpack
+  http://www.mlpack.org/doxygen.php     <-- API documentation for mlpack
+  http://www.mlpack.org/trac/           <-- development site for mlpack (Trac)
+
+================================================================================
+
+7. Bug reporting
+   (see also http://www.mlpack.org/help.html )
+
+If you find a bug in mlpack or have any problems, numerous routes are available
+for help.
+
+Trac is used for bug tracking, and can be found at http://www.mlpack.org/trac/.
+It is easy to register an account and file a bug there, and the mlpack
+development team will try to quickly resolve your issue.
+
+In addition, mailing lists are available.  The mlpack discussion list is
+available at
+
+  https://lists.cc.gatech.edu/mailman/listinfo/mlpack
+
+and the subversion commit list is available at
+
+  https://lists.cc.gatech.edu/mailman/listinfo/mlpack-svn
+
+Lastly, the IRC channel #mlpack on Freenode can be used to get help.
+
+================================================================================

Modified: mlpack/branches/mlpack-1.x/doc/tutorials/det/det.txt
===================================================================
--- mlpack/branches/mlpack-1.x/doc/tutorials/det/det.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/doc/tutorials/det/det.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -9,13 +9,17 @@
 @section intro_det_tut Introduction
 
 DETs perform the unsupervised task of density estimation using decision trees.
+Using a trained density estimation tree (DET), the density at any particular
+point can be estimated very quickly (O(log n) time, where n is the number of
+points the tree is built on).
 
 The details of this work is presented in the following paper:
 @code
 @inproceedings{ram2011density,
   title={Density estimation trees},
   author={Ram, P. and Gray, A.G.},
-  booktitle={Proceedings of the 17th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining},
+  booktitle={Proceedings of the 17th ACM SIGKDD International Conference on
+      Knowledge Discovery and Data Mining},
   pages={627--635},
   year={2011},
   organization={ACM}
@@ -36,7 +40,6 @@
  - \ref toc_det_tut
  - \ref cli_det_tut
    - \ref cli_ex1_de_tut
-   - \ref cli_alt_reg_tut
    - \ref cli_ex2_de_test_tut
    - \ref cli_ex3_de_p_tut
    - \ref cli_ex4_de_vi_tut
@@ -47,90 +50,81 @@
    - \ref dtutils_util_funcs
  - \ref further_doc_det_tut
 
- at section cli_det_tut Command-Line 'dt_main'
+ at section cli_det_tut Command-Line 'det'
 The command line arguments of this program can be viewed using the '-h' option:
 
 @code
-$ ./dt_main -h
+$ det -h
+Density Estimation With Density Estimation Trees
 
-Density estimation with DET
+  This program performs a number of functions related to Density Estimation
+  Trees.  The optimal Density Estimation Tree (DET) can be trained on a set of
+  data (specified by --train_file) using cross-validation (with number of folds
+  specified by --folds).  In addition, the density of a set of test points
+  (specified by --test_file) can be estimated, and the importance of each
+  dimension can be computed.  If class labels are given for the training points
+  (with --labels_file), the class memberships of each leaf in the DET can be
+  calculated.
 
-  This program provides an example use of the Density Estimation Tree for
-  density estimation. For more details, please look at the paper titled 'Density
-  Estimation Trees'.
+  The created DET can be saved to a file, along with the density estimates for
+  the test set and the variable importances.
 
 Required options:
 
-  --input/training_set (-S) [string]
-                                The data set on which to perform density
-                                estimation.
+  --train_file (-t) [string]    The data set on which to build a density
+                                estimation tree.
 
 Options:
 
-  --DET/max_leaf_size (-M) [int]
-                                The maximum size of a leaf in the unpruned fully
-                                grown DET.  Default value 10.
-  --DET/min_leaf_size (-N) [int]
-                                The minimum size of a leaf in the unpruned fully
-                                grown DET.  Default value 5.
-  --DET/use_volume_reg (-R)     This flag gives the used the option to use a
-                                form of regularization similar to the usual
-                                alpha-pruning in decision tree. But instead of
-                                regularizing on the number of leaves, you
-                                regularize on the sum of the inverse of the
-                                volume of the leaves (meaning you penalize  low
-                                volume leaves.
-  --flag/print_tree (-P)        If you just wish to print the tree out on the
-                                command line.
-  --flag/print_vi (-I)          If you just wish to print the variable
-                                importance of each feature out on the command
-                                line.
+  --folds (-f) [int]            The number of folds of cross-validation to
+                                perform for the estimation (0 is LOOCV)  Default
+                                value 10.
   --help (-h)                   Default help info.
   --info [string]               Get help on a specific module or option.
                                 Default value ''.
-  --input/labels (-L) [string]  The labels for the given training data to
+  --labels_file (-l) [string]   The labels for the given training data to
                                 generate the class membership of each leaf (as
                                 an extra statistic)  Default value ''.
-  --input/test_set (-T) [string]
-                                An extra set of test points on which to estimate
-                                the density given the estimator.  Default value
-                                ''.
-  --output/leaf_class_table (-l) [string]
+  --leaf_class_table_file (-L) [string]
                                 The file in which to output the leaf class
                                 membership table.  Default value
                                 'leaf_class_membership.txt'.
-  --output/test_set_estimates (-t) [string]
+  --max_leaf_size (-M) [int]    The maximum size of a leaf in the unpruned,
+                                fully grown DET.  Default value 10.
+  --min_leaf_size (-N) [int]    The minimum size of a leaf in the unpruned,
+                                fully grown DET.  Default value 5.
+  --print_tree (-p)             Print the tree out on the command line (or in
+                                the file specified with --tree_file).
+  --print_vi (-I)               Print the variable importance of each feature
+                                out on the command line (or in the file
+                                specified with --vi_file).
+  --test_file (-T) [string]     A set of test points to estimate the density of.
+                                 Default value ''.
+  --test_set_estimates_file (-E) [string]
                                 The file in which to output the estimates on the
                                 test set from the final optimally pruned tree.
                                 Default value ''.
-  --output/training_set_estimates (-s) [string]
-                                The file in which to output the estimates on the
-                                training set from the final optimally pruned
-                                tree.  Default value ''.
-  --output/tree (-p) [string]   The file in which to print the final optimally
+  --training_set_estimates_file (-e) [string]
+                                The file in which to output the density
+                                estimates on the training set from the final
+                                optimally pruned tree.  Default value ''.
+  --tree_file (-r) [string]     The file in which to print the final optimally
                                 pruned tree.  Default value ''.
-  --output/unpruned_tree_estimates (-u) [string]
-                                The file in which to output the estimates on the
-                                training set from the large unpruned tree.
-                                Default value ''.
-  --output/vi (-i) [string]     The file to output the variable importance
-                                values for each feature.  Default value ''.
-  --param/folds (-F) [int]      The number of folds of cross-validation to
-                                performed for the estimation (enter 0 for LOOCV)
-                                 Default value 10.
-  --param/number_of_classes (-C) [int]
-                                The number of classes present in the 'labels'
-                                set provided  Default value 0.
+  --unpruned_tree_estimates_file (-u) [string]
+                                The file in which to output the density
+                                estimates on the training set from the large
+                                unpruned tree.  Default value ''.
   --verbose (-v)                Display informational messages and the full list
                                 of parameters and timers at the end of
                                 execution.
+  --vi_file (-i) [string]       The file to output the variable importance
+                                values for each feature.  Default value ''.
 
 For further information, including relevant papers, citations, and theory,
 consult the documentation found at http://www.mlpack.org or included with your
 distribution of MLPACK.
 @endcode
 
-
 @subsection cli_ex1_de_tut Plain-vanilla density estimation
 
 We can just train a DET on the provided data set \e S.  Like all datasets
@@ -139,230 +133,265 @@
 for more information).
 
 @code
-$ ./dt_main -S dataset.csv -v
+$ det -t dataset.csv -v
 @endcode
 
-By default, dt_main performs 10-fold cross-validation (using the
+By default, det performs 10-fold cross-validation (using the
 \f$\alpha\f$-pruning regularization for decision trees). To perform LOOCV
-(leave-one-out cross-validation), use the following command:
+(leave-one-out cross-validation), which can provide better results but will take
+longer, use the following command:
 
 @code
-$ ./dt_main -S dataset.csv -F 0 -v
+$ det -t dataset.csv -f 0 -v
 @endcode
 
-To perform k-fold crossvalidation, use \c -F \c k. There are certain other
-options available for training. For example, for the construction of the initial
-tree, you can specify the maximum and minimum leaf sizes. By default, they are
-10 and 5 respectively, you can set them using the \c -M (\c --maximum_leaf_size)
-and the \c -N (\c --minimum_leaf_size) options.
+To perform k-fold crossvalidation, use \c -f \c k (or \c --folds \c k). There
+are certain other options available for training. For example, in the
+construction of the initial tree, you can specify the maximum and minimum leaf
+sizes. By default, they are 10 and 5 respectively; you can set them using the \c
+-M (\c --max_leaf_size) and the \c -N (\c --min_leaf_size) options.
 
 @code
-$ ./dt_main -S dataset.csv -M 20 -N 10
+$ det -t dataset.csv -M 20 -N 10
 @endcode
 
 In case you want to output the density estimates at the points in the training
-set, use the \c -s option to specify the output file.
+set, use the \c -e (\c --training_set_estimates_file) option to specify the
+output file to which the estimates will be saved.  The first line in
+density_estimates.txt will correspond to the density at the first point in the
+training set.  Note that the logarithm of the density estimates are given, which
+allows smaller estimates to be saved.
 
 @code
-$ ./dt_main -S dataset.csv -s density_estimates.txt -v
+$ ./det -t dataset.csv -s density_estimates.txt -v
 @endcode
 
- at subsection cli_alt_reg_tut Alternate DET regularization
-
-The usual regularized error \f$R_\alpha(t)\f$ of a node \f$t\f$ is given by:
-\f$R_\alpha(t) = R(t) + \alpha |\tilde{t}|\f$ where \f$R(t) = -\frac{|t|^2}{N^2
-V(t)}\f$. \f$V(t)\f$ is the volume of the node \f$t\f$ and \f$\tilde{t}\f$ is
-the set of leaves in the subtree rooted at \f$t\f$.
-
-For the purposes of density estimation, I have developed a different form of
-regularization -- instead of penalizing the number of leaves in the subtree, we
-penalize the sum of the inverse of the volumes of the leaves. Here really small
-volume nodes are discouraged unless the data actually warrants it. Thus,
-\f$R_\alpha'(t) = R(t) + \alpha I_v(\tilde{t})\f$ where \f$I_v(\tilde{t}) =
-\sum_{l \in \tilde{t}} \frac{1}{V(l)}.\f$ To use this form of regularization,
-use the \e -R flag.
-
- at code
-$ ./dt_utils -S dataset.csv -R -v
- at endcode
-
 @subsection cli_ex2_de_test_tut Estimation on a test set
 
-There is the option of training the DET on a certain set and obtaining the
-density from the learned estimator at some out of sample (new) test points. The
-\e -T option is the set of test points and the \e -t is the file in which the
-estimates are to be output.
+Often, it is useful to train a density estimation tree on a training set and
+then obtain density estimates from the learned estimator for a separate set of
+test points.  The \c -T (\c --test_file) option allows specification of a set of
+test points, and the \c -E (\c --test_set_estimates_file) option allows
+specification of the file into which the test set estimates are saved.  Note
+that the logarithm of the density estimates are saved; this allows smaller
+values to be saved.
 
 @code
-$ ./dt_main -S dataset.csv -T test_points.csv -t test_density_estimates.txt -v
+$ det -t dataset.csv -T test_points.csv -E test_density_estimates.txt -v
 @endcode
 
 @subsection cli_ex3_de_p_tut Printing a trained DET
 
-A depth-first visualization of the DET can be obtained by using the \e -P flag.
+A depth-first visualization of the DET can be obtained by using the \c -p (\c
+--print_tree) flag.
 
 @code
-$ ./dt_main -S dataset.csv -P -v
+$ det -t dataset.csv -p -v
 @endcode
 
-To print this tree in a file, use the \e -p option to specify the output file
-along with the \e -P flag.
+To print this tree in a file, use the \c -r (\c --tree_file) option to specify
+the output file along with the \c -P (\c --print_tree) flag.
 
 @code
-$ ./dt_main -S dataset.csv -P -p tree.txt -v
+$ det -t dataset.csv -p -r tree.txt -v
 @endcode
 
 @subsection cli_ex4_de_vi_tut Computing the variable importance
 
 The variable importance (with respect to density estimation) of the different
-features in the data set can be obtained by using the \e -I option. This outputs
-the (absolute as opposed to relative) variable importance of the all the
-features.
+features in the data set can be obtained by using the \c -I (\c --print_vi)
+option. This outputs the absolute (as opposed to relative) variable importance
+of the all the features.
 
 @code
-$ ./dt_main -S dataset.csv -I -v
+$ det -t dataset.csv -I -v
 @endcode
 
-To print this in a file, use the \e -i option
+To print this in a file, use the \c -i (\c --vi_file) option.
 
 @code
-$ ./dt_main -S dataset.csv -I -i variable_importance.txt -v
+$ det -t dataset.csv -I -i variable_importance.txt -v
 @endcode
 
 @subsection cli_ex5_de_lm Leaf Membership
 
-In case the dataset is labeled and you are curious to find the class membership
-of the leaves of the DET, there is an option of view the class membership. The
-training data has to still be input in an unlabeled format, but an additional
+In case the dataset is labeled and you want to find the class membership
+of the leaves of the tree, there is an option to print the class membership into
+a file. The training data has to still be input in an unlabeled format, but an additional
 label file containing the corresponding labels of each point has to be input
-using the \e -L option. You are required to specify the number of classes
-present in this set using the \e -C option.
+using the \c -l (\c --labels_file) option.  The file to output the class
+memberships into can be specified with \c -L (\c --leaf_class_table_file).  If
+\c -L is left unspecified, leaf_class_membership.txt is used by default.
 
 @code
-$ ./dt_main -S dataset.csv -L labels.csv -C <number-of-classes> -v
+$ det -t dataset.csv -l labels.csv -v
+$ det -t dataset.csv -l labels.csv -l leaf_class_membership_file.txt -v
 @endcode
-The leaf membership matrix is output into a file called 'leaf_class_membership.txt' by default. An user-specified file can be used by utilizing the \e -l option.
- at code
-$ ./dt_main -S dataset.csv -L labels.csv -C <number-of-classes> -l leaf_class_membership_file.txt -v
- at endcode
 
 
 @section dtree_det_tut The 'DTree' class
-This class implements the DET.
 
+This class implements density estimation trees.  Below is a simple example which
+initializes a density estimation tree.
+
 @code
 #include <mlpack/methods/det/dtree.hpp>
 
 using namespace mlpack::det;
 
-// The dataset matrix, on which to learn the DET
+// The dataset matrix, on which to learn the density estimation tree.
 extern arma::Mat<float> data;
 
-// Initializing the class
-// This function creates and saves the bounding box of the data.
-DTree<>* det = new DTree<>(&data);
+// Initialize the tree.  This function also creates and saves the bounding box
+// of the data.  Note that it does not actually build the tree.
+DTree<> det(data);
 @endcode
 
 @subsection dtree_pub_func_det_tut Public Functions
-\b Growing the tree to the full size:
 
+The function \c Grow() greedily grows the tree, adding new points to the tree.
+Note that the points in the dataset will be reordered.  This should only be run
+on a tree which has not already been built.  In general, it is more useful to
+use the \c Trainer() function found in \ref dtutils_det_tut.
+
 @code
-// This keeps track of the data during the shuffle
-// that occurs while growing the tree.
-arma::Col<size_t>* old_from_new = new arma::Col<size_t>(data.n_cols);
-for (size_t i = 0; i < data.n_cols; i++) {
-  (*old_from_new)[i] = i;
-}
+// This keeps track of the data during the shuffle that occurs while growing the
+// tree.
+arma::Col<size_t> oldFromNew(data.n_cols);
+for (size_t i = 0; i < data.n_cols; i++)
+  oldFromNew[i] = i;
 
-// This function grows the tree down to the leaf
-// any regularization. It returns the current minimum
-// value of the regularization parameter 'alpha'.
-bool use_volume_reg = false;
-size_t max_leaf_size = 10, min_leaf_size = 5;
+// This function grows the tree down to the leaves. It returns the current
+// minimum value of the regularization parameter alpha.
+size_t maxLeafSize = 10;
+size_t minLeafSize = 5;
 
-long double alpha
-  = det->Grow(&data, old_from_new, use_volume_reg,
-	      max_leaf_size, min_leaf_size);
+double alpha = det.Grow(data, oldFromNew, false, maxLeafSize, minLeafSize);
 @endcode
 
-One step of \b pruning the tree back up:
+Note that the alternate volume regularization should not be used (see ticket
+#238).
 
- at code
-// This function performs a single pruning of the
-// decision tree for the given value of alpha
-// and returns the next minimum value of alpha
-// that would induce a pruning
-alpha = det->PruneAndUpdate(alpha, use_volume_reg);
- at endcode
+To estimate the density at a given query point, use the following code.  Note
+that the logarithm of the density is returned.
 
-\b Estimating the density at a given query point:
-
 @code
-// for a given query, you can obtain the density estimate
+// For a given query, you can obtain the density estimate.
 extern arma::Col<float> query;
-long double estimate = det->Compute(&query);
+extern DTree* det;
+double estimate = det->ComputeValue(&query);
 @endcode
 
 Computing the \b variable \b importance of each feature for the given DET.
 
 @code
-// Initialize the importance of every dimension to zero.
-arma::Col<double> v_imps = arma::zeros<arma::Col<double> >(data.n_rows);
+// The data matrix and density estimation tree.
+extern arma::mat data;
+extern DTree* det;
 
+// The variable importances will be saved into this vector.
+arma::Col<double> varImps;
+
 // You can obtain the variable importance from the current tree.
-det->ComputeVariableImportance(&v_imps);
+det->ComputeVariableImportance(varImps);
 @endcode
 
 @section dtutils_det_tut 'namespace mlpack::det'
-The functions in this namespace allows the user to perform certain tasks with the 'DTree' class.
+
+The functions in this namespace allows the user to perform tasks with the
+'DTree' class.  Most importantly, the \c Trainer() method allows the full
+training of a density estimation tree with cross-validation.  There are also
+utility functions which allow printing of leaf membership and variable
+importance.
+
 @subsection dtutils_util_funcs Utility Functions
 
-\b Training a DET (with cross-validation)
+The code below details how to train a density estimation tree with
+cross-validation.
 
 @code
 #include <mlpack/methods/det/dt_utils.hpp>
 
 using namespace mlpack::det;
 
-// The dataset matrix, on which to learn the DET
+// The dataset matrix, on which to learn the density estimation tree.
 extern arma::Mat<float> data;
 
-// the number of folds in the cross-validation
-size_t folds = 10; // set folds = 0 for LOOCV
+// The number of folds for cross-validation.
+const size_t folds = 10; // Set folds = 0 for LOOCV.
 
-bool use_volume_reg = false;
-size_t max_leaf_size = 10, min_leaf_size = 5;
+const size_t maxLeafSize = 10;
+const size_t minLeafSize = 5;
 
-// obtain the trained DET
-DTree<>* dtree_opt = Trainer(&data, folds, use_volume_reg,
-			     max_leaf_size, min_leaf_size);
+// Train the density estimation tree with cross-validation.
+DTree<>* dtree_opt = Trainer(data, folds, false, maxLeafSize, minLeafSize);
 @endcode
 
-Generating \b leaf-class \b membership
+Note that the alternate volume regularization should be set to false because it
+has known bugs (see #238).
 
+To print the class membership of leaves in the tree into a file, see the
+following code.
+
 @code
-extern arma::Mat<int> labels;
-size_t number_of_classes = 3; // this is required
+extern arma::Mat<size_t> labels;
+extern DTree* det;
+const size_t numClasses = 3; // The number of classes must be known.
 
-extern string leaf_class_membership_file;
+extern string leafClassMembershipFile;
 
-PrintLeafMembership(dtree_opt, data, labels, number_of_classes,
-		    leaf_class_membership_file);
+PrintLeafMembership(det, data, labels, numClasses, leafClassMembershipFile);
 @endcode
 
-Generating \b variable \bimportance
+Note that you can find the number of classes with \c max(labels) \c + \c 1.
+The variable importance can also be printed to a file in a similar manner.
 
 @code
-extern string variable_importance_file;
-size_t number_of_features = data.n_rows;
+extern DTree* det;
 
-PrintVariableImportance(dtree_opt, nunmber_of_features,
-			variable_importance_file);
+extern string variableImportanceFile;
+const size_t numFeatures = data.n_rows;
+
+PrintVariableImportance(det, numFeatures, variableImportanceFile);
 @endcode
 
-
 @section further_doc_det_tut Further Documentation
 For further documentation on the DTree class, consult the
 \ref mlpack::det::DTree "complete API documentation".
 
 */
+
+----- this option is not available in DET right now; see #238! -----
+ at subsection cli_alt_reg_tut Alternate DET regularization
+
+The usual regularized error \f$R_\alpha(t)\f$ of a node \f$t\f$ is given by:
+\f$R_\alpha(t) = R(t) + \alpha |\tilde{t}|\f$ where
+
+\f[
+R(t) = -\frac{|t|^2}{N^2 V(t)}.
+\f]
+
+\f$V(t)\f$ is the volume of the node \f$t\f$ and \f$\tilde{t}\f$ is
+the set of leaves in the subtree rooted at \f$t\f$.
+
+For the purposes of density estimation, there is a different form of
+regularization: instead of penalizing the number of leaves in the subtree, we
+penalize the sum of the inverse of the volumes of the leaves.  With this
+regularization, very small volume nodes are discouraged unless the data actually
+warrants it. Thus,
+
+\f[
+R_\alpha'(t) = R(t) + \alpha I_v(\tilde{t})
+\f]
+
+where
+
+\f[
+I_v(\tilde{t}) = \sum_{l \in \tilde{t}} \frac{1}{V(l)}.
+\f]
+
+To use this form of regularization, use the \c -R flag.
+
+ at code
+$ det -t dataset.csv -R -v
+ at endcode

Modified: mlpack/branches/mlpack-1.x/doc/tutorials/emst/emst.txt
===================================================================
--- mlpack/branches/mlpack-1.x/doc/tutorials/emst/emst.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/doc/tutorials/emst/emst.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -4,26 +4,26 @@
 @author Bill March
 @brief Tutorial for the Euclidean Minimum Spanning Tree algorithm.
 
- at page emst_tutorial EMST Tutorial 
+ at page emst_tutorial EMST Tutorial
 
 @section intro_emsttut Introduction
 
-The Euclidean Minimum Spanning Tree problem is widely used in machine learning 
+The Euclidean Minimum Spanning Tree problem is widely used in machine learning
 and data mining applications.  Given a set \f$S\f$ of points in \f$\mathbf{R}^d\f$,
 our task is to compute lowest weight spanning tree in the complete graph on \f$S\f$
-with edge weights given by the Euclidean distance between points. 
+with edge weights given by the Euclidean distance between points.
 
 Among other applications, the EMST can be used to compute hierarchical clusterings
 of data.  A <em>single-linkage clustering</em> can be obtained from the EMST by deleting
 all edges longer than a given cluster length.  This technique is also referred to as a <em>Friends-of-Friends</em> clustering in the astronomy literature.
 
-MLPACK includes an implementation of <b>Dual-Tree Boruvka</b> on \f$kd\f$-trees, the empirically and 
+MLPACK includes an implementation of <b>Dual-Tree Boruvka</b> on \f$kd\f$-trees, the empirically and
 theoretically fastest EMST algorithm.  For more details, see March, <em>et al.</em>, <em>Euclidean Minimum Spanning Tree: Algorithm, Analysis, and Applications</em>, in KDD, 2010.  An implementation using cover trees is forthcoming.
 
 \b mlpack provides:
 
  - a \ref cli_emsttut "simple command-line executable" to compute the EMST of a given data set
- - a \ref class_emsttut "simple C++ interface" to compute the EMST
+ - a \ref dtb_emsttut "simple C++ interface" to compute the EMST
 
 @section toc_emsttut Table of Contents
 
@@ -37,9 +37,9 @@
 
 @section cli_emsttut Command-Line 'EMST'
 
-The emst executable in \b mlpack will compute the EMST of a given set of points and store the resulting edge list to a file.  
+The emst executable in \b mlpack will compute the EMST of a given set of points and store the resulting edge list to a file.
 
-The output file contains an edge list representation of the MST in an \f$n-1 \times 3 \f$ matrix, where the first and second columns are labels of points and the third column is the edge weight.  The edges are sorted in order of increasing weight.  
+The output file contains an edge list representation of the MST in an \f$n-1 \times 3 \f$ matrix, where the first and second columns are labels of points and the third column is the edge weight.  The edges are sorted in order of increasing weight.
 
 Below are several examples of simple usage (and the resultant output).  The '-v'
 option is used so that verbose output is given.  Further documentation on each
@@ -59,7 +59,7 @@
 [INFO ] 5 edges found so far.
 [INFO ] Total squared length: 1002.45
 [INFO ] Saving CSV data to 'edge_list.csv'.
-[INFO ] 
+[INFO ]
 [INFO ] Execution parameters:
 [INFO ]   help: false
 [INFO ]   info: ""
@@ -68,14 +68,14 @@
 [INFO ]   naive: false
 [INFO ]   output_file: edge_list.csv
 [INFO ]   verbose: true
-[INFO ] 
+[INFO ]
 [INFO ] Program timers:
 [INFO ]   emst/mst_computation: 0.000179s
 [INFO ]   emst/tree_building: 0.000061s
 [INFO ]   total_time: 0.052641s
 @endcode
 
-The code performs at most \f$\log N\f$ iterations for \f$N\f$ data points.  It will print an update on the number of MST edges found after each iteration.  
+The code performs at most \f$\log N\f$ iterations for \f$N\f$ data points.  It will print an update on the number of MST edges found after each iteration.
 Convenient program timers are given for different parts of the calculation at
 the bottom of the output, as well as the parameters the simulation was run with.
 
@@ -98,22 +98,22 @@
 
 The input points are labeled 0-5.  The output tells us that the MST connects point 0 to point 3, point 4 to point 5, point 1 to point 3, point 1 to point 2, and point 2 to point 4, with the corresponding edge weights given in the third column.  The total squared length of the MST is also given in the verbose output.
 
-Note that it is also possible to compute the EMST using a naive (\f$O(N^2)\f$) algorithm for timing and comparison purposes.  
+Note that it is also possible to compute the EMST using a naive (\f$O(N^2)\f$) algorithm for timing and comparison purposes.
 
 @section dtb_emsttut The 'DualTreeBoruvka' class
 
-The 'DualTreeBoruvka' class contains our implementation of the Dual-Tree Boruvka algorithm. 
+The 'DualTreeBoruvka' class contains our implementation of the Dual-Tree Boruvka algorithm.
 
-The class has two constructors: the first takes the data set, constructs the \f$kd\f$-tree, and computes the MST.  The second takes data set and an already constructed tree.  
+The class has two constructors: the first takes the data set, constructs the \f$kd\f$-tree, and computes the MST.  The second takes data set and an already constructed tree.
 
 The class provides one method that performs the MST computation:
 @code
 void ComputeMST(const arma::mat& results);
 @endcode
 
-This method stores the computed MST in the matrix results in the format given above. 
+This method stores the computed MST in the matrix results in the format given above.
 
- at subsection further_doc_emsttut Further documentation
+ at section further_doc_emsttut Further documentation
 
 For further documentation on the DualTreeBoruvka class, consult the
 \ref mlpack::emst::DualTreeBoruvka "complete API documentation".

Modified: mlpack/branches/mlpack-1.x/doc/tutorials/linear_regression/linear_regression.txt
===================================================================
--- mlpack/branches/mlpack-1.x/doc/tutorials/linear_regression/linear_regression.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/doc/tutorials/linear_regression/linear_regression.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -290,7 +290,7 @@
 // Now, the vector 'predictions' will contain the predicted values.
 @endcode
 
- at subsection further_doc_lrtut Further documentation
+ at section further_doc_lrtut Further documentation
 
 For further documentation on the LinearRegression class, consult the
 \ref mlpack::regression::LinearRegression "complete API documentation".

Modified: mlpack/branches/mlpack-1.x/doc/tutorials/neighbor_search/neighbor_search.txt
===================================================================
--- mlpack/branches/mlpack-1.x/doc/tutorials/neighbor_search/neighbor_search.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/doc/tutorials/neighbor_search/neighbor_search.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -127,7 +127,7 @@
 
 So, the nearest neighbor to point 0 is point 14, with a distance of 7.096144e-4.
 The second nearest neighbor to point 0 is point 5, with a distance of
-2.059402e-3.  The third nearest neighbor to point 6 is point 16, with a distance
+2.059402e-3.  The third nearest neighbor to point 5 is point 16, with a distance
 of 9.9748395e-3.
 
 @subsection cli_ex2_nstut Query and reference dataset, 10 nearest neighbors
@@ -382,7 +382,7 @@
 mlpack::tree::BinarySpaceTree documentation for more information on tree
 statistics.
 
- at subsection further_doc_nstut Further documentation
+ at section further_doc_nstut Further documentation
 
 For further documentation on the NeighborSearch class, consult the
 \ref mlpack::neighbor::NeighborSearch "complete API documentation".

Modified: mlpack/branches/mlpack-1.x/doc/tutorials/range_search/range_search.txt
===================================================================
--- mlpack/branches/mlpack-1.x/doc/tutorials/range_search/range_search.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/doc/tutorials/range_search/range_search.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -379,7 +379,7 @@
 used for the StatisticType parameter of the BinarySpaceTree (but this is not
 technically necessary -- RangeSearch simply makes no use of the tree statistic).
 
- at subsection further_doc_rstut Further documentation
+ at section further_doc_rstut Further documentation
 
 For further documentation on the RangeSearch class, consult the
 \ref mlpack::range::RangeSearch "complete API documentation".

Modified: mlpack/branches/mlpack-1.x/doc/tutorials/tutorials.txt
===================================================================
--- mlpack/branches/mlpack-1.x/doc/tutorials/tutorials.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/doc/tutorials/tutorials.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -28,5 +28,8 @@
  - \ref lrtutorial
  - \ref rstutorial
  - \ref dettutorial
+ - \ref kmtutorial
+ - \ref fmkstutorial
+ - \ref emst_tutorial
 
 */


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/core/arma_extend
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/core/arma_extend:13981-14227

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/arma_extend/hdf5_misc.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/arma_extend/hdf5_misc.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/arma_extend/hdf5_misc.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,7 @@
 // To hack in u64/s64 support to Armadillo when it is not compiled with
 // ARMA_64BIT_WORD.
+namespace hdf5_misc {
+
 #if defined(ARMA_USE_HDF5)
   #if !(defined(ARMA_64BIT_WORD) || defined(ARMA_USE_U64S64))
     #if defined(ULLONG_MAX)
@@ -21,3 +23,5 @@
     #endif
   #endif
 #endif
+
+} // namespace hdf5_misc


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/core/data
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/core/data:13981-14231

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/data/load_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/data/load_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/data/load_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -50,6 +50,7 @@
       Log::Warn << "Cannot determine type of file '" << filename << "'; "
           << "no extension is present.  Load failed." << std::endl;
 
+    Timer::Stop("loading_data");
     return false;
   }
 
@@ -70,6 +71,7 @@
       Log::Warn << "Cannot open file '" << filename << "'; load failed."
           << std::endl;
 
+    Timer::Stop("loading_data");
     return false;
   }
 
@@ -165,6 +167,7 @@
           << "Armadillo was compiled without HDF5 support.  Load failed."
           << std::endl;
 
+    Timer::Stop("loading_data");
     return false;
 #endif
   }
@@ -185,6 +188,7 @@
       Log::Warn << "Unable to detect type of '" << filename << "'; load failed."
           << " Incorrect extension?" << std::endl;
 
+    Timer::Stop("loading_data");
     return false;
   }
 
@@ -196,7 +200,7 @@
     Log::Info << "Loading '" << filename << "' as " << stringType << ".  "
         << std::flush;
 
-  bool success = matrix.load(stream, loadType);
+  const bool success = matrix.load(stream, loadType);
 
   if (!success)
   {

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/data/save_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/data/save_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/data/save_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -66,6 +66,7 @@
       Log::Warn << "Cannot open file '" << filename << "' for writing; save "
           << "failed." << std::endl;
 
+    Timer::Stop("saving_data");
     return false;
   }
 
@@ -109,6 +110,7 @@
           << "Armadillo was compiled without HDF5 support.  Save failed."
           << std::endl;
 
+    Timer::Stop("saving_data");
     return false;
 #endif
   }
@@ -146,6 +148,7 @@
       else
         Log::Warn << "Save to '" << filename << "' failed." << std::endl;
 
+      Timer::Stop("saving_data");
       return false;
     }
   }
@@ -158,6 +161,7 @@
       else
         Log::Warn << "Save to '" << filename << "' failed." << std::endl;
 
+      Timer::Stop("saving_data");
       return false;
     }
   }


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/core/dists
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/core/dists:13981-14232

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -61,8 +61,20 @@
   // observation is to turn the default flooring operation of the size_t cast
   // into a rounding operation.
   for (size_t i = 0; i < observations.n_cols; i++)
-    probabilities((size_t) (observations(0, i) + 0.5))++;
+  {
+    const size_t obs = size_t(observations(0, i) + 0.5);
 
+    // Ensure that the observation is within the bounds.
+    if (obs >= probabilities.n_elem)
+    {
+      Log::Debug << "DiscreteDistribution::Estimate(): observation " << i
+          << " (" << obs << ") is invalid; observation must be in [0, "
+          << probabilities.n_elem << "] for this distribution." << std::endl;
+    }
+
+    probabilities(obs)++;
+  }
+
   // Now normalize the distribution.
   double sum = accu(probabilities);
   if (sum > 0)
@@ -85,8 +97,20 @@
   // observation is to turn the default flooring operation of the size_t cast
   // into a rounding observation.
   for (size_t i = 0; i < observations.n_cols; i++)
-    probabilities((size_t) (observations(0, i) + 0.5)) += probObs[i];
+  {
+    const size_t obs = size_t(observations(0, i) + 0.5);
 
+    // Ensure that the observation is within the bounds.
+    if (obs >= probabilities.n_elem)
+    {
+      Log::Debug << "DiscreteDistribution::Estimate(): observation " << i
+          << " (" << obs << ") is invalid; observation must be in [0, "
+          << probabilities.n_elem << "] for this distribution." << std::endl;
+    }
+
+    probabilities(obs) += probObs[i];
+  }
+
   // Now normalize the distribution.
   double sum = accu(probabilities);
   if (sum > 0)

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/dists/discrete_distribution.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -106,7 +106,17 @@
   {
     // Adding 0.5 helps ensure that we cast the floating point to a size_t
     // correctly.
-    return probabilities((size_t) (observation[0] + 0.5));
+    const size_t obs = size_t(observation[0] + 0.5);
+
+    // Ensure that the observation is within the bounds.
+    if (obs >= probabilities.n_elem)
+    {
+      Log::Debug << "DiscreteDistribution::Probability(): received observation "
+          << obs << "; observation must be in [0, " << probabilities.n_elem
+          << "] for this distribution." << std::endl;
+    }
+
+    return probabilities(obs);
   }
 
   /**
@@ -143,7 +153,7 @@
   const arma::vec& Probabilities() const { return probabilities; }
   //! Modify the vector of probabilities.
   arma::vec& Probabilities() { return probabilities; }
-  
+
   /*
    * Returns a string representation of this object.
    */

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/dists/gaussian_distribution.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/dists/gaussian_distribution.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/dists/gaussian_distribution.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -37,8 +37,6 @@
  */
 void GaussianDistribution::Estimate(const arma::mat& observations)
 {
-  // Calculate the mean and covariance with each point.  Because this is a
-  // std::vector and not a matrix, this is a little more difficult.
   if (observations.n_cols > 0)
   {
     mean.zeros(observations.n_rows);
@@ -48,6 +46,7 @@
   {
     mean.zeros(0);
     covariance.zeros(0);
+    return;
   }
 
   // Calculate the mean.
@@ -67,6 +66,20 @@
   // Finish estimating the covariance by normalizing, with the (1 / (n - 1)) so
   // that it is the unbiased estimator.
   covariance /= (observations.n_cols - 1);
+
+  // Ensure that the covariance is positive definite.
+  if (det(covariance) <= 1e-50)
+  {
+    Log::Debug << "GaussianDistribution::Estimate(): Covariance matrix is not "
+        << "positive definite. Adding perturbation." << std::endl;
+
+    double perturbation = 1e-30;
+    while (det(covariance) <= 1e-50)
+    {
+      covariance.diag() += perturbation;
+      perturbation *= 10; // Slow, but we don't want to add too much.
+    }
+  }
 }
 
 /**
@@ -86,6 +99,7 @@
   {
     mean.zeros(0);
     covariance.zeros(0);
+    return;
   }
 
   double sumProb = 0;
@@ -98,6 +112,14 @@
     sumProb += probabilities[i];
   }
 
+  if (sumProb == 0)
+  {
+    // Nothing in this Gaussian!  At least set the covariance so that it's
+    // invertible.
+    covariance.diag() += 1e-50;
+    return;
+  }
+
   // Normalize.
   mean /= sumProb;
 
@@ -111,6 +133,19 @@
   // This is probably biased, but I don't know how to unbias it.
   covariance /= sumProb;
 
+  // Ensure that the covariance is positive definite.
+  if (det(covariance) <= 1e-50)
+  {
+    Log::Debug << "GaussianDistribution::Estimate(): Covariance matrix is not "
+        << "positive definite. Adding perturbation." << std::endl;
+
+    double perturbation = 1e-30;
+    while (det(covariance) <= 1e-50)
+    {
+      covariance.diag() += perturbation;
+      perturbation *= 10; // Slow, but we don't want to add too much.
+    }
+  }
 }
 
 /**

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/kernels/polynomial_kernel.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/kernels/polynomial_kernel.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/kernels/polynomial_kernel.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -28,34 +28,26 @@
 namespace kernel {
 
 /**
- * The simple polynomial kernel.  For any two vectors @f$ x @f$,
- * @f$ y @f$, @f$ degree @f$ and @f$ offset @f$
+ * The simple polynomial kernel.  For any two vectors @f$ x @f$, @f$ y @f$,
+ * @f$ degree @f$ and @f$ offset @f$,
  *
  * @f[
- * K(x, y) = (x^T * y + offset) ^ {degree}
+ * K(x, y) = (x^T * y + offset) ^ {degree}.
  * @f]
- *
  */
 class PolynomialKernel
 {
  public:
   /**
-   * Default constructor; sets offset to 0.0 and degree to 1.0
-   */
-  PolynomialKernel() :
-    offset(0.0),
-    degree(1.0)
-  { }
-
-  /* Construct the Polynomial Kernel with custom
-   * offset and degree
+   * Construct the Polynomial Kernel with the given offset and degree.  If the
+   * arguments are omitted, the default degree is 2 and the default offset is 0.
    *
-   * @param offset offset to the polynomial
-   * @param degree degree of the polynomial
+   * @param offset Offset of the dot product of the arguments.
+   * @param degree Degree of the polynomial.
    */
-  PolynomialKernel(double offset, double degree) :
-    offset(offset),
-    degree(degree)
+  PolynomialKernel(const double degree = 2.0, const double offset = 0.0) :
+      degree(degree),
+      offset(offset)
   { }
 
   /**
@@ -68,19 +60,26 @@
    * @return K(a, b).
    */
   template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b)
+  double Evaluate(const VecType& a, const VecType& b) const
   {
     return pow((arma::dot(a, b) + offset), degree);
   }
 
-  //! Get the offset
-  const double& Offset() const { return offset; }
-  //! Get the degree of the polynomial
+  //! Get the degree of the polynomial.
   const double& Degree() const { return degree; }
+  //! Modify the degree of the polynomial.
+  double& Degree() { return degree; }
 
+  //! Get the offset of the dot product of the arguments.
+  const double& Offset() const { return offset; }
+  //! Modify the offset of the dot product of the arguments.
+  double& Offset() { return offset; }
+
  private:
-  double offset;
+  //! The degree of the polynomial.
   double degree;
+  //! The offset of the dot product of the arguments.
+  double offset;
 };
 
 }; // namespace kernel


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/core/math
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/core/math:13981-14233

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/math/random.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/math/random.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/math/random.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -117,12 +117,12 @@
 inline int RandInt(const int lo, const int hiExclusive)
 {
 #if BOOST_VERSION >= 103900
-  return lo + (int) std::floor((double)(hiExclusive - lo) 
+  return lo + (int) std::floor((double) (hiExclusive - lo)
                                * randUniformDist(randGen));
 #else
   // Before Boost 1.39, we did not give the random object when we wanted a
   // random number; that gets given at construction time.
-  return lo + (int) std::floor((double)(hiExclusive - lo) 
+  return lo + (int) std::floor((double) (hiExclusive - lo)
                                * randUniformDist());
 #endif
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/metrics/lmetric.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/metrics/lmetric.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/metrics/lmetric.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -69,7 +69,7 @@
  *    is returned.  Setting this to false causes the metric to not satisfy the
  *    Triangle Inequality (be careful!).
  */
-template<int Power, bool TakeRoot = false>
+template<int Power, bool TakeRoot = true>
 class LMetric
 {
  public:

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/CMakeLists.txt
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/CMakeLists.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/CMakeLists.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -9,6 +9,7 @@
   binary_space_tree/dual_tree_traverser_impl.hpp
   binary_space_tree/single_tree_traverser.hpp
   binary_space_tree/single_tree_traverser_impl.hpp
+  binary_space_tree/traits.hpp
   bounds.hpp
   cover_tree/cover_tree.hpp
   cover_tree/cover_tree_impl.hpp
@@ -17,12 +18,16 @@
   cover_tree/single_tree_traverser_impl.hpp
   cover_tree/dual_tree_traverser.hpp
   cover_tree/dual_tree_traverser_impl.hpp
+  cover_tree/traits.hpp
   hrectbound.hpp
   hrectbound_impl.hpp
+  mrkd_statistic.hpp
+  mrkd_statistic_impl.hpp
+  mrkd_statistic.cpp
   periodichrectbound.hpp
   periodichrectbound_impl.hpp
   statistic.hpp
-  mrkd_statistic.hpp
+  tree_traits.hpp
   mrkd_statistic_impl.hpp
   mrkd_statistic.cpp
 )

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -137,6 +137,12 @@
    */
   template<typename MatType>
   const BallBound& operator|=(const MatType& data);
+
+  /**
+   * Returns a string representation of this object.
+   */
+  std::string ToString() const;
+
 };
 
 }; // namespace bound

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/ballbound_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -27,6 +27,8 @@
 // In case it hasn't been included already.
 #include "ballbound.hpp"
 
+#include <string>
+
 namespace mlpack {
 namespace bound {
 
@@ -203,6 +205,18 @@
 
   return *this;
 }
+/**
+ * Returns a string representation of this object.
+ */
+template<typename VecType>
+std::string BallBound<VecType>::ToString() const
+{
+  std::ostringstream convert;
+  convert << "BallBound [" << this << "]" << std::endl;
+  convert << "Radius:  " << radius << std::endl;
+  convert << "Center:  " << std::endl << center;
+  return convert.str();
+}
 
 }; // namespace bound
 }; // namespace mlpack

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -25,9 +25,6 @@
 
 #include "../statistic.hpp"
 
-// Bad!
-#include <mlpack/methods/neighbor_search/neighbor_search_rules.hpp>
-
 namespace mlpack {
 namespace tree /** Trees and tree-building procedures. */ {
 
@@ -59,20 +56,26 @@
   BinarySpaceTree* left;
   //! The right child node.
   BinarySpaceTree* right;
+  //! The parent node (NULL if this is the root of the tree).
+  BinarySpaceTree* parent;
   //! The index of the first point in the dataset contained in this node (and
   //! its children).
   size_t begin;
   //! The number of points of the dataset contained in this node (and its
   //! children).
   size_t count;
+  //! The leaf size.
+  size_t leafSize;
   //! The bound object for this node.
   BoundType bound;
   //! Any extra data contained in the node.
   StatisticType stat;
-  //! The leaf size.
-  size_t leafSize;
   //! The dimension this node split on if it is a parent.
   size_t splitDimension;
+  //! The distance to the furthest descendant, cached to speed things up.
+  double furthestDescendantDistance;
+  //! The dataset.
+  MatType& dataset;
 
  public:
   //! So other classes can use TreeType::Mat.
@@ -142,6 +145,7 @@
   BinarySpaceTree(MatType& data,
                   const size_t begin,
                   const size_t count,
+                  BinarySpaceTree* parent = NULL,
                   const size_t leafSize = 20);
 
   /**
@@ -166,6 +170,7 @@
                   const size_t begin,
                   const size_t count,
                   std::vector<size_t>& oldFromNew,
+                  BinarySpaceTree* parent = NULL,
                   const size_t leafSize = 20);
 
   /**
@@ -194,12 +199,16 @@
                   const size_t count,
                   std::vector<size_t>& oldFromNew,
                   std::vector<size_t>& newFromOld,
+                  BinarySpaceTree* parent = NULL,
                   const size_t leafSize = 20);
 
   /**
-   * Create an empty tree node.
+   * Create a binary space tree by copying the other tree.  Be careful!  This
+   * can take a long time and use a lot of memory.
+   *
+   * @param other Tree to be replicated.
    */
-  BinarySpaceTree();
+  BinarySpaceTree(const BinarySpaceTree& other);
 
   /**
    * Deletes this node, deallocating the memory for the children and calling
@@ -236,30 +245,57 @@
   BinarySpaceTree* FindByBeginCount(size_t begin, size_t count);
 
   //! Return the bound object for this node.
-  const BoundType& Bound() const;
+  const BoundType& Bound() const { return bound; }
   //! Return the bound object for this node.
-  BoundType& Bound();
+  BoundType& Bound() { return bound; }
 
   //! Return the statistic object for this node.
-  const StatisticType& Stat() const;
+  const StatisticType& Stat() const { return stat; }
   //! Return the statistic object for this node.
-  StatisticType& Stat();
+  StatisticType& Stat() { return stat; }
 
   //! Return whether or not this node is a leaf (true if it has no children).
   bool IsLeaf() const;
 
   //! Return the leaf size.
-  size_t LeafSize() const;
+  size_t LeafSize() const { return leafSize; }
+  //! Modify the leaf size.
+  size_t& LeafSize() { return leafSize; }
 
   //! Fills the tree to the specified level.
   size_t ExtendTree(const size_t level);
 
   //! Gets the left child of this node.
-  BinarySpaceTree* Left() const;
+  BinarySpaceTree* Left() const { return left; }
+  //! Modify the left child of this node.
+  BinarySpaceTree*& Left() { return left; }
 
   //! Gets the right child of this node.
-  BinarySpaceTree* Right() const;
+  BinarySpaceTree* Right() const { return right; }
+  //! Modify the right child of this node.
+  BinarySpaceTree*& Right() { return right; }
 
+  //! Gets the parent of this node.
+  BinarySpaceTree* Parent() const { return parent; }
+  //! Modify the parent of this node.
+  BinarySpaceTree*& Parent() { return parent; }
+
+  //! Get the split dimension for this node.
+  size_t SplitDimension() const { return splitDimension; }
+  //! Modify the split dimension for this node.
+  size_t& SplitDimension() { return splitDimension; }
+
+  //! Get the dataset which the tree is built on.
+  const arma::mat& Dataset() const { return dataset; }
+  //! Modify the dataset which the tree is built on.  Be careful!
+  arma::mat& Dataset() { return dataset; }
+
+  //! Get the metric which the tree uses.
+  typename BoundType::MetricType Metric() const { return bound.Metric(); }
+
+  //! Get the centroid of the node and store it in the given vector.
+  void Centroid(arma::vec& centroid) { bound.Centroid(centroid); }
+
   //! Return the number of children in this node.
   size_t NumChildren() const;
 
@@ -333,20 +369,20 @@
    */
   size_t TreeDepth() const;
 
-  /**
-   * Gets the index of the beginning point of this subset.
-   */
-  size_t Begin() const;
+  //! Return the index of the beginning point of this subset.
+  size_t Begin() const { return begin; }
+  //! Modify the index of the beginning point of this subset.
+  size_t& Begin() { return begin; }
 
   /**
    * Gets the index one beyond the last index in the subset.
    */
   size_t End() const;
 
-  /**
-   * Gets the number of points in this subset.
-   */
-  size_t Count() const;
+  //! Return the number of points in this subset.
+  size_t Count() const { return count; }
+  //! Modify the number of points in this subset.
+  size_t& Count() { return count; }
 
   //! Returns false: this tree type does not have self children.
   static bool HasSelfChildren() { return false; }
@@ -412,6 +448,12 @@
    */
   size_t GetSplitIndex(MatType& data, int splitDim, double splitVal,
       std::vector<size_t>& oldFromNew);
+ public:
+  /**
+   * Returns a string representation of this object.
+   */
+  std::string ToString() const;
+
 };
 
 }; // namespace tree

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -26,6 +26,7 @@
 
 #include <mlpack/core/util/cli.hpp>
 #include <mlpack/core/util/log.hpp>
+#include <mlpack/core/util/string_util.hpp>
 
 namespace mlpack {
 namespace tree {
@@ -38,20 +39,18 @@
     const size_t leafSize) :
     left(NULL),
     right(NULL),
+    parent(NULL),
     begin(0), /* This root node starts at index 0, */
     count(data.n_cols), /* and spans all of the dataset. */
+    leafSize(leafSize),
     bound(data.n_rows),
-    stat(),
-    leafSize(leafSize)
+    dataset(data)
 {
   // Do the actual splitting of this node.
   SplitNode(data);
 
   // Create the statistic depending on if we are a leaf or not.
-  if (IsLeaf())
-    stat = StatisticType(data, begin, count);
-  else
-    stat = StatisticType(data, begin, count, left->Stat(), right->Stat());
+  stat = StatisticType(*this);
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -61,11 +60,12 @@
     const size_t leafSize) :
     left(NULL),
     right(NULL),
+    parent(NULL),
     begin(0),
     count(data.n_cols),
+    leafSize(leafSize),
     bound(data.n_rows),
-    stat(),
-    leafSize(leafSize)
+    dataset(data)
 {
   // Initialize oldFromNew correctly.
   oldFromNew.resize(data.n_cols);
@@ -76,10 +76,7 @@
   SplitNode(data, oldFromNew);
 
   // Create the statistic depending on if we are a leaf or not.
-  if (IsLeaf())
-    stat = StatisticType(data, begin, count);
-  else
-    stat = StatisticType(data, begin, count, left->Stat(), right->Stat());
+  stat = StatisticType(*this);
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -90,11 +87,12 @@
     const size_t leafSize) :
     left(NULL),
     right(NULL),
+    parent(NULL),
     begin(0),
     count(data.n_cols),
+    leafSize(leafSize),
     bound(data.n_rows),
-    stat(),
-    leafSize(leafSize)
+    dataset(data)
 {
   // Initialize the oldFromNew vector correctly.
   oldFromNew.resize(data.n_cols);
@@ -105,10 +103,7 @@
   SplitNode(data, oldFromNew);
 
   // Create the statistic depending on if we are a leaf or not.
-  if (IsLeaf())
-    stat = StatisticType(data, begin, count);
-  else
-    stat = StatisticType(data, begin, count, left->Stat(), right->Stat());
+  stat = StatisticType(*this);
 
   // Map the newFromOld indices correctly.
   newFromOld.resize(data.n_cols);
@@ -121,23 +116,22 @@
     MatType& data,
     const size_t begin,
     const size_t count,
+    BinarySpaceTree* parent,
     const size_t leafSize) :
     left(NULL),
     right(NULL),
+    parent(parent),
     begin(begin),
     count(count),
+    leafSize(leafSize),
     bound(data.n_rows),
-    stat(),
-    leafSize(leafSize)
+    dataset(data)
 {
   // Perform the actual splitting.
   SplitNode(data);
 
   // Create the statistic depending on if we are a leaf or not.
-  if (IsLeaf())
-    stat = StatisticType(data, begin, count);
-  else
-    stat = StatisticType(data, begin, count, left->Stat(), right->Stat());
+  stat = StatisticType(*this);
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -146,14 +140,16 @@
     const size_t begin,
     const size_t count,
     std::vector<size_t>& oldFromNew,
+    BinarySpaceTree* parent,
     const size_t leafSize) :
     left(NULL),
     right(NULL),
+    parent(parent),
     begin(begin),
     count(count),
+    leafSize(leafSize),
     bound(data.n_rows),
-    stat(),
-    leafSize(leafSize)
+    dataset(data)
 {
   // Hopefully the vector is initialized correctly!  We can't check that
   // entirely but we can do a minor sanity check.
@@ -163,10 +159,7 @@
   SplitNode(data, oldFromNew);
 
   // Create the statistic depending on if we are a leaf or not.
-  if (IsLeaf())
-    stat = StatisticType(data, begin, count);
-  else
-    stat = StatisticType(data, begin, count, left->Stat(), right->Stat());
+  stat = StatisticType(*this);
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -176,14 +169,16 @@
     const size_t count,
     std::vector<size_t>& oldFromNew,
     std::vector<size_t>& newFromOld,
+    BinarySpaceTree* parent,
     const size_t leafSize) :
     left(NULL),
     right(NULL),
+    parent(parent),
     begin(begin),
     count(count),
+    leafSize(leafSize),
     bound(data.n_rows),
-    stat(),
-    leafSize(leafSize)
+    dataset(data)
 {
   // Hopefully the vector is initialized correctly!  We can't check that
   // entirely but we can do a minor sanity check.
@@ -193,10 +188,7 @@
   SplitNode(data, oldFromNew);
 
   // Create the statistic depending on if we are a leaf or not.
-  if (IsLeaf())
-    stat = StatisticType(data, begin, count);
-  else
-    stat = StatisticType(data, begin, count, left->Stat(), right->Stat());
+  stat = StatisticType(*this);
 
   // Map the newFromOld indices correctly.
   newFromOld.resize(data.n_cols);
@@ -204,10 +196,12 @@
     newFromOld[oldFromNew[i]] = i;
 }
 
+/*
 template<typename BoundType, typename StatisticType, typename MatType>
 BinarySpaceTree<BoundType, StatisticType, MatType>::BinarySpaceTree() :
     left(NULL),
     right(NULL),
+    parent(NULL),
     begin(0),
     count(0),
     bound(),
@@ -215,6 +209,39 @@
     leafSize(20) // Default leaf size is 20.
 {
   // Nothing to do.
+}*/
+
+/**
+ * Create a binary space tree by copying the other tree.  Be careful!  This can
+ * take a long time and use a lot of memory.
+ */
+template<typename BoundType, typename StatisticType, typename MatType>
+BinarySpaceTree<BoundType, StatisticType, MatType>::BinarySpaceTree(
+    const BinarySpaceTree& other) :
+    left(NULL),
+    right(NULL),
+    parent(other.parent),
+    begin(other.begin),
+    count(other.count),
+    leafSize(other.leafSize),
+    bound(other.bound),
+    stat(other.stat),
+    splitDimension(other.splitDimension),
+    furthestDescendantDistance(other.furthestDescendantDistance),
+    dataset(other.dataset)
+{
+  // Create left and right children (if any).
+  if (other.Left())
+  {
+    left = new BinarySpaceTree(*other.Left());
+    left->Parent() = this; // Set parent to this, not other tree.
+  }
+
+  if (other.Right())
+  {
+    right = new BinarySpaceTree(*other.Right());
+    right->Parent() = this; // Set parent to this, not other tree.
+  }
 }
 
 /**
@@ -342,64 +369,12 @@
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
-inline const
-    BoundType& BinarySpaceTree<BoundType, StatisticType, MatType>::Bound() const
-{
-  return bound;
-}
-
-template<typename BoundType, typename StatisticType, typename MatType>
-inline BoundType& BinarySpaceTree<BoundType, StatisticType, MatType>::Bound()
-{
-  return bound;
-}
-
-template<typename BoundType, typename StatisticType, typename MatType>
-inline const StatisticType&
-    BinarySpaceTree<BoundType, StatisticType, MatType>::Stat() const
-{
-  return stat;
-}
-
-template<typename BoundType, typename StatisticType, typename MatType>
-inline StatisticType& BinarySpaceTree<BoundType, StatisticType, MatType>::Stat()
-{
-  return stat;
-}
-
-template<typename BoundType, typename StatisticType, typename MatType>
-inline size_t BinarySpaceTree<BoundType, StatisticType, MatType>::GetSplitDimension() const
-{
-  return splitDimension;
-}
-
-template<typename BoundType, typename StatisticType, typename MatType>
 inline bool BinarySpaceTree<BoundType, StatisticType, MatType>::IsLeaf() const
 {
   return !left;
 }
 
 /**
- * Gets the left branch of the tree.
- */
-template<typename BoundType, typename StatisticType, typename MatType>
-inline BinarySpaceTree<BoundType, StatisticType, MatType>*
-    BinarySpaceTree<BoundType, StatisticType, MatType>::Left() const
-{
-  return left;
-}
-
-/**
- * Gets the right branch.
- */
-template<typename BoundType, typename StatisticType, typename MatType>
-inline BinarySpaceTree<BoundType, StatisticType, MatType>*
-    BinarySpaceTree<BoundType, StatisticType, MatType>::Right() const
-{
-  return right;
-}
-
-/**
  * Returns the number of children in this node.
  */
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -425,9 +400,7 @@
 inline double BinarySpaceTree<BoundType, StatisticType, MatType>::
     FurthestDescendantDistance() const
 {
-  arma::vec centroid;
-  bound.Centroid(centroid);
-  return bound.MaxDistance(centroid);
+  return furthestDescendantDistance;
 }
 
 /**
@@ -469,15 +442,6 @@
 }
 
 /**
- * Gets the index of the begin point of this subset.
- */
-template<typename BoundType, typename StatisticType, typename MatType>
-inline size_t BinarySpaceTree<BoundType, StatisticType, MatType>::Begin() const
-{
-  return begin;
-}
-
-/**
  * Gets the index one beyond the last index in the series.
  */
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -486,22 +450,16 @@
   return begin + count;
 }
 
-/**
- * Gets the number of points in this subset.
- */
 template<typename BoundType, typename StatisticType, typename MatType>
-inline size_t BinarySpaceTree<BoundType, StatisticType, MatType>::Count() const
-{
-  return count;
-}
-
-template<typename BoundType, typename StatisticType, typename MatType>
 void
     BinarySpaceTree<BoundType, StatisticType, MatType>::SplitNode(MatType& data)
 {
   // We need to expand the bounds of this node properly.
   bound |= data.cols(begin, begin + count - 1);
 
+  // Calculate the furthest descendant distance.
+  furthestDescendantDistance = 0.5 * bound.Diameter();
+
   // Now, check if we need to split at all.
   if (count <= leafSize)
     return; // We can't split this.
@@ -538,9 +496,9 @@
   // Now that we know the split column, we will recursively split the children
   // by calling their constructors (which perform this splitting process).
   left = new BinarySpaceTree<BoundType, StatisticType, MatType>(data, begin,
-      splitCol - begin, leafSize);
+      splitCol - begin, this, leafSize);
   right = new BinarySpaceTree<BoundType, StatisticType, MatType>(data, splitCol,
-      begin + count - splitCol, leafSize);
+      begin + count - splitCol, this, leafSize);
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -552,6 +510,9 @@
   // We need to expand the bounds of this node properly.
   bound |= data.cols(begin, begin + count - 1);
 
+  // Calculate the furthest descendant distance.
+  furthestDescendantDistance = 0.5 * bound.Diameter();
+
   // First, check if we need to split at all.
   if (count <= leafSize)
     return; // We can't split this.
@@ -588,9 +549,9 @@
   // Now that we know the split column, we will recursively split the children
   // by calling their constructors (which perform this splitting process).
   left = new BinarySpaceTree<BoundType, StatisticType, MatType>(data, begin,
-      splitCol - begin, oldFromNew, leafSize);
+      splitCol - begin, oldFromNew, this, leafSize);
   right = new BinarySpaceTree<BoundType, StatisticType, MatType>(data, splitCol,
-      begin + count - splitCol, oldFromNew, leafSize);
+      begin + count - splitCol, oldFromNew, this, leafSize);
 }
 
 template<typename BoundType, typename StatisticType, typename MatType>
@@ -687,6 +648,33 @@
   return left;
 }
 
+/**
+ * Returns a string representation of this object.
+ */
+template<typename BoundType, typename StatisticType, typename MatType>
+std::string BinarySpaceTree<BoundType, StatisticType, MatType>::ToString() const
+{
+  std::ostringstream convert;
+  convert << "BinarySpaceTree [" << this << "]" << std::endl;
+  convert << "begin: " << begin << std::endl;
+  convert << "count: " << count << std::endl;
+  convert << "bound: " << mlpack::util::Indent(bound.ToString());
+  convert << "statistic: " << stat.ToString();
+  convert << "leaf size: " << leafSize << std::endl;
+  convert << "splitDimension: " << splitDimension << std::endl;
+  if (left != NULL)
+  {
+    convert << "left:" << std::endl;
+    convert << mlpack::util::Indent(left->ToString());
+  }
+  if (right != NULL)
+  {
+    convert << "right:" << std::endl;
+    convert << mlpack::util::Indent(right->ToString());
+  }
+  return convert.str();
+}
+
 }; // namespace tree
 }; // namespace mlpack
 

Copied: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/traits.hpp (from rev 14992, mlpack/trunk/src/mlpack/core/tree/binary_space_tree/traits.hpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/traits.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree/traits.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,49 @@
+/**
+ * @file traits.hpp
+ * @author Ryan Curtin
+ *
+ * Specialization of the TreeTraits class for the BinarySpaceTree type of tree.
+ */
+#ifndef __MLPACK_CORE_TREE_BINARY_SPACE_TREE_TRAITS_HPP
+#define __MLPACK_CORE_TREE_BINARY_SPACE_TREE_TRAITS_HPP
+
+#include <mlpack/core/tree/tree_traits.hpp>
+
+namespace mlpack {
+namespace tree {
+
+/**
+ * This is a specialization of the TreeType class to the BinarySpaceTree tree
+ * type.  It defines characteristics of the binary space tree, and is used to
+ * help write tree-independent (but still optimized) tree-based algorithms.  See
+ * mlpack/core/tree/tree_traits.hpp for more information.
+ */
+template<typename BoundType,
+         typename StatisticType,
+         typename MatType>
+class TreeTraits<BinarySpaceTree<BoundType, StatisticType, MatType> >
+{
+ public:
+  /**
+   * The binary space tree cannot easily calculate the distance from a node to
+   * its parent; so BinarySpaceTree<...>::ParentDistance() does not exist.
+   */
+  static const bool HasParentDistance = false;
+
+  /**
+   * Each binary space tree node has two children which represent
+   * non-overlapping subsets of the space which the node represents.  Therefore,
+   * children are not overlapping.
+   */
+  static const bool HasOverlappingChildren = false;
+
+  /**
+   * There is no guarantee that the first point in a node is its centroid.
+   */
+  static const bool FirstPointIsCentroid = false;
+};
+
+}; // namespace tree
+}; // namespace mlpack
+
+#endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/binary_space_tree.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -26,5 +26,6 @@
 #include "binary_space_tree/binary_space_tree.hpp"
 #include "binary_space_tree/single_tree_traverser.hpp"
 #include "binary_space_tree/dual_tree_traverser.hpp"
+#include "binary_space_tree/traits.hpp"
 
 #endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -110,6 +110,8 @@
    * The dataset will not be modified during the building procedure (unlike
    * BinarySpaceTree).
    *
+   * The last argument will be removed in mlpack 1.1.0 (see #274 and #273).
+   *
    * @param dataset Reference to the dataset to build a tree on.
    * @param base Base to use during tree building (default 2.0).
    */
@@ -118,6 +120,19 @@
             MetricType* metric = NULL);
 
   /**
+   * Create the cover tree with the given dataset and the given instantiated
+   * metric.  Optionally, set the base.  The dataset will not be modified during
+   * the building procedure (unlike BinarySpaceTree).
+   *
+   * @param dataset Reference to the dataset to build a tree on.
+   * @param metric Instantiated metric to use during tree building.
+   * @param base Base to use during tree building (default 2.0).
+   */
+  CoverTree(const arma::mat& dataset,
+            MetricType& metric,
+            const double base = 2.0);
+
+  /**
    * Construct a child cover tree node.  This constructor is not meant to be
    * used externally, but it could be used to insert another node into a tree.
    * This procedure uses only one vector for the near set, the far set, and the
@@ -136,6 +151,8 @@
    * @param base Base to use during tree building.
    * @param pointIndex Index of the point this node references.
    * @param scale Scale of this level in the tree.
+   * @param parent Parent of this node (NULL indicates no parent).
+   * @param parentDistance Distance to the parent node.
    * @param indices Array of indices, ordered [ nearSet | farSet | usedSet ];
    *     will be modified to [ farSet | usedSet ].
    * @param distances Array of distances, ordered the same way as the indices.
@@ -150,6 +167,7 @@
             const double base,
             const size_t pointIndex,
             const int scale,
+            CoverTree* parent,
             const double parentDistance,
             arma::Col<size_t>& indices,
             arma::vec& distances,
@@ -169,17 +187,29 @@
    * @param pointIndex Index of the point in the dataset which this node refers
    *      to.
    * @param scale Scale of this node's level in the tree.
+   * @param parent Parent node (NULL indicates no parent).
    * @param parentDistance Distance to parent node point.
    * @param furthestDescendantDistance Distance to furthest descendant point.
+   * @param metric Instantiated metric (optional).
    */
   CoverTree(const arma::mat& dataset,
             const double base,
             const size_t pointIndex,
             const int scale,
+            CoverTree* parent,
             const double parentDistance,
-            const double furthestDescendantDistance);
+            const double furthestDescendantDistance,
+            MetricType* metric = NULL);
 
   /**
+   * Create a cover tree from another tree.  Be careful!  This may use a lot of
+   * memory and take a lot of time.
+   *
+   * @param other Cover tree to copy from.
+   */
+  CoverTree(const CoverTree& other);
+
+  /**
    * Delete this cover tree node and its children.
    */
   ~CoverTree();
@@ -269,6 +299,11 @@
   //! Returns true: this tree does have self-children.
   static bool HasSelfChildren() { return true; }
 
+  //! Get the parent node.
+  CoverTree* Parent() const { return parent; }
+  //! Modify the parent node.
+  CoverTree*& Parent() { return parent; }
+
   //! Get the distance to the parent.
   double ParentDistance() const { return parentDistance; }
   //! Modify the distance to the parent.
@@ -280,6 +315,12 @@
   //! Modify the distance to the furthest descendant.
   double& FurthestDescendantDistance() { return furthestDescendantDistance; }
 
+  //! Get the centroid of the node and store it in the given vector.
+  void Centroid(arma::vec& centroid) const { centroid = dataset.col(point); }
+
+  //! Get the instantiated metric.
+  MetricType& Metric() const { return *metric; }
+
  private:
   //! Reference to the matrix which this tree is built on.
   const arma::mat& dataset;
@@ -299,13 +340,31 @@
   //! The instantiated statistic.
   StatisticType stat;
 
+  //! The parent node (NULL if this is the root of the tree).
+  CoverTree* parent;
+
   //! Distance to the parent.
   double parentDistance;
 
   //! Distance to the furthest descendant.
   double furthestDescendantDistance;
 
+  //! Whether or not we need to destroy the metric in the destructor.
+  bool localMetric;
+
+  //! The metric used for this tree.
+  MetricType* metric;
+
   /**
+   * Create the children for this node.
+   */
+  void CreateChildren(arma::Col<size_t>& indices,
+                      arma::vec& distances,
+                      size_t nearSetSize,
+                      size_t& farSetSize,
+                      size_t& usedSetSize);
+
+  /**
    * Fill the vector of distances with the distances between the point specified
    * by pointIndex and each point in the indices array.  The distances of the
    * first pointSetSize points in indices are calculated (so, this does not
@@ -319,8 +378,7 @@
   void ComputeDistances(const size_t pointIndex,
                         const arma::Col<size_t>& indices,
                         arma::vec& distances,
-                        const size_t pointSetSize,
-                        MetricType& metric);
+                        const size_t pointSetSize);
   /**
    * Split the given indices and distances into a near and a far set, returning
    * the number of points in the near set.  The distances must already be
@@ -378,6 +436,11 @@
                      const double bound,
                      const size_t nearSetSize,
                      const size_t pointSetSize);
+ public:
+  /**
+   * Returns a string representation of this object.
+   */
+  std::string ToString() const;
 };
 
 }; // namespace tree

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -25,6 +25,9 @@
 // In case it hasn't already been included.
 #include "cover_tree.hpp"
 
+#include <mlpack/core/util/string_util.hpp>
+#include <string>
+
 namespace mlpack {
 namespace tree {
 
@@ -36,18 +39,22 @@
     MetricType* metric) :
     dataset(dataset),
     point(RootPointPolicy::ChooseRoot(dataset)),
+    scale(INT_MAX),
     base(base),
+    parent(NULL),
     parentDistance(0),
-    furthestDescendantDistance(0)
+    furthestDescendantDistance(0),
+    localMetric(metric == NULL),
+    metric(metric)
 {
   // If we need to create a metric, do that.  We'll just do it on the heap.
-  bool localMetric = false;
-  if (metric == NULL)
-  {
-    localMetric = true; // So we know we need to free it.
-    metric = new MetricType();
-  }
+  if (localMetric)
+    this->metric = new MetricType();
 
+  // If there is only one point in the dataset... uh, we're done.
+  if (dataset.n_cols == 1)
+    return;
+
   // Kick off the building.  Create the indices array and the distances array.
   arma::Col<size_t> indices = arma::linspace<arma::Col<size_t> >(1,
       dataset.n_cols - 1, dataset.n_cols - 1);
@@ -59,145 +66,66 @@
   arma::vec distances(dataset.n_cols - 1);
 
   // Build the initial distances.
-  ComputeDistances(point, indices, distances, dataset.n_cols - 1, *metric);
+  ComputeDistances(point, indices, distances, dataset.n_cols - 1);
 
-  // Now determine the scale factor of the root node.
-  const double maxDistance = max(distances);
-  scale = (int) ceil(log(maxDistance) / log(base));
-  const double bound = pow(base, scale - 1);
-
-  // Unfortunately, we can't call out to other constructors, so we have to copy
-  // a little bit of code from the other constructor.  First we build the self
-  // child.
-  size_t childNearSetSize = SplitNearFar(indices, distances, bound,
-      dataset.n_cols - 1);
-  size_t childFarSetSize = (dataset.n_cols - 1) - childNearSetSize;
+  // Create the children.
+  size_t farSetSize = 0;
   size_t usedSetSize = 0;
-  children.push_back(new CoverTree(dataset, base, point, scale - 1,
-      0, indices, distances, childNearSetSize, childFarSetSize, usedSetSize,
-      *metric));
+  CreateChildren(indices, distances, dataset.n_cols - 1, farSetSize,
+      usedSetSize);
 
-  furthestDescendantDistance = children[0]->FurthestDescendantDistance();
+  // Use the furthest descendant distance to determine the scale of the root
+  // node.
+  scale = (int) ceil(log(furthestDescendantDistance) / log(base));
 
-  // If we created an implicit node, take its self-child instead (this could
-  // happen multiple times).
-  while (children[children.size() - 1]->NumChildren() == 1)
-  {
-    CoverTree* old = children[children.size() - 1];
-    children.erase(children.begin() + children.size() - 1);
+  // Initialize statistic.
+  stat = StatisticType(*this);
+}
 
-    // Now take its child.
-    children.push_back(&(old->Child(0)));
+template<typename MetricType, typename RootPointPolicy, typename StatisticType>
+CoverTree<MetricType, RootPointPolicy, StatisticType>::CoverTree(
+    const arma::mat& dataset,
+    MetricType& metric,
+    const double base) :
+    dataset(dataset),
+    point(RootPointPolicy::ChooseRoot(dataset)),
+    scale(INT_MAX),
+    base(base),
+    parent(NULL),
+    parentDistance(0),
+    furthestDescendantDistance(0),
+    localMetric(false),
+    metric(&metric)
+{
+  // If there is only one point in the dataset, uh, we're done.
+  if (dataset.n_cols == 1)
+    return;
 
-    // Remove its child (so it doesn't delete it).
-    old->Children().erase(old->Children().begin() + old->Children().size() - 1);
+  // Kick off the building.  Create the indices array and the distances array.
+  arma::Col<size_t> indices = arma::linspace<arma::Col<size_t> >(1,
+      dataset.n_cols - 1, dataset.n_cols - 1);
+  // This is now [1 2 3 4 ... n].  We must be sure that our point does not
+  // occur.
+  if (point != 0)
+    indices[point - 1] = 0; // Put 0 back into the set; remove what was there.
 
-    // Now delete it.
-    delete old;
-  }
+  arma::vec distances(dataset.n_cols - 1);
 
-  size_t nearSetSize = (dataset.n_cols - 1) - usedSetSize;
+  // Build the initial distances.
+  ComputeDistances(point, indices, distances, dataset.n_cols - 1);
 
-  // We have no far set, so the array is organized thusly:
-  // [ near | used ].  No resorting is necessary.
-  // Therefore, go ahead and build the children.
-  while (nearSetSize > 0)
-  {
-    // We want to select the furthest point in the near set as the next child.
-    size_t newPointIndex = nearSetSize - 1;
+  // Create the children.
+  size_t farSetSize = 0;
+  size_t usedSetSize = 0;
+  CreateChildren(indices, distances, dataset.n_cols - 1, farSetSize,
+      usedSetSize);
 
-    // Swap to front if necessary.
-    if (newPointIndex != 0)
-    {
-      const size_t tempIndex = indices[newPointIndex];
-      const double tempDist = distances[newPointIndex];
+  // Use the furthest descendant distance to determine the scale of the root
+  // node.
+  scale = (int) ceil(log(furthestDescendantDistance) / log(base));
 
-      indices[newPointIndex] = indices[0];
-      distances[newPointIndex] = distances[0];
-
-      indices[0] = tempIndex;
-      distances[0] = tempDist;
-    }
-
-    if (distances[0] > furthestDescendantDistance)
-      furthestDescendantDistance = distances[0];
-
-    size_t childUsedSetSize = 0;
-
-    // If there's only one point left, we don't need this crap.
-    if (nearSetSize == 1)
-    {
-      size_t childNearSetSize = 0;
-      size_t childFarSetSize = 0;
-      children.push_back(new CoverTree(dataset, base,
-          indices[0], scale - 1, distances[0], indices, distances,
-          childNearSetSize, childFarSetSize, usedSetSize, *metric));
-
-      // And we're done.
-      break;
-    }
-
-    // Create the near and far set indices and distance vectors.
-    arma::Col<size_t> childIndices(nearSetSize);
-    childIndices.rows(0, (nearSetSize - 2)) = indices.rows(1, nearSetSize - 1);
-    // Put the current point into the used set, so when we move our indices to
-    // the used set, this will be done for us.
-    childIndices(nearSetSize - 1) = indices[0];
-    arma::vec childDistances(nearSetSize);
-
-    // Build distances for the child.
-    ComputeDistances(indices[0], childIndices, childDistances,
-        nearSetSize - 1, *metric);
-    childDistances(nearSetSize - 1) = 0;
-
-    // Split into near and far sets for this point.
-    childNearSetSize = SplitNearFar(childIndices, childDistances, bound,
-        nearSetSize - 1);
-
-    // Build this child (recursively).
-    childUsedSetSize = 1; // Mark self point as used.
-    childFarSetSize = ((nearSetSize - 1) - childNearSetSize);
-    children.push_back(new CoverTree(dataset, base, indices[0],
-        scale - 1, distances[0], childIndices, childDistances, childNearSetSize,
-        childFarSetSize, childUsedSetSize, *metric));
-
-    // If we created an implicit node, take its self-child instead (this could
-    // happen multiple times).
-    while (children[children.size() - 1]->NumChildren() == 1)
-    {
-      CoverTree* old = children[children.size() - 1];
-      children.erase(children.begin() + children.size() - 1);
-
-      // Now take its child.
-      children.push_back(&(old->Child(0)));
-
-      // Remove its child (so it doesn't delete it).
-      old->Children().erase(old->Children().begin() + old->Children().size()
-          - 1);
-
-      // Now delete it.
-      delete old;
-    }
-
-    // Now with the child created, it returns the childIndices and
-    // childDistances vectors in this form:
-    // [ childFar | childUsed ]
-    // For each point in the childUsed set, we must move that point to the used
-    // set in our own vector.
-    size_t farSetSize = 0;
-    MoveToUsedSet(indices, distances, nearSetSize, farSetSize, usedSetSize,
-        childIndices, childFarSetSize, childUsedSetSize);
-  }
-
-  // Calculate furthest descendant.
-  for (size_t i = 0; i < usedSetSize; ++i)
-    if (distances[i] > furthestDescendantDistance)
-      furthestDescendantDistance = distances[i];
-
-  Log::Assert(furthestDescendantDistance <= pow(base, scale + 1));
-
-  if (localMetric)
-    delete metric;
+  // Initialize statistic.
+  stat = StatisticType(*this);
 }
 
 template<typename MetricType, typename RootPointPolicy, typename StatisticType>
@@ -206,6 +134,7 @@
     const double base,
     const size_t pointIndex,
     const int scale,
+    CoverTree* parent,
     const double parentDistance,
     arma::Col<size_t>& indices,
     arma::vec& distances,
@@ -217,20 +146,40 @@
     point(pointIndex),
     scale(scale),
     base(base),
+    parent(parent),
     parentDistance(parentDistance),
-    furthestDescendantDistance(0)
+    furthestDescendantDistance(0),
+    localMetric(false),
+    metric(&metric)
 {
   // If the size of the near set is 0, this is a leaf.
   if (nearSetSize == 0)
   {
     this->scale = INT_MIN;
+    stat = StatisticType(*this);
     return;
   }
 
+  // Otherwise, create the children.
+  CreateChildren(indices, distances, nearSetSize, farSetSize, usedSetSize);
+
+  // Initialize statistic.
+  stat = StatisticType(*this);
+}
+
+template<typename MetricType, typename RootPointPolicy, typename StatisticType>
+inline void
+CoverTree<MetricType, RootPointPolicy, StatisticType>::CreateChildren(
+    arma::Col<size_t>& indices,
+    arma::vec& distances,
+    size_t nearSetSize,
+    size_t& farSetSize,
+    size_t& usedSetSize)
+{
   // Determine the next scale level.  This should be the first level where there
   // are any points in the far set.  So, if we know the maximum distance in the
   // distances array, this will be the largest i such that
-  //   maxDistance > pow(ec, i)
+  //   maxDistance > pow(base, i)
   // and using this for the scale factor should guarantee we are not creating an
   // implicit node.  If the maximum distance is 0, every point in the near set
   // will be created as a leaf, and a child to this node.  We also do not need
@@ -242,15 +191,16 @@
     // Make the self child at the lowest possible level.
     // This should not modify farSetSize or usedSetSize.
     size_t tempSize = 0;
-    children.push_back(new CoverTree(dataset, base, pointIndex,
-        INT_MIN, 0, indices, distances, 0, tempSize, usedSetSize, metric));
+    children.push_back(new CoverTree(dataset, base, point, INT_MIN, this, 0,
+        indices, distances, 0, tempSize, usedSetSize, *metric));
 
     // Every point in the near set should be a leaf.
     for (size_t i = 0; i < nearSetSize; ++i)
     {
       // farSetSize and usedSetSize will not be modified.
       children.push_back(new CoverTree(dataset, base, indices[i],
-          INT_MIN, 0, indices, distances, 0, tempSize, usedSetSize, metric));
+          INT_MIN, this, distances[i], indices, distances, 0, tempSize,
+          usedSetSize, *metric));
       usedSetSize++;
     }
 
@@ -260,6 +210,9 @@
     // [ far | all used ].
     SortPointSet(indices, distances, 0, usedSetSize, farSetSize);
 
+    // Initialize the statistic.
+    stat = StatisticType(*this);
+
     return;
   }
 
@@ -267,9 +220,6 @@
       (int) ceil(log(maxDistance) / log(base))) - 1;
   const double bound = pow(base, nextScale);
 
-  // This needs to be taken out.  It's a sanity check for now.
-  Log::Assert(nextScale < scale);
-
   // First, make the self child.  We must split the given near set into the near
   // set and far set for the self child.
   size_t childNearSetSize =
@@ -278,9 +228,9 @@
   // Build the self child (recursively).
   size_t childFarSetSize = nearSetSize - childNearSetSize;
   size_t childUsedSetSize = 0;
-  children.push_back(new CoverTree(dataset, base, pointIndex,
-      nextScale, 0, indices, distances, childNearSetSize, childFarSetSize,
-      childUsedSetSize, metric));
+  children.push_back(new CoverTree(dataset, base, point, nextScale, this, 0,
+      indices, distances, childNearSetSize, childFarSetSize, childUsedSetSize,
+      *metric));
 
   // The self-child can't modify the furthestChildDistance away from 0, but it
   // can modify the furthestDescendantDistance.
@@ -296,6 +246,9 @@
     // Now take its child.
     children.push_back(&(old->Child(0)));
 
+    // Set its parent correctly.
+    old->Child(0).Parent() = this;
+
     // Remove its child (so it doesn't delete it).
     old->Children().erase(old->Children().begin() + old->Children().size() - 1);
 
@@ -346,9 +299,9 @@
     if ((nearSetSize == 1) && (farSetSize == 0))
     {
       size_t childNearSetSize = 0;
-      children.push_back(new CoverTree(dataset, base,
-          indices[0], nextScale, distances[0], indices, distances,
-          childNearSetSize, farSetSize, usedSetSize, metric));
+      children.push_back(new CoverTree(dataset, base, indices[0], nextScale,
+          this, distances[0], indices, distances, childNearSetSize, farSetSize,
+          usedSetSize, *metric));
 
       // Because the far set size is 0, we don't have to do any swapping to
       // move the point into the used set.
@@ -368,7 +321,7 @@
 
     // Build distances for the child.
     ComputeDistances(indices[0], childIndices, childDistances, nearSetSize
-        + farSetSize - 1, metric);
+        + farSetSize - 1);
 
     // Split into near and far sets for this point.
     childNearSetSize = SplitNearFar(childIndices, childDistances, bound,
@@ -386,9 +339,9 @@
 
     // Build this child (recursively).
     childUsedSetSize = 1; // Mark self point as used.
-    children.push_back(new CoverTree(dataset, base, indices[0],
-        nextScale, distances[0], childIndices, childDistances, childNearSetSize,
-        childFarSetSize, childUsedSetSize, metric));
+    children.push_back(new CoverTree(dataset, base, indices[0], nextScale,
+        this, distances[0], childIndices, childDistances, childNearSetSize,
+        childFarSetSize, childUsedSetSize, *metric));
 
     // If we created an implicit node, take its self-child instead (this could
     // happen multiple times).
@@ -400,6 +353,9 @@
       // Now take its child.
       children.push_back(&(old->Child(0)));
 
+      // Set its parent correctly.
+      old->Child(0).Parent() = this;
+
       // Remove its child (so it doesn't delete it).
       old->Children().erase(old->Children().begin() + old->Children().size()
           - 1);
@@ -422,8 +378,6 @@
       usedSetSize); ++i)
     if (distances[i] > furthestDescendantDistance)
       furthestDescendantDistance = distances[i];
-
-  Log::Assert(furthestDescendantDistance <= pow(base, scale + 1));
 }
 
 // Manually create a cover tree node.
@@ -433,24 +387,60 @@
     const double base,
     const size_t pointIndex,
     const int scale,
+    CoverTree* parent,
     const double parentDistance,
-    const double furthestDescendantDistance) :
+    const double furthestDescendantDistance,
+    MetricType* metric) :
     dataset(dataset),
     point(pointIndex),
     scale(scale),
     base(base),
+    parent(parent),
     parentDistance(parentDistance),
-    furthestDescendantDistance(furthestDescendantDistance)
+    furthestDescendantDistance(furthestDescendantDistance),
+    localMetric(metric == NULL),
+    metric(metric)
 {
-  // Nothing to do.
+  // If necessary, create a local metric.
+  if (localMetric)
+    this->metric = new MetricType();
+
+  // Initialize the statistic.
+  stat = StatisticType(*this);
 }
 
 template<typename MetricType, typename RootPointPolicy, typename StatisticType>
+CoverTree<MetricType, RootPointPolicy, StatisticType>::CoverTree(
+    const CoverTree& other) :
+    dataset(other.dataset),
+    point(other.point),
+    scale(other.scale),
+    base(other.base),
+    stat(other.stat),
+    parent(other.parent),
+    parentDistance(other.parentDistance),
+    furthestDescendantDistance(other.furthestDescendantDistance),
+    localMetric(false),
+    metric(other.metric)
+{
+  // Copy each child by hand.
+  for (size_t i = 0; i < other.NumChildren(); ++i)
+  {
+    children.push_back(new CoverTree(other.Child(i)));
+    children[i]->Parent() = this;
+  }
+}
+
+template<typename MetricType, typename RootPointPolicy, typename StatisticType>
 CoverTree<MetricType, RootPointPolicy, StatisticType>::~CoverTree()
 {
   // Delete each child.
   for (size_t i = 0; i < children.size(); ++i)
     delete children[i];
+
+  // Delete the local metric, if necessary.
+  if (localMetric)
+    delete metric;
 }
 
 template<typename MetricType, typename RootPointPolicy, typename StatisticType>
@@ -458,7 +448,7 @@
     const CoverTree<MetricType, RootPointPolicy, StatisticType>* other) const
 {
   // Every cover tree node will contain points up to EC^(scale + 1) away.
-  return std::max(MetricType::Evaluate(dataset.unsafe_col(point),
+  return std::max(metric->Evaluate(dataset.unsafe_col(point),
       other->Dataset().unsafe_col(other->Point())) -
       furthestDescendantDistance - other->FurthestDescendantDistance(), 0.0);
 }
@@ -477,7 +467,7 @@
 double CoverTree<MetricType, RootPointPolicy, StatisticType>::MinDistance(
     const arma::vec& other) const
 {
-  return std::max(MetricType::Evaluate(dataset.unsafe_col(point), other) -
+  return std::max(metric->Evaluate(dataset.unsafe_col(point), other) -
       furthestDescendantDistance, 0.0);
 }
 
@@ -493,7 +483,7 @@
 double CoverTree<MetricType, RootPointPolicy, StatisticType>::MaxDistance(
     const CoverTree<MetricType, RootPointPolicy, StatisticType>* other) const
 {
-  return MetricType::Evaluate(dataset.unsafe_col(point),
+  return metric->Evaluate(dataset.unsafe_col(point),
       other->Dataset().unsafe_col(other->Point())) +
       furthestDescendantDistance + other->FurthestDescendantDistance();
 }
@@ -512,7 +502,7 @@
 double CoverTree<MetricType, RootPointPolicy, StatisticType>::MaxDistance(
     const arma::vec& other) const
 {
-  return MetricType::Evaluate(dataset.unsafe_col(point), other) +
+  return metric->Evaluate(dataset.unsafe_col(point), other) +
       furthestDescendantDistance;
 }
 
@@ -582,14 +572,13 @@
     const size_t pointIndex,
     const arma::Col<size_t>& indices,
     arma::vec& distances,
-    const size_t pointSetSize,
-    MetricType& metric)
+    const size_t pointSetSize)
 {
   // For each point, rebuild the distances.  The indices do not need to be
   // modified.
   for (size_t i = 0; i < pointSetSize; ++i)
   {
-    distances[i] = metric.Evaluate(dataset.unsafe_col(pointIndex),
+    distances[i] = metric->Evaluate(dataset.unsafe_col(pointIndex),
         dataset.unsafe_col(indices[i]));
   }
 }
@@ -832,6 +821,33 @@
   return (left - nearSetSize);
 }
 
+/**
+ * Returns a string representation of this object.
+ */
+template<typename MetricType, typename RootPointPolicy, typename StatisticType>
+std::string CoverTree<MetricType, RootPointPolicy, StatisticType>::ToString() const
+{
+  std::ostringstream convert;
+  convert << "CoverTree [" << this << "]" << std::endl;
+  convert << "dataset: " << &dataset << std::endl;
+  convert << "point: " << point << std::endl;
+  convert << "scale: " << scale << std::endl;
+  convert << "base: " << base << std::endl;
+//  convert << "StatisticType: " << stat << std::endl;
+  convert << "parent distance : " << parentDistance << std::endl;
+  convert << "furthest child distance: " << furthestDescendantDistance;
+  convert << std::endl;
+  convert << "children:";
+
+  if (IsLeaf() == false)
+  {
+    for (int i = 0; i < children.size(); i++)
+    {
+      convert << std::endl << mlpack::util::Indent(children.at(i)->ToString());
+    }
+  }
+  return convert.str();
+}
 }; // namespace tree
 }; // namespace mlpack
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -71,7 +71,8 @@
   size_t numPrunes;
 
   //! Prepare map for recursion.
-  void PruneMap(CoverTree& candidateQueryNode,
+  void PruneMap(CoverTree& queryNode,
+                CoverTree& candidateQueryNode,
                 std::map<int, std::vector<DualCoverTreeMapEntry<
                     MetricType, RootPointPolicy, StatisticType> > >&
                     referenceMap,

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -118,7 +118,7 @@
     for (size_t i = 1; i < queryNode.NumChildren(); ++i)
     {
       std::map<int, std::vector<MapEntryType> > childMap;
-      PruneMap(queryNode.Child(i), referenceMap, childMap);
+      PruneMap(queryNode, queryNode.Child(i), referenceMap, childMap);
 
 //      Log::Debug << "Recurse into query child " << i << ": " <<
 //          queryNode.Child(i).Point() << " scale " << queryNode.Child(i).Scale()
@@ -191,6 +191,7 @@
 template<typename RuleType>
 void CoverTree<MetricType, RootPointPolicy, StatisticType>::
 DualTreeTraverser<RuleType>::PruneMap(
+    CoverTree& /* queryNode */,
     CoverTree& candidateQueryNode,
     std::map<int, std::vector<DualCoverTreeMapEntry<MetricType,
         RootPointPolicy, StatisticType> > >& referenceMap,
@@ -224,6 +225,17 @@
           frame.referenceNode;
       const double oldScore = frame.score;
 
+      // Try to prune based on shell().  This is hackish and will need to be
+      // refined or cleaned at some point.
+//      double score = rule.PrescoreQ(queryNode, candidateQueryNode, *refNode,
+//          frame.baseCase);
+
+//      if (score == DBL_MAX)
+//      {
+//        ++numPrunes;
+//        continue;
+//      }
+
 //      Log::Debug << "Recheck reference node " << refNode->Point() <<
 //          " scale " << refNode->Scale() << " which has old score " <<
 //          oldScore << " with old reference index " << frame.referenceIndex
@@ -482,21 +494,21 @@
 //            " scale " << refNode->Scale() << ", reference child " <<
 //            refNode->Child(j).Point() << " scale " << refNode->Child(j).Scale()
 //            << " with base case " << baseCase;
-        childScore = rule.Prescore(queryNode, *refNode, refNode->Child(j),
-            frame.baseCase);
+//        childScore = rule.Prescore(queryNode, *refNode, refNode->Child(j),
+//            frame.baseCase);
 //        Log::Debug << " and result " << childScore << ".\n";
 
-        if (childScore == DBL_MAX)
-        {
-          ++numPrunes;
-          continue;
-        }
+//        if (childScore == DBL_MAX)
+//        {
+//          ++numPrunes;
+//          continue;
+//        }
 
         // Calculate the base case of each child.
         baseCase = rule.BaseCase(queryIndex, refIndex);
 
         // See if we can prune it.
-        childScore = rule.Score(queryNode, refNode->Child(j), baseCase);
+        double childScore = rule.Score(queryNode, refNode->Child(j), baseCase);
 
         if (childScore == DBL_MAX)
         {

Copied: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/traits.hpp (from rev 14992, mlpack/trunk/src/mlpack/core/tree/cover_tree/traits.hpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/traits.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree/traits.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,56 @@
+/**
+ * @file traits.hpp
+ * @author Ryan Curtin
+ *
+ * This file contains the specialization of the TreeTraits class for the
+ * CoverTree type of tree.
+ */
+#ifndef __MLPACK_CORE_TREE_COVER_TREE_TRAITS_HPP
+#define __MLPACK_CORE_TREE_COVER_TREE_TRAITS_HPP
+
+#include <mlpack/core/tree/tree_traits.hpp>
+
+namespace mlpack {
+namespace tree {
+
+/**
+ * The specialization of the TreeTraits class for the CoverTree tree type.  It
+ * defines characteristics of the cover tree, and is used to help write
+ * tree-independent (but still optimized) tree-based algorithms.  See
+ * mlpack/core/tree/tree_traits.hpp for more information.
+ */
+template<typename MetricType,
+         typename RootPointPolicy,
+         typename StatisticType>
+class TreeTraits<CoverTree<MetricType, RootPointPolicy, StatisticType> >
+{
+ public:
+  /**
+   * The cover tree calculates the distance between parent and child during
+   * construction, so that value is saved and CoverTree<...>::ParentDistance()
+   * does exist.
+   */
+  static const bool HasParentDistance = true;
+
+  /**
+   * The cover tree (or, this implementation of it) does not require that
+   * children represent non-overlapping subsets of the parent node.
+   */
+  static const bool HasOverlappingChildren = true;
+
+  /**
+   * Each cover tree node contains only one point, and that point is its
+   * centroid.
+   */
+  static const bool FirstPointIsCentroid = true;
+
+  /**
+   * Cover trees do have self-children.
+   */
+  static const bool HasSelfChildren = true;
+};
+
+}; // namespace tree
+}; // namespace mlpack
+
+#endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/cover_tree.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -26,5 +26,6 @@
 #include "cover_tree/cover_tree.hpp"
 #include "cover_tree/single_tree_traverser.hpp"
 #include "cover_tree/dual_tree_traverser.hpp"
+#include "cover_tree/traits.hpp"
 
 #endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -26,6 +26,7 @@
 
 #include <mlpack/core.hpp>
 #include <mlpack/core/math/range.hpp>
+#include <mlpack/core/metrics/lmetric.hpp>
 
 namespace mlpack {
 namespace bound {
@@ -39,10 +40,13 @@
  * @tparam TakeRoot Whether or not the root should be taken (see LMetric
  *     documentation).
  */
-template<int Power = 2, bool TakeRoot = false>
+template<int Power = 2, bool TakeRoot = true>
 class HRectBound
 {
  public:
+  //! This is the metric type that this bound is using.
+  typedef metric::LMetric<Power, TakeRoot> MetricType;
+
   /**
    * Empty constructor; creates a bound of dimensionality 0.
    */
@@ -54,15 +58,12 @@
    */
   HRectBound(const size_t dimension);
 
-  /***
-   * Copy constructor; necessary to prevent memory leaks.
-   */
+  //! Copy constructor; necessary to prevent memory leaks.
   HRectBound(const HRectBound& other);
-  HRectBound& operator=(const HRectBound& other); // Same as copy constructor.
+  //! Same as copy constructor; necessary to prevent memory leaks.
+  HRectBound& operator=(const HRectBound& other);
 
-  /**
-   * Destructor: clean up memory.
-   */
+  //! Destructor: clean up memory.
   ~HRectBound();
 
   /**
@@ -71,14 +72,13 @@
    */
   void Clear();
 
-  /** Gets the dimensionality */
+  //! Gets the dimensionality.
   size_t Dim() const { return dim; }
 
-  /**
-   * Sets and gets the range for a particular dimension.
-   */
-  math::Range& operator[](const size_t i);
-  const math::Range& operator[](const size_t i) const;
+  //! Get the range for a particular dimension.  No bounds checking.
+  math::Range& operator[](const size_t i) { return bounds[i]; }
+  //! Modify the range for a particular dimension.  No bounds checking.
+  const math::Range& operator[](const size_t i) const { return bounds[i]; }
 
   /**
    * Calculates the centroid of the range, placing it into the given vector.
@@ -155,6 +155,23 @@
   template<typename VecType>
   bool Contains(const VecType& point) const;
 
+  /**
+   * Returns the diameter of the hyperrectangle (that is, the longest diagonal).
+   */
+  double Diameter() const;
+
+  /**
+   * Returns a string representation of this object.
+   */
+  std::string ToString() const;
+
+  /**
+   * Return the metric associated with this bound.  Because it is an LMetric, it
+   * cannot store state, so we can make it on the fly.  It is also static
+   * because the metric is only dependent on the template arguments.
+   */
+  static MetricType Metric() { return metric::LMetric<Power, TakeRoot>(); }
+
  private:
   //! The dimensionality of the bound.
   size_t dim;

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/hrectbound_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -108,25 +108,6 @@
     bounds[i] = math::Range();
 }
 
-/**
- * Gets the range for a particular dimension.
- */
-template<int Power, bool TakeRoot>
-inline const math::Range& HRectBound<Power, TakeRoot>::operator[](
-    const size_t i) const
-{
-  return bounds[i];
-}
-
-/**
- * Sets the range for the given dimension.
- */
-template<int Power, bool TakeRoot>
-inline math::Range& HRectBound<Power, TakeRoot>::operator[](const size_t i)
-{
-  return bounds[i];
-}
-
 /***
  * Calculates the centroid of the range, placing it into the given vector.
  *
@@ -399,6 +380,38 @@
   return true;
 }
 
+/**
+ * Returns the diameter of the hyperrectangle (that is, the longest diagonal).
+ */
+template<int Power, bool TakeRoot>
+double HRectBound<Power, TakeRoot>::Diameter() const
+{
+  double d = 0;
+  for (size_t i = 0; i < dim; ++i)
+    d += std::pow(bounds[i].Hi() - bounds[i].Lo(), (double) Power);
+
+  if (TakeRoot)
+    return std::pow(d, 1.0 / (double) Power);
+  else
+    return d;
+}
+
+/**
+ * Returns a string representation of this object.
+ */
+template<int Power, bool TakeRoot>
+std::string HRectBound<Power, TakeRoot>::ToString() const
+{
+  std::ostringstream convert;
+  convert << "HRectBound [" << this << "]" << std::endl;
+  convert << "dim: " << dim << std::endl;
+  convert << "bounds: " << std::endl;
+  for (size_t i = 0; i < dim; ++i)
+    convert << util::Indent(bounds[i].ToString()) << std::endl;
+
+  return convert.str();
+}
+
 }; // namespace bound
 }; // namespace mlpack
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -37,35 +37,14 @@
   MRKDStatistic();
 
   /**
-   * This constructor is called when a leaf is created.
+   * This constructor is called when a node is finished initializing.
    *
-   * @param dataset Matrix that the tree is being built on.
-   * @param begin Starting index corresponding to this leaf.
-   * @param count Number of points held in this leaf.
+   * @param node The node that has been finished.
    */
-  template<typename MatType>
-  MRKDStatistic(const MatType& dataset,
-                const size_t begin,
-                const size_t count);
+  template<typename TreeType>
+  MRKDStatistic(const TreeType& /* node */);
 
   /**
-   * This constructor is called when a non-leaf node is created.
-   * This lets you build fast bottom-up statistics when building trees.
-   *
-   * @param dataset Matrix that the tree is being built on.
-   * @param begin Starting index corresponding to this leaf.
-   * @param count Number of points held in this leaf.
-   * @param leftStat MRKDStatistic object of the left child node.
-   * @param rightStat MRKDStatistic object of the right child node.
-   */
-  template<typename MatType>
-  MRKDStatistic(const MatType& dataset,
-                const size_t begin,
-                const size_t count,
-                MRKDStatistic& leftStat,
-                MRKDStatistic& rightStat);
-
-  /**
    * Returns a string representation of this object.
    */
   std::string ToString() const;
@@ -112,7 +91,7 @@
   // Computed statistics.
   //! The center of mass for this dataset.
   arma::colvec centerOfMass;
-  //! The sum of the squared Euclidian norms for this dataset.
+  //! The sum of the squared Euclidean norms for this dataset.
   double sumOfSquaredNorms;
 
   // There may be a better place to store this -- HRectBound?


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic.hpp
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/core/tree/mrkd_statistic.hpp:13981-14236

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/mrkd_statistic_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -3,21 +3,6 @@
  * @author James Cline
  *
  * Definition of the statistic for multi-resolution kd-trees.
- *
- * This file is part of MLPACK 1.0.4.
- *
- * MLPACK 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, either version 3 of the License, or (at your option) any
- * later version.
- *
- * MLPACK 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 (LICENSE.txt).
- *
- * You should have received a copy of the GNU General Public License along with
- * MLPACK.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifndef __MLPACK_CORE_TREE_MRKD_STATISTIC_IMPL_HPP
 #define __MLPACK_CORE_TREE_MRKD_STATISTIC_IMPL_HPP
@@ -28,17 +13,25 @@
 namespace mlpack {
 namespace tree {
 
+template<typename TreeType>
+MRKDStatistic::MRKDStatistic(const TreeType& /* node */) :
+    dataset(NULL),
+    begin(0),
+    count(0),
+    leftStat(NULL),
+    rightStat(NULL),
+    parentStat(NULL)
+{ }
+
 /**
  * This constructor is called when a leaf is created.
  *
  * @param dataset Matrix that the tree is being built on.
  * @param begin Starting index corresponding to this leaf.
  * @param count Number of points held in this leaf.
- */
+ *
 template<typename MatType>
-MRKDStatistic::MRKDStatistic(const MatType& dataset,
-                             const size_t begin,
-                             const size_t count) :
+MRKDStatistic::MRKDStatistic(const TreeType& node) :
     dataset(&dataset),
     begin(begin),
     count(count),
@@ -47,15 +40,15 @@
     parentStat(NULL)
 {
   centerOfMass = dataset.col(begin);
-  for (size_t i = begin+1; i < begin+count; ++i)
+  for (size_t i = begin + 1; i < begin + count; ++i)
     centerOfMass += dataset.col(i);
 
   sumOfSquaredNorms = 0.0;
-  for (size_t i = begin; i < begin+count; ++i)
+  for (size_t i = begin; i < begin + count; ++i)
     sumOfSquaredNorms += arma::norm(dataset.col(i), 2);
 }
 
-/**
+ **
  * This constructor is called when a non-leaf node is created.
  * This lets you build fast bottom-up statistics when building trees.
  *
@@ -64,7 +57,7 @@
  * @param count Number of points held in this leaf.
  * @param leftStat MRKDStatistic object of the left child node.
  * @param rightStat MRKDStatistic object of the right child node.
- */
+ *
 template<typename MatType>
 MRKDStatistic::MRKDStatistic(const MatType& dataset,
                              const size_t begin,
@@ -80,11 +73,11 @@
 {
   sumOfSquaredNorms = leftStat.sumOfSquaredNorms + rightStat.sumOfSquaredNorms;
 
-  /*
+  *
   centerOfMass = ((leftStat.centerOfMass * leftStat.count) +
                   (rightStat.centerOfMass * rightStat.count)) /
                   (leftStat.count + rightStat.count);
-  */
+  *
   centerOfMass = leftStat.centerOfMass + rightStat.centerOfMass;
 
   isWhitelistValid = false;
@@ -92,6 +85,7 @@
   leftStat.parentStat = this;
   rightStat.parentStat = this;
 }
+*/
 
 }; // namespace tree
 }; // namespace mlpack

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file tree/periodichrectbound.h
+ * @file periodichrectbound.hpp
  *
  * Bounds that are useful for binary space partitioning trees.
  *
@@ -146,6 +146,11 @@
    */
   bool Contains(const arma::vec& point) const;
 
+  /**
+   * Returns a string representation of an object.
+   */
+  std::string ToString() const;
+
  private:
   math::Range *bounds;
   size_t dim;

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/periodichrectbound_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file tree/periodichrectbound_impl.h
+ * @file periodichrectbound_impl.hpp
  *
  * Implementation of periodic hyper-rectangle bound policy class.
  * Template parameter t_pow is the metric to use; use 2 for Euclidian (L2).
@@ -580,6 +580,20 @@
   return true;
 }
 
+/**
+ * Returns a string representation of this object.
+ */
+template<int t_pow>
+std::string PeriodicHRectBound<t_pow>::ToString() const
+{
+  std::ostringstream convert;
+  convert << "PeriodicHRectBound [" << this << "]" << std::endl;
+  convert << "bounds: " << bounds->ToString() << std::endl;
+  convert << "dim: " << dim << std::endl;
+  convert << "box: " << box;
+  return convert.str();
+}
+
 }; // namespace bound
 }; // namespace mlpack
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/statistic.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/statistic.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/statistic.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -34,39 +34,29 @@
 class EmptyStatistic
 {
   public:
-    EmptyStatistic() {}
-    ~EmptyStatistic() {}
+    EmptyStatistic() { }
+    ~EmptyStatistic() { }
 
     /**
-     * This constructor is called when a leaf is created.
+     * This constructor is called when a node is finished being created.  The
+     * node is finished, and its children are finished, but it is not
+     * necessarily true that the statistics of other nodes are initialized yet.
      *
-     * @param dataset Matrix that the tree is being built on.
-     * @param begin Starting index corresponding to this leaf.
-     * @param count Number of points held in this leaf.
+     * @param node Node which this corresponds to.
      */
-    template<typename MatType>
-    EmptyStatistic(const MatType& /* dataset */,
-                   const size_t /* begin */,
-                   const size_t /* count */)
-    { }
+    template<typename TreeType>
+    EmptyStatistic(TreeType& /* node */) { }
 
+  public:
     /**
-     * This constructor is called when a non-leaf node is created.
-     * This lets you build fast bottom-up statistics when building trees.
-     *
-     * @param dataset Matrix that the tree is being built on.
-     * @param begin Starting index corresponding to this leaf.
-     * @param count Number of points held in this leaf.
-     * @param leftStat EmptyStatistic object of the left child node.
-     * @param rightStat EmptyStatistic object of the right child node.
+     * Returns a string representation of this object.
      */
-    template<typename MatType>
-    EmptyStatistic(const MatType& /* dataset */,
-                   const size_t /* start */,
-                   const size_t /* count */,
-                   const EmptyStatistic& /* leftStat */,
-                   const EmptyStatistic& /* rightStat */)
-    { }
+    std::string ToString() const
+    {
+      std::stringstream convert;
+      convert << "EmptyStatistic [" << this << "]" << std::endl;
+      return convert.str();
+    }
 };
 
 }; // namespace tree

Copied: mlpack/branches/mlpack-1.x/src/mlpack/core/tree/tree_traits.hpp (from rev 14992, mlpack/trunk/src/mlpack/core/tree/tree_traits.hpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/tree/tree_traits.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/tree/tree_traits.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,97 @@
+/**
+ * @file tree_traits.hpp
+ * @author Ryan Curtin
+ *
+ * This file implements the basic, unspecialized TreeTraits class, which
+ * provides information about tree types.  If you create a tree class, you
+ * should specialize this class with the characteristics of your tree.
+ */
+#ifndef __MLPACK_CORE_TREE_TREE_TRAITS_HPP
+#define __MLPACK_CORE_TREE_TREE_TRAITS_HPP
+
+namespace mlpack {
+namespace tree {
+
+/**
+ * The TreeTraits class provides compile-time information on the characteristics
+ * of a given tree type.  These include traits such as whether or not a node
+ * knows the distance to its parent node, or whether or not the subspaces
+ * represented by children can overlap.
+ *
+ * These traits can be used for static compile-time optimization:
+ *
+ * @code
+ * // This if statement will be optimized out at compile time!
+ * if (TreeTraits<TreeType>::HasOverlappingChildren == false)
+ * {
+ *   // Do a simpler computation because no children overlap.
+ * }
+ * else
+ * {
+ *   // Do the full, complex calculation.
+ * }
+ * @endcode
+ *
+ * The traits can also be used in conjunction with SFINAE to write specialized
+ * versions of functions:
+ *
+ * @code
+ * template<typename TreeType>
+ * void Compute(TreeType& node,
+ *              boost::enable_if<
+ *                  TreeTraits<TreeType>::HasParentDistance>::type*)
+ * {
+ *   // Computation with TreeType::ParentDistance().
+ * }
+ *
+ * template<typename TreeType>
+ * void Compute(TreeType& node,
+ *              boost::enable_if<
+ *                  !TreeTraits<TreeType>::HasParentDistance>::type*)
+ * {
+ *   // Computation without TreeType::ParentDistance().
+ * }
+ * @endcode
+ *
+ * In those two examples, the boost::enable_if<> class takes a boolean template
+ * parameter which allows that function to be called when the boolean is true.
+ *
+ * Each trait must be a static const value and not a function; only const values
+ * can be used as template parameters (with the exception of constexprs, which
+ * are a C++11 feature; but MLPACK is not using C++11).  By default (the
+ * unspecialized implementation of TreeTraits), each parameter is set to make as
+ * few assumptions about the tree as possible; so, even if TreeTraits is not
+ * specialized for a particular tree type, tree-based algorithms should still
+ * work.
+ *
+ * When you write your own tree, you must specialize the TreeTraits class to
+ * your tree type and set the corresponding values appropriately.  See
+ * mlpack/core/tree/binary_space_tree/traits.hpp for an example.
+ */
+template<typename TreeType>
+class TreeTraits
+{
+ public:
+  /**
+   * This is true if TreeType::ParentDistance() exists and works.  The
+   * ParentDistance() function returns the distance between the center of a node
+   * and the center of its parent.
+   */
+  static const bool HasParentDistance = false;
+
+  /**
+   * This is true if the subspaces represented by the children of a node can
+   * overlap.
+   */
+  static const bool HasOverlappingChildren = true;
+
+  /**
+   * This is true if Point(0) is the centroid of the node.
+   */
+  static const bool FirstPointIsCentroid = false;
+};
+
+}; // namespace tree
+}; // namespace mlpack
+
+#endif


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/core/util
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/core/util:13981-14230

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -138,27 +138,27 @@
   void CallBaseLogic(const T& s,
       typename boost::disable_if<
           boost::is_class<T>
-      >::type*);
+      >::type* = 0);
 
   //! Forward all objects that do not implement a ToString() method
   template<typename T>
   void CallBaseLogic(const T& s,
       typename boost::enable_if<
           boost::is_class<T>
-      >::type*,
+      >::type* = 0,
       typename boost::disable_if<
           HasToString<T, std::string(T::*)() const>
-      >::type*);
+      >::type* = 0);
 
   //! Call ToString() on all objects that implement ToString() before forwarding
   template<typename T>
   void CallBaseLogic(const T& s,
       typename boost::enable_if<
           boost::is_class<T>
-      >::type*,
+      >::type* = 0,
       typename boost::enable_if<
           HasToString<T, std::string(T::*)() const>
-      >::type*);
+      >::type* = 0);
 
   /**
    * @brief Conducts the base logic required in all the operator << overloads.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/util/prefixedoutstream_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -42,7 +42,7 @@
 void PrefixedOutStream::CallBaseLogic(const T& s,
     typename boost::disable_if<
         boost::is_class<T>
-    >::type* = 0)
+    >::type*)
 {
   BaseLogic<T>(s);
 }
@@ -52,10 +52,10 @@
 void PrefixedOutStream::CallBaseLogic(const T& s,
     typename boost::enable_if<
         boost::is_class<T>
-    >::type* = 0,
+    >::type*,
     typename boost::disable_if<
         HasToString<T, std::string(T::*)() const>
-    >::type* = 0)
+    >::type*)
 {
   BaseLogic<T>(s);
 }
@@ -65,10 +65,10 @@
 void PrefixedOutStream::CallBaseLogic(const T& s,
     typename boost::enable_if<
         boost::is_class<T>
-    >::type* = 0,
+    >::type*,
     typename boost::enable_if<
         HasToString<T, std::string(T::*)() const>
-    >::type* = 0)
+    >::type*)
 {
   std::string result = s.ToString();
   BaseLogic<std::string>(result);

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -73,8 +73,10 @@
     /* TODO: perhaps we'll add more later?
      * xmlNewProp(child, BAD_CAST "attr", BAD_CAST "add more addibutes?"); */
   }
-  /* save the file */
-  xmlSaveFormatFileEnc(filename.c_str(), xmlDocTree, "UTF-8", 1);
+
+  // Actually save the file.
+  success =
+      (xmlSaveFormatFileEnc(filename.c_str(), xmlDocTree, "UTF-8", 1) != -1);
   xmlFreeDoc(xmlDocTree);
   return success;
 }

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file utilities/save_restore_utility.hpp
+ * @file save_restore_utility.hpp
  * @author Neil Slagle
  *
  * The SaveRestoreUtility provides helper functions in saving and
@@ -22,8 +22,8 @@
  * You should have received a copy of the GNU General Public License along with
  * MLPACK.  If not, see <http://www.gnu.org/licenses/>.
  */
-#ifndef SAVE_RESTORE_MODEL_HPP
-#define SAVE_RESTORE_MODEL_HPP
+#ifndef __MLPACK_CORE_UTIL_SAVE_RESTORE_MODEL_HPP
+#define __MLPACK_CORE_UTIL_SAVE_RESTORE_MODEL_HPP
 
 #include <list>
 #include <map>

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core/util/save_restore_utility_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file utilities/save_restore_utility_impl.hpp
+ * @file save_restore_utility_impl.hpp
  * @author Neil Slagle
  *
  * The SaveRestoreUtility provides helper functions in saving and

Modified: mlpack/branches/mlpack-1.x/src/mlpack/core.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/core.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/core.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -85,6 +85,8 @@
  *  - @ref rstutorial
  *  - @ref dettutorial
  *  - @ref emst_tutorial
+ *  - @ref kmtutorial
+ *  - @ref fmkstutorial
  *
  * @section methods Methods in MLPACK
  *
@@ -98,15 +100,16 @@
  *  - K-Means Clustering - mlpack::kmeans::KMeans
  *  - Least-Angle Regression (LARS/LASSO) - mlpack::regression::LARS
  *  - Local Coordinate Coding - mlpack::lcc::LocalCoordinateCoding
+ *  - Locality-Sensitive Hashing - mlpack::neighbor::LSHSearch
  *  - Naive Bayes Classifier - mlpack::naive_bayes::NaiveBayesClassifier
  *  - Neighborhood Components Analysis (NCA) - mlpack::nca::NCA
  *  - Principal Components Analysis (PCA) - mlpack::pca::PCA
  *  - RADICAL (ICA) - mlpack::radical::Radical
  *  - Simple Least-Squares Linear Regression -
- *      mlpack::regression::LinearRegression
+ *        mlpack::regression::LinearRegression
  *  - Sparse Coding - mlpack::sparse_coding::SparseCoding
  *  - Tree-based neighbor search (AllkNN, AllkFN) -
- *      mlpack::neighbor::NeighborSearch
+ *        mlpack::neighbor::NeighborSearch
  *  - Tree-based range search - mlpack::range::RangeSearch
  *
  * @section remarks Final Remarks
@@ -164,21 +167,6 @@
   #define M_PI 3.141592653589793238462643383279
 #endif
 
-// Now MLPACK-specific includes.
-#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
-#include <mlpack/core/util/log.hpp>
-#include <mlpack/core/util/cli.hpp>
-#include <mlpack/core/data/load.hpp>
-#include <mlpack/core/data/save.hpp>
-#include <mlpack/core/math/clamp.hpp>
-#include <mlpack/core/math/random.hpp>
-#include <mlpack/core/math/lin_alg.hpp>
-#include <mlpack/core/math/range.hpp>
-#include <mlpack/core/math/round.hpp>
-#include <mlpack/core/util/save_restore_utility.hpp>
-#include <mlpack/core/dists/discrete_distribution.hpp>
-#include <mlpack/core/dists/gaussian_distribution.hpp>
-
 // Clean up unfortunate Windows preprocessor definitions.
 // Use std::min and std::max!
 #ifdef _WIN32
@@ -201,4 +189,19 @@
   #define force_inline __forceinline
 #endif
 
+// Now MLPACK-specific includes.
+#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
+#include <mlpack/core/util/log.hpp>
+#include <mlpack/core/util/cli.hpp>
+#include <mlpack/core/data/load.hpp>
+#include <mlpack/core/data/save.hpp>
+#include <mlpack/core/math/clamp.hpp>
+#include <mlpack/core/math/random.hpp>
+#include <mlpack/core/math/lin_alg.hpp>
+#include <mlpack/core/math/range.hpp>
+#include <mlpack/core/math/round.hpp>
+#include <mlpack/core/util/save_restore_utility.hpp>
+#include <mlpack/core/dists/discrete_distribution.hpp>
+#include <mlpack/core/dists/gaussian_distribution.hpp>
+
 #endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/CMakeLists.txt
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/CMakeLists.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/CMakeLists.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -9,8 +9,8 @@
   kmeans
   lars
   linear_regression
-#  lmnn
   local_coordinate_coding
+  lsh
   mvu
   naive_bayes
   nca
@@ -19,6 +19,7 @@
   pca
   radical
   range_search
+  rann
   sparse_coding
 )
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/det/dt_utils.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/det/dt_utils.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/det/dt_utils.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -61,7 +61,8 @@
 
 /**
  * Train the optimal decision tree using cross-validation with the given number
- * of folds.  Optionally, give a filename to print the unpruned tree to.
+ * of folds.  Optionally, give a filename to print the unpruned tree to.  This
+ * initializes a tree on the heap, so you are responsible for deleting it.
  *
  * @param dataset Dataset for the tree to use.
  * @param folds Number of folds to use for cross-validation.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -63,23 +63,21 @@
 
  public:
   /**
-   * A generic initializer.
+   * A generic initializer.  Sets the maximum neighbor distance to its default,
+   * and the component membership to -1 (no component).
    */
   DTBStat();
 
   /**
-   * An initializer for leaves.
+   * This is called when a node is finished initializing.  We set the maximum
+   * neighbor distance to its default, and if possible, we set the component
+   * membership of the node (if it has only one point and no children).
+   *
+   * @param node Node that has been finished.
    */
-  template<typename MatType>
-  DTBStat(const MatType& dataset, const size_t start, const size_t count);
+  template<typename TreeType>
+  DTBStat(const TreeType& node);
 
-  /**
-   * An initializer for non-leaves.
-   */
-  template<typename MatType>
-  DTBStat(const MatType& dataset, const size_t start, const size_t count,
-          const DTBStat& leftStat, const DTBStat& rightStat);
-
   //! Get the maximum neighbor distance.
   double MaxNeighborDistance() const { return maxNeighborDistance; }
   //! Modify the maximum neighbor distance.
@@ -94,7 +92,7 @@
 
 /**
  * Performs the MST calculation using the Dual-Tree Boruvka algorithm, using any
- * type of tree.  
+ * type of tree.
  *
  * For more information on the algorithm, see the following citation:
  *
@@ -124,9 +122,9 @@
  * More advanced usage of the class can use different types of trees, pass in an
  * already-built tree, or compute the MST using the O(n^2) naive algorithm.
  *
- * @tparam MetricType The metric to use.  IMPORTANT: this hasn't really been 
- * tested with anything other than the L2 metric, so user beware. Note that the 
- * tree type needs to compute bounds using the same metric as the type 
+ * @tparam MetricType The metric to use.  IMPORTANT: this hasn't really been
+ * tested with anything other than the L2 metric, so user beware. Note that the
+ * tree type needs to compute bounds using the same metric as the type
  * specified here.
  * @tparam TreeType Type of tree to use.  Should use DTBStat as a statistic.
  */
@@ -167,7 +165,7 @@
 
   //! Total distance of the tree.
   double totalDist;
-  
+
   //! The metric
   MetricType metric;
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/dtb_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -41,31 +41,15 @@
 /**
  * An initializer for leaves.
  */
-template<typename MatType>
-DTBStat::DTBStat(const MatType& /* dataset */,
-                 const size_t start,
-                 const size_t count) :
+template<typename TreeType>
+DTBStat::DTBStat(const TreeType& node) :
     maxNeighborDistance(DBL_MAX),
-    componentMembership((count == 1) ? start : -1)
+    componentMembership(((node.NumPoints() == 1) && (node.NumChildren() == 0)) ?
+        node.Point(0) : -1)
 {
   // Nothing to do.
 }
 
-/**
- * An initializer for non-leaves.
- */
-template<typename MatType>
-DTBStat::DTBStat(const MatType& /* dataset */,
-                 const size_t start,
-                 const size_t count,
-                 const DTBStat& /* leftStat */,
-                 const DTBStat& /* rightStat */) :
-    maxNeighborDistance(DBL_MAX),
-    componentMembership((count == 1) ? start : -1)
-{
-  // Nothing to do.
-}
-
 // DualTreeBoruvka
 
 /**
@@ -155,11 +139,11 @@
 
   while (edges.size() < (data.n_cols - 1))
   {
-    
+
     typename TreeType::template DualTreeTraverser<RuleType> traverser(rules);
-    
+
     traverser.Traverse(*tree, *tree);
-    
+
     AddAllEdges();
 
     Cleanup();

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/edge_pair.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/edge_pair.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/emst/edge_pair.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file emst.h
+ * @file edge_pair.hpp
  *
  * @author Bill March (march at gatech.edu)
  *

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/CMakeLists.txt
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/CMakeLists.txt	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/CMakeLists.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,28 @@
+# Define the files we need to compile.
+# Anything not in this list will not be compiled into MLPACK.
+set(SOURCES
+  ip_metric.hpp
+  ip_metric_impl.hpp
+  fastmks.hpp
+  fastmks_impl.hpp
+  fastmks_rules.hpp
+  fastmks_rules_impl.hpp
+)
+
+# Add directory name to sources.
+set(DIR_SRCS)
+foreach(file ${SOURCES})
+  set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+endforeach()
+# Append sources (with directory name) to list of all MLPACK sources (used at
+# the parent scope).
+set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
+
+add_executable(fastmks
+  fastmks_main.cpp
+)
+target_link_libraries(fastmks
+  mlpack
+)
+
+install(TARGETS fastmks RUNTIME DESTINATION bin)

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,220 @@
+/**
+ * @file fastmks.hpp
+ * @author Ryan Curtin
+ *
+ * Definition of the FastMKS class, which implements fast exact max-kernel
+ * search.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_HPP
+
+#include <mlpack/core.hpp>
+#include "ip_metric.hpp"
+#include "fastmks_stat.hpp"
+#include <mlpack/core/tree/cover_tree.hpp>
+
+namespace mlpack {
+namespace fastmks {
+
+/**
+ * An implementation of fast exact max-kernel search.  Given a query dataset and
+ * a reference dataset (or optionally just a reference dataset which is also
+ * used as the query dataset), fast exact max-kernel search finds, for each
+ * point in the query dataset, the k points in the reference set with maximum
+ * kernel value K(p_q, p_r), where k is a specified parameter and K() is a
+ * Mercer kernel.
+ *
+ * For more information, see the following paper.
+ *
+ * @code
+ * @inproceedings{curtin2013fast,
+ *   title={Fast Exact Max-Kernel Search},
+ *   author={Curtin, Ryan R. and Ram, Parikshit and Gray, Alexander G.},
+ *   booktitle={Proceedings of the 2013 SIAM International Conference on Data
+ *       Mining (SDM 13)},
+ *   year={2013}
+ * }
+ * @endcode
+ *
+ * This class allows specification of the type of kernel and also of the type of
+ * tree.  FastMKS can be run on kernels that work on arbitrary objects --
+ * however, this only works with cover trees and other trees that are built only
+ * on points in the dataset (and not centroids of regions or anything like
+ * that).
+ *
+ * @tparam KernelType Type of kernel to run FastMKS with.
+ * @tparam TreeType Type of tree to run FastMKS with; it must have metric
+ *     IPMetric<KernelType>.
+ */
+template<
+    typename KernelType,
+    typename TreeType = tree::CoverTree<IPMetric<KernelType>,
+        tree::FirstPointIsRoot, FastMKSStat>
+>
+class FastMKS
+{
+ public:
+  /**
+   * Create the FastMKS object using the reference set as the query set.
+   * Optionally, specify whether or not single-tree search or naive
+   * (brute-force) search should be used.
+   *
+   * @param referenceSet Set of data to run FastMKS on.
+   * @param single Whether or not to run single-tree search.
+   * @param naive Whether or not to run brute-force (naive) search.
+   */
+  FastMKS(const arma::mat& referenceSet,
+          const bool single = false,
+          const bool naive = false);
+
+  /**
+   * Create the FastMKS object using separate reference and query sets.
+   * Optionally, specify whether or not single-tree search or naive
+   * (brute-force) search should be used.
+   *
+   * @param referenceSet Reference set of data for FastMKS.
+   * @param querySet Set of query points for FastMKS.
+   * @param single Whether or not to run single-tree search.
+   * @param naive Whether or not to run brute-force (naive) search.
+   */
+  FastMKS(const arma::mat& referenceSet,
+          const arma::mat& querySet,
+          const bool single = false,
+          const bool naive = false);
+
+  /**
+   * Create the FastMKS object using the reference set as the query set, and
+   * with an initialized kernel.  This is useful for when the kernel stores
+   * state.  Optionally, specify whether or not single-tree search or naive
+   * (brute-force) search should be used.
+   *
+   * @param referenceSet Reference set of data for FastMKS.
+   * @param kernel Initialized kernel.
+   * @param single Whether or not to run single-tree search.
+   * @param naive Whether or not to run brute-force (naive) search.
+   */
+  FastMKS(const arma::mat& referenceSet,
+          KernelType& kernel,
+          const bool single = false,
+          const bool naive = false);
+
+  /**
+   * Create the FastMKS object using separate reference and query sets, and with
+   * an initialized kernel.  This is useful for when the kernel stores state.
+   * Optionally, specify whether or not single-tree search or naive
+   * (brute-force) search should be used.
+   *
+   * @param referenceSet Reference set of data for FastMKS.
+   * @param querySet Set of query points for FastMKS.
+   * @param kernel Initialized kernel.
+   * @param single Whether or not to run single-tree search.
+   * @param naive Whether or not to run brute-force (naive) search.
+   */
+  FastMKS(const arma::mat& referenceSet,
+          const arma::mat& querySet,
+          KernelType& kernel,
+          const bool single = false,
+          const bool naive = false);
+
+  /**
+   * Create the FastMKS object with an already-initialized tree built on the
+   * reference points.  Be sure that the tree is built with the metric type
+   * IPMetric<KernelType>.  For this constructor, the reference set and the
+   * query set are the same points.  Optionally, whether or not to run
+   * single-tree search or brute-force (naive) search can be specified.
+   *
+   * @param referenceSet Reference set of data for FastMKS.
+   * @param referenceTree Tree built on reference data.
+   * @param single Whether or not to run single-tree search.
+   * @param naive Whether or not to run brute-force (naive) search.
+   */
+  FastMKS(const arma::mat& referenceSet,
+          TreeType* referenceTree,
+          const bool single = false,
+          const bool naive = false);
+
+  /**
+   * Create the FastMKS object with already-initialized trees built on the
+   * reference and query points.  Be sure that the trees are built with the
+   * metric type IPMetric<KernelType>.  Optionally, whether or not to run
+   * single-tree search or naive (brute-force) search can be specified.
+   *
+   * @param referenceSet Reference set of data for FastMKS.
+   * @param referenceTree Tree built on reference data.
+   * @param querySet Set of query points for FastMKS.
+   * @param queryTree Tree built on query data.
+   * @param single Whether or not to use single-tree search.
+   * @param naive Whether or not to use naive (brute-force) search.
+   */
+  FastMKS(const arma::mat& referenceSet,
+          TreeType* referenceTree,
+          const arma::mat& querySet,
+          TreeType* queryTree,
+          const bool single = false,
+          const bool naive = false);
+
+  //! Destructor for the FastMKS object.
+  ~FastMKS();
+
+  /**
+   * Search for the maximum inner products of the query set (or if no query set
+   * was passed, the reference set is used).  The resulting maximum inner
+   * products are stored in the products matrix and the corresponding point
+   * indices are stores in the indices matrix.  The results for each point in
+   * the query set are stored in the corresponding column of the indices and
+   * products matrices; for instance, the index of the point with maximum inner
+   * product to point 4 in the query set will be stored in row 0 and column 4 of
+   * the indices matrix.
+   *
+   * @param k The number of maximum kernels to find.
+   * @param indices Matrix to store resulting indices of max-kernel search in.
+   * @param products Matrix to store resulting max-kernel values in.
+   */
+  void Search(const size_t k,
+              arma::Mat<size_t>& indices,
+              arma::mat& products);
+
+  //! Get the inner-product metric induced by the given kernel.
+  const IPMetric<KernelType>& Metric() const { return metric; }
+  //! Modify the inner-product metric induced by the given kernel.
+  IPMetric<KernelType>& Metric() { return metric; }
+
+ private:
+  //! The reference dataset.
+  const arma::mat& referenceSet;
+  //! The query dataset.
+  const arma::mat& querySet;
+
+  //! The tree built on the reference dataset.
+  TreeType* referenceTree;
+  //! The tree built on the query dataset.  This is NULL if there is no query
+  //! set.
+  TreeType* queryTree;
+
+  //! If true, this object created the trees and is responsible for them.
+  bool treeOwner;
+
+  //! If true, single-tree search is used.
+  bool single;
+  //! If true, naive (brute-force) search is used.
+  bool naive;
+
+  //! The instantiated inner-product metric induced by the given kernel.
+  IPMetric<KernelType> metric;
+
+  //! Utility function.  Copied too many times from too many places.
+  void InsertNeighbor(arma::Mat<size_t>& indices,
+                      arma::mat& products,
+                      const size_t queryIndex,
+                      const size_t pos,
+                      const size_t neighbor,
+                      const double distance);
+};
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+// Include implementation.
+#include "fastmks_impl.hpp"
+
+#endif

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_impl.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,506 @@
+/**
+ * @file fastmks_impl.hpp
+ * @author Ryan Curtin
+ *
+ * Implementation of the FastMKS class (fast max-kernel search).
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_IMPL_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_IMPL_HPP
+
+// In case it hasn't yet been included.
+#include "fastmks.hpp"
+
+#include "fastmks_rules.hpp"
+
+#include <mlpack/core/kernels/gaussian_kernel.hpp>
+#include <queue>
+
+namespace mlpack {
+namespace fastmks {
+
+// Single dataset, no instantiated kernel.
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::FastMKS(const arma::mat& referenceSet,
+                                       const bool single,
+                                       const bool naive) :
+    referenceSet(referenceSet),
+    querySet(referenceSet),
+    referenceTree(NULL),
+    queryTree(NULL),
+    treeOwner(true),
+    single(single),
+    naive(naive)
+{
+  Timer::Start("tree_building");
+
+  if (!naive)
+    referenceTree = new TreeType(referenceSet);
+
+  Timer::Stop("tree_building");
+}
+
+// Two datasets, no instantiated kernel.
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::FastMKS(const arma::mat& referenceSet,
+                                       const arma::mat& querySet,
+                                       const bool single,
+                                       const bool naive) :
+    referenceSet(referenceSet),
+    querySet(querySet),
+    referenceTree(NULL),
+    queryTree(NULL),
+    treeOwner(true),
+    single(single),
+    naive(naive)
+{
+  Timer::Start("tree_building");
+
+  // If necessary, the trees should be built.
+  if (!naive)
+    referenceTree = new TreeType(referenceSet);
+
+  if (!naive && !single)
+    queryTree = new TreeType(querySet);
+
+  Timer::Stop("tree_building");
+}
+
+// One dataset, instantiated kernel.
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::FastMKS(const arma::mat& referenceSet,
+                                       KernelType& kernel,
+                                       const bool single,
+                                       const bool naive) :
+    referenceSet(referenceSet),
+    querySet(referenceSet),
+    referenceTree(NULL),
+    queryTree(NULL),
+    treeOwner(true),
+    single(single),
+    naive(naive),
+    metric(kernel)
+{
+  Timer::Start("tree_building");
+
+  // If necessary, the reference tree should be built.  There is no query tree.
+  if (!naive)
+    referenceTree = new TreeType(referenceSet, metric);
+
+  Timer::Stop("tree_building");
+}
+
+// Two datasets, instantiated kernel.
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::FastMKS(const arma::mat& referenceSet,
+                                       const arma::mat& querySet,
+                                       KernelType& kernel,
+                                       const bool single,
+                                       const bool naive) :
+    referenceSet(referenceSet),
+    querySet(querySet),
+    referenceTree(NULL),
+    queryTree(NULL),
+    treeOwner(true),
+    single(single),
+    naive(naive),
+    metric(kernel)
+{
+  Timer::Start("tree_building");
+
+  // If necessary, the trees should be built.
+  if (!naive)
+    referenceTree = new TreeType(referenceSet, metric);
+
+  if (!naive && !single)
+    queryTree = new TreeType(querySet, metric);
+
+  Timer::Stop("tree_building");
+}
+
+// One dataset, pre-built tree.
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::FastMKS(const arma::mat& referenceSet,
+                                       TreeType* referenceTree,
+                                       const bool single,
+                                       const bool naive) :
+    referenceSet(referenceSet),
+    querySet(referenceSet),
+    referenceTree(referenceTree),
+    queryTree(NULL),
+    treeOwner(false),
+    single(single),
+    naive(naive),
+    metric(referenceTree->Metric())
+{
+  // Nothing to do.
+}
+
+// Two datasets, pre-built trees.
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::FastMKS(const arma::mat& referenceSet,
+                                       TreeType* referenceTree,
+                                       const arma::mat& querySet,
+                                       TreeType* queryTree,
+                                       const bool single,
+                                       const bool naive) :
+    referenceSet(referenceSet),
+    querySet(querySet),
+    referenceTree(referenceTree),
+    queryTree(queryTree),
+    treeOwner(false),
+    single(single),
+    naive(naive),
+    metric(referenceTree->Metric())
+{
+  // Nothing to do.
+}
+
+template<typename KernelType, typename TreeType>
+FastMKS<KernelType, TreeType>::~FastMKS()
+{
+  // If we created the trees, we must delete them.
+  if (treeOwner)
+  {
+    if (queryTree)
+      delete queryTree;
+    if (referenceTree)
+      delete referenceTree;
+  }
+}
+
+template<typename KernelType, typename TreeType>
+void FastMKS<KernelType, TreeType>::Search(const size_t k,
+                                           arma::Mat<size_t>& indices,
+                                           arma::mat& products)
+{
+  // No remapping will be necessary because we are using the cover tree.
+  indices.set_size(k, querySet.n_cols);
+  products.set_size(k, querySet.n_cols);
+  products.fill(-DBL_MAX);
+
+  Timer::Start("computing_products");
+
+  // Naive implementation.
+  if (naive)
+  {
+    // Simple double loop.  Stupid, slow, but a good benchmark.
+    for (size_t q = 0; q < querySet.n_cols; ++q)
+    {
+      for (size_t r = 0; r < referenceSet.n_cols; ++r)
+      {
+        if ((&querySet == &referenceSet) && (q == r))
+          continue;
+
+        const double eval = metric.Kernel().Evaluate(querySet.unsafe_col(q),
+            referenceSet.unsafe_col(r));
+
+        size_t insertPosition;
+        for (insertPosition = 0; insertPosition < indices.n_rows;
+            ++insertPosition)
+          if (eval > products(insertPosition, q))
+            break;
+
+        if (insertPosition < indices.n_rows)
+          InsertNeighbor(indices, products, q, insertPosition, r, eval);
+      }
+    }
+
+    Timer::Stop("computing_products");
+
+    return;
+  }
+
+  // Single-tree implementation.
+  if (single)
+  {
+    // Create rules object (this will store the results).  This constructor
+    // precalculates each self-kernel value.
+    typedef FastMKSRules<KernelType, TreeType> RuleType;
+    RuleType rules(referenceSet, querySet, indices, products, metric.Kernel());
+
+    typename TreeType::template SingleTreeTraverser<RuleType> traverser(rules);
+
+    for (size_t i = 0; i < querySet.n_cols; ++i)
+      traverser.Traverse(i, *referenceTree);
+
+    // Save the number of pruned nodes.
+    const size_t numPrunes = traverser.NumPrunes();
+
+    Log::Info << "Pruned " << numPrunes << " nodes." << std::endl;
+
+    Timer::Stop("computing_products");
+    return;
+  }
+
+  // Dual-tree implementation.
+  typedef FastMKSRules<KernelType, TreeType> RuleType;
+  RuleType rules(referenceSet, querySet, indices, products, metric.Kernel());
+
+  typename TreeType::template DualTreeTraverser<RuleType> traverser(rules);
+
+  if (queryTree)
+    traverser.Traverse(*queryTree, *referenceTree);
+  else
+    traverser.Traverse(*referenceTree, *referenceTree);
+
+  const size_t numPrunes = traverser.NumPrunes();
+
+  Log::Info << "Pruned " << numPrunes << " nodes." << std::endl;
+
+  Timer::Stop("computing_products");
+  return;
+}
+
+/**
+ * Helper function to insert a point into the neighbors and distances matrices.
+ *
+ * @param queryIndex Index of point whose neighbors we are inserting into.
+ * @param pos Position in list to insert into.
+ * @param neighbor Index of reference point which is being inserted.
+ * @param distance Distance from query point to reference point.
+ */
+template<typename KernelType, typename TreeType>
+void FastMKS<KernelType, TreeType>::InsertNeighbor(arma::Mat<size_t>& indices,
+                                                   arma::mat& products,
+                                                   const size_t queryIndex,
+                                                   const size_t pos,
+                                                   const size_t neighbor,
+                                                   const double distance)
+{
+  // We only memmove() if there is actually a need to shift something.
+  if (pos < (products.n_rows - 1))
+  {
+    int len = (products.n_rows - 1) - pos;
+    memmove(products.colptr(queryIndex) + (pos + 1),
+        products.colptr(queryIndex) + pos,
+        sizeof(double) * len);
+    memmove(indices.colptr(queryIndex) + (pos + 1),
+        indices.colptr(queryIndex) + pos,
+        sizeof(size_t) * len);
+  }
+
+  // Now put the new information in the right index.
+  products(pos, queryIndex) = distance;
+  indices(pos, queryIndex) = neighbor;
+}
+
+// Specialized implementation for tighter bounds for Gaussian.
+/*
+template<>
+void FastMKS<kernel::GaussianKernel>::Search(const size_t k,
+                                             arma::Mat<size_t>& indices,
+                                             arma::mat& products)
+{
+  Log::Warn << "Alternate implementation!" << std::endl;
+
+  // Terrible copypasta.  Bad bad bad.
+  // No remapping will be necessary.
+  indices.set_size(k, querySet.n_cols);
+  products.set_size(k, querySet.n_cols);
+  products.fill(-1.0);
+
+  Timer::Start("computing_products");
+
+  size_t kernelEvaluations = 0;
+
+  // Naive implementation.
+  if (naive)
+  {
+    // Simple double loop.  Stupid, slow, but a good benchmark.
+    for (size_t q = 0; q < querySet.n_cols; ++q)
+    {
+      for (size_t r = 0; r < referenceSet.n_cols; ++r)
+      {
+        const double eval = metric.Kernel().Evaluate(querySet.unsafe_col(q),
+            referenceSet.unsafe_col(r));
+        ++kernelEvaluations;
+
+        size_t insertPosition;
+        for (insertPosition = 0; insertPosition < indices.n_rows;
+            ++insertPosition)
+          if (eval > products(insertPosition, q))
+            break;
+
+        if (insertPosition < indices.n_rows)
+          InsertNeighbor(indices, products, q, insertPosition, r, eval);
+      }
+    }
+
+    Timer::Stop("computing_products");
+
+    Log::Info << "Kernel evaluations: " << kernelEvaluations << "." << std::endl;
+    return;
+  }
+
+  // Single-tree implementation.
+  if (single)
+  {
+    // Calculate number of pruned nodes.
+    size_t numPrunes = 0;
+
+    // Precalculate query products ( || q || for all q).
+    arma::vec queryProducts(querySet.n_cols);
+    for (size_t queryIndex = 0; queryIndex < querySet.n_cols; ++queryIndex)
+      queryProducts[queryIndex] = sqrt(metric.Kernel().Evaluate(
+          querySet.unsafe_col(queryIndex), querySet.unsafe_col(queryIndex)));
+    kernelEvaluations += querySet.n_cols;
+
+    // Screw the CoverTreeTraverser, we'll implement it by hand.
+    for (size_t queryIndex = 0; queryIndex < querySet.n_cols; ++queryIndex)
+    {
+      // Use an array of priority queues?
+      std::priority_queue<
+          SearchFrame<tree::CoverTree<IPMetric<kernel::GaussianKernel> > >,
+          std::vector<SearchFrame<tree::CoverTree<IPMetric<
+              kernel::GaussianKernel> > > >,
+          SearchFrameCompare<tree::CoverTree<IPMetric<
+              kernel::GaussianKernel> > > >
+          frameQueue;
+
+      // Add initial frame.
+      SearchFrame<tree::CoverTree<IPMetric<kernel::GaussianKernel> > >
+          nextFrame;
+      nextFrame.node = referenceTree;
+      nextFrame.eval = metric.Kernel().Evaluate(querySet.unsafe_col(queryIndex),
+          referenceSet.unsafe_col(referenceTree->Point()));
+      Log::Assert(nextFrame.eval <= 1);
+      ++kernelEvaluations;
+
+      // The initial evaluation will be the best so far.
+      indices(0, queryIndex) = referenceTree->Point();
+      products(0, queryIndex) = nextFrame.eval;
+
+      frameQueue.push(nextFrame);
+
+      tree::CoverTree<IPMetric<kernel::GaussianKernel> >* referenceNode;
+      double eval;
+      double maxProduct;
+
+      while (!frameQueue.empty())
+      {
+        // Get the information for this node.
+        const SearchFrame<tree::CoverTree<IPMetric<kernel::GaussianKernel> > >&
+            frame = frameQueue.top();
+
+        referenceNode = frame.node;
+        eval = frame.eval;
+
+        // Loop through the children, seeing if we can prune them; if not, add
+        // them to the queue.  The self-child is different -- it has the same
+        // parent (and therefore the same kernel evaluation).
+        if (referenceNode->NumChildren() > 0)
+        {
+          SearchFrame<tree::CoverTree<IPMetric<kernel::GaussianKernel> > >
+              childFrame;
+
+          // We must handle the self-child differently, to avoid adding it to
+          // the results twice.
+          childFrame.node = &(referenceNode->Child(0));
+          childFrame.eval = eval;
+
+          // Alternate pruning rule.
+          const double mdd = childFrame.node->FurthestDescendantDistance();
+          if (eval >= (1 - std::pow(mdd, 2.0) / 2.0))
+            maxProduct = 1;
+          else
+            maxProduct = eval * (1 - std::pow(mdd, 2.0) / 2.0) + sqrt(1 -
+                std::pow(eval, 2.0)) * mdd * sqrt(1 - std::pow(mdd, 2.0) / 4.0);
+
+          // Add self-child if we can't prune it.
+          if (maxProduct > products(products.n_rows - 1, queryIndex))
+          {
+            // But only if it has children of its own.
+            if (childFrame.node->NumChildren() > 0)
+              frameQueue.push(childFrame);
+          }
+          else
+            ++numPrunes;
+
+          for (size_t i = 1; i < referenceNode->NumChildren(); ++i)
+          {
+            // Before we evaluate the child, let's see if it can possibly have
+            // a better evaluation.
+            const double mpdd = std::min(
+                referenceNode->Child(i).ParentDistance() +
+                referenceNode->Child(i).FurthestDescendantDistance(), 2.0);
+            double maxChildEval = 1;
+            if (eval < (1 - std::pow(mpdd, 2.0) / 2.0))
+              maxChildEval = eval * (1 - std::pow(mpdd, 2.0) / 2.0) + sqrt(1 -
+                  std::pow(eval, 2.0)) * mpdd * sqrt(1 - std::pow(mpdd, 2.0)
+                  / 4.0);
+
+            if (maxChildEval > products(products.n_rows - 1, queryIndex))
+            {
+              // Evaluate child.
+              childFrame.node = &(referenceNode->Child(i));
+              childFrame.eval = metric.Kernel().Evaluate(
+                  querySet.unsafe_col(queryIndex),
+                  referenceSet.unsafe_col(referenceNode->Child(i).Point()));
+              ++kernelEvaluations;
+
+              // Can we prune it?  If we can, we can avoid putting it in the
+              // queue (saves time).
+              const double cmdd = childFrame.node->FurthestDescendantDistance();
+              if (childFrame.eval > (1 - std::pow(cmdd, 2.0) / 2.0))
+                maxProduct = 1;
+              else
+                maxProduct = childFrame.eval * (1 - std::pow(cmdd, 2.0) / 2.0)
+                    + sqrt(1 - std::pow(eval, 2.0)) * cmdd * sqrt(1 -
+                    std::pow(cmdd, 2.0) / 4.0);
+
+              if (maxProduct > products(products.n_rows - 1, queryIndex))
+              {
+                // Good enough to recurse into.  While we're at it, check the
+                // actual evaluation and see if it's an improvement.
+                if (childFrame.eval > products(products.n_rows - 1, queryIndex))
+                {
+                  // This is a better result.  Find out where to insert.
+                  size_t insertPosition = 0;
+                  for ( ; insertPosition < products.n_rows - 1;
+                      ++insertPosition)
+                    if (childFrame.eval > products(insertPosition, queryIndex))
+                      break;
+
+                  // Insert into the correct position; we are guaranteed that
+                  // insertPosition is valid.
+                  InsertNeighbor(indices, products, queryIndex, insertPosition,
+                      childFrame.node->Point(), childFrame.eval);
+                }
+
+                // Now add this to the queue (if it has any children which may
+                // need to be recursed into).
+                if (childFrame.node->NumChildren() > 0)
+                  frameQueue.push(childFrame);
+              }
+              else
+                ++numPrunes;
+            }
+            else
+              ++numPrunes;
+          }
+        }
+
+        frameQueue.pop();
+      }
+    }
+
+    Log::Info << "Pruned " << numPrunes << " nodes." << std::endl;
+    Log::Info << "Kernel evaluations: " << kernelEvaluations << "."
+        << std::endl;
+    Log::Info << "Distance evaluations: " << distanceEvaluations << "."
+        << std::endl;
+
+    Timer::Stop("computing_products");
+    return;
+  }
+
+  // Double-tree implementation.
+  Log::Fatal << "Dual-tree search not implemented yet... oops..." << std::endl;
+
+}
+*/
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+#endif

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_main.cpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,310 @@
+/**
+ * @file fastmks_main.cpp
+ * @author Ryan Curtin
+ *
+ * Main executable for maximum inner product search.
+ */
+#include <mlpack/core.hpp>
+#include <mlpack/core/kernels/linear_kernel.hpp>
+#include <mlpack/core/kernels/polynomial_kernel.hpp>
+#include <mlpack/core/kernels/cosine_distance.hpp>
+#include <mlpack/core/kernels/gaussian_kernel.hpp>
+#include <mlpack/core/kernels/hyperbolic_tangent_kernel.hpp>
+#include <mlpack/core/kernels/triangular_kernel.hpp>
+#include <mlpack/core/kernels/epanechnikov_kernel.hpp>
+
+#include "fastmks.hpp"
+
+using namespace std;
+using namespace mlpack;
+using namespace mlpack::fastmks;
+using namespace mlpack::kernel;
+using namespace mlpack::tree;
+
+PROGRAM_INFO("FastMKS (Fast Max-Kernel Search)",
+    "This program will find the k maximum kernel of a set of points, "
+    "using a query set and a reference set (which can optionally be the same "
+    "set). More specifically, for each point in the query set, the k points in"
+    " the reference set with maximum kernel evaluations are found.  The kernel "
+    "function used is specified by --kernel."
+    "\n\n"
+    "For example, the following command will calculate, for each point in "
+    "'query.csv', the five points in 'reference.csv' with maximum kernel "
+    "evaluation using the linear kernel.  The kernel evaluations are stored in "
+    "'kernels.csv' and the indices are stored in 'indices.csv'."
+    "\n\n"
+    "$ fastmks --k 5 --reference_file reference.csv --query_file query.csv\n"
+    "  --indices_file indices.csv --products_file kernels.csv --kernel linear"
+    "\n\n"
+    "The output files are organized such that row i and column j in the indices"
+    " output file corresponds to the index of the point in the reference set "
+    "that has i'th largest kernel evaluation with the point in the query set "
+    "with index j.  Row i and column j in the products output file corresponds "
+    "to the kernel evaluation between those two points."
+    "\n\n"
+    "This executable performs FastMKS using a cover tree.  The base used to "
+    "build the cover tree can be specified with the --base option.");
+
+// Define our input parameters.
+PARAM_STRING_REQ("reference_file", "File containing the reference dataset.",
+    "r");
+PARAM_STRING("query_file", "File containing the query dataset.", "q", "");
+
+PARAM_INT_REQ("k", "Number of maximum inner products to find.", "k");
+
+PARAM_STRING("products_file", "File to save inner products into.", "p", "");
+PARAM_STRING("indices_file", "File to save indices of inner products into.",
+    "i", "");
+
+PARAM_STRING("kernel", "Kernel type to use: 'linear', 'polynomial', 'cosine', "
+    "'gaussian', 'epanechnikov', 'triangular', 'hyptan'.", "K", "linear");
+
+PARAM_FLAG("naive", "If true, O(n^2) naive mode is used for computation.", "N");
+PARAM_FLAG("single", "If true, single-tree search is used (as opposed to "
+    "dual-tree search.", "s");
+
+// Cover tree parameter.
+PARAM_DOUBLE("base", "Base to use during cover tree construction.", "b", 2.0);
+
+// Kernel parameters.
+PARAM_DOUBLE("degree", "Degree of polynomial kernel.", "d", 2.0);
+PARAM_DOUBLE("offset", "Offset of kernel (for polynomial and hyptan kernels).",
+    "o", 0.0);
+PARAM_DOUBLE("bandwidth", "Bandwidth (for Gaussian, Epanechnikov, and "
+    "triangular kernels).", "w", 1.0);
+PARAM_DOUBLE("scale", "Scale of kernel (for hyptan kernel).", "s", 1.0);
+
+//! Run FastMKS on a single dataset for the given kernel type.
+template<typename KernelType>
+void RunFastMKS(const arma::mat& referenceData,
+                const bool single,
+                const bool naive,
+                const double base,
+                const size_t k,
+                arma::Mat<size_t>& indices,
+                arma::mat& products,
+                KernelType& kernel)
+{
+  // Create the tree with the specified base.
+  typedef CoverTree<IPMetric<KernelType>, FirstPointIsRoot, FastMKSStat>
+      TreeType;
+  IPMetric<KernelType> metric(kernel);
+  TreeType tree(referenceData, metric, base);
+
+  // Create FastMKS object.
+  FastMKS<KernelType> fastmks(referenceData, &tree, (single && !naive), naive);
+
+  // Now search with it.
+  fastmks.Search(k, indices, products);
+}
+
+//! Run FastMKS for a given query and reference set using the given kernel type.
+template<typename KernelType>
+void RunFastMKS(const arma::mat& referenceData,
+                const arma::mat& queryData,
+                const bool single,
+                const bool naive,
+                const double base,
+                const size_t k,
+                arma::Mat<size_t>& indices,
+                arma::mat& products,
+                KernelType& kernel)
+{
+  // Create the tree with the specified base.
+  typedef CoverTree<IPMetric<KernelType>, FirstPointIsRoot, FastMKSStat>
+      TreeType;
+  IPMetric<KernelType> metric(kernel);
+  TreeType referenceTree(referenceData, metric, base);
+  TreeType queryTree(queryData, metric, base);
+
+  // Create FastMKS object.
+  FastMKS<KernelType> fastmks(referenceData, &referenceTree, queryData,
+      &queryTree, (single && !naive), naive);
+
+  // Now search with it.
+  fastmks.Search(k, indices, products);
+}
+
+int main(int argc, char** argv)
+{
+  CLI::ParseCommandLine(argc, argv);
+
+  // Get reference dataset filename.
+  const string referenceFile = CLI::GetParam<string>("reference_file");
+
+  // The number of max kernel values to find.
+  const size_t k = CLI::GetParam<int>("k");
+
+  // Runtime parameters.
+  const bool naive = CLI::HasParam("naive");
+  const bool single = CLI::HasParam("single");
+
+  // For cover tree construction.
+  const double base = CLI::GetParam<double>("base");
+
+  // Kernel parameters.
+  const string kernelType = CLI::GetParam<string>("kernel");
+  const double degree = CLI::GetParam<double>("degree");
+  const double offset = CLI::GetParam<double>("offset");
+  const double bandwidth = CLI::GetParam<double>("bandwidth");
+  const double scale = CLI::GetParam<double>("scale");
+
+  // The datasets.  The query matrix may never be used.
+  arma::mat referenceData;
+  arma::mat queryData;
+
+  data::Load(referenceFile, referenceData, true);
+
+  Log::Info << "Loaded reference data from '" << referenceFile << "' ("
+      << referenceData.n_rows << " x " << referenceData.n_cols << ")." << endl;
+
+  // Sanity check on k value.
+  if (k > referenceData.n_cols)
+  {
+    Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less ";
+    Log::Fatal << "than or equal to the number of reference points (";
+    Log::Fatal << referenceData.n_cols << ")." << endl;
+  }
+
+  // Check on kernel type.
+  if ((kernelType != "linear") && (kernelType != "polynomial") &&
+      (kernelType != "cosine") && (kernelType != "gaussian") &&
+      (kernelType != "graph") && (kernelType != "approxGraph") &&
+      (kernelType != "triangular") && (kernelType != "hyptan") &&
+      (kernelType != "inv-mq") && (kernelType != "epanechnikov"))
+  {
+    Log::Fatal << "Invalid kernel type: '" << kernelType << "'; must be ";
+    Log::Fatal << "'linear' or 'polynomial'." << endl;
+  }
+
+  // Load the query matrix, if we can.
+  if (CLI::HasParam("query_file"))
+  {
+    const string queryFile = CLI::GetParam<string>("query_file");
+    data::Load(queryFile, queryData, true);
+
+    Log::Info << "Loaded query data from '" << queryFile << "' ("
+        << queryData.n_rows << " x " << queryData.n_cols << ")." << endl;
+  }
+  else
+  {
+    Log::Info << "Using reference dataset as query dataset (--query_file not "
+        << "specified)." << endl;
+  }
+
+  // Naive mode overrides single mode.
+  if (naive && single)
+  {
+    Log::Warn << "--single ignored because --naive is present." << endl;
+  }
+
+  // Matrices for output storage.
+  arma::Mat<size_t> indices;
+  arma::mat products;
+
+  // Construct FastMKS object.
+  if (queryData.n_elem == 0)
+  {
+    if (kernelType == "linear")
+    {
+      LinearKernel lk;
+      RunFastMKS<LinearKernel>(referenceData, single, naive, base, k, indices,
+          products, lk);
+    }
+    else if (kernelType == "polynomial")
+    {
+
+      PolynomialKernel pk(degree, offset);
+      RunFastMKS<PolynomialKernel>(referenceData, single, naive, base, k,
+          indices, products, pk);
+    }
+    else if (kernelType == "cosine")
+    {
+      CosineDistance cd;
+      RunFastMKS<CosineDistance>(referenceData, single, naive, base, k, indices,
+          products, cd);
+    }
+    else if (kernelType == "gaussian")
+    {
+      GaussianKernel gk(bandwidth);
+      RunFastMKS<GaussianKernel>(referenceData, single, naive, base, k, indices,
+          products, gk);
+    }
+    else if (kernelType == "epanechnikov")
+    {
+      EpanechnikovKernel ek(bandwidth);
+      RunFastMKS<EpanechnikovKernel>(referenceData, single, naive, base, k,
+          indices, products, ek);
+    }
+    else if (kernelType == "triangular")
+    {
+      TriangularKernel tk(bandwidth);
+      RunFastMKS<TriangularKernel>(referenceData, single, naive, base, k,
+          indices, products, tk);
+    }
+    else if (kernelType == "hyptan")
+    {
+      HyperbolicTangentKernel htk(scale, offset);
+      RunFastMKS<HyperbolicTangentKernel>(referenceData, single, naive, base, k,
+          indices, products, htk);
+    }
+  }
+  else
+  {
+    if (kernelType == "linear")
+    {
+      LinearKernel lk;
+      RunFastMKS<LinearKernel>(referenceData, queryData, single, naive, base, k,
+          indices, products, lk);
+    }
+    else if (kernelType == "polynomial")
+    {
+      PolynomialKernel pk(degree, offset);
+      RunFastMKS<PolynomialKernel>(referenceData, queryData, single, naive,
+          base, k, indices, products, pk);
+    }
+    else if (kernelType == "cosine")
+    {
+      CosineDistance cd;
+      RunFastMKS<CosineDistance>(referenceData, queryData, single, naive, base,
+          k, indices, products, cd);
+    }
+    else if (kernelType == "gaussian")
+    {
+      GaussianKernel gk(bandwidth);
+      RunFastMKS<GaussianKernel>(referenceData, queryData, single, naive, base,
+          k, indices, products, gk);
+    }
+    else if (kernelType == "epanechnikov")
+    {
+      EpanechnikovKernel ek(bandwidth);
+      RunFastMKS<EpanechnikovKernel>(referenceData, queryData, single, naive,
+          base, k, indices, products, ek);
+    }
+    else if (kernelType == "triangular")
+    {
+      TriangularKernel tk(bandwidth);
+      RunFastMKS<TriangularKernel>(referenceData, queryData, single, naive,
+          base, k, indices, products, tk);
+    }
+    else if (kernelType == "hyptan")
+    {
+      HyperbolicTangentKernel htk(scale, offset);
+      RunFastMKS<HyperbolicTangentKernel>(referenceData, queryData, single,
+          naive, base, k, indices, products, htk);
+    }
+  }
+
+  // Save output, if we were asked to.
+  if (CLI::HasParam("products_file"))
+  {
+    const string productsFile = CLI::GetParam<string>("products_file");
+    data::Save(productsFile, products, false);
+  }
+
+  if (CLI::HasParam("indices_file"))
+  {
+    const string indicesFile = CLI::GetParam<string>("indices_file");
+    data::Save(indicesFile, indices, false);
+  }
+}

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,145 @@
+/**
+ * @file fastmks_rules.hpp
+ * @author Ryan Curtin
+ *
+ * Rules for the single or dual tree traversal for fast max-kernel search.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_RULES_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_RULES_HPP
+
+#include <mlpack/core.hpp>
+#include <mlpack/core/tree/cover_tree/cover_tree.hpp>
+
+namespace mlpack {
+namespace fastmks {
+
+/**
+ * The base case and pruning rules for FastMKS (fast max-kernel search).
+ */
+template<typename KernelType, typename TreeType>
+class FastMKSRules
+{
+ public:
+  FastMKSRules(const arma::mat& referenceSet,
+               const arma::mat& querySet,
+               arma::Mat<size_t>& indices,
+               arma::mat& products,
+               KernelType& kernel);
+
+  //! Compute the base case (kernel value) between two points.
+  double BaseCase(const size_t queryIndex, const size_t referenceIndex);
+
+  /**
+   * Get the score for recursion order.  A low score indicates priority for
+   * recursion, while DBL_MAX indicates that the node should not be recursed
+   * into at all (it should be pruned).
+   *
+   * @param queryIndex Index of query point.
+   * @param referenceNode Candidate to be recursed into.
+   */
+  double Score(const size_t queryIndex, TreeType& referenceNode) const;
+
+  /**
+   * Get the score for recursion order, passing the base case result (in the
+   * situation where it may be needed to calculate the recursion order).  A low
+   * score indicates priority for recursion, while DBL_MAX indicates that the
+   * node should not be recursed into at all (it should be pruned).
+   *
+   * @param queryIndex Index of query point.
+   * @param referenceNode Candidate node to be recursed into.
+   * @param baseCaseResult Result of BaseCase(queryIndex, referenceNode).
+   */
+  double Score(const size_t queryIndex,
+               TreeType& referenceNode,
+               const double baseCaseResult) const;
+
+  /**
+   * Get the score for recursion order.  A low score indicates priority for
+   * recursion, while DBL_MAX indicates that the node should not be recursed
+   * into at all (it should be pruned).
+   *
+   * @param queryNode Candidate query node to be recursed into.
+   * @param referenceNode Candidate reference node to be recursed into.
+   */
+  double Score(TreeType& queryNode, TreeType& referenceNode) const;
+
+  /**
+   * Get the score for recursion order, passing the base case result (in the
+   * situation where it may be needed to calculate the recursion order).  A low
+   * score indicates priority for recursion, while DBL_MAX indicates that the
+   * node should not be recursed into at all (it should be pruned).
+   *
+   * @param queryNode Candidate query node to be recursed into.
+   * @param referenceNode Candidate reference node to be recursed into.
+   * @param baseCaseResult Result of BaseCase(queryNode, referenceNode).
+   */
+  double Score(TreeType& queryNode,
+               TreeType& referenceNode,
+               const double baseCaseResult) const;
+
+  /**
+   * Re-evaluate the score for recursion order.  A low score indicates priority
+   * for recursion, while DBL_MAX indicates that a node should not be recursed
+   * into at all (it should be pruned).  This is used when the score has already
+   * been calculated, but another recursion may have modified the bounds for
+   * pruning.  So the old score is checked against the new pruning bound.
+   *
+   * @param queryIndex Index of query point.
+   * @param referenceNode Candidate node to be recursed into.
+   * @param oldScore Old score produced by Score() (or Rescore()).
+   */
+  double Rescore(const size_t queryIndex,
+                 TreeType& referenceNode,
+                 const double oldScore) const;
+
+  /**
+   * Re-evaluate the score for recursion order.  A low score indicates priority
+   * for recursion, while DBL_MAX indicates that a node should not be recursed
+   * into at all (it should be pruned).  This is used when the score has already
+   * been calculated, but another recursion may have modified the bounds for
+   * pruning.  So the old score is checked against the new pruning bound.
+   *
+   * @param queryNode Candidate query node to be recursed into.
+   * @param referenceNode Candidate reference node to be recursed into.
+   * @param oldScore Old score produced by Score() (or Rescore()).
+   */
+  double Rescore(TreeType& queryNode,
+                 TreeType& referenceNode,
+                 const double oldScore) const;
+
+ private:
+  //! The reference dataset.
+  const arma::mat& referenceSet;
+  //! The query dataset.
+  const arma::mat& querySet;
+
+  //! The indices of the maximum kernel results.
+  arma::Mat<size_t>& indices;
+  //! The maximum kernels.
+  arma::mat& products;
+
+  //! Cached query set self-kernels (|| q || for each q).
+  arma::vec queryKernels;
+  //! Cached reference set self-kernels (|| r || for each r).
+  arma::vec referenceKernels;
+
+  //! The instantiated kernel.
+  KernelType& kernel;
+
+  //! Calculate the bound for a given query node.
+  double CalculateBound(TreeType& queryNode) const;
+
+  //! Utility function to insert neighbor into list of results.
+  void InsertNeighbor(const size_t queryIndex,
+                      const size_t pos,
+                      const size_t neighbor,
+                      const double distance);
+};
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+// Include implementation.
+#include "fastmks_rules_impl.hpp"
+
+#endif

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules_impl.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_rules_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,284 @@
+/**
+ * @file fastmks_rules_impl.hpp
+ * @author Ryan Curtin
+ *
+ * Implementation of FastMKSRules for cover tree search.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_RULES_IMPL_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_RULES_IMPL_HPP
+
+// In case it hasn't already been included.
+#include "fastmks_rules.hpp"
+
+namespace mlpack {
+namespace fastmks {
+
+template<typename KernelType, typename TreeType>
+FastMKSRules<KernelType, TreeType>::FastMKSRules(const arma::mat& referenceSet,
+                                                 const arma::mat& querySet,
+                                                 arma::Mat<size_t>& indices,
+                                                 arma::mat& products,
+                                                 KernelType& kernel) :
+    referenceSet(referenceSet),
+    querySet(querySet),
+    indices(indices),
+    products(products),
+    kernel(kernel)
+{
+  // Precompute each self-kernel.
+  queryKernels.set_size(querySet.n_cols);
+  for (size_t i = 0; i < querySet.n_cols; ++i)
+    queryKernels[i] = sqrt(kernel.Evaluate(querySet.unsafe_col(i),
+                                           querySet.unsafe_col(i)));
+
+  referenceKernels.set_size(referenceSet.n_cols);
+  for (size_t i = 0; i < referenceSet.n_cols; ++i)
+    referenceKernels[i] = sqrt(kernel.Evaluate(referenceSet.unsafe_col(i),
+                                               referenceSet.unsafe_col(i)));
+}
+
+template<typename KernelType, typename TreeType>
+inline force_inline
+double FastMKSRules<KernelType, TreeType>::BaseCase(
+    const size_t queryIndex,
+    const size_t referenceIndex)
+{
+
+  double kernelEval = kernel.Evaluate(querySet.unsafe_col(queryIndex),
+                                      referenceSet.unsafe_col(referenceIndex));
+
+  // If the reference and query sets are identical, we still need to compute the
+  // base case (so that things can be bounded properly), but we won't add it to
+  // the results.
+  if ((&querySet == &referenceSet) && (queryIndex == referenceIndex))
+    return kernelEval;
+
+  // If this is a better candidate, insert it into the list.
+  if (kernelEval < products(products.n_rows - 1, queryIndex))
+    return kernelEval;
+
+  size_t insertPosition = 0;
+  for ( ; insertPosition < products.n_rows; ++insertPosition)
+    if (kernelEval >= products(insertPosition, queryIndex))
+      break;
+
+  InsertNeighbor(queryIndex, insertPosition, referenceIndex, kernelEval);
+
+  return kernelEval;
+}
+
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::Score(const size_t queryIndex,
+                                                 TreeType& referenceNode) const
+{
+  // Calculate the maximum possible kernel value.
+  const arma::vec queryPoint = querySet.unsafe_col(queryIndex);
+  const arma::vec refCentroid;
+  referenceNode.Bound().Centroid(refCentroid);
+
+  const double maxKernel = kernel.Evaluate(queryPoint, refCentroid) +
+      referenceNode.FurthestDescendantDistance() * queryKernels[queryIndex];
+
+  // Compare with the current best.
+  const double bestKernel = products(products.n_rows - 1, queryIndex);
+
+  // We return the inverse of the maximum kernel so that larger kernels are
+  // recursed into first.
+  return (maxKernel > bestKernel) ? (1.0 / maxKernel) : DBL_MAX;
+}
+
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::Score(
+    const size_t queryIndex,
+    TreeType& referenceNode,
+    const double baseCaseResult) const
+{
+  // We already have the base case result.  Add the bound.
+  const double maxKernel = baseCaseResult +
+      referenceNode.FurthestDescendantDistance() * queryKernels[queryIndex];
+  const double bestKernel = products(products.n_rows - 1, queryIndex);
+
+  // We return the inverse of the maximum kernel so that larger kernels are
+  // recursed into first.
+  return (maxKernel > bestKernel) ? (1.0 / maxKernel) : DBL_MAX;
+}
+
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::Score(TreeType& queryNode,
+                                                 TreeType& referenceNode) const
+{
+  // Calculate the maximum possible kernel value.
+  const arma::vec queryCentroid;
+  const arma::vec refCentroid;
+  queryNode.Bound().Centroid(queryCentroid);
+  referenceNode.Bound().Centroid(refCentroid);
+
+  const double refKernelTerm = queryNode.FurthestDescendantDistance() *
+      referenceNode.Stat().SelfKernel();
+  const double queryKernelTerm = referenceNode.FurthestDescendantDistance() *
+      queryNode.Stat().SelfKernel();
+
+  const double maxKernel = kernel.Evaluate(queryCentroid, refCentroid) +
+      refKernelTerm + queryKernelTerm +
+      (queryNode.FurthestDescendantDistance() *
+       referenceNode.FurthestDescendantDistance());
+
+  // The existing bound.
+  queryNode.Stat().Bound() = CalculateBound(queryNode);
+  const double bestKernel = queryNode.Stat().Bound();
+
+  // We return the inverse of the maximum kernel so that larger kernels are
+  // recursed into first.
+  return (maxKernel > bestKernel) ? (1.0 / maxKernel) : DBL_MAX;
+}
+
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::Score(
+    TreeType& queryNode,
+    TreeType& referenceNode,
+    const double baseCaseResult) const
+{
+  // We already have the base case, so we need to add the bounds.
+  const double refKernelTerm = queryNode.FurthestDescendantDistance() *
+      referenceNode.Stat().SelfKernel();
+  const double queryKernelTerm = referenceNode.FurthestDescendantDistance() *
+      queryNode.Stat().SelfKernel();
+
+  const double maxKernel = baseCaseResult + refKernelTerm + queryKernelTerm +
+      (queryNode.FurthestDescendantDistance() *
+       referenceNode.FurthestDescendantDistance());
+
+  // The existing bound.
+  queryNode.Stat().Bound() = CalculateBound(queryNode);
+  const double bestKernel = queryNode.Stat().Bound();
+
+  // We return the inverse of the maximum kernel so that larger kernels are
+  // recursed into first.
+  return (maxKernel > bestKernel) ? (1.0 / maxKernel) : DBL_MAX;
+}
+
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::Rescore(const size_t queryIndex,
+                                                   TreeType& /*referenceNode*/,
+                                                   const double oldScore) const
+{
+  const double bestKernel = products(products.n_rows - 1, queryIndex);
+
+  return ((1.0 / oldScore) > bestKernel) ? oldScore : DBL_MAX;
+}
+
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::Rescore(TreeType& queryNode,
+                                                   TreeType& /*referenceNode*/,
+                                                   const double oldScore) const
+{
+  queryNode.Stat().Bound() = CalculateBound(queryNode);
+  const double bestKernel = queryNode.Stat().Bound();
+
+  return ((1.0 / oldScore) > bestKernel) ? oldScore : DBL_MAX;
+}
+
+/**
+ * Calculate the bound for the given query node.  This bound represents the
+ * minimum value which a node combination must achieve to guarantee an
+ * improvement in the results.
+ *
+ * @param queryNode Query node to calculate bound for.
+ */
+template<typename MetricType, typename TreeType>
+double FastMKSRules<MetricType, TreeType>::CalculateBound(TreeType& queryNode)
+    const
+{
+  // We have four possible bounds -- just like NeighborSearchRules, but they are
+  // slightly different in this context.
+  //
+  // (1) min ( min_{all points p in queryNode} P_p[k],
+  //           min_{all children c in queryNode} B(c) );
+  // (2) max_{all points p in queryNode} P_p[k] + (worst child distance + worst
+  //           descendant distance) sqrt(K(I_p[k], I_p[k]));
+  // (3) max_{all children c in queryNode} B(c) + <-- not done yet.  ignored.
+  // (4) B(parent of queryNode);
+  double worstPointKernel = DBL_MAX;
+  double bestAdjustedPointKernel = -DBL_MAX;
+//  double bestPointSelfKernel = -DBL_MAX;
+  const double queryDescendantDistance = queryNode.FurthestDescendantDistance();
+
+  // Loop over all points in this node to find the best and worst.
+  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
+  {
+    const size_t point = queryNode.Point(i);
+    if (products(products.n_rows - 1, point) < worstPointKernel)
+      worstPointKernel = products(products.n_rows - 1, point);
+
+    if (products(products.n_rows - 1, point) == -DBL_MAX)
+      continue; // Avoid underflow.
+
+    const double candidateKernel = products(products.n_rows - 1, point) -
+        (2 * queryDescendantDistance) *
+        referenceKernels[indices(indices.n_rows - 1, point)];
+
+    if (candidateKernel > bestAdjustedPointKernel)
+      bestAdjustedPointKernel = candidateKernel;
+  }
+
+  // Loop over all the children in the node.
+  double worstChildKernel = DBL_MAX;
+
+  for (size_t i = 0; i < queryNode.NumChildren(); ++i)
+  {
+    if (queryNode.Child(i).Stat().Bound() < worstChildKernel)
+      worstChildKernel = queryNode.Child(i).Stat().Bound();
+  }
+
+  // Now assemble bound (1).
+  const double firstBound = (worstPointKernel < worstChildKernel) ?
+      worstPointKernel : worstChildKernel;
+
+  // Bound (2) is bestAdjustedPointKernel.
+  const double fourthBound = (queryNode.Parent() == NULL) ? -DBL_MAX :
+      queryNode.Parent()->Stat().Bound();
+
+  // Pick the best of these bounds.
+  const double interA = (firstBound > bestAdjustedPointKernel) ? firstBound :
+      bestAdjustedPointKernel;
+//  const double interA = 0.0;
+  const double interB = fourthBound;
+
+  return (interA > interB) ? interA : interB;
+}
+
+/**
+ * Helper function to insert a point into the neighbors and distances matrices.
+ *
+ * @param queryIndex Index of point whose neighbors we are inserting into.
+ * @param pos Position in list to insert into.
+ * @param neighbor Index of reference point which is being inserted.
+ * @param distance Distance from query point to reference point.
+ */
+template<typename MetricType, typename TreeType>
+void FastMKSRules<MetricType, TreeType>::InsertNeighbor(const size_t queryIndex,
+                                                        const size_t pos,
+                                                        const size_t neighbor,
+                                                        const double distance)
+{
+  // We only memmove() if there is actually a need to shift something.
+  if (pos < (products.n_rows - 1))
+  {
+    int len = (products.n_rows - 1) - pos;
+    memmove(products.colptr(queryIndex) + (pos + 1),
+        products.colptr(queryIndex) + pos,
+        sizeof(double) * len);
+    memmove(indices.colptr(queryIndex) + (pos + 1),
+        indices.colptr(queryIndex) + pos,
+        sizeof(size_t) * len);
+  }
+
+  // Now put the new information in the right index.
+  products(pos, queryIndex) = distance;
+  indices(pos, queryIndex) = neighbor;
+}
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+#endif

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_stat.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_stat.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/fastmks_stat.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,89 @@
+/**
+ * @file fastmks_stat.hpp
+ * @author Ryan Curtin
+ *
+ * The statistic used in trees with FastMKS.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_STAT_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_STAT_HPP
+
+#include <mlpack/core.hpp>
+#include <mlpack/core/tree/tree_traits.hpp>
+
+namespace mlpack {
+namespace fastmks {
+
+/**
+ * The statistic used in trees with FastMKS.  This stores both the bound and the
+ * self-kernels for each node in the tree.
+ */
+class FastMKSStat
+{
+ public:
+  /**
+   * Default initialization.
+   */
+  FastMKSStat() : bound(-DBL_MAX), selfKernel(0.0) { }
+
+  /**
+   * Initialize this statistic for the given tree node.  The TreeType's metric
+   * better be IPMetric with some kernel type (that is, Metric().Kernel() must
+   * exist).
+   *
+   * @param node Node that this statistic is built for.
+   */
+  template<typename TreeType>
+  FastMKSStat(const TreeType& node) :
+      bound(-DBL_MAX)
+  {
+    // Do we have to calculate the centroid?
+    if (tree::TreeTraits<TreeType>::FirstPointIsCentroid)
+    {
+      // If this type of tree has self-children, then maybe the evaluation is
+      // already done.  These statistics are built bottom-up, so the child stat
+      // should already be done.
+      if ((tree::TreeTraits<TreeType>::HasSelfChildren) &&
+          (node.NumChildren() > 0) &&
+          (node.Point(0) == node.Child(0).Point(0)))
+      {
+        selfKernel = node.Child(0).Stat().SelfKernel();
+      }
+      else
+      {
+        selfKernel = sqrt(node.Metric().Kernel().Evaluate(
+            node.Dataset().unsafe_col(node.Point(0)),
+            node.Dataset().unsafe_col(node.Point(0))));
+      }
+    }
+    else
+    {
+      // Calculate the centroid.
+      arma::vec centroid;
+      node.Centroid(centroid);
+
+      selfKernel = sqrt(node.Metric().Kernel().Evaluate(centroid, centroid));
+    }
+  }
+
+  //! Get the self-kernel.
+  double SelfKernel() const { return selfKernel; }
+  //! Modify the self-kernel.
+  double& SelfKernel() { return selfKernel; }
+
+  //! Get the bound.
+  double Bound() const { return bound; }
+  //! Modify the bound.
+  double& Bound() { return bound; }
+
+ private:
+  //! The bound for pruning.
+  double bound;
+
+  //! The self-kernel evaluation: sqrt(K(centroid, centroid)).
+  double selfKernel;
+};
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+#endif

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,51 @@
+/**
+ * @file ip_metric.hpp
+ * @author Ryan Curtin
+ *
+ * Inner product induced metric.  If given a kernel function, this gives the
+ * complementary metric.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_IP_METRIC_HPP
+#define __MLPACK_METHODS_FASTMKS_IP_METRIC_HPP
+
+namespace mlpack {
+namespace fastmks /** Fast maximum kernel search. */ {
+
+template<typename KernelType>
+class IPMetric
+{
+ public:
+  //! Create the IPMetric without an instantiated kernel.
+  IPMetric();
+
+  //! Create the IPMetric with an instantiated kernel.
+  IPMetric(KernelType& kernel);
+
+  //! Destroy the IPMetric object.
+  ~IPMetric();
+
+  /**
+   * Evaluate the metric.
+   */
+  template<typename Vec1Type, typename Vec2Type>
+  double Evaluate(const Vec1Type& a, const Vec2Type& b);
+
+  //! Get the kernel.
+  const KernelType& Kernel() const { return kernel; }
+  //! Modify the kernel.
+  KernelType& Kernel() { return kernel; }
+
+ private:
+  //! The locally stored kernel, if it is necessary.
+  KernelType* localKernel;
+  //! The reference to the kernel that is being used.
+  KernelType& kernel;
+};
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+// Include implementation.
+#include "ip_metric_impl.hpp"
+
+#endif

Added: mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric_impl.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/fastmks/ip_metric_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,69 @@
+/**
+ * @file ip_metric_impl.hpp
+ * @author Ryan Curtin
+ *
+ * Implementation of the IPMetric.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_IP_METRIC_IMPL_HPP
+#define __MLPACK_METHODS_FASTMKS_IP_METRIC_IMPL_HPP
+
+// In case it hasn't been included yet.
+#include "ip_metric_impl.hpp"
+
+#include <mlpack/core/metrics/lmetric.hpp>
+#include <mlpack/core/kernels/linear_kernel.hpp>
+
+namespace mlpack {
+namespace fastmks {
+
+// Constructor with no instantiated kernel.
+template<typename KernelType>
+IPMetric<KernelType>::IPMetric() :
+    localKernel(new KernelType()),
+    kernel(*localKernel)
+{
+  // Nothing to do.
+}
+
+// Constructor with instantiated kernel.
+template<typename KernelType>
+IPMetric<KernelType>::IPMetric(KernelType& kernel) :
+    localKernel(NULL),
+    kernel(kernel)
+{
+  // Nothing to do.
+}
+
+// Destructor for the IPMetric.
+template<typename KernelType>
+IPMetric<KernelType>::~IPMetric()
+{
+  if (localKernel != NULL)
+    delete localKernel;
+}
+
+template<typename KernelType>
+template<typename Vec1Type, typename Vec2Type>
+inline double IPMetric<KernelType>::Evaluate(const Vec1Type& a,
+                                             const Vec2Type& b)
+{
+  // This is the metric induced by the kernel function.
+  // Maybe we can do better by caching some of this?
+  return sqrt(kernel.Evaluate(a, a) + kernel.Evaluate(b, b) -
+      2 * kernel.Evaluate(a, b));
+}
+
+// A specialization for the linear kernel, which actually just turns out to be
+// the Euclidean distance.
+template<>
+template<typename Vec1Type, typename Vec2Type>
+inline double IPMetric<kernel::LinearKernel>::Evaluate(const Vec1Type& a,
+                                                       const Vec2Type& b)
+{
+  return metric::LMetric<2, true>::Evaluate(a, b);
+}
+
+}; // namespace fastmks
+}; // namespace mlpack
+
+#endif


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/methods/gmm:13981-14234

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -50,10 +50,25 @@
  public:
   /**
    * Construct the EMFit object, optionally passing an InitialClusteringType
-   * object (just in case it needs to store state).
+   * object (just in case it needs to store state).  Setting the maximum number
+   * of iterations to 0 means that the EM algorithm will iterate until
+   * convergence (with the given tolerance).
+   *
+   * The parameter forcePositive controls whether or not the covariance matrices
+   * are checked for positive definiteness at each iteration.  This could be a
+   * time-consuming task, so, if you know your data is well-behaved, you can set
+   * it to false and save some runtime.
+   *
+   * @param maxIterations Maximum number of iterations for EM.
+   * @param tolerance Log-likelihood tolerance required for convergence.
+   * @param forcePositive Check for positive-definiteness of each covariance
+   *     matrix at each iteration.
+   * @param clusterer Object which will perform the initial clustering.
    */
-  EMFit(InitialClusteringType clusterer = InitialClusteringType()) :
-      clusterer(clusterer) { /* Nothing to do. */ }
+  EMFit(const size_t maxIterations = 300,
+        const double tolerance = 1e-10,
+        const bool forcePositive = true,
+        InitialClusteringType clusterer = InitialClusteringType());
 
   /**
    * Fit the observations to a Gaussian mixture model (GMM) using the EM
@@ -88,6 +103,28 @@
                 std::vector<arma::mat>& covariances,
                 arma::vec& weights);
 
+  //! Get the clusterer.
+  const InitialClusteringType& Clusterer() const { return clusterer; }
+  //! Modify the clusterer.
+  InitialClusteringType& Clusterer() { return clusterer; }
+
+  //! Get the maximum number of iterations of the EM algorithm.
+  size_t MaxIterations() const { return maxIterations; }
+  //! Modify the maximum number of iterations of the EM algorithm.
+  size_t& MaxIterations() { return maxIterations; }
+
+  //! Get the tolerance for the convergence of the EM algorithm.
+  double Tolerance() const { return tolerance; }
+  //! Modify the tolerance for the convergence of the EM algorithm.
+  double& Tolerance() { return tolerance; }
+
+  //! Get whether or not the covariance matrices are forced to be positive
+  //! definite.
+  bool ForcePositive() const { return forcePositive; }
+  //! Modify whether or not the covariance matrices are forced to be positive
+  //! definite.
+  bool& ForcePositive() { return forcePositive; }
+
  private:
   /**
    * Run the clusterer, and then turn the cluster assignments into Gaussians.
@@ -119,6 +156,13 @@
                        const std::vector<arma::mat>& covariances,
                        const arma::vec& weights) const;
 
+  //! Maximum iterations of EM algorithm.
+  size_t maxIterations;
+  //! Tolerance for convergence of EM.
+  double tolerance;
+  //! Whether or not to force positive definiteness of covariance matrices.
+  bool forcePositive;
+  //! Object which will perform the clustering.
   InitialClusteringType clusterer;
 };
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/em_fit_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -31,7 +31,19 @@
 namespace mlpack {
 namespace gmm {
 
+//! Constructor.
 template<typename InitialClusteringType>
+EMFit<InitialClusteringType>::EMFit(const size_t maxIterations,
+                                    const double tolerance,
+                                    const bool forcePositive,
+                                    InitialClusteringType clusterer) :
+    maxIterations(maxIterations),
+    tolerance(tolerance),
+    forcePositive(forcePositive),
+    clusterer(clusterer)
+{ /* Nothing to do. */ }
+
+template<typename InitialClusteringType>
 void EMFit<InitialClusteringType>::Estimate(const arma::mat& observations,
                                             std::vector<arma::vec>& means,
                                             std::vector<arma::mat>& covariances,
@@ -48,10 +60,12 @@
   arma::mat condProb(observations.n_cols, means.size());
 
   // Iterate to update the model until no more improvement is found.
-  size_t maxIterations = 300;
-  size_t iteration = 0;
-  while (std::abs(l - lOld) > 1e-10 && iteration < maxIterations)
+  size_t iteration = 1;
+  while (std::abs(l - lOld) > tolerance && iteration != maxIterations)
   {
+    Log::Info << "EMFit::Estimate(): iteration " << iteration << ", "
+        << "log-likelihood " << l << "." << std::endl;
+
     // Calculate the conditional probabilities of choosing a particular
     // Gaussian given the observations and the present theta value.
     for (size_t i = 0; i < means.size(); i++)
@@ -65,7 +79,13 @@
 
     // Normalize row-wise.
     for (size_t i = 0; i < condProb.n_rows; i++)
-      condProb.row(i) /= accu(condProb.row(i));
+    {
+      // Avoid dividing by zero; if the probability for everything is 0, we
+      // don't want to make it NaN.
+      const double probSum = accu(condProb.row(i));
+      if (probSum != 0.0)
+        condProb.row(i) /= probSum;
+    }
 
     // Store the sum of the probability of each state over all the observations.
     arma::vec probRowSums = trans(arma::sum(condProb, 0 /* columnwise */));
@@ -74,16 +94,34 @@
     // probabilities.
     for (size_t i = 0; i < means.size(); i++)
     {
-      means[i] = (observations * condProb.col(i)) / probRowSums[i];
+      // Don't update if there's no probability of the Gaussian having points.
+      if (probRowSums[i] != 0)
+        means[i] = (observations * condProb.col(i)) / probRowSums[i];
 
       // Calculate the new value of the covariances using the updated
       // conditional probabilities and the updated means.
       arma::mat tmp = observations - (means[i] *
           arma::ones<arma::rowvec>(observations.n_cols));
-      arma::mat tmp_b = tmp % (arma::ones<arma::vec>(observations.n_rows) *
+      arma::mat tmpB = tmp % (arma::ones<arma::vec>(observations.n_rows) *
           trans(condProb.col(i)));
 
-      covariances[i] = (tmp * trans(tmp_b)) / probRowSums[i];
+      // Don't update if there's no probability of the Gaussian having points.
+      if (probRowSums[i] != 0.0)
+        covariances[i] = (tmp * trans(tmpB)) / probRowSums[i];
+
+      // Ensure positive-definiteness.  TODO: make this more efficient.
+      if (forcePositive && det(covariances[i]) <= 1e-50)
+      {
+        Log::Debug << "Covariance matrix " << i << " is not positive definite. "
+            << "Adding perturbation." << std::endl;
+
+        double perturbation = 1e-30;
+        while (det(covariances[i]) <= 1e-50)
+        {
+          covariances[i].diag() += perturbation;
+          perturbation *= 10; // Slow, but we don't want to add too much.
+        }
+      }
     }
 
     // Calculate the new values for omega using the updated conditional
@@ -116,9 +154,8 @@
   arma::mat condProb(observations.n_cols, means.size());
 
   // Iterate to update the model until no more improvement is found.
-  size_t maxIterations = 300;
-  size_t iteration = 0;
-  while (std::abs(l - lOld) > 1e-10 && iteration < maxIterations)
+  size_t iteration = 1;
+  while (std::abs(l - lOld) > tolerance && iteration != maxIterations)
   {
     // Calculate the conditional probabilities of choosing a particular
     // Gaussian given the observations and the present theta value.
@@ -133,7 +170,13 @@
 
     // Normalize row-wise.
     for (size_t i = 0; i < condProb.n_rows; i++)
-      condProb.row(i) /= accu(condProb.row(i));
+    {
+      // Avoid dividing by zero; if the probability for everything is 0, we
+      // don't want to make it NaN.
+      const double probSum = accu(condProb.row(i));
+      if (probSum != 0.0)
+        condProb.row(i) /= probSum;
+    }
 
     // This will store the sum of probabilities of each state over all the
     // observations.
@@ -156,10 +199,24 @@
       // conditional probabilities and the updated means.
       arma::mat tmp = observations - (means[i] *
           arma::ones<arma::rowvec>(observations.n_cols));
-      arma::mat tmp_b = tmp % (arma::ones<arma::vec>(observations.n_rows) *
+      arma::mat tmpB = tmp % (arma::ones<arma::vec>(observations.n_rows) *
           trans(condProb.col(i) % probabilities));
 
-      covariances[i] = (tmp * trans(tmp_b)) / probRowSums[i];
+      covariances[i] = (tmp * trans(tmpB)) / probRowSums[i];
+
+      // Ensure positive-definiteness.  TODO: make this more efficient.
+      if (forcePositive && det(covariances[i]) <= 1e-50)
+      {
+        Log::Debug << "Covariance matrix " << i << " is not positive definite. "
+            << "Adding perturbation." << std::endl;
+
+        double perturbation = 1e-30;
+        while (det(covariances[i]) <= 1e-50)
+        {
+          covariances[i].diag() += perturbation;
+          perturbation *= 10; // Slow, but we don't want to add too much.
+        }
+      }
     }
 
     // Calculate the new values for omega using the updated conditional
@@ -198,13 +255,13 @@
   // From the assignments, generate our means, covariances, and weights.
   for (size_t i = 0; i < observations.n_cols; ++i)
   {
-    size_t cluster = assignments[i];
+    const size_t cluster = assignments[i];
 
     // Add this to the relevant mean.
     means[cluster] += observations.col(i);
 
     // Add this to the relevant covariance.
-    covariances[cluster] += observations.col(i) * trans(observations.col(i));
+//    covariances[cluster] += observations.col(i) * trans(observations.col(i));
 
     // Now add one to the weights (we will normalize).
     weights[cluster]++;
@@ -213,10 +270,36 @@
   // Now normalize the mean and covariance.
   for (size_t i = 0; i < means.size(); ++i)
   {
-    covariances[i] -= means[i] * trans(means[i]) / weights[i];
+//    covariances[i] -= means[i] * trans(means[i]);
 
-    means[i] /= weights[i];
+    means[i] /= (weights[i] > 1) ? weights[i] : 1;
+//    covariances[i] /= (weights[i] > 1) ? weights[i] : 1;
+  }
+
+  for (size_t i = 0; i < observations.n_cols; ++i)
+  {
+    const size_t cluster = assignments[i];
+    const arma::vec normObs = observations.col(i) - means[cluster];
+    covariances[cluster] += normObs * normObs.t();
+  }
+
+  for (size_t i = 0; i < means.size(); ++i)
+  {
     covariances[i] /= (weights[i] > 1) ? weights[i] : 1;
+
+    // Ensure positive-definiteness.  TODO: make this more efficient.
+    if (forcePositive && det(covariances[i]) <= 1e-50)
+    {
+      Log::Debug << "Covariance matrix " << i << " is not positive definite. "
+          << "Adding perturbation." << std::endl;
+
+      double perturbation = 1e-50;
+      while (det(covariances[i]) <= 1e-50)
+      {
+        covariances[i].diag() += perturbation;
+        perturbation *= 10; // Slow, but we don't want to add too much.
+      }
+    }
   }
 
   // Finally, normalize weights.
@@ -242,7 +325,12 @@
 
   // Now sum over every point.
   for (size_t j = 0; j < observations.n_cols; ++j)
+  {
+    if (accu(likelihoods.col(j)) == 0)
+      Log::Info << "Likelihood of point " << j << " is 0!  It is probably an "
+          << "outlier." << std::endl;
     logLikelihood += log(accu(likelihoods.col(j)));
+  }
 
   return logLikelihood;
 }

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,6 +1,6 @@
 /**
  * @author Parikshit Ram (pram at cc.gatech.edu)
- * @file mog_em.h
+ * @file gmm.hpp
  *
  * Defines a Gaussian Mixture model and
  * estimates the parameters of the model
@@ -215,6 +215,21 @@
    */
   GMM& operator=(const GMM& other);
 
+  /**
+   * Load a GMM from an XML file.  The format of the XML file should be the same
+   * as is generated by the Save() method.
+   *
+   * @param filename Name of XML file containing model to be loaded.
+   */
+  void Load(const std::string& filename);
+
+  /**
+   * Save a GMM to an XML file.
+   *
+   * @param filename Name of XML file to write to.
+   */
+  void Save(const std::string& filename) const;
+
   //! Return the number of gaussians in the model.
   size_t Gaussians() const { return gaussians; }
   //! Modify the number of gaussians in the model.  Careful!  You will have to

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -26,6 +26,8 @@
 // In case it hasn't already been included.
 #include "gmm.hpp"
 
+#include <mlpack/core/util/save_restore_utility.hpp>
+
 namespace mlpack {
 namespace gmm {
 
@@ -79,6 +81,67 @@
   return *this;
 }
 
+// Load a GMM from file.
+template<typename FittingType>
+void GMM<FittingType>::Load(const std::string& filename)
+{
+  util::SaveRestoreUtility load;
+
+  if (!load.ReadFile(filename))
+    Log::Fatal << "GMM::Load(): could not read file '" << filename << "'!\n";
+
+  load.LoadParameter(gaussians, "gaussians");
+  load.LoadParameter(dimensionality, "dimensionality");
+  load.LoadParameter(weights, "weights");
+
+  // We need to do a little error checking here.
+  if (weights.n_elem != gaussians)
+  {
+    Log::Fatal << "GMM::Load('" << filename << "'): file reports " << gaussians
+        << " gaussians but weights vector only contains " << weights.n_elem
+        << " elements!" << std::endl;
+  }
+
+  means.resize(gaussians);
+  covariances.resize(gaussians);
+
+  for (size_t i = 0; i < gaussians; ++i)
+  {
+    std::stringstream o;
+    o << i;
+    std::string meanName = "mean" + o.str();
+    std::string covName = "covariance" + o.str();
+
+    load.LoadParameter(means[i], meanName);
+    load.LoadParameter(covariances[i], covName);
+  }
+}
+
+// Save a GMM to a file.
+template<typename FittingType>
+void GMM<FittingType>::Save(const std::string& filename) const
+{
+  util::SaveRestoreUtility save;
+  save.SaveParameter(gaussians, "gaussians");
+  save.SaveParameter(dimensionality, "dimensionality");
+  save.SaveParameter(weights, "weights");
+  for (size_t i = 0; i < gaussians; ++i)
+  {
+    // Generate names for the XML nodes.
+    std::stringstream o;
+    o << i;
+    std::string meanName = "mean" + o.str();
+    std::string covName = "covariance" + o.str();
+
+    // Now save them.
+    save.SaveParameter(means[i], meanName);
+    save.SaveParameter(covariances[i], covName);
+  }
+
+  if (!save.WriteFile(filename))
+    Log::Warn << "GMM::Save(): error saving to '" << filename << "'.\n";
+}
+
 /**
  * Return the probability of the given observation being from this GMM.
  */
@@ -163,7 +226,7 @@
 
     bestLikelihood = LogLikelihood(observations, means, covariances, weights);
 
-    Log::Debug << "GMM::Estimate(): Log-likelihood of trial 0 is "
+    Log::Info << "GMM::Estimate(): Log-likelihood of trial 0 is "
         << bestLikelihood << "." << std::endl;
 
     // Now the temporary model.
@@ -180,7 +243,7 @@
       double newLikelihood = LogLikelihood(observations, meansTrial,
           covariancesTrial, weightsTrial);
 
-      Log::Debug << "GMM::Estimate(): Log-likelihood of trial " << trial
+      Log::Info << "GMM::Estimate(): Log-likelihood of trial " << trial
           << " is " << newLikelihood << "." << std::endl;
 
       if (newLikelihood > bestLikelihood)

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_main.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/gmm/gmm_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -19,13 +19,35 @@
  * You should have received a copy of the GNU General Public License along with
  * MLPACK.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <mlpack/core.hpp>
+
 #include "gmm.hpp"
 
+#include <mlpack/methods/kmeans/refined_start.hpp>
+
+using namespace mlpack;
+using namespace mlpack::gmm;
+using namespace mlpack::util;
+using namespace mlpack::kmeans;
+
 PROGRAM_INFO("Gaussian Mixture Model (GMM) Training",
     "This program takes a parametric estimate of a Gaussian mixture model (GMM)"
     " using the EM algorithm to find the maximum likelihood estimate.  The "
     "model is saved to an XML file, which contains information about each "
-    "Gaussian.");
+    "Gaussian."
+    "\n\n"
+    "If GMM training fails with an error indicating that a covariance matrix "
+    "could not be inverted, be sure that the 'no_force_positive' flag was not "
+    "specified.  Alternately, adding a small amount of Gaussian noise to the "
+    "entire dataset may help prevent Gaussians with zero variance in a "
+    "particular dimension, which is usually the cause of non-invertible "
+    "covariance matrices."
+    "\n\n"
+    "The 'no_force_positive' flag, if set, will avoid the checks after each "
+    "iteration of the EM algorithm which ensure that the covariance matrices "
+    "are positive definite.  Specifying the flag can cause faster runtime, "
+    "but may also cause non-positive definite covariance matrices, which will "
+    "cause the program to crash.");
 
 PARAM_STRING_REQ("input_file", "File containing the data on which the model "
     "will be fit.", "i");
@@ -33,11 +55,28 @@
 PARAM_STRING("output_file", "The file to write the trained GMM parameters into "
     "(as XML).", "o", "gmm.xml");
 PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);
+PARAM_INT("trials", "Number of trials to perform in training GMM.", "t", 10);
 
-using namespace mlpack;
-using namespace mlpack::gmm;
-using namespace mlpack::util;
+// Parameters for EM algorithm.
+PARAM_DOUBLE("tolerance", "Tolerance for convergence of EM.", "T", 1e-10);
+PARAM_FLAG("no_force_positive", "Do not force the covariance matrices to be "
+    "positive definite.", "P");
+PARAM_INT("max_iterations", "Maximum number of iterations of EM algorithm "
+    "(passing 0 will run until convergence).", "n", 250);
 
+// Parameters for dataset modification.
+PARAM_DOUBLE("noise", "Variance of zero-mean Gaussian noise to add to data.",
+    "N", 0);
+
+// Parameters for k-means initialization.
+PARAM_FLAG("refined_start", "During the initialization, use refined initial "
+    "positions for k-means clustering (Bradley and Fayyad, 1998).", "r");
+PARAM_INT("samplings", "If using --refined_start, specify the number of "
+    "samplings used for initial points.", "S", 100);
+PARAM_DOUBLE("percentage", "If using --refined_start, specify the percentage of"
+    " the dataset used for each sampling (should be between 0.0 and 1.0).",
+    "p", 0.02);
+
 int main(int argc, char* argv[])
 {
   CLI::ParseCommandLine(argc, argv);
@@ -52,40 +91,80 @@
   data::Load(CLI::GetParam<std::string>("input_file").c_str(), dataPoints,
       true);
 
-  int gaussians = CLI::GetParam<int>("gaussians");
+  const int gaussians = CLI::GetParam<int>("gaussians");
   if (gaussians <= 0)
   {
     Log::Fatal << "Invalid number of Gaussians (" << gaussians << "); must "
         "be greater than or equal to 1." << std::endl;
   }
 
-  // Calculate mixture of Gaussians.
-  GMM<> gmm(size_t(gaussians), dataPoints.n_rows);
+  // Do we need to add noise to the dataset?
+  if (CLI::HasParam("noise"))
+  {
+    Timer::Start("noise_addition");
+    const double noise = CLI::GetParam<double>("noise");
+    dataPoints += noise * arma::randn(dataPoints.n_rows, dataPoints.n_cols);
+    Log::Info << "Added zero-mean Gaussian noise with variance " << noise
+        << " to dataset." << std::endl;
+    Timer::Stop("noise_addition");
+  }
 
-  ////// Computing the parameters of the model using the EM algorithm //////
-  Timer::Start("em");
-  double likelihood = gmm.Estimate(dataPoints);
-  Timer::Stop("em");
+  // Gather parameters for EMFit object.
+  const size_t maxIterations = (size_t) CLI::GetParam<int>("max_iterations");
+  const double tolerance = CLI::GetParam<double>("tolerance");
+  const bool forcePositive = !CLI::HasParam("no_force_positive");
 
-  Log::Info << "Log-likelihood of estimate: " << likelihood << ".\n";
+  // This gets a bit weird because we need different types depending on whether
+  // --refined_start is specified.
+  double likelihood;
+  if (CLI::HasParam("refined_start"))
+  {
+    const int samplings = CLI::GetParam<int>("samplings");
+    const double percentage = CLI::GetParam<double>("percentage");
 
-  ////// OUTPUT RESULTS //////
-  SaveRestoreUtility save;
-  save.SaveParameter(gmm.Gaussians(), "gaussians");
-  save.SaveParameter(gmm.Dimensionality(), "dimensionality");
-  save.SaveParameter(trans(gmm.Weights()), "weights");
-  for (size_t i = 0; i < gmm.Gaussians(); ++i)
+    if (samplings <= 0)
+      Log::Fatal << "Number of samplings (" << samplings << ") must be greater"
+          << " than 0!" << std::endl;
+
+    if (percentage <= 0.0 || percentage > 1.0)
+      Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
+          << "greater than 0.0 and less than or equal to 1.0!" << std::endl;
+
+    typedef KMeans<metric::SquaredEuclideanDistance, RefinedStart> KMeansType;
+
+    // These are default parameters.
+    KMeansType k(1000, 1.0, metric::SquaredEuclideanDistance(),
+        RefinedStart(samplings, percentage));
+
+    EMFit<KMeansType> em(maxIterations, tolerance, forcePositive, k);
+
+    GMM<EMFit<KMeansType> > gmm(size_t(gaussians), dataPoints.n_rows, em);
+
+    // Compute the parameters of the model using the EM algorithm.
+    Timer::Start("em");
+    likelihood = gmm.Estimate(dataPoints, CLI::GetParam<int>("trials"));
+    Timer::Stop("em");
+
+    // Save results.
+    gmm.Save(CLI::GetParam<std::string>("output_file"));
+  }
+  else
   {
-    // Generate names for the XML nodes.
-    std::stringstream o;
-    o << i;
-    std::string meanName = "mean" + o.str();
-    std::string covName = "covariance" + o.str();
+    EMFit<> em(maxIterations, tolerance, forcePositive);
 
-    // Now save them.
-    save.SaveParameter(trans(gmm.Means()[0]), meanName);
-    save.SaveParameter(gmm.Covariances()[0], covName);
+    // Calculate mixture of Gaussians.
+    GMM<> gmm(size_t(gaussians), dataPoints.n_rows, em);
+
+    // Compute the parameters of the model using the EM algorithm.
+    Timer::Start("em");
+    likelihood = gmm.Estimate(dataPoints, CLI::GetParam<int>("trials"));
+    Timer::Stop("em");
+
+    // Save results.
+    gmm.Save(CLI::GetParam<std::string>("output_file"));
   }
 
-  save.WriteFile(CLI::GetParam<std::string>("output_file").c_str());
+  Log::Info << "Log-likelihood of estimate: " << likelihood << ".\n";
+
+
 }

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -92,26 +92,30 @@
 template<typename Distribution = distribution::DiscreteDistribution>
 class HMM
 {
- private:
-  //! Transition probability matrix.
-  arma::mat transition;
-
-  //! Set of emission probability distributions; one for each state.
-  std::vector<Distribution> emission;
-
  public:
   /**
    * Create the Hidden Markov Model with the given number of hidden states and
-   * the given default distribution for emissions.
+   * the given default distribution for emissions.  The dimensionality of the
+   * observations is taken from the emissions variable, so it is important that
+   * the given default emission distribution is set with the correct
+   * dimensionality.  Alternately, set the dimensionality with Dimensionality().
+   * Optionally, the tolerance for convergence of the Baum-Welch algorithm can
+   * be set.
    *
    * @param states Number of states.
    * @param emissions Default distribution for emissions.
+   * @param tolerance Tolerance for convergence of training algorithm
+   *      (Baum-Welch).
    */
-  HMM(const size_t states, const Distribution emissions);
+  HMM(const size_t states,
+      const Distribution emissions,
+      const double tolerance = 1e-5);
 
   /**
    * Create the Hidden Markov Model with the given transition matrix and the
-   * given emission distributions.
+   * given emission distributions.  The dimensionality of the observations of
+   * the HMM are taken from the given emission distributions.  Alternately, the
+   * dimensionality can be set with Dimensionality().
    *
    * The transition matrix should be such that T(i, j) is the probability of
    * transition to state i from state j.  The columns of the matrix should sum
@@ -120,16 +124,38 @@
    * The emission matrix should be such that E(i, j) is the probability of
    * emission i while in state j.  The columns of the matrix should sum to 1.
    *
+   * Optionally, the tolerance for convergence of the Baum-Welch algorithm can
+   * be set.
+   *
    * @param transition Transition matrix.
    * @param emission Emission distributions.
+   * @param tolerance Tolerance for convergence of training algorithm
+   *      (Baum-Welch).
    */
-  HMM(const arma::mat& transition, const std::vector<Distribution>& emission);
+  HMM(const arma::mat& transition,
+      const std::vector<Distribution>& emission,
+      const double tolerance = 1e-5);
 
   /**
    * Train the model using the Baum-Welch algorithm, with only the given
    * unlabeled observations.  Instead of giving a guess transition and emission
-   * matrix here, do that in the constructor.
+   * matrix here, do that in the constructor.  Each matrix in the vector of data
+   * sequences holds an individual data sequence; each point in each individual
+   * data sequence should be a column in the matrix.  The number of rows in each
+   * matrix should be equal to the dimensionality of the HMM (which is set in
+   * the constructor).
    *
+   * It is preferable to use the other overload of Train(), with labeled data.
+   * That will produce much better results.  However, if labeled data is
+   * unavailable, this will work.  In addition, it is possible to use Train()
+   * with labeled data first, and then continue to train the model using this
+   * overload of Train() with unlabeled data.
+   *
+   * The tolerance of the Baum-Welch algorithm can be set either in the
+   * constructor or with the Tolerance() method.  When the change in
+   * log-likelihood of the model between iterations is less than the tolerance,
+   * the Baum-Welch algorithm terminates.
+   *
    * @note
    * Train() can be called multiple times with different sequences; each time it
    * is called, it uses the current parameters of the HMM as a starting point
@@ -142,7 +168,14 @@
 
   /**
    * Train the model using the given labeled observations; the transition and
-   * emission matrices are directly estimated.
+   * emission matrices are directly estimated.  Each matrix in the vector of
+   * data sequences corresponds to a vector in the vector of state sequences.
+   * Each point in each individual data sequence should be a column in the
+   * matrix, and its state should be the corresponding element in the state
+   * sequence vector.  For instance, dataSeq[0].col(3) corresponds to the fourth
+   * observation in the first data sequence, and its state is stateSeq[0][3].
+   * The number of rows in each matrix should be equal to the dimensionality of
+   * the HMM (which is set in the constructor).
    *
    * @note
    * Train() can be called multiple times with different sequences; each time it
@@ -152,7 +185,7 @@
    *
    * @param dataSeq Vector of observation sequences.
    * @param stateSeq Vector of state sequences, corresponding to each
-   *    observation.
+   *     observation.
    */
   void Train(const std::vector<arma::mat>& dataSeq,
              const std::vector<arma::Col<size_t> >& stateSeq);
@@ -197,8 +230,9 @@
 
   /**
    * Generate a random data sequence of the given length.  The data sequence is
-   * stored in the data_sequence parameter, and the state sequence is stored in
-   * the state_sequence parameter.
+   * stored in the dataSequence parameter, and the state sequence is stored in
+   * the stateSequence parameter.  Each column of dataSequence represents a
+   * random observation.
    *
    * @param length Length of random sequence to generate.
    * @param dataSequence Vector to store data in.
@@ -231,24 +265,14 @@
    */
   double LogLikelihood(const arma::mat& dataSeq) const;
 
-  /**
-   * Return the transition matrix.
-   */
+  //! Return the transition matrix.
   const arma::mat& Transition() const { return transition; }
-
-  /**
-   * Return a modifiable transition matrix reference.
-   */
+  //! Return a modifiable transition matrix reference.
   arma::mat& Transition() { return transition; }
 
-  /**
-   * Return the emission distributions.
-   */
+  //! Return the emission distributions.
   const std::vector<Distribution>& Emission() const { return emission; }
-
-  /**
-   * Return a modifiable emission probability matrix reference.
-   */
+  //! Return a modifiable emission probability matrix reference.
   std::vector<Distribution>& Emission() { return emission; }
 
   //! Get the dimensionality of observations.
@@ -256,6 +280,11 @@
   //! Set the dimensionality of observations.
   size_t& Dimensionality() { return dimensionality; }
 
+  //! Get the tolerance of the Baum-Welch algorithm.
+  double Tolerance() const { return tolerance; }
+  //! Modify the tolerance of the Baum-Welch algorithm.
+  double& Tolerance() { return tolerance; }
+
  private:
   // Helper functions.
 
@@ -288,8 +317,17 @@
                 const arma::vec& scales,
                 arma::mat& backwardProb) const;
 
+  //! Transition probability matrix.
+  arma::mat transition;
+
+  //! Set of emission probability distributions; one for each state.
+  std::vector<Distribution> emission;
+
   //! Dimensionality of observations.
   size_t dimensionality;
+
+  //! Tolerance of Baum-Welch algorithm.
+  double tolerance;
 };
 
 }; // namespace hmm

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -34,10 +34,13 @@
  * given number of emission states.
  */
 template<typename Distribution>
-HMM<Distribution>::HMM(const size_t states, const Distribution emissions) :
+HMM<Distribution>::HMM(const size_t states,
+                       const Distribution emissions,
+                       const double tolerance) :
     transition(arma::ones<arma::mat>(states, states) / (double) states),
     emission(states, /* default distribution */ emissions),
-    dimensionality(emissions.Dimensionality())
+    dimensionality(emissions.Dimensionality()),
+    tolerance(tolerance)
 { /* nothing to do */ }
 
 /**
@@ -46,18 +49,38 @@
  */
 template<typename Distribution>
 HMM<Distribution>::HMM(const arma::mat& transition,
-                       const std::vector<Distribution>& emission) :
+                       const std::vector<Distribution>& emission,
+                       const double tolerance) :
     transition(transition),
-    emission(emission)
+    emission(emission),
+    tolerance(tolerance)
 {
   // Set the dimensionality, if we can.
   if (emission.size() > 0)
     dimensionality = emission[0].Dimensionality();
+  else
+  {
+    Log::Warn << "HMM::HMM(): no emission distributions given; assuming a "
+        << "dimensionality of 0 and hoping it gets set right later."
+        << std::endl;
+    dimensionality = 0;
+  }
 }
 
 /**
  * Train the model using the Baum-Welch algorithm, with only the given unlabeled
- * observations.
+ * observations.  Each matrix in the vector of data sequences holds an
+ * individual data sequence; each point in each individual data sequence should
+ * be a column in the matrix.  The number of rows in each matrix should be equal
+ * to the dimensionality of the HMM.
+ *
+ * It is preferable to use the other overload of Train(), with labeled data.
+ * That will produce much better results.  However, if labeled data is
+ * unavailable, this will work.  In addition, it is possible to use Train() with
+ * labeled data first, and then continue to train the model using this overload
+ * of Train() with unlabeled data.
+ *
+ * @param dataSeq Set of data sequences to train on.
  */
 template<typename Distribution>
 void HMM<Distribution>::Train(const std::vector<arma::mat>& dataSeq)
@@ -69,14 +92,17 @@
   // Maximum iterations?
   size_t iterations = 1000;
 
-  // Find length of all sequences.
+  // Find length of all sequences and ensure they are the correct size.
   size_t totalLength = 0;
   for (size_t seq = 0; seq < dataSeq.size(); seq++)
+  {
     totalLength += dataSeq[seq].n_cols;
 
-  // Re-set the dimensionality, if we need to.
-  if (dataSeq.size() > 0) // Just in case a user passed an empty sequence...
-    dimensionality = dataSeq[0].n_rows;
+    if (dataSeq[seq].n_rows != dimensionality)
+      Log::Fatal << "HMM::Train(): data sequence " << seq << " has "
+          << "dimensionality " << dataSeq[seq].n_rows << " (expected "
+          << dimensionality << " dimensions)." << std::endl;
+  }
 
   // These are used later for training of each distribution.  We initialize it
   // all now so we don't have to do any allocation later on.
@@ -154,7 +180,7 @@
     Log::Debug << "Iteration " << iter << ": log-likelihood " << loglik
         << std::endl;
 
-    if (fabs(oldLoglik - loglik) < 1e-5)
+    if (std::abs(oldLoglik - loglik) < tolerance)
     {
       Log::Debug << "Converged after " << iter << " iterations." << std::endl;
       break;
@@ -182,10 +208,6 @@
 
   transition.zeros();
 
-  // Re-set the dimensionality, if we need to.
-  if (dataSeq.size() > 0)
-    dimensionality = dataSeq[0].n_rows;
-
   // Estimate the transition and emission matrices directly from the
   // observations.  The emission list holds the time indices for observations
   // from each state.
@@ -202,6 +224,13 @@
           << ") in sequence " << seq << "." << std::endl;
     }
 
+    if (dataSeq[seq].n_rows != dimensionality)
+    {
+      Log::Fatal << "HMM::Train(): data sequence " << seq << " has "
+          << "dimensionality " << dataSeq[seq].n_rows << " (expected "
+          << dimensionality << " dimensions)." << std::endl;
+    }
+
     // Loop over each observation in the sequence.  For estimation of the
     // transition matrix, we must ignore the last observation.
     for (size_t t = 0; t < dataSeq[seq].n_cols - 1; t++)

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_train_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_train_main.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/hmm/hmm_train_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -29,14 +29,18 @@
 PROGRAM_INFO("Hidden Markov Model (HMM) Training", "This program allows a "
     "Hidden Markov Model to be trained on labeled or unlabeled data.  It "
     "support three types of HMMs: discrete HMMs, Gaussian HMMs, or GMM HMMs."
-    "\n"
+    "\n\n"
     "Either one input sequence can be specified (with --input_file), or, a "
     "file containing files in which input sequences can be found (when "
     "--input_file and --batch are used together).  In addition, labels can be "
     "provided in the file specified by --label_file, and if --batch is used, "
     "the file given to --label_file should contain a list of files of labels "
-    "corresponding to the sequences in the file given to --input_file.\n"
-    "\n"
+    "corresponding to the sequences in the file given to --input_file."
+    "\n\n"
+    "The HMM is trained with the Baum-Welch algorithm if no labels are "
+    "provided.  The tolerance of the Baum-Welch algorithm can be set with the "
+    "--tolerance option."
+    "\n\n"
     "Optionally, a pre-created HMM model can be used as a guess for the "
     "transition matrix and emission probabilities; this is specifiable with "
     "--model_file.");
@@ -57,6 +61,7 @@
 PARAM_STRING("output_file", "File to save trained HMM to (XML).", "o",
     "output_hmm.xml");
 PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);
+PARAM_DOUBLE("tolerance", "Tolerance of the Baum-Welch algorithm.", "T", 1e-5);
 
 using namespace mlpack;
 using namespace mlpack::hmm;
@@ -86,6 +91,7 @@
   const string type = CLI::GetParam<string>("type");
   const int states = CLI::GetParam<int>("states");
   const bool batch = CLI::HasParam("batch");
+  const double tolerance = CLI::GetParam<double>("tolerance");
 
   // Validate number of states.
   if (states == 0 && modelFile == "")
@@ -222,7 +228,7 @@
             << "HMMs!" << endl;
 
     // Do we have a model to preload?
-    HMM<DiscreteDistribution> hmm(1, DiscreteDistribution(1));
+    HMM<DiscreteDistribution> hmm(1, DiscreteDistribution(1), tolerance);
 
     if (modelFile != "")
     {
@@ -248,7 +254,7 @@
 
       // Create HMM object.
       hmm = HMM<DiscreteDistribution>(size_t(states),
-          DiscreteDistribution(maxEmission));
+          DiscreteDistribution(maxEmission), tolerance);
     }
 
     // Do we have labels?
@@ -266,7 +272,7 @@
   else if (type == "gaussian")
   {
     // Create HMM object.
-    HMM<GaussianDistribution> hmm(1, GaussianDistribution(1));
+    HMM<GaussianDistribution> hmm(1, GaussianDistribution(1), tolerance);
 
     // Do we have a model to load?
     size_t dimensionality = 0;
@@ -284,7 +290,7 @@
       dimensionality = trainSeq[0].n_rows;
 
       hmm = HMM<GaussianDistribution>(size_t(states),
-          GaussianDistribution(dimensionality));
+          GaussianDistribution(dimensionality), tolerance);
     }
 
     // Verify dimensionality of data.
@@ -337,7 +343,7 @@
             << "be greater than or equal to 1." << endl;
 
       hmm = HMM<GMM<> >(size_t(states), GMM<>(size_t(gaussians),
-          dimensionality));
+          dimensionality), tolerance);
     }
 
     // Verify dimensionality of data.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -136,7 +136,7 @@
     const double degree = CLI::GetParam<double>("degree");
     const double offset = CLI::GetParam<double>("offset");
 
-    PolynomialKernel kernel(offset, degree);
+    PolynomialKernel kernel(degree, offset);
     KernelPCA<PolynomialKernel> kpca(kernel, scaleData);
     kpca.Apply(dataset, newDim);
   }


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/methods/kmeans:13981-14235

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/CMakeLists.txt
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/CMakeLists.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/CMakeLists.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -7,6 +7,8 @@
   max_variance_new_cluster.hpp
   max_variance_new_cluster_impl.hpp
   random_partition.hpp
+  refined_start.hpp
+  refined_start_impl.hpp
 )
 
 # Add directory name to sources.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -49,7 +49,7 @@
  * extern arma::mat data; // Dataset we want to run K-Means on.
  * arma::Col<size_t> assignments; // Cluster assignments.
  *
- * KMeans<> k(); // Default options.
+ * KMeans<> k; // Default options.
  * k.Cluster(data, 3, assignments); // 3 clusters.
  *
  * // Cluster using the Manhattan distance, 100 iterations maximum, and an
@@ -58,16 +58,18 @@
  * k.Cluster(data, 6, assignments); // 6 clusters.
  * @endcode
  *
- * @tparam DistanceMetric The distance metric to use for this KMeans; see
+ * @tparam MetricType The distance metric to use for this KMeans; see
  *     metric::LMetric for an example.
  * @tparam InitialPartitionPolicy Initial partitioning policy; must implement a
  *     default constructor and 'void Cluster(const arma::mat&, const size_t,
- *     arma::Col<size_t>&)'.  @see RandomPartition for an example.
+ *     arma::Col<size_t>&)'.
  * @tparam EmptyClusterPolicy Policy for what to do on an empty cluster; must
  *     implement a default constructor and 'void EmptyCluster(const arma::mat&,
- *     arma::Col<size_t&)'.  @see AllowEmptyClusters and MaxVarianceNewCluster.
+ *     arma::Col<size_t&)'.
+ *
+ * @see RandomPartition, RefinedStart, AllowEmptyClusters, MaxVarianceNewCluster
  */
-template<typename DistanceMetric = metric::SquaredEuclideanDistance,
+template<typename MetricType = metric::SquaredEuclideanDistance,
          typename InitialPartitionPolicy = RandomPartition,
          typename EmptyClusterPolicy = MaxVarianceNewCluster>
 class KMeans
@@ -88,7 +90,7 @@
    *     (0 is valid, but the algorithm may never terminate).
    * @param overclusteringFactor Factor controlling how many extra clusters are
    *     found and then merged to get the desired number of clusters.
-   * @param metric Optional DistanceMetric object; for when the metric has state
+   * @param metric Optional MetricType object; for when the metric has state
    *     it needs to store.
    * @param partitioner Optional InitialPartitionPolicy object; for when a
    *     specially initialized partitioning policy is required.
@@ -97,70 +99,88 @@
    */
   KMeans(const size_t maxIterations = 1000,
          const double overclusteringFactor = 1.0,
-         const DistanceMetric metric = DistanceMetric(),
+         const MetricType metric = MetricType(),
          const InitialPartitionPolicy partitioner = InitialPartitionPolicy(),
          const EmptyClusterPolicy emptyClusterAction = EmptyClusterPolicy());
 
 
   /**
-   * Perform K-Means clustering on the data, returning a list of cluster
+   * Perform k-means clustering on the data, returning a list of cluster
    * assignments.  Optionally, the vector of assignments can be set to an
-   * initial guess of the cluster assignments; to do this, the number of
-   * elements in the list of assignments must be equal to the number of points
-   * (columns) in the dataset.
+   * initial guess of the cluster assignments; to do this, set initialGuess to
+   * true.
    *
-   * @tparam MatType Type of matrix (arma::mat or arma::spmat).
+   * @tparam MatType Type of matrix (arma::mat or arma::sp_mat).
    * @param data Dataset to cluster.
    * @param clusters Number of clusters to compute.
-   * @param assignments Vector to store cluster assignments in.  Can contain an
-   *     initial guess at cluster assignments.
+   * @param assignments Vector to store cluster assignments in.
+   * @param initialGuess If true, then it is assumed that assignments has a list
+   *      of initial cluster assignments.
    */
   template<typename MatType>
   void Cluster(const MatType& data,
                const size_t clusters,
-               arma::Col<size_t>& assignments) const;
-  template<typename MatType>
-  void FastCluster(MatType& data,
-               const size_t clusters,
-               arma::Col<size_t>& assignments) const;
+               arma::Col<size_t>& assignments,
+               const bool initialGuess = false) const;
 
   /**
-   * Return the overclustering factor.
+   * Perform k-means clustering on the data, returning a list of cluster
+   * assignments and also the centroids of each cluster.  Optionally, the vector
+   * of assignments can be set to an initial guess of the cluster assignments;
+   * to do this, set initialAssignmentGuess to true.  Another way to set initial
+   * cluster guesses is to fill the centroids matrix with the centroid guesses,
+   * and then set initialCentroidGuess to true.  initialAssignmentGuess
+   * supersedes initialCentroidGuess, so if both are set to true, the
+   * assignments vector is used.
+   *
+   * Note that if the overclustering factor is greater than 1, the centroids
+   * matrix will be resized in the method.  Regardless of the overclustering
+   * factor, the centroid guess matrix (if initialCentroidGuess is set to true)
+   * should have the same number of rows as the data matrix, and number of
+   * columns equal to 'clusters'.
+   *
+   * @tparam MatType Type of matrix (arma::mat or arma::sp_mat).
+   * @param data Dataset to cluster.
+   * @param clusters Number of clusters to compute.
+   * @param assignments Vector to store cluster assignments in.
+   * @param centroids Matrix in which centroids are stored.
+   * @param initialAssignmentGuess If true, then it is assumed that assignments
+   *      has a list of initial cluster assignments.
+   * @param initialCentroidGuess If true, then it is assumed that centroids
+   *      contains the initial centroids of each cluster.
    */
-  double OverclusteringFactor() const { return overclusteringFactor; }
+  template<typename MatType>
+  void Cluster(const MatType& data,
+               const size_t clusters,
+               arma::Col<size_t>& assignments,
+               MatType& centroids,
+               const bool initialAssignmentGuess = false,
+               const bool initialCentroidGuess = false) const;
 
   /**
-   * Set the overclustering factor.
+   * An implementation of k-means using the Pelleg-Moore algorithm; this is
+   * known to not work -- do not use it!  (Fixing it is TODO, of course; see
+   * #251.)
    */
-  void OverclusteringFactor(const double overclusteringFactor)
-  {
-    if (overclusteringFactor < 1.0)
-    {
-      Log::Warn << "KMeans::OverclusteringFactor(): invalid value (<= 1.0) "
-          "ignored." << std::endl;
-      return;
-    }
+  template<typename MatType>
+  void FastCluster(MatType& data,
+                   const size_t clusters,
+                   arma::Col<size_t>& assignments) const;
 
-    this->overclusteringFactor = overclusteringFactor;
-  }
+  //! Return the overclustering factor.
+  double OverclusteringFactor() const { return overclusteringFactor; }
+  //! Set the overclustering factor.  Must be greater than 1.
+  double& OverclusteringFactor() { return overclusteringFactor; }
 
-  /**
-   * Get the maximum number of iterations.
-   */
+  //! Get the maximum number of iterations.
   size_t MaxIterations() const { return maxIterations; }
+  //! Set the maximum number of iterations.
+  size_t& MaxIterations() { return maxIterations; }
 
-  /**
-   * Set the maximum number of iterations.
-   */
-  void MaxIterations(const size_t maxIterations)
-  {
-    this->maxIterations = maxIterations;
-  }
-
   //! Get the distance metric.
-  const DistanceMetric& Metric() const { return metric; }
+  const MetricType& Metric() const { return metric; }
   //! Modify the distance metric.
-  DistanceMetric& Metric() { return metric; }
+  MetricType& Metric() { return metric; }
 
   //! Get the initial partitioning policy.
   const InitialPartitionPolicy& Partitioner() const { return partitioner; }
@@ -169,9 +189,7 @@
 
   //! Get the empty cluster policy.
   const EmptyClusterPolicy& EmptyClusterAction() const
-  {
-    return emptyClusterAction;
-  }
+  { return emptyClusterAction; }
   //! Modify the empty cluster policy.
   EmptyClusterPolicy& EmptyClusterAction() { return emptyClusterAction; }
 
@@ -181,7 +199,7 @@
   //! Maximum number of iterations before giving up.
   size_t maxIterations;
   //! Instantiated distance metric.
-  DistanceMetric metric;
+  MetricType metric;
   //! Instantiated initial partitioning policy.
   InitialPartitionPolicy partitioner;
   //! Instantiated empty cluster policy.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -34,16 +34,16 @@
 /**
  * Construct the K-Means object.
  */
-template<typename DistanceMetric,
+template<typename MetricType,
          typename InitialPartitionPolicy,
          typename EmptyClusterPolicy>
 KMeans<
-    DistanceMetric,
+    MetricType,
     InitialPartitionPolicy,
     EmptyClusterPolicy>::
 KMeans(const size_t maxIterations,
        const double overclusteringFactor,
-       const DistanceMetric metric,
+       const MetricType metric,
        const InitialPartitionPolicy partitioner,
        const EmptyClusterPolicy emptyClusterAction) :
     maxIterations(maxIterations),
@@ -64,12 +64,12 @@
   }
 }
 
-template<typename DistanceMetric,
+template<typename MetricType,
          typename InitialPartitionPolicy,
          typename EmptyClusterPolicy>
 template<typename MatType>
 void KMeans<
-    DistanceMetric,
+    MetricType,
     InitialPartitionPolicy,
     EmptyClusterPolicy>::
 FastCluster(MatType& data,
@@ -187,8 +187,7 @@
         for (size_t i = mrkd.Begin(); i < mrkd.Count() + mrkd.Begin(); ++i)
         {
           // Initialize minDistance to be nonzero.
-          double minDistance = metric::SquaredEuclideanDistance::Evaluate(
-              data.col(i), centroids.col(0));
+          double minDistance = metric.Evaluate(data.col(i), centroids.col(0));
 
           // Find the minimal distance centroid for this point.
           for (size_t j = 1; j < centroids.n_cols; ++j)
@@ -201,8 +200,7 @@
             }
 
             ++comps;
-            double distance = metric::SquaredEuclideanDistance::Evaluate(
-                data.col(i), centroids.col(j));
+            double distance = metric.Evaluate(data.col(i), centroids.col(j));
             if (minDistance > distance)
             {
               minIndex = j;
@@ -292,8 +290,7 @@
                 p(j) = bound[j].Hi();
             }
 
-            distance = metric::SquaredEuclideanDistance::Evaluate(
-                p.col(0), centroids.col(i));
+            distance = metric.Evaluate(p.col(0), centroids.col(i));
           */
           for (size_t j = 0; j < dimensionality; ++j)
           {
@@ -386,10 +383,9 @@
                   bound[k].Hi() : bound[k].Lo();
               }
 
-              double distancei = metric::SquaredEuclideanDistance::Evaluate(
-                  p.col(0), centroids.col(i));
-              double distanceMin = metric::SquaredEuclideanDistance::Evaluate(
-                  p.col(0), centroids.col(minIndex));
+              double distancei = metric.Evaluate(p.col(0), centroids.col(i));
+              double distanceMin = metric.Evaluate(p.col(0),
+                  centroids.col(minIndex));
             */
 
             comps += 1;
@@ -502,20 +498,46 @@
 }
 
 /**
- * Perform K-Means clustering on the data, returning a list of cluster
- * assignments.
+ * Perform k-means clustering on the data, returning a list of cluster
+ * assignments.  This just forward to the other function, which returns the
+ * centroids too.  If this is properly inlined, there shouldn't be any
+ * performance penalty whatsoever.
  */
-template<typename DistanceMetric,
+template<typename MetricType,
          typename InitialPartitionPolicy,
          typename EmptyClusterPolicy>
 template<typename MatType>
+inline void KMeans<
+    MetricType,
+    InitialPartitionPolicy,
+    EmptyClusterPolicy>::
+Cluster(const MatType& data,
+        const size_t clusters,
+        arma::Col<size_t>& assignments,
+        const bool initialGuess) const
+{
+  MatType centroids(data.n_rows, clusters);
+  Cluster(data, clusters, assignments, centroids, initialGuess);
+}
+
+/**
+ * Perform k-means clustering on the data, returning a list of cluster
+ * assignments and the centroids of each cluster.
+ */
+template<typename MetricType,
+         typename InitialPartitionPolicy,
+         typename EmptyClusterPolicy>
+template<typename MatType>
 void KMeans<
-    DistanceMetric,
+    MetricType,
     InitialPartitionPolicy,
     EmptyClusterPolicy>::
 Cluster(const MatType& data,
         const size_t clusters,
-        arma::Col<size_t>& assignments) const
+        arma::Col<size_t>& assignments,
+        MatType& centroids,
+        const bool initialAssignmentGuess,
+        const bool initialCentroidGuess) const
 {
   // Make sure we have more points than clusters.
   if (clusters > data.n_cols)
@@ -524,7 +546,7 @@
 
   // Make sure our overclustering factor is valid.
   size_t actualClusters = size_t(overclusteringFactor * clusters);
-  if (actualClusters > data.n_cols)
+  if (actualClusters > data.n_cols && overclusteringFactor != 1.0)
   {
     Log::Warn << "KMeans::Cluster(): overclustering factor is too large.  No "
         << "overclustering will be done." << std::endl;
@@ -532,18 +554,62 @@
   }
 
   // Now, the initial assignments.  First determine if they are necessary.
-  if (assignments.n_elem != data.n_cols)
+  if (initialAssignmentGuess)
   {
+    if (assignments.n_elem != data.n_cols)
+      Log::Fatal << "KMeans::Cluster(): initial cluster assignments (length "
+          << assignments.n_elem << ") not the same size as the dataset (size "
+          << data.n_cols << ")!" << std::endl;
+  }
+  else if (initialCentroidGuess)
+  {
+    if (centroids.n_cols != clusters)
+      Log::Fatal << "KMeans::Cluster(): wrong number of initial cluster "
+        << "centroids (" << centroids.n_cols << ", should be " << clusters
+        << ")!" << std::endl;
+
+    if (centroids.n_rows != data.n_rows)
+      Log::Fatal << "KMeans::Cluster(): initial cluster centroids have wrong "
+        << " dimensionality (" << centroids.n_rows << ", should be "
+        << data.n_rows << ")!" << std::endl;
+
+    // If there were no problems, construct the initial assignments from the
+    // given centroids.
+    assignments.set_size(data.n_cols);
+    for (size_t i = 0; i < data.n_cols; ++i)
+    {
+      // Find the closest centroid to this point.
+      double minDistance = std::numeric_limits<double>::infinity();
+      size_t closestCluster = clusters; // Invalid value.
+
+      for (size_t j = 0; j < clusters; j++)
+      {
+        double distance = metric.Evaluate(data.col(i), centroids.col(j));
+
+        if (distance < minDistance)
+        {
+          minDistance = distance;
+          closestCluster = j;
+        }
+      }
+
+      // Assign the point to the closest cluster that we found.
+      assignments[i] = closestCluster;
+    }
+  }
+  else
+  {
     // Use the partitioner to come up with the partition assignments.
     partitioner.Cluster(data, actualClusters, assignments);
   }
 
-  // Centroids of each cluster.  Each column corresponds to a centroid.
-  MatType centroids(data.n_rows, actualClusters);
   // Counts of points in each cluster.
   arma::Col<size_t> counts(actualClusters);
   counts.zeros();
 
+  // Resize to correct size.
+  centroids.set_size(data.n_rows, actualClusters);
+
   // Set counts correctly.
   for (size_t i = 0; i < assignments.n_elem; i++)
     counts[assignments[i]]++;
@@ -574,8 +640,7 @@
 
       for (size_t j = 0; j < actualClusters; j++)
       {
-        double distance = metric::SquaredEuclideanDistance::Evaluate(
-            data.col(i), centroids.col(j));
+        double distance = metric.Evaluate(data.col(i), centroids.col(j));
 
         if (distance < minDistance)
         {
@@ -607,8 +672,26 @@
 
   } while (changedAssignments > 0 && iteration != maxIterations);
 
-  Log::Debug << "Iterations: " << iteration << std::endl;
+  if (iteration != maxIterations)
+  {
+    Log::Debug << "KMeans::Cluster(): converged after " << iteration
+        << " iterations." << std::endl;
+  }
+  else
+  {
+    Log::Debug << "KMeans::Cluster(): terminated after limit of " << iteration
+        << " iterations." << std::endl;
 
+    // Recalculate final clusters.
+    centroids.zeros();
+
+    for (size_t i = 0; i < data.n_cols; i++)
+      centroids.col(assignments[i]) += data.col(i);
+
+    for (size_t i = 0; i < actualClusters; i++)
+      centroids.col(i) /= counts[i];
+  }
+
   // If we have overclustered, we need to merge the nearest clusters.
   if (actualClusters != clusters)
   {
@@ -629,8 +712,8 @@
     {
       for (size_t second = first + 1; second < actualClusters; second++)
       {
-        distances(i) = metric::SquaredEuclideanDistance::Evaluate(
-            centroids.col(first), centroids.col(second));
+        distances(i) = metric.Evaluate(centroids.col(first),
+                                       centroids.col(second));
         firstCluster(i) = first;
         secondCluster(i) = second;
         i++;
@@ -673,8 +756,7 @@
         {
           // Make sure it isn't already DBL_MAX.
           if (distances(offset + (first - cluster)) != DBL_MAX)
-            distances(offset + (first - cluster)) =
-                metric::SquaredEuclideanDistance::Evaluate(
+            distances(offset + (first - cluster)) = metric.Evaluate(
                 centroids.col(first), centroids.col(cluster));
         }
 
@@ -689,8 +771,7 @@
         // Make sure it isn't already DBL_MAX.
         if (distances(offset + (cluster - first)) != DBL_MAX)
         {
-          distances(offset + (cluster - first)) =
-              metric::SquaredEuclideanDistance::Evaluate(
+          distances(offset + (cluster - first)) = metric.Evaluate(
               centroids.col(first), centroids.col(cluster));
         }
       }

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_main.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/kmeans_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -23,6 +23,7 @@
 
 #include "kmeans.hpp"
 #include "allow_empty_clusters.hpp"
+#include "refined_start.hpp"
 
 using namespace mlpack;
 using namespace mlpack::kmeans;
@@ -34,16 +35,35 @@
     "a column of labels in the file containing the input dataset or in a "
     "separate file.  Empty clusters are not allowed by default; when a cluster "
     "becomes empty, the point furthest from the centroid of the cluster with "
-    "maximum variance is taken to fill that cluster.");
+    "maximum variance is taken to fill that cluster."
+    "\n\n"
+    "Optionally, the Bradley and Fayyad approach (\"Refining initial points for"
+    " k-means clustering\", 1998) can be used to select initial points by "
+    "specifying the --refined_start (-r) option.  This approach works by taking"
+    " random samples of the dataset; to specify the number of samples, the "
+    "--samples parameter is used, and to specify the percentage of the dataset "
+    "to be used in each sample, the --percentage parameter is used (it should "
+    "be a value between 0.0 and 1.0)."
+    "\n\n"
+    "If you want to specify your own initial cluster assignments or initial "
+    "cluster centroids, this functionality is available in the C++ interface. "
+    "Alternately, file a bug (well, a feature request) on the mlpack bug "
+    "tracker.");
 
+// Required options.
 PARAM_STRING_REQ("inputFile", "Input dataset to perform clustering on.", "i");
 PARAM_INT_REQ("clusters", "Number of clusters to find.", "c");
 
+// Output options.
 PARAM_FLAG("in_place", "If specified, a column of the learned cluster "
     "assignments will be added to the input dataset file.  In this case, "
     "--outputFile is not necessary.", "p");
-PARAM_STRING("outputFile", "File to write output labels or labeled data to.",
+PARAM_STRING("output_file", "File to write output labels or labeled data to.",
     "o", "output.csv");
+PARAM_STRING("centroid_file", "If specified, the centroids of each cluster will"
+    " be written to the given file.", "C", "");
+
+// k-means configuration options.
 PARAM_FLAG("allow_empty_clusters", "Allow empty clusters to be created.", "e");
 PARAM_FLAG("labels_only", "Only output labels into output file.", "l");
 PARAM_DOUBLE("overclustering", "Finds (overclustering * clusters) clusters, "
@@ -52,8 +72,20 @@
 PARAM_INT("max_iterations", "Maximum number of iterations before K-Means "
     "terminates.", "m", 1000);
 PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);
-PARAM_FLAG("fast_kmeans", "Use the experimental fast k-means algorithm by Pelleg and Moore", "f")
 
+// This is known to not work (#251).
+//PARAM_FLAG("fast_kmeans", "Use the experimental fast k-means algorithm by "
+//    "Pelleg and Moore.", "f");
+
+// Parameters for "refined start" k-means.
+PARAM_FLAG("refined_start", "Use the refined initial point strategy by Bradley "
+    "and Fayyad to choose initial points.", "r");
+PARAM_INT("samplings", "Number of samplings to perform for refined start (use "
+    "when --refined_start is specified).", "S", 100);
+PARAM_DOUBLE("percentage", "Percentage of dataset to use for each refined start"
+    " sampling (use when --refined_start is specified).", "p", 0.02);
+
+
 int main(int argc, char** argv)
 {
   CLI::ParseCommandLine(argc, argv);
@@ -88,7 +120,7 @@
   }
 
   // Make sure we have an output file if we're not doing the work in-place.
-  if (!CLI::HasParam("in_place") && !CLI::HasParam("outputFile"))
+  if (!CLI::HasParam("in_place") && !CLI::HasParam("output_file"))
   {
     Log::Fatal << "--outputFile not specified (and --in_place not set)."
         << std::endl;
@@ -96,34 +128,87 @@
 
   // Load our dataset.
   arma::mat dataset;
-  data::Load(inputFile.c_str(), dataset);
+  data::Load(inputFile.c_str(), dataset, true); // Fatal upon failure.
 
   // Now create the KMeans object.  Because we could be using different types,
   // it gets a little weird...
   arma::Col<size_t> assignments;
+  arma::mat centroids;
 
   if (CLI::HasParam("allow_empty_clusters"))
   {
-    KMeans<metric::SquaredEuclideanDistance, RandomPartition,
-        AllowEmptyClusters> k(maxIterations, overclustering);
+    if (CLI::HasParam("refined_start"))
+    {
+      const int samplings = CLI::GetParam<int>("samplings");
+      const double percentage = CLI::GetParam<int>("percentage");
 
-    Timer::Start("clustering");
-    if (CLI::HasParam("fast_kmeans"))
-      k.FastCluster(dataset, clusters, assignments);
+      if (samplings < 0)
+        Log::Fatal << "Number of samplings (" << samplings << ") must be "
+            << "greater than 0!" << std::endl;
+      if (percentage <= 0.0 || percentage > 1.0)
+        Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
+            << "greater than 0.0 and less than or equal to 1.0!" << std::endl;
+
+      KMeans<metric::SquaredEuclideanDistance, RefinedStart, AllowEmptyClusters>
+          k(maxIterations, overclustering, metric::SquaredEuclideanDistance(),
+          RefinedStart(samplings, percentage));
+
+      Timer::Start("clustering");
+      if (CLI::HasParam("fast_kmeans"))
+        k.FastCluster(dataset, clusters, assignments);
+      else
+        k.Cluster(dataset, clusters, assignments, centroids);
+      Timer::Stop("clustering");
+    }
     else
-      k.Cluster(dataset, clusters, assignments);
-    Timer::Stop("clustering");
+    {
+      KMeans<metric::SquaredEuclideanDistance, RandomPartition,
+          AllowEmptyClusters> k(maxIterations, overclustering);
+
+      Timer::Start("clustering");
+      if (CLI::HasParam("fast_kmeans"))
+        k.FastCluster(dataset, clusters, assignments);
+      else
+        k.Cluster(dataset, clusters, assignments, centroids);
+      Timer::Stop("clustering");
+    }
   }
   else
   {
-    KMeans<> k(maxIterations, overclustering);
+    if (CLI::HasParam("refined_start"))
+    {
+      const int samplings = CLI::GetParam<int>("samplings");
+      const double percentage = CLI::GetParam<int>("percentage");
 
-    Timer::Start("clustering");
-    if (CLI::HasParam("fast_kmeans"))
-      k.FastCluster(dataset, clusters, assignments);
+      if (samplings < 0)
+        Log::Fatal << "Number of samplings (" << samplings << ") must be "
+            << "greater than 0!" << std::endl;
+      if (percentage <= 0.0 || percentage > 1.0)
+        Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
+            << "greater than 0.0 and less than or equal to 1.0!" << std::endl;
+
+      KMeans<metric::SquaredEuclideanDistance, RefinedStart, AllowEmptyClusters>
+          k(maxIterations, overclustering, metric::SquaredEuclideanDistance(),
+          RefinedStart(samplings, percentage));
+
+      Timer::Start("clustering");
+      if (CLI::HasParam("fast_kmeans"))
+        k.FastCluster(dataset, clusters, assignments);
+      else
+        k.Cluster(dataset, clusters, assignments, centroids);
+      Timer::Stop("clustering");
+    }
     else
-      k.Cluster(dataset, clusters, assignments);
-    Timer::Stop("clustering");
+    {
+      KMeans<> k(maxIterations, overclustering);
+
+      Timer::Start("clustering");
+      if (CLI::HasParam("fast_kmeans"))
+        k.FastCluster(dataset, clusters, assignments);
+      else
+        k.Cluster(dataset, clusters, assignments, centroids);
+      Timer::Stop("clustering");
+    }
   }
 
   // Now figure out what to do with our results.
@@ -138,16 +223,16 @@
     dataset.insert_rows(dataset.n_rows, trans(converted));
 
     // Save the dataset.
-    data::Save(inputFile.c_str(), dataset);
+    data::Save(inputFile, dataset);
   }
   else
   {
     if (CLI::HasParam("labels_only"))
     {
       // Save only the labels.
-      string outputFile = CLI::GetParam<string>("outputFile");
+      string outputFile = CLI::GetParam<string>("output_file");
       arma::Mat<size_t> output = trans(assignments);
-      data::Save(outputFile.c_str(), output);
+      data::Save(outputFile, output);
     }
     else
     {
@@ -159,9 +244,13 @@
       dataset.insert_rows(dataset.n_rows, trans(converted));
 
       // Now save, in the different file.
-      string outputFile = CLI::GetParam<string>("outputFile");
-      data::Save(outputFile.c_str(), dataset);
+      string outputFile = CLI::GetParam<string>("output_file");
+      data::Save(outputFile, dataset);
     }
   }
+
+  // Should we write the centroids to a file?
+  if (CLI::HasParam("centroid_file"))
+    data::Save(CLI::GetParam<std::string>("centroid_file"), centroids);
 }
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/random_partition.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/random_partition.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/random_partition.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -44,7 +44,7 @@
    * are random, and the number of points in each cluster should be equal (or
    * approximately equal).
    *
-   * @tparam MatType Type of data (arma::mat or arma::spmat).
+   * @tparam MatType Type of data (arma::mat or arma::sp_mat).
    * @param data Dataset to partition.
    * @param clusters Number of clusters to split dataset into.
    * @param assignments Vector to store cluster assignments into.  Values will

Copied: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start.hpp (from rev 14992, mlpack/trunk/src/mlpack/methods/kmeans/refined_start.hpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,82 @@
+/**
+ * @file refined_start.hpp
+ * @author Ryan Curtin
+ *
+ * An implementation of Bradley and Fayyad's "Refining Initial Points for
+ * K-Means clustering".  This class is meant to provide better initial points
+ * for the k-means algorithm.
+ */
+#ifndef __MLPACK_METHODS_KMEANS_REFINED_START_HPP
+#define __MLPACK_METHODS_KMEANS_REFINED_START_HPP
+
+#include <mlpack/core.hpp>
+
+namespace mlpack {
+namespace kmeans {
+
+/**
+ * A refined approach for choosing initial points for k-means clustering.  This
+ * approach runs k-means several times on random subsets of the data, and then
+ * clusters those solutions to select refined initial cluster assignments.  It
+ * is an implementation of the following paper:
+ *
+ * @inproceedings{bradley1998refining,
+ *   title={Refining initial points for k-means clustering},
+ *   author={Bradley, Paul S and Fayyad, Usama M},
+ *   booktitle={Proceedings of the Fifteenth International Conference on Machine
+ *       Learning (ICML 1998)},
+ *   volume={66},
+ *   year={1998}
+ * }
+ */
+class RefinedStart
+{
+ public:
+  /**
+   * Create the RefinedStart object, optionally specifying parameters for the
+   * number of samplings to perform and the percentage of the dataset to use in
+   * each sampling.
+   */
+  RefinedStart(const size_t samplings = 100,
+               const double percentage = 0.02) :
+      samplings(samplings), percentage(percentage) { }
+
+  /**
+   * Partition the given dataset into the given number of clusters according to
+   * the random sampling scheme outlined in Bradley and Fayyad's paper.
+   *
+   * @tparam MatType Type of data (arma::mat or arma::sp_mat).
+   * @param data Dataset to partition.
+   * @param clusters Number of clusters to split dataset into.
+   * @param assignments Vector to store cluster assignments into.  Values will
+   *     be between 0 and (clusters - 1).
+   */
+  template<typename MatType>
+  void Cluster(const MatType& data,
+               const size_t clusters,
+               arma::Col<size_t>& assignments) const;
+
+  //! Get the number of samplings that will be performed.
+  size_t Samplings() const { return samplings; }
+  //! Modify the number of samplings that will be performed.
+  size_t& Samplings() { return samplings; }
+
+  //! Get the percentage of the data used by each subsampling.
+  double Percentage() const { return percentage; }
+  //! Modify the percentage of the data used by each subsampling.
+  double& Percentage() { return percentage; }
+
+ private:
+  //! The number of samplings to perform.
+  size_t samplings;
+  //! The percentage of the data to use for each subsampling.
+  double percentage;
+};
+
+}; // namespace kmeans
+}; // namespace mlpack
+
+// Include implementation.
+#include "refined_start_impl.hpp"
+
+#endif

Copied: mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start_impl.hpp (from rev 14992, mlpack/trunk/src/mlpack/methods/kmeans/refined_start_impl.hpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start_impl.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/kmeans/refined_start_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,99 @@
+/**
+ * @file refined_start_impl.hpp
+ * @author Ryan Curtin
+ *
+ * An implementation of Bradley and Fayyad's "Refining Initial Points for
+ * K-Means clustering".  This class is meant to provide better initial points
+ * for the k-means algorithm.
+ */
+#ifndef __MLPACK_METHODS_KMEANS_REFINED_START_IMPL_HPP
+#define __MLPACK_METHODS_KMEANS_REFINED_START_IMPL_HPP
+
+// In case it hasn't been included yet.
+#include "refined_start.hpp"
+
+namespace mlpack {
+namespace kmeans {
+
+//! Partition the given dataset according to Bradley and Fayyad's algorithm.
+template<typename MatType>
+void RefinedStart::Cluster(const MatType& data,
+                           const size_t clusters,
+                           arma::Col<size_t>& assignments) const
+{
+  math::RandomSeed(std::time(NULL));
+
+  // This will hold the sampled datasets.
+  const size_t numPoints = size_t(percentage * data.n_cols);
+  MatType sampledData(data.n_rows, numPoints);
+  // vector<bool> is packed so each bool is 1 bit.
+  std::vector<bool> pointsUsed(data.n_cols, false);
+  arma::mat sampledCentroids(data.n_rows, samplings * clusters);
+
+  // We will use these objects repeatedly for clustering.
+  arma::Col<size_t> sampledAssignments;
+  arma::mat centroids;
+  KMeans<> kmeans;
+
+  for (size_t i = 0; i < samplings; ++i)
+  {
+    // First, assemble the sampled dataset.
+    size_t curSample = 0;
+    while (curSample < numPoints)
+    {
+      // Pick a random point in [0, numPoints).
+      size_t sample = (size_t) math::RandInt(data.n_cols);
+
+      if (!pointsUsed[sample])
+      {
+        // This point isn't used yet.  So we'll put it in our sample.
+        pointsUsed[sample] = true;
+        sampledData.col(curSample) = data.col(sample);
+        ++curSample;
+      }
+    }
+
+    // Now, using the sampled dataset, run k-means.  In the case of an empty
+    // cluster, we re-initialize that cluster as the point furthest away from
+    // the cluster with maximum variance.  This is not *exactly* what the paper
+    // implements, but it is quite similar, and we'll call it "good enough".
+    kmeans.Cluster(sampledData, clusters, sampledAssignments, centroids);
+
+    // Store the sampled centroids.
+    sampledCentroids.cols(i * clusters, (i + 1) * clusters - 1) = centroids;
+
+    pointsUsed.assign(data.n_cols, false);
+  }
+
+  // Now, we run k-means on the sampled centroids to get our final clusters.
+  kmeans.Cluster(sampledCentroids, clusters, sampledAssignments, centroids);
+
+  // Turn the final centroids into assignments.
+  assignments.set_size(data.n_cols);
+  for (size_t i = 0; i < data.n_cols; ++i)
+  {
+    // Find the closest centroid to this point.
+    double minDistance = std::numeric_limits<double>::infinity();
+    size_t closestCluster = clusters;
+
+    for (size_t j = 0; j < clusters; ++j)
+    {
+      const double distance = kmeans.Metric().Evaluate(data.col(i),
+          centroids.col(j));
+
+      if (distance < minDistance)
+      {
+        minDistance = distance;
+        closestCluster = j;
+      }
+    }
+
+    // Assign the point to its closest cluster.
+    assignments[i] = closestCluster;
+  }
+}
+
+}; // namespace kmeans
+}; // namespace mlpack
+
+#endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -54,15 +54,15 @@
 void LARS::Regress(const arma::mat& matX,
                    const arma::vec& y,
                    arma::vec& beta,
-                   const bool rowMajor)
+                   const bool transposeData)
 {
   Timer::Start("lars_regression");
 
   // This matrix may end up holding the transpose -- if necessary.
   arma::mat dataTrans;
   // dataRef is row-major.
-  const arma::mat& dataRef = (rowMajor ? matX : dataTrans);
-  if (!rowMajor)
+  const arma::mat& dataRef = (transposeData ? dataTrans : matX);
+  if (transposeData)
     dataTrans = trans(matX);
 
   // Compute X' * y.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/lars/lars.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -138,19 +138,19 @@
    * column-major -- each column is an observation and each row is a dimension.
    * However, because LARS is more efficient on a row-major matrix, this method
    * will (internally) transpose the matrix.  If this transposition is not
-   * necessary (i.e., you want to pass in a row-major matrix), pass 'true' for
-   * the rowMajor parameter.
+   * necessary (i.e., you want to pass in a row-major matrix), pass 'false' for
+   * the transposeData parameter.
    *
    * @param data Column-major input data (or row-major input data if rowMajor =
    *     true).
    * @param responses A vector of targets.
    * @param beta Vector to store the solution (the coefficients) in.
-   * @param rowMajor Set to true if matX is row-major.
+   * @param rowMajor Set to false if the data is row-major.
    */
   void Regress(const arma::mat& data,
                const arma::vec& responses,
                arma::vec& beta,
-               const bool rowMajor = false);
+               const bool transposeData = true);
 
   //! Access the set of active dimensions.
   const std::vector<size_t>& ActiveSet() const { return activeSet; }

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -138,7 +138,7 @@
     // Run LARS for this point, by making an alias of the point and passing
     // that.
     arma::vec beta = codes.unsafe_col(i);
-    lars.Regress(dictPrime, data.unsafe_col(i), beta, true);
+    lars.Regress(dictPrime, data.unsafe_col(i), beta, false);
     beta %= invW; // Remember, beta is an alias of codes.col(i).
   }
 }

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/CMakeLists.txt
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/CMakeLists.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/CMakeLists.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -12,6 +12,8 @@
   sort_policies/furthest_neighbor_sort.cpp
   sort_policies/furthest_neighbor_sort_impl.hpp
   typedef.hpp
+  unmap.hpp
+  unmap.cpp
 )
 
 # Add directory name to sources.

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allkfn_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allkfn_main.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allkfn_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -27,6 +27,7 @@
 #include <iostream>
 
 #include "neighbor_search.hpp"
+#include "unmap.hpp"
 
 using namespace std;
 using namespace mlpack;
@@ -187,36 +188,16 @@
   arma::mat distancesOut(distances.n_rows, distances.n_cols);
   arma::Mat<size_t> neighborsOut(neighbors.n_rows, neighbors.n_cols);
 
-  // Do the actual remapping.
-  if (CLI::GetParam<string>("query_file") != "")
-  {
-    for (size_t i = 0; i < distances.n_cols; ++i)
-    {
-      // Map distances (copy a column).
-      distancesOut.col(oldFromNewQueries[i]) = distances.col(i);
-
-      // Map indices of neighbors.
-      for (size_t j = 0; j < distances.n_rows; ++j)
-      {
-        neighborsOut(j, oldFromNewQueries[i]) = oldFromNewRefs[neighbors(j, i)];
-      }
-    }
-  }
+  // Map the points back to their original locations.
+  if ((CLI::GetParam<string>("query_file") != "") && !singleMode)
+    Unmap(neighbors, distances, oldFromNewRefs, oldFromNewQueries, neighborsOut,
+        distancesOut);
+  else if ((CLI::GetParam<string>("query_file") != "") && singleMode)
+    Unmap(neighbors, distances, oldFromNewRefs, neighborsOut, distancesOut);
   else
-  {
-    for (size_t i = 0; i < distances.n_cols; ++i)
-    {
-      // Map distances (copy a column).
-      distancesOut.col(oldFromNewRefs[i]) = distances.col(i);
+    Unmap(neighbors, distances, oldFromNewRefs, oldFromNewRefs, neighborsOut,
+        distancesOut);
 
-      // Map indices of neighbors.
-      for (size_t j = 0; j < distances.n_rows; ++j)
-      {
-        neighborsOut(j, oldFromNewRefs[i]) = oldFromNewRefs[neighbors(j, i)];
-      }
-    }
-  }
-
   // Clean up.
   if (queryTree)
     delete queryTree;

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allknn_main.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allknn_main.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/allknn_main.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -28,6 +28,7 @@
 #include <iostream>
 
 #include "neighbor_search.hpp"
+#include "unmap.hpp"
 
 using namespace std;
 using namespace mlpack;
@@ -68,20 +69,29 @@
 PARAM_INT("leaf_size", "Leaf size for tree building.", "l", 20);
 PARAM_FLAG("naive", "If true, O(n^2) naive mode is used for computation.", "N");
 PARAM_FLAG("single_mode", "If true, single-tree search is used (as opposed to "
-    "dual-tree search.", "s");
+    "dual-tree search).", "s");
 PARAM_FLAG("cover_tree", "If true, use cover trees to perform the search "
     "(experimental, may be slow).", "c");
+PARAM_FLAG("random_basis", "Before tree-building, project the data onto a "
+    "random orthogonal basis.", "R");
+PARAM_INT("seed", "Random seed (if 0, std::time(NULL) is used).", "s", 0);
 
 int main(int argc, char *argv[])
 {
   // Give CLI the command line parameters the user passed in.
   CLI::ParseCommandLine(argc, argv);
 
+  if (CLI::GetParam<int>("seed") != 0)
+    math::RandomSeed((size_t) CLI::GetParam<int>("seed"));
+  else
+    math::RandomSeed((size_t) std::time(NULL));
+
   // Get all the parameters.
-  string referenceFile = CLI::GetParam<string>("reference_file");
+  const string referenceFile = CLI::GetParam<string>("reference_file");
+  const string queryFile = CLI::GetParam<string>("query_file");
 
-  string distancesFile = CLI::GetParam<string>("distances_file");
-  string neighborsFile = CLI::GetParam<string>("neighbors_file");
+  const string distancesFile = CLI::GetParam<string>("distances_file");
+  const string neighborsFile = CLI::GetParam<string>("neighbors_file");
 
   int lsInt = CLI::GetParam<int>("leaf_size");
 
@@ -89,14 +99,22 @@
 
   bool naive = CLI::HasParam("naive");
   bool singleMode = CLI::HasParam("single_mode");
+  const bool randomBasis = CLI::HasParam("random_basis");
 
   arma::mat referenceData;
   arma::mat queryData; // So it doesn't go out of scope.
-  data::Load(referenceFile.c_str(), referenceData, true);
+  data::Load(referenceFile, referenceData, true);
 
   Log::Info << "Loaded reference data from '" << referenceFile << "' ("
       << referenceData.n_rows << " x " << referenceData.n_cols << ")." << endl;
 
+  if (queryFile != "")
+  {
+    data::Load(queryFile, queryData, true);
+    Log::Info << "Loaded query data from '" << queryFile << "' ("
+      << queryData.n_rows << " x " << queryData.n_cols << ")." << endl;
+  }
+
   // Sanity check on k value: must be greater than 0, must be less than the
   // number of reference points.
   if (k > referenceData.n_cols)
@@ -123,6 +141,43 @@
   if (naive)
     leafSize = referenceData.n_cols;
 
+  // See if we want to project onto a random basis.
+  if (randomBasis)
+  {
+    // Generate the random basis.
+    while (true)
+    {
+      // [Q, R] = qr(randn(d, d));
+      // Q = Q * diag(sign(diag(R)));
+      arma::mat q, r;
+      if (arma::qr(q, r, arma::randn<arma::mat>(referenceData.n_rows,
+          referenceData.n_rows)))
+      {
+        arma::vec rDiag(r.n_rows);
+        for (size_t i = 0; i < rDiag.n_elem; ++i)
+        {
+          if (r(i, i) < 0)
+            rDiag(i) = -1;
+          else if (r(i, i) > 0)
+            rDiag(i) = 1;
+          else
+            rDiag(i) = 0;
+        }
+
+        q *= arma::diagmat(rDiag);
+
+        // Check if the determinant is positive.
+        if (arma::det(q) >= 0)
+        {
+          referenceData = q * referenceData;
+          if (queryFile != "")
+            queryData = q * queryData;
+          break;
+        }
+      }
+    }
+  }
+
   arma::Mat<size_t> neighbors;
   arma::mat distances;
 
@@ -140,9 +195,9 @@
     Timer::Start("tree_building");
 
     BinarySpaceTree<bound::HRectBound<2>, QueryStat<NearestNeighborSort> >
-      refTree(referenceData, oldFromNewRefs, leafSize);
+        refTree(referenceData, oldFromNewRefs, leafSize);
     BinarySpaceTree<bound::HRectBound<2>, QueryStat<NearestNeighborSort> >*
-      queryTree = NULL; // Empty for now.
+        queryTree = NULL; // Empty for now.
 
     Timer::Stop("tree_building");
 
@@ -150,15 +205,11 @@
 
     if (CLI::GetParam<string>("query_file") != "")
     {
-      string queryFile = CLI::GetParam<string>("query_file");
-
-      data::Load(queryFile.c_str(), queryData, true);
-
       if (naive && leafSize < queryData.n_cols)
         leafSize = queryData.n_cols;
 
       Log::Info << "Loaded query data from '" << queryFile << "' ("
-        << queryData.n_rows << " x " << queryData.n_cols << ")." << endl;
+          << queryData.n_rows << " x " << queryData.n_cols << ")." << endl;
 
       Log::Info << "Building query tree..." << endl;
 
@@ -199,51 +250,16 @@
     // construction.
     Log::Info << "Re-mapping indices..." << endl;
 
-    neighbors.set_size(neighborsOut.n_rows, neighborsOut.n_cols);
-    distances.set_size(distancesOut.n_rows, distancesOut.n_cols);
-
-    // Do the actual remapping.
+    // Map the results back to the correct places.
     if ((CLI::GetParam<string>("query_file") != "") && !singleMode)
-    {
-      for (size_t i = 0; i < distancesOut.n_cols; ++i)
-      {
-        // Map distances (copy a column) and square root.
-        distances.col(oldFromNewQueries[i]) = sqrt(distancesOut.col(i));
-
-        // Map indices of neighbors.
-        for (size_t j = 0; j < distancesOut.n_rows; ++j)
-        {
-          neighbors(j, oldFromNewQueries[i]) =
-              oldFromNewRefs[neighborsOut(j, i)];
-        }
-      }
-    }
+      Unmap(neighborsOut, distancesOut, oldFromNewRefs, oldFromNewQueries,
+          neighbors, distances);
     else if ((CLI::GetParam<string>("query_file") != "") && singleMode)
-    {
-      // No remapping of queries is necessary.  So distances are the same.
-      distances = sqrt(distancesOut);
-
-      // The neighbor indices must be mapped.
-      for (size_t j = 0; j < neighborsOut.n_elem; ++j)
-      {
-        neighbors[j] = oldFromNewRefs[neighborsOut[j]];
-      }
-    }
+      Unmap(neighborsOut, distancesOut, oldFromNewRefs, neighbors, distances);
     else
-    {
-      for (size_t i = 0; i < distancesOut.n_cols; ++i)
-      {
-        // Map distances (copy a column).
-        distances.col(oldFromNewRefs[i]) = sqrt(distancesOut.col(i));
+      Unmap(neighborsOut, distancesOut, oldFromNewRefs, oldFromNewRefs,
+          neighbors, distances);
 
-        // Map indices of neighbors.
-        for (size_t j = 0; j < distancesOut.n_rows; ++j)
-        {
-          neighbors(j, oldFromNewRefs[i]) = oldFromNewRefs[neighborsOut(j, i)];
-        }
-      }
-    }
-
     // Clean up.
     if (queryTree)
       delete queryTree;
@@ -271,10 +287,6 @@
     // See if we have query data.
     if (CLI::HasParam("query_file"))
     {
-      string queryFile = CLI::GetParam<string>("query_file");
-
-      data::Load(queryFile, queryData, true);
-
       // Build query tree.
       if (!singleMode)
       {

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -45,7 +45,15 @@
 class QueryStat
 {
  private:
-  //! The bound on the node's neighbor distances.
+  //! The first bound on the node's neighbor distances (B_1).  This represents
+  //! the worst candidate distance of any descendants of this node.
+  double firstBound;
+  //! The second bound on the node's neighbor distances (B_2).  This represents
+  //! a bound on the worst distance of any descendants of this node assembled
+  //! using the best descendant candidate distance modified by the furthest
+  //! descendant distance.
+  double secondBound;
+  //! The better of the two bounds.
   double bound;
 
  public:
@@ -53,29 +61,32 @@
    * Initialize the statistic with the worst possible distance according to
    * our sorting policy.
    */
-  QueryStat() : bound(SortPolicy::WorstDistance()) { }
+  QueryStat() :
+      firstBound(SortPolicy::WorstDistance()),
+      secondBound(SortPolicy::WorstDistance()),
+      bound(SortPolicy::WorstDistance()) { }
 
   /**
-   * Initialization for a leaf, required by the StatisticType policy.
+   * Initialization for a fully initialized node.  In this case, we don't need
+   * to worry about the node.
    */
-  template<typename MatType>
-  QueryStat(const MatType& /* dataset */, const size_t /* begin */, const size_t /* count */)
-      : bound(SortPolicy::WorstDistance()) { }
+  template<typename TreeType>
+  QueryStat(TreeType& /* node */) :
+      firstBound(SortPolicy::WorstDistance()),
+      secondBound(SortPolicy::WorstDistance()),
+      bound(SortPolicy::WorstDistance()) { }
 
-  /**
-   * Initialization for a node, required by the StatisticType policy.
-   */
-  template<typename MatType>
-  QueryStat(const MatType& /* dataset */,
-            const size_t /* begin */,
-            const size_t /* count */,
-            const QueryStat& /* leftStat */,
-            const QueryStat& /* rightStat */)
-      : bound(SortPolicy::WorstDistance()) { }
-
-  //! Get the bound.
+  //! Get the first bound.
+  double FirstBound() const { return firstBound; }
+  //! Modify the first bound.
+  double& FirstBound() { return firstBound; }
+  //! Get the second bound.
+  double SecondBound() const { return secondBound; }
+  //! Modify the second bound.
+  double& SecondBound() { return secondBound; }
+  //! Get the overall bound (the better of the two bounds).
   double Bound() const { return bound; }
-  //! Modify the bound.
+  //! Modify the overall bound (it should be the better of the two bounds).
   double& Bound() { return bound; }
 };
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -51,6 +51,10 @@
                   TreeType& referenceNode,
                   TreeType& referenceChildNode,
                   const double baseCaseResult) const;
+  double PrescoreQ(TreeType& queryNode,
+                   TreeType& queryChildNode,
+                   TreeType& referenceNode,
+                   const double baseCaseResult) const;
 
   /**
    * Get the score for recursion order.  A low score indicates priority for
@@ -147,6 +151,11 @@
   MetricType& metric;
 
   /**
+   * Recalculate the bound for a given query node.
+   */
+  double CalculateBound(TreeType& queryNode) const;
+
+  /**
    * Insert a point into the neighbors and distances matrices; this is a helper
    * function.
    *

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -58,7 +58,7 @@
   // If this distance is better than any of the current candidates, the
   // SortDistance() function will give us the position to insert it into.
   arma::vec queryDist = distances.unsafe_col(queryIndex);
-  size_t insertPosition = SortPolicy::SortDistance(queryDist, distance);
+  const size_t insertPosition = SortPolicy::SortDistance(queryDist, distance);
 
   // SortDistance() returns (size_t() - 1) if we shouldn't add it.
   if (insertPosition != (size_t() - 1))
@@ -77,35 +77,24 @@
   const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
       &referenceNode, &referenceChildNode, baseCaseResult);
 
-  // Calculate the bound on the fly.  This bound will be the minimum of
-  // pointBound (the bounds given by the points in this node) and childBound
-  // (the bounds given by the children of this node).
-  double pointBound = DBL_MAX;
-  double childBound = DBL_MAX;
-  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();
+  // Update our bound.
+  const double bestDistance = CalculateBound(queryNode);
 
-  // Find the bound of the points contained in this node.
-  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
-  {
-    // The bound for this point is the k-th best distance plus the maximum
-    // distance to a child of this node.
-    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
-        maxDescendantDistance;
-    if (bound < pointBound)
-      pointBound = bound;
-  }
+  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
+}
 
-  // Find the bound of the children.
-  for (size_t i = 0; i < queryNode.NumChildren(); ++i)
-  {
-    const double bound = queryNode.Child(i).Stat().Bound();
-    if (bound < childBound)
-      childBound = bound;
-  }
+template<typename SortPolicy, typename MetricType, typename TreeType>
+inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::PrescoreQ(
+    TreeType& queryNode,
+    TreeType& queryChildNode,
+    TreeType& referenceNode,
+    const double baseCaseResult) const
+{
+  const double distance = SortPolicy::BestNodeToNodeDistance(&referenceNode,
+      &queryNode, &queryChildNode, baseCaseResult);
 
   // Update our bound.
-  queryNode.Stat().Bound() = std::min(pointBound, childBound);
-  const double bestDistance = queryNode.Stat().Bound();
+  const double bestDistance = CalculateBound(queryNode);
 
   return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
 }
@@ -161,35 +150,8 @@
   const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
       &referenceNode);
 
-  // Calculate the bound on the fly.  This bound will be the minimum of
-  // pointBound (the bounds given by the points in this node) and childBound
-  // (the bounds given by the children of this node).
-  double pointBound = DBL_MAX;
-  double childBound = DBL_MAX;
-  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();
-
-  // Find the bound of the points contained in this node.
-  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
-  {
-    // The bound for this point is the k-th best distance plus the maximum
-    // distance to a child of this node.
-    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
-        maxDescendantDistance;
-    if (bound < pointBound)
-      pointBound = bound;
-  }
-
-  // Find the bound of the children.
-  for (size_t i = 0; i < queryNode.NumChildren(); ++i)
-  {
-    const double bound = queryNode.Child(i).Stat().Bound();
-    if (bound < childBound)
-      childBound = bound;
-  }
-
   // Update our bound.
-  queryNode.Stat().Bound() = std::min(pointBound, childBound);
-  const double bestDistance = queryNode.Stat().Bound();
+  const double bestDistance = CalculateBound(queryNode);
 
   return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
 }
@@ -203,35 +165,8 @@
   const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
       &referenceNode, baseCaseResult);
 
-  // Calculate the bound on the fly.  This bound will be the minimum of
-  // pointBound (the bounds given by the points in this node) and childBound
-  // (the bounds given by the children of this node).
-  double pointBound = DBL_MAX;
-  double childBound = DBL_MAX;
-  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();
-
-  // Find the bound of the points contained in this node.
-  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
-  {
-    // The bound for this point is the k-th best distance plus the maximum
-    // distance to a child of this node.
-    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
-        maxDescendantDistance;
-    if (bound < pointBound)
-      pointBound = bound;
-  }
-
-  // Find the bound of the children.
-  for (size_t i = 0; i < queryNode.NumChildren(); ++i)
-  {
-    const double bound = queryNode.Child(i).Stat().Bound();
-    if (bound < childBound)
-      childBound = bound;
-  }
-
   // Update our bound.
-  queryNode.Stat().Bound() = std::min(pointBound, childBound);
-  const double bestDistance = queryNode.Stat().Bound();
+  const double bestDistance = CalculateBound(queryNode);
 
   return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
 }
@@ -245,37 +180,118 @@
   if (oldScore == DBL_MAX)
     return oldScore;
 
-  // Calculate the bound on the fly.  This bound will be the minimum of
-  // pointBound (the bounds given by the points in this node) and childBound
-  // (the bounds given by the children of this node).
-  double pointBound = DBL_MAX;
-  double childBound = DBL_MAX;
-  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();
+  // Update our bound.
+  const double bestDistance = CalculateBound(queryNode);
 
-  // Find the bound of the points contained in this node.
+  return (SortPolicy::IsBetter(oldScore, bestDistance)) ? oldScore : DBL_MAX;
+}
+
+// Calculate the bound for a given query node in its current state and update
+// it.
+template<typename SortPolicy, typename MetricType, typename TreeType>
+inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
+    CalculateBound(TreeType& queryNode) const
+{
+  // We have five possible bounds, and we must take the best of them all.  We
+  // don't use min/max here, but instead "best/worst", because this is general
+  // to the nearest-neighbors/furthest-neighbors cases.  For nearest neighbors,
+  // min = best, max = worst.
+  //
+  // (1) worst ( worst_{all points p in queryNode} D_p[k],
+  //             worst_{all children c in queryNode} B(c) );
+  // (2) best_{all points p in queryNode} D_p[k] + worst child distance +
+  //        worst descendant distance;
+  // (3) best_{all children c in queryNode} B(c) +
+  //      2 ( worst descendant distance of queryNode -
+  //          worst descendant distance of c );
+  // (4) B_1(parent of queryNode)
+  // (5) B_2(parent of queryNode);
+  //
+  // D_p[k] is the current k'th candidate distance for point p.
+  // So we will loop over the points in queryNode and the children in queryNode
+  // to calculate all five of these quantities.
+
+  double worstPointDistance = SortPolicy::BestDistance();
+  double bestPointDistance = SortPolicy::WorstDistance();
+
+  // Loop over all points in this node to find the best and worst distance
+  // candidates (for (1) and (2)).
   for (size_t i = 0; i < queryNode.NumPoints(); ++i)
   {
-    // The bound for this point is the k-th best distance plus the maximum
-    // distance to a child of this node.
-    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
-        maxDescendantDistance;
-    if (bound < pointBound)
-      pointBound = bound;
+    const double distance = distances(distances.n_rows - 1, queryNode.Point(i));
+    if (SortPolicy::IsBetter(distance, bestPointDistance))
+      bestPointDistance = distance;
+    if (SortPolicy::IsBetter(worstPointDistance, distance))
+      worstPointDistance = distance;
   }
 
-  // Find the bound of the children.
+  // Loop over all the children in this node to find the worst bound (for (1))
+  // and the best bound with the correcting factor for descendant distances (for
+  // (3)).
+  double worstChildBound = SortPolicy::BestDistance();
+  double bestAdjustedChildBound = SortPolicy::WorstDistance();
+  const double queryMaxDescendantDistance =
+      queryNode.FurthestDescendantDistance();
+
   for (size_t i = 0; i < queryNode.NumChildren(); ++i)
   {
-    const double bound = queryNode.Child(i).Stat().Bound();
-    if (bound < childBound)
-      childBound = bound;
+    const double firstBound = queryNode.Child(i).Stat().FirstBound();
+    const double secondBound = queryNode.Child(i).Stat().SecondBound();
+    const double childMaxDescendantDistance =
+        queryNode.Child(i).FurthestDescendantDistance();
+
+    if (SortPolicy::IsBetter(worstChildBound, firstBound))
+      worstChildBound = firstBound;
+
+    // Now calculate adjustment for maximum descendant distances.
+    const double adjustedBound = SortPolicy::CombineWorst(secondBound,
+        2 * (queryMaxDescendantDistance - childMaxDescendantDistance));
+    if (SortPolicy::IsBetter(adjustedBound, bestAdjustedChildBound))
+      bestAdjustedChildBound = adjustedBound;
   }
 
-  // Update our bound.
-  queryNode.Stat().Bound() = std::min(pointBound, childBound);
-  const double bestDistance = queryNode.Stat().Bound();
+  // This is bound (1).
+  const double firstBound =
+      (SortPolicy::IsBetter(worstPointDistance, worstChildBound)) ?
+      worstChildBound : worstPointDistance;
 
-  return (SortPolicy::IsBetter(oldScore, bestDistance)) ? oldScore : DBL_MAX;
+  // This is bound (2).
+  const double secondBound = SortPolicy::CombineWorst(bestPointDistance,
+      2 * queryMaxDescendantDistance);
+
+  // Bound (3) is bestAdjustedChildBound.
+
+  // Bounds (4) and (5) are the parent bounds.
+  const double fourthBound = (queryNode.Parent() != NULL) ?
+      queryNode.Parent()->Stat().FirstBound() : SortPolicy::WorstDistance();
+  const double fifthBound = (queryNode.Parent() != NULL) ?
+      queryNode.Parent()->Stat().SecondBound() : SortPolicy::WorstDistance();
+
+  // Now, we will take the best of these.  Unfortunately due to the way
+  // IsBetter() is defined, this sort of has to be a little ugly.
+  // The variable interA represents the first bound (B_1), which is the worst
+  // candidate distance of any descendants of this node.
+  // The variable interC represents the second bound (B_2), which is a bound on
+  // the worst distance of any descendants of this node assembled using the best
+  // descendant candidate distance modified using the furthest descendant
+  // distance.
+  const double interA = (SortPolicy::IsBetter(firstBound, fourthBound)) ?
+      firstBound : fourthBound;
+  const double interB =
+      (SortPolicy::IsBetter(bestAdjustedChildBound, secondBound)) ?
+      bestAdjustedChildBound : secondBound;
+  const double interC = (SortPolicy::IsBetter(interB, fifthBound)) ? interB :
+      fifthBound;
+
+  // Update the first and second bounds of the node.
+  queryNode.Stat().FirstBound() = interA;
+  queryNode.Stat().SecondBound() = interC;
+
+  // Update the actual bound of the node.
+  queryNode.Stat().Bound() = (SortPolicy::IsBetter(interA, interC)) ? interA :
+      interC;
+
+  return queryNode.Stat().Bound();
 }
 
 /**

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/furthest_neighbor_sort.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/furthest_neighbor_sort.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/furthest_neighbor_sort.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -142,6 +142,12 @@
    * @return DBL_MAX
    */
   static inline double BestDistance() { return DBL_MAX; }
+
+  /**
+   * Return the worst combination of the two distances.
+   */
+  static inline double CombineWorst(const double a, const double b)
+  { return std::max(a - b, 0.0); }
 };
 
 }; // namespace neighbor

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/nearest_neighbor_sort.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/nearest_neighbor_sort.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/sort_policies/nearest_neighbor_sort.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -145,6 +145,15 @@
    * @return 0.0
    */
   static inline double BestDistance() { return 0.0; }
+
+  /**
+   * Return the worst combination of the two distances.
+   */
+  static inline double CombineWorst(const double a, const double b)
+  {
+    if (a == DBL_MAX || b == DBL_MAX)
+      return DBL_MAX;
+    return a + b; }
 };
 
 }; // namespace neighbor

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/typedef.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/typedef.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/typedef.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -36,22 +36,16 @@
 namespace neighbor {
 
 /**
- * The AllkNN class is the all-k-nearest-neighbors method.  It returns squared
- * L2 distances (squared Euclidean distances) for each of the k nearest
- * neighbors.  Squared distances are used because they are slightly faster than
- * non-squared distances (they have one fewer call to sqrt()).
+ * The AllkNN class is the all-k-nearest-neighbors method.  It returns L2
+ * distances (Euclidean distances) for each of the k nearest neighbors.
  */
-typedef NeighborSearch<NearestNeighborSort, metric::SquaredEuclideanDistance>
-    AllkNN;
+typedef NeighborSearch<NearestNeighborSort, metric::EuclideanDistance> AllkNN;
 
 /**
- * The AllkFN class is the all-k-furthest-neighbors method.  It returns squared
- * L2 distances (squared Euclidean distances) for each of the k furthest
- * neighbors.  Squared distances are used because they are slightly faster than
- * non-squared distances (they have one fewer call to sqrt()).
+ * The AllkFN class is the all-k-furthest-neighbors method.  It returns L2
+ * distances (Euclidean distances) for each of the k furthest neighbors.
  */
-typedef NeighborSearch<FurthestNeighborSort, metric::SquaredEuclideanDistance>
-    AllkFN;
+typedef NeighborSearch<FurthestNeighborSort, metric::EuclideanDistance> AllkFN;
 
 }; // namespace neighbor
 }; // namespace mlpack

Copied: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.cpp (from rev 14992, mlpack/trunk/src/mlpack/methods/neighbor_search/unmap.cpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.cpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,64 @@
+/**
+ * @file unmap.cpp
+ * @author Ryan Curtin
+ *
+ * Auxiliary function to unmap neighbor search results.
+ */
+#include "unmap.hpp"
+
+namespace mlpack {
+namespace neighbor {
+
+// Useful in the dual-tree setting.
+void Unmap(const arma::Mat<size_t>& neighbors,
+           const arma::mat& distances,
+           const std::vector<size_t>& referenceMap,
+           const std::vector<size_t>& queryMap,
+           arma::Mat<size_t>& neighborsOut,
+           arma::mat& distancesOut,
+           const bool squareRoot)
+{
+  // Set matrices to correct size.
+  neighborsOut.set_size(neighbors.n_rows, neighbors.n_cols);
+  distancesOut.set_size(distances.n_rows, distances.n_cols);
+
+  // Unmap distances.
+  for (size_t i = 0; i < distances.n_cols; ++i)
+  {
+    // Map columns to the correct place.  The ternary operator does not work
+    // here...
+    if (squareRoot)
+      distancesOut.col(queryMap[i]) = sqrt(distances.col(i));
+    else
+      distancesOut.col(queryMap[i]) = distances.col(i);
+
+    // Map indices of neighbors.
+    for (size_t j = 0; j < distances.n_rows; ++j)
+      neighborsOut(j, queryMap[i]) = referenceMap[neighbors(j, i)];
+  }
+}
+
+// Useful in the single-tree setting.
+void Unmap(const arma::Mat<size_t>& neighbors,
+           const arma::mat& distances,
+           const std::vector<size_t>& referenceMap,
+           arma::Mat<size_t>& neighborsOut,
+           arma::mat& distancesOut,
+           const bool squareRoot)
+{
+  // Set matrices to correct size.
+  neighborsOut.set_size(neighbors.n_rows, neighbors.n_cols);
+
+  // Take square root of distances, if necessary.
+  if (squareRoot)
+    distancesOut = sqrt(distances);
+  else
+    distancesOut = distances;
+
+  // Map neighbors back to original locations.
+  for (size_t j = 0; j < neighbors.n_elem; ++j)
+    neighborsOut[j] = referenceMap[neighbors[j]];
+}
+
+}; // namespace neighbor
+}; // namespace mlpack

Copied: mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.hpp (from rev 14992, mlpack/trunk/src/mlpack/methods/neighbor_search/unmap.hpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.hpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/neighbor_search/unmap.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,61 @@
+/**
+ * @file unmap.hpp
+ * @author Ryan Curtin
+ *
+ * Convenience methods to unmap results.
+ */
+#ifndef __MLPACK_METHODS_NEIGHBOR_SEARCH_UNMAP_HPP
+#define __MLPACK_METHODS_NEIGHBOR_SEARCH_UNMAP_HPP
+
+#include <mlpack/core.hpp>
+
+namespace mlpack {
+namespace neighbor {
+
+/**
+ * Assuming that the datasets have been mapped using the referenceMap and the
+ * queryMap (such as during kd-tree construction), unmap the columns of the
+ * distances and neighbors matrices into neighborsOut and distancesOut, and also
+ * unmap the entries in each row of neighbors.  This is useful for the dual-tree
+ * case.
+ *
+ * @param neighbors Matrix of neighbors resulting from neighbor search.
+ * @param distances Matrix of distances resulting from neighbor search.
+ * @param referenceMap Mapping of reference set to old points.
+ * @param queryMap Mapping of query set to old points.
+ * @param neighborsOut Matrix to store unmapped neighbors into.
+ * @param distancesOut Matrix to store unmapped distances into.
+ * @param squareRoot If true, take the square root of the distances.
+ */
+void Unmap(const arma::Mat<size_t>& neighbors,
+           const arma::mat& distances,
+           const std::vector<size_t>& referenceMap,
+           const std::vector<size_t>& queryMap,
+           arma::Mat<size_t>& neighborsOut,
+           arma::mat& distancesOut,
+           const bool squareRoot = false);
+
+/**
+ * Assuming that the datasets have been mapped using referenceMap (such as
+ * during kd-tree construction), unmap the columns of the distances and
+ * neighbors matrices into neighborsOut and distancesOut, and also unmap the
+ * entries in each row of neighbors.  This is useful for the single-tree case.
+ *
+ * @param neighbors Matrix of neighbors resulting from neighbor search.
+ * @param distances Matrix of distances resulting from neighbor search.
+ * @param referenceMap Mapping of reference set to old points.
+ * @param neighborsOut Matrix to store unmapped neighbors into.
+ * @param distancesOut Matrix to store unmapped distances into.
+ * @param squareRoot If true, take the square root of the distances.
+ */
+void Unmap(const arma::Mat<size_t>& neighbors,
+           const arma::mat& distances,
+           const std::vector<size_t>& referenceMap,
+           arma::Mat<size_t>& neighborsOut,
+           arma::mat& distancesOut,
+           const bool squareRoot = false);
+
+}; // namespace neighbor
+}; // namespace mlpack
+
+#endif

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/nmf.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/nmf.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/nmf.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -74,9 +74,11 @@
  * @endcode
  *
  * @tparam WUpdateRule The update rule for calculating W matrix at each
- *     iteration; @see MultiplicativeDistanceW for an example.
+ *     iteration.
  * @tparam HUpdateRule The update rule for calculating H matrix at each
- *     iteration; @see MultiplicativeDistanceH for an example.
+ *     iteration.
+ *
+ * @see WMultiplicativeDistanceRule, HMultiplicativeDistanceRule
  */
 template<typename InitializationRule = RandomInitialization,
          typename WUpdateRule = WMultiplicativeDistanceRule,

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/random_init.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/random_init.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/nmf/random_init.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file randominit.hpp
+ * @file random_init.hpp
  * @author Mohan Rajendran
  *
  * Intialization rule for Non-Negative Matrix Factorization (NMF). This simple

Modified: mlpack/branches/mlpack-1.x/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -122,7 +122,7 @@
     // place the result directly into that; then we will not need to have an
     // extra copy.
     arma::vec code = codes.unsafe_col(i);
-    lars.Regress(dictionary, data.unsafe_col(i), code, true);
+    lars.Regress(dictionary, data.unsafe_col(i), code, false);
   }
 }
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/CMakeLists.txt
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/CMakeLists.txt	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/CMakeLists.txt	2013-05-02 02:38:08 UTC (rev 14993)
@@ -3,9 +3,11 @@
   mlpack_test.cpp
   allkfn_test.cpp
   allknn_test.cpp
+  allkrann_search_test.cpp
   arma_extend_test.cpp
   aug_lagrangian_test.cpp
   cli_test.cpp
+  det_test.cpp
   distribution_test.cpp
   emst_test.cpp
   gmm_test.cpp
@@ -19,6 +21,7 @@
   load_save_test.cpp
   local_coordinate_coding_test.cpp
   lrsdp_test.cpp
+  lsh_test.cpp
   math_test.cpp
   nbc_test.cpp
   nca_test.cpp
@@ -31,8 +34,8 @@
   sort_policy_test.cpp
   sparse_coding_test.cpp
   tree_test.cpp
+  tree_traits_test.cpp
   union_find_test.cpp
-  det_test.cpp
 )
 # Link dependencies of test executable.
 target_link_libraries(mlpack_test

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/allkfn_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/allkfn_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/allkfn_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -1,5 +1,5 @@
 /**
- * @file allkfn_test.cpp
+ * @file allkfntest.cpp
  *
  * Tests for AllkFN (all-k-furthest-neighbors).
  *
@@ -83,245 +83,245 @@
 
     // Neighbors of point 0.
     BOOST_REQUIRE(neighbors(9, 0) == 2);
-    BOOST_REQUIRE_CLOSE(distances(9, 0), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 0), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(8, 0) == 5);
-    BOOST_REQUIRE_CLOSE(distances(8, 0), (0.27 * 0.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 0), 0.27, 1e-5);
     BOOST_REQUIRE(neighbors(7, 0) == 1);
-    BOOST_REQUIRE_CLOSE(distances(7, 0), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 0), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(6, 0) == 8);
-    BOOST_REQUIRE_CLOSE(distances(6, 0), (0.40 * 0.40), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 0), 0.40, 1e-5);
     BOOST_REQUIRE(neighbors(5, 0) == 9);
-    BOOST_REQUIRE_CLOSE(distances(5, 0), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 0), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(4, 0) == 10);
-    BOOST_REQUIRE_CLOSE(distances(4, 0), (0.95 * 0.95), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 0), 0.95, 1e-5);
     BOOST_REQUIRE(neighbors(3, 0) == 3);
-    BOOST_REQUIRE_CLOSE(distances(3, 0), (1.20 * 1.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 0), 1.20, 1e-5);
     BOOST_REQUIRE(neighbors(2, 0) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 0), (1.35 * 1.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 0), 1.35, 1e-5);
     BOOST_REQUIRE(neighbors(1, 0) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 0), (2.05 * 2.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 0), 2.05, 1e-5);
     BOOST_REQUIRE(neighbors(0, 0) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 0), (5.00 * 5.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 0), 5.00, 1e-5);
 
     // Neighbors of point 1.
     BOOST_REQUIRE(neighbors(9, 1) == 8);
-    BOOST_REQUIRE_CLOSE(distances(9, 1), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 1), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(8, 1) == 2);
-    BOOST_REQUIRE_CLOSE(distances(8, 1), (0.20 * 0.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 1), 0.20, 1e-5);
     BOOST_REQUIRE(neighbors(7, 1) == 0);
-    BOOST_REQUIRE_CLOSE(distances(7, 1), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 1), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(6, 1) == 9);
-    BOOST_REQUIRE_CLOSE(distances(6, 1), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 1), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(5, 1) == 5);
-    BOOST_REQUIRE_CLOSE(distances(5, 1), (0.57 * 0.57), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 1), 0.57, 1e-5);
     BOOST_REQUIRE(neighbors(4, 1) == 10);
-    BOOST_REQUIRE_CLOSE(distances(4, 1), (0.65 * 0.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 1), 0.65, 1e-5);
     BOOST_REQUIRE(neighbors(3, 1) == 3);
-    BOOST_REQUIRE_CLOSE(distances(3, 1), (0.90 * 0.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 1), 0.90, 1e-5);
     BOOST_REQUIRE(neighbors(2, 1) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 1), (1.65 * 1.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 1), 1.65, 1e-5);
     BOOST_REQUIRE(neighbors(1, 1) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 1), (2.35 * 2.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 1), 2.35, 1e-5);
     BOOST_REQUIRE(neighbors(0, 1) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 1), (4.70 * 4.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 1), 4.70, 1e-5);
 
     // Neighbors of point 2.
     BOOST_REQUIRE(neighbors(9, 2) == 0);
-    BOOST_REQUIRE_CLOSE(distances(9, 2), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 2), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(8, 2) == 1);
-    BOOST_REQUIRE_CLOSE(distances(8, 2), (0.20 * 0.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 2), 0.20, 1e-5);
     BOOST_REQUIRE(neighbors(7, 2) == 8);
-    BOOST_REQUIRE_CLOSE(distances(7, 2), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 2), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(6, 2) == 5);
-    BOOST_REQUIRE_CLOSE(distances(6, 2), (0.37 * 0.37), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 2), 0.37, 1e-5);
     BOOST_REQUIRE(neighbors(5, 2) == 9);
-    BOOST_REQUIRE_CLOSE(distances(5, 2), (0.75 * 0.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 2), 0.75, 1e-5);
     BOOST_REQUIRE(neighbors(4, 2) == 10);
-    BOOST_REQUIRE_CLOSE(distances(4, 2), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 2), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(3, 2) == 3);
-    BOOST_REQUIRE_CLOSE(distances(3, 2), (1.10 * 1.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 2), 1.10, 1e-5);
     BOOST_REQUIRE(neighbors(2, 2) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 2), (1.45 * 1.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 2), 1.45, 1e-5);
     BOOST_REQUIRE(neighbors(1, 2) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 2), (2.15 * 2.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 2), 2.15, 1e-5);
     BOOST_REQUIRE(neighbors(0, 2) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 2), (4.90 * 4.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 2), 4.90, 1e-5);
 
     // Neighbors of point 3.
     BOOST_REQUIRE(neighbors(9, 3) == 10);
-    BOOST_REQUIRE_CLOSE(distances(9, 3), (0.25 * 0.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 3), 0.25, 1e-5);
     BOOST_REQUIRE(neighbors(8, 3) == 9);
-    BOOST_REQUIRE_CLOSE(distances(8, 3), (0.35 * 0.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 3), 0.35, 1e-5);
     BOOST_REQUIRE(neighbors(7, 3) == 8);
-    BOOST_REQUIRE_CLOSE(distances(7, 3), (0.80 * 0.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 3), 0.80, 1e-5);
     BOOST_REQUIRE(neighbors(6, 3) == 1);
-    BOOST_REQUIRE_CLOSE(distances(6, 3), (0.90 * 0.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 3), 0.90, 1e-5);
     BOOST_REQUIRE(neighbors(5, 3) == 2);
-    BOOST_REQUIRE_CLOSE(distances(5, 3), (1.10 * 1.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 3), 1.10, 1e-5);
     BOOST_REQUIRE(neighbors(4, 3) == 0);
-    BOOST_REQUIRE_CLOSE(distances(4, 3), (1.20 * 1.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 3), 1.20, 1e-5);
     BOOST_REQUIRE(neighbors(3, 3) == 5);
-    BOOST_REQUIRE_CLOSE(distances(3, 3), (1.47 * 1.47), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 3), 1.47, 1e-5);
     BOOST_REQUIRE(neighbors(2, 3) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 3), (2.55 * 2.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 3), 2.55, 1e-5);
     BOOST_REQUIRE(neighbors(1, 3) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 3), (3.25 * 3.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 3), 3.25, 1e-5);
     BOOST_REQUIRE(neighbors(0, 3) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 3), (3.80 * 3.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 3), 3.80, 1e-5);
 
     // Neighbors of point 4.
     BOOST_REQUIRE(neighbors(9, 4) == 3);
-    BOOST_REQUIRE_CLOSE(distances(9, 4), (3.80 * 3.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 4), 3.80, 1e-5);
     BOOST_REQUIRE(neighbors(8, 4) == 10);
-    BOOST_REQUIRE_CLOSE(distances(8, 4), (4.05 * 4.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 4), 4.05, 1e-5);
     BOOST_REQUIRE(neighbors(7, 4) == 9);
-    BOOST_REQUIRE_CLOSE(distances(7, 4), (4.15 * 4.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 4), 4.15, 1e-5);
     BOOST_REQUIRE(neighbors(6, 4) == 8);
-    BOOST_REQUIRE_CLOSE(distances(6, 4), (4.60 * 4.60), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 4), 4.60, 1e-5);
     BOOST_REQUIRE(neighbors(5, 4) == 1);
-    BOOST_REQUIRE_CLOSE(distances(5, 4), (4.70 * 4.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 4), 4.70, 1e-5);
     BOOST_REQUIRE(neighbors(4, 4) == 2);
-    BOOST_REQUIRE_CLOSE(distances(4, 4), (4.90 * 4.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 4), 4.90, 1e-5);
     BOOST_REQUIRE(neighbors(3, 4) == 0);
-    BOOST_REQUIRE_CLOSE(distances(3, 4), (5.00 * 5.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 4), 5.00, 1e-5);
     BOOST_REQUIRE(neighbors(2, 4) == 5);
-    BOOST_REQUIRE_CLOSE(distances(2, 4), (5.27 * 5.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 4), 5.27, 1e-5);
     BOOST_REQUIRE(neighbors(1, 4) == 7);
-    BOOST_REQUIRE_CLOSE(distances(1, 4), (6.35 * 6.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 4), 6.35, 1e-5);
     BOOST_REQUIRE(neighbors(0, 4) == 6);
-    BOOST_REQUIRE_CLOSE(distances(0, 4), (7.05 * 7.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 4), 7.05, 1e-5);
 
     // Neighbors of point 5.
     BOOST_REQUIRE(neighbors(9, 5) == 0);
-    BOOST_REQUIRE_CLOSE(distances(9, 5), (0.27 * 0.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 5), 0.27, 1e-5);
     BOOST_REQUIRE(neighbors(8, 5) == 2);
-    BOOST_REQUIRE_CLOSE(distances(8, 5), (0.37 * 0.37), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 5), 0.37, 1e-5);
     BOOST_REQUIRE(neighbors(7, 5) == 1);
-    BOOST_REQUIRE_CLOSE(distances(7, 5), (0.57 * 0.57), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 5), 0.57, 1e-5);
     BOOST_REQUIRE(neighbors(6, 5) == 8);
-    BOOST_REQUIRE_CLOSE(distances(6, 5), (0.67 * 0.67), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 5), 0.67, 1e-5);
     BOOST_REQUIRE(neighbors(5, 5) == 7);
-    BOOST_REQUIRE_CLOSE(distances(5, 5), (1.08 * 1.08), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 5), 1.08, 1e-5);
     BOOST_REQUIRE(neighbors(4, 5) == 9);
-    BOOST_REQUIRE_CLOSE(distances(4, 5), (1.12 * 1.12), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 5), 1.12, 1e-5);
     BOOST_REQUIRE(neighbors(3, 5) == 10);
-    BOOST_REQUIRE_CLOSE(distances(3, 5), (1.22 * 1.22), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 5), 1.22, 1e-5);
     BOOST_REQUIRE(neighbors(2, 5) == 3);
-    BOOST_REQUIRE_CLOSE(distances(2, 5), (1.47 * 1.47), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 5), 1.47, 1e-5);
     BOOST_REQUIRE(neighbors(1, 5) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 5), (1.78 * 1.78), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 5), 1.78, 1e-5);
     BOOST_REQUIRE(neighbors(0, 5) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 5), (5.27 * 5.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 5), 5.27, 1e-5);
 
     // Neighbors of point 6.
     BOOST_REQUIRE(neighbors(9, 6) == 7);
-    BOOST_REQUIRE_CLOSE(distances(9, 6), (0.70 * 0.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 6), 0.70, 1e-5);
     BOOST_REQUIRE(neighbors(8, 6) == 5);
-    BOOST_REQUIRE_CLOSE(distances(8, 6), (1.78 * 1.78), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 6), 1.78, 1e-5);
     BOOST_REQUIRE(neighbors(7, 6) == 0);
-    BOOST_REQUIRE_CLOSE(distances(7, 6), (2.05 * 2.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 6), 2.05, 1e-5);
     BOOST_REQUIRE(neighbors(6, 6) == 2);
-    BOOST_REQUIRE_CLOSE(distances(6, 6), (2.15 * 2.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 6), 2.15, 1e-5);
     BOOST_REQUIRE(neighbors(5, 6) == 1);
-    BOOST_REQUIRE_CLOSE(distances(5, 6), (2.35 * 2.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 6), 2.35, 1e-5);
     BOOST_REQUIRE(neighbors(4, 6) == 8);
-    BOOST_REQUIRE_CLOSE(distances(4, 6), (2.45 * 2.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 6), 2.45, 1e-5);
     BOOST_REQUIRE(neighbors(3, 6) == 9);
-    BOOST_REQUIRE_CLOSE(distances(3, 6), (2.90 * 2.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 6), 2.90, 1e-5);
     BOOST_REQUIRE(neighbors(2, 6) == 10);
-    BOOST_REQUIRE_CLOSE(distances(2, 6), (3.00 * 3.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 6), 3.00, 1e-5);
     BOOST_REQUIRE(neighbors(1, 6) == 3);
-    BOOST_REQUIRE_CLOSE(distances(1, 6), (3.25 * 3.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 6), 3.25, 1e-5);
     BOOST_REQUIRE(neighbors(0, 6) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 6), (7.05 * 7.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 6), 7.05, 1e-5);
 
     // Neighbors of point 7.
     BOOST_REQUIRE(neighbors(9, 7) == 6);
-    BOOST_REQUIRE_CLOSE(distances(9, 7), (0.70 * 0.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 7), 0.70, 1e-5);
     BOOST_REQUIRE(neighbors(8, 7) == 5);
-    BOOST_REQUIRE_CLOSE(distances(8, 7), (1.08 * 1.08), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 7), 1.08, 1e-5);
     BOOST_REQUIRE(neighbors(7, 7) == 0);
-    BOOST_REQUIRE_CLOSE(distances(7, 7), (1.35 * 1.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 7), 1.35, 1e-5);
     BOOST_REQUIRE(neighbors(6, 7) == 2);
-    BOOST_REQUIRE_CLOSE(distances(6, 7), (1.45 * 1.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 7), 1.45, 1e-5);
     BOOST_REQUIRE(neighbors(5, 7) == 1);
-    BOOST_REQUIRE_CLOSE(distances(5, 7), (1.65 * 1.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 7), 1.65, 1e-5);
     BOOST_REQUIRE(neighbors(4, 7) == 8);
-    BOOST_REQUIRE_CLOSE(distances(4, 7), (1.75 * 1.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 7), 1.75, 1e-5);
     BOOST_REQUIRE(neighbors(3, 7) == 9);
-    BOOST_REQUIRE_CLOSE(distances(3, 7), (2.20 * 2.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 7), 2.20, 1e-5);
     BOOST_REQUIRE(neighbors(2, 7) == 10);
-    BOOST_REQUIRE_CLOSE(distances(2, 7), (2.30 * 2.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 7), 2.30, 1e-5);
     BOOST_REQUIRE(neighbors(1, 7) == 3);
-    BOOST_REQUIRE_CLOSE(distances(1, 7), (2.55 * 2.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 7), 2.55, 1e-5);
     BOOST_REQUIRE(neighbors(0, 7) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 7), (6.35 * 6.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 7), 6.35, 1e-5);
 
     // Neighbors of point 8.
     BOOST_REQUIRE(neighbors(9, 8) == 1);
-    BOOST_REQUIRE_CLOSE(distances(9, 8), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 8), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(8, 8) == 2);
-    BOOST_REQUIRE_CLOSE(distances(8, 8), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 8), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(7, 8) == 0);
-    BOOST_REQUIRE_CLOSE(distances(7, 8), (0.40 * 0.40), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 8), 0.40, 1e-5);
     BOOST_REQUIRE(neighbors(6, 8) == 9);
-    BOOST_REQUIRE_CLOSE(distances(6, 8), (0.45 * 0.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 8), 0.45, 1e-5);
     BOOST_REQUIRE(neighbors(5, 8) == 10);
-    BOOST_REQUIRE_CLOSE(distances(5, 8), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 8), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(4, 8) == 5);
-    BOOST_REQUIRE_CLOSE(distances(4, 8), (0.67 * 0.67), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 8), 0.67, 1e-5);
     BOOST_REQUIRE(neighbors(3, 8) == 3);
-    BOOST_REQUIRE_CLOSE(distances(3, 8), (0.80 * 0.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 8), 0.80, 1e-5);
     BOOST_REQUIRE(neighbors(2, 8) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 8), (1.75 * 1.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 8), 1.75, 1e-5);
     BOOST_REQUIRE(neighbors(1, 8) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 8), (2.45 * 2.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 8), 2.45, 1e-5);
     BOOST_REQUIRE(neighbors(0, 8) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 8), (4.60 * 4.60), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 8), 4.60, 1e-5);
 
     // Neighbors of point 9.
     BOOST_REQUIRE(neighbors(9, 9) == 10);
-    BOOST_REQUIRE_CLOSE(distances(9, 9), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 9), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(8, 9) == 3);
-    BOOST_REQUIRE_CLOSE(distances(8, 9), (0.35 * 0.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 9), 0.35, 1e-5);
     BOOST_REQUIRE(neighbors(7, 9) == 8);
-    BOOST_REQUIRE_CLOSE(distances(7, 9), (0.45 * 0.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 9), 0.45, 1e-5);
     BOOST_REQUIRE(neighbors(6, 9) == 1);
-    BOOST_REQUIRE_CLOSE(distances(6, 9), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 9), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(5, 9) == 2);
-    BOOST_REQUIRE_CLOSE(distances(5, 9), (0.75 * 0.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 9), 0.75, 1e-5);
     BOOST_REQUIRE(neighbors(4, 9) == 0);
-    BOOST_REQUIRE_CLOSE(distances(4, 9), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 9), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(3, 9) == 5);
-    BOOST_REQUIRE_CLOSE(distances(3, 9), (1.12 * 1.12), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 9), 1.12, 1e-5);
     BOOST_REQUIRE(neighbors(2, 9) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 9), (2.20 * 2.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 9), 2.20, 1e-5);
     BOOST_REQUIRE(neighbors(1, 9) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 9), (2.90 * 2.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 9), 2.90, 1e-5);
     BOOST_REQUIRE(neighbors(0, 9) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 9), (4.15 * 4.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 9), 4.15, 1e-5);
 
     // Neighbors of point 10.
     BOOST_REQUIRE(neighbors(9, 10) == 9);
-    BOOST_REQUIRE_CLOSE(distances(9, 10), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 10), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(8, 10) == 3);
-    BOOST_REQUIRE_CLOSE(distances(8, 10), (0.25 * 0.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 10), 0.25, 1e-5);
     BOOST_REQUIRE(neighbors(7, 10) == 8);
-    BOOST_REQUIRE_CLOSE(distances(7, 10), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 10), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(6, 10) == 1);
-    BOOST_REQUIRE_CLOSE(distances(6, 10), (0.65 * 0.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 10), 0.65, 1e-5);
     BOOST_REQUIRE(neighbors(5, 10) == 2);
-    BOOST_REQUIRE_CLOSE(distances(5, 10), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 10), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(4, 10) == 0);
-    BOOST_REQUIRE_CLOSE(distances(4, 10), (0.95 * 0.95), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 10), 0.95, 1e-5);
     BOOST_REQUIRE(neighbors(3, 10) == 5);
-    BOOST_REQUIRE_CLOSE(distances(3, 10), (1.22 * 1.22), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 10), 1.22, 1e-5);
     BOOST_REQUIRE(neighbors(2, 10) == 7);
-    BOOST_REQUIRE_CLOSE(distances(2, 10), (2.30 * 2.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 10), 2.30, 1e-5);
     BOOST_REQUIRE(neighbors(1, 10) == 6);
-    BOOST_REQUIRE_CLOSE(distances(1, 10), (3.00 * 3.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 10), 3.00, 1e-5);
     BOOST_REQUIRE(neighbors(0, 10) == 4);
-    BOOST_REQUIRE_CLOSE(distances(0, 10), (4.05 * 4.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 10), 4.05, 1e-5);
 
     // Clean the memory.
     delete allkfn;
@@ -336,29 +336,29 @@
  */
 BOOST_AUTO_TEST_CASE(DualTreeVsNaive1)
 {
-  arma::mat dataForTree_;
+  arma::mat dataForTree;
 
   // Hard-coded filename: bad!
-  if (!data::Load("test_data_3_1000.csv", dataForTree_))
+  if (!data::Load("test_data_3_1000.csv", dataForTree))
     BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!");
 
   // Set up matrices to work with.
-  arma::mat dualQuery(dataForTree_);
-  arma::mat dualReferences(dataForTree_);
-  arma::mat naiveQuery(dataForTree_);
-  arma::mat naiveReferences(dataForTree_);
+  arma::mat dualQuery(dataForTree);
+  arma::mat dualReferences(dataForTree);
+  arma::mat naiveQuery(dataForTree);
+  arma::mat naiveReferences(dataForTree);
 
-  AllkFN allkfn_(dualQuery, dualReferences);
+  AllkFN allkfn(dualQuery, dualReferences);
 
-  AllkFN naive_(naiveQuery, naiveReferences, true);
+  AllkFN naive(naiveQuery, naiveReferences, true);
 
   arma::Mat<size_t> resultingNeighborsTree;
   arma::mat distancesTree;
-  allkfn_.Search(15, resultingNeighborsTree, distancesTree);
+  allkfn.Search(15, resultingNeighborsTree, distancesTree);
 
   arma::Mat<size_t> resultingNeighborsNaive;
   arma::mat distancesNaive;
-  naive_.Search(15, resultingNeighborsNaive, distancesNaive);
+  naive.Search(15, resultingNeighborsNaive, distancesNaive);
 
   for (size_t i = 0; i < resultingNeighborsTree.n_elem; i++)
   {
@@ -375,28 +375,28 @@
  */
 BOOST_AUTO_TEST_CASE(DualTreeVsNaive2)
 {
-  arma::mat dataForTree_;
+  arma::mat dataForTree;
 
   // Hard-coded filename: bad!
   // Code duplication: also bad!
-  if (!data::Load("test_data_3_1000.csv", dataForTree_))
+  if (!data::Load("test_data_3_1000.csv", dataForTree))
     BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!");
 
   // Set up matrices to work with.
-  arma::mat dualReferences(dataForTree_);
-  arma::mat naiveReferences(dataForTree_);
+  arma::mat dualReferences(dataForTree);
+  arma::mat naiveReferences(dataForTree);
 
-  AllkFN allkfn_(dualReferences);
+  AllkFN allkfn(dualReferences);
 
-  AllkFN naive_(naiveReferences, true);
+  AllkFN naive(naiveReferences, true);
 
   arma::Mat<size_t> resultingNeighborsTree;
   arma::mat distancesTree;
-  allkfn_.Search(15, resultingNeighborsTree, distancesTree);
+  allkfn.Search(15, resultingNeighborsTree, distancesTree);
 
   arma::Mat<size_t> resultingNeighborsNaive;
   arma::mat distancesNaive;
-  naive_.Search(15, resultingNeighborsNaive, distancesNaive);
+  naive.Search(15, resultingNeighborsNaive, distancesNaive);
 
   for (size_t i = 0; i < resultingNeighborsTree.n_elem; i++)
   {
@@ -413,27 +413,27 @@
  */
 BOOST_AUTO_TEST_CASE(SingleTreeVsNaive)
 {
-  arma::mat dataForTree_;
+  arma::mat dataForTree;
 
   // Hard-coded filename: bad!
   // Code duplication: also bad!
-  if (!data::Load("test_data_3_1000.csv", dataForTree_))
+  if (!data::Load("test_data_3_1000.csv", dataForTree))
     BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!");
 
-  arma::mat single_query(dataForTree_);
-  arma::mat naiveQuery(dataForTree_);
+  arma::mat singleQuery(dataForTree);
+  arma::mat naiveQuery(dataForTree);
 
-  AllkFN allkfn_(single_query, false, true);
+  AllkFN allkfn(singleQuery, false, true);
 
-  AllkFN naive_(naiveQuery, true);
+  AllkFN naive(naiveQuery, true);
 
   arma::Mat<size_t> resultingNeighborsTree;
   arma::mat distancesTree;
-  allkfn_.Search(15, resultingNeighborsTree, distancesTree);
+  allkfn.Search(15, resultingNeighborsTree, distancesTree);
 
   arma::Mat<size_t> resultingNeighborsNaive;
   arma::mat distancesNaive;
-  naive_.Search(15, resultingNeighborsNaive, distancesNaive);
+  naive.Search(15, resultingNeighborsNaive, distancesNaive);
 
   for (size_t i = 0; i < resultingNeighborsTree.n_elem; i++)
   {

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/allknn_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/allknn_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/allknn_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -20,6 +20,7 @@
  */
 #include <mlpack/core.hpp>
 #include <mlpack/methods/neighbor_search/neighbor_search.hpp>
+#include <mlpack/methods/neighbor_search/unmap.hpp>
 #include <mlpack/core/tree/cover_tree.hpp>
 #include <boost/test/unit_test.hpp>
 #include "old_boost_test_definitions.hpp"
@@ -30,6 +31,147 @@
 BOOST_AUTO_TEST_SUITE(AllkNNTest);
 
 /**
+ * Test that Unmap() works in the dual-tree case (see unmap.hpp).
+ */
+BOOST_AUTO_TEST_CASE(DualTreeUnmapTest)
+{
+  std::vector<size_t> refMap;
+  refMap.push_back(3);
+  refMap.push_back(4);
+  refMap.push_back(1);
+  refMap.push_back(2);
+  refMap.push_back(0);
+
+  std::vector<size_t> queryMap;
+  queryMap.push_back(2);
+  queryMap.push_back(0);
+  queryMap.push_back(4);
+  queryMap.push_back(3);
+  queryMap.push_back(1);
+  queryMap.push_back(5);
+
+  // Now generate some results.  6 queries, 5 references.
+  arma::Mat<size_t> neighbors("3 1 2 0 4;"
+                              "1 0 2 3 4;"
+                              "0 1 2 3 4;"
+                              "4 1 0 3 2;"
+                              "3 0 4 1 2;"
+                              "3 0 4 1 2;");
+  neighbors = neighbors.t();
+
+  // Integer distances will work fine here.
+  arma::mat distances("3 1 2 0 4;"
+                      "1 0 2 3 4;"
+                      "0 1 2 3 4;"
+                      "4 1 0 3 2;"
+                      "3 0 4 1 2;"
+                      "3 0 4 1 2;");
+  distances = distances.t();
+
+  // This is what the results should be when they are unmapped.
+  arma::Mat<size_t> correctNeighbors("4 3 1 2 0;"
+                                     "2 3 0 4 1;"
+                                     "2 4 1 3 0;"
+                                     "0 4 3 2 1;"
+                                     "3 4 1 2 0;"
+                                     "2 3 0 4 1;");
+  correctNeighbors = correctNeighbors.t();
+
+  arma::mat correctDistances("1 0 2 3 4;"
+                             "3 0 4 1 2;"
+                             "3 1 2 0 4;"
+                             "4 1 0 3 2;"
+                             "0 1 2 3 4;"
+                             "3 0 4 1 2;");
+  correctDistances = correctDistances.t();
+
+  // Perform the unmapping.
+  arma::Mat<size_t> neighborsOut;
+  arma::mat distancesOut;
+
+  Unmap(neighbors, distances, refMap, queryMap, neighborsOut, distancesOut);
+
+  for (size_t i = 0; i < correctNeighbors.n_elem; ++i)
+  {
+    BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]);
+    BOOST_REQUIRE_CLOSE(distancesOut[i], correctDistances[i], 1e-5);
+  }
+
+  // Now try taking the square root.
+  Unmap(neighbors, distances, refMap, queryMap, neighborsOut, distancesOut,
+      true);
+
+  for (size_t i = 0; i < correctNeighbors.n_elem; ++i)
+  {
+    BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]);
+    BOOST_REQUIRE_CLOSE(distancesOut[i], sqrt(correctDistances[i]), 1e-5);
+  }
+}
+
+/**
+ * Check that Unmap() works in the single-tree case.
+ */
+BOOST_AUTO_TEST_CASE(SingleTreeUnmapTest)
+{
+  std::vector<size_t> refMap;
+  refMap.push_back(3);
+  refMap.push_back(4);
+  refMap.push_back(1);
+  refMap.push_back(2);
+  refMap.push_back(0);
+
+  // Now generate some results.  6 queries, 5 references.
+  arma::Mat<size_t> neighbors("3 1 2 0 4;"
+                              "1 0 2 3 4;"
+                              "0 1 2 3 4;"
+                              "4 1 0 3 2;"
+                              "3 0 4 1 2;"
+                              "3 0 4 1 2;");
+  neighbors = neighbors.t();
+
+  // Integer distances will work fine here.
+  arma::mat distances("3 1 2 0 4;"
+                      "1 0 2 3 4;"
+                      "0 1 2 3 4;"
+                      "4 1 0 3 2;"
+                      "3 0 4 1 2;"
+                      "3 0 4 1 2;");
+  distances = distances.t();
+
+  // This is what the results should be when they are unmapped.
+  arma::Mat<size_t> correctNeighbors("2 4 1 3 0;"
+                                     "4 3 1 2 0;"
+                                     "3 4 1 2 0;"
+                                     "0 4 3 2 1;"
+                                     "2 3 0 4 1;"
+                                     "2 3 0 4 1;");
+  correctNeighbors = correctNeighbors.t();
+
+  arma::mat correctDistances = distances;
+
+  // Perform the unmapping.
+  arma::Mat<size_t> neighborsOut;
+  arma::mat distancesOut;
+
+  Unmap(neighbors, distances, refMap, neighborsOut, distancesOut);
+
+  for (size_t i = 0; i < correctNeighbors.n_elem; ++i)
+  {
+    BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]);
+    BOOST_REQUIRE_CLOSE(distancesOut[i], correctDistances[i], 1e-5);
+  }
+
+  // Now try taking the square root.
+  Unmap(neighbors, distances, refMap, neighborsOut, distancesOut, true);
+
+  for (size_t i = 0; i < correctNeighbors.n_elem; ++i)
+  {
+    BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]);
+    BOOST_REQUIRE_CLOSE(distancesOut[i], sqrt(correctDistances[i]), 1e-5);
+  }
+}
+
+/**
  * Simple nearest-neighbors test with small, synthetic dataset.  This is an
  * exhaustive test, which checks that each method for performing the calculation
  * (dual-tree, single-tree, naive) produces the correct results.  An
@@ -84,245 +226,245 @@
 
     // Neighbors of point 0.
     BOOST_REQUIRE(neighbors(0, 0) == 2);
-    BOOST_REQUIRE_CLOSE(distances(0, 0), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 0), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(1, 0) == 5);
-    BOOST_REQUIRE_CLOSE(distances(1, 0), (0.27 * 0.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 0), 0.27, 1e-5);
     BOOST_REQUIRE(neighbors(2, 0) == 1);
-    BOOST_REQUIRE_CLOSE(distances(2, 0), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 0), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(3, 0) == 8);
-    BOOST_REQUIRE_CLOSE(distances(3, 0), (0.40 * 0.40), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 0), 0.40, 1e-5);
     BOOST_REQUIRE(neighbors(4, 0) == 9);
-    BOOST_REQUIRE_CLOSE(distances(4, 0), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 0), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(5, 0) == 10);
-    BOOST_REQUIRE_CLOSE(distances(5, 0), (0.95 * 0.95), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 0), 0.95, 1e-5);
     BOOST_REQUIRE(neighbors(6, 0) == 3);
-    BOOST_REQUIRE_CLOSE(distances(6, 0), (1.20 * 1.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 0), 1.20, 1e-5);
     BOOST_REQUIRE(neighbors(7, 0) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 0), (1.35 * 1.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 0), 1.35, 1e-5);
     BOOST_REQUIRE(neighbors(8, 0) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 0), (2.05 * 2.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 0), 2.05, 1e-5);
     BOOST_REQUIRE(neighbors(9, 0) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 0), (5.00 * 5.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 0), 5.00, 1e-5);
 
     // Neighbors of point 1.
     BOOST_REQUIRE(neighbors(0, 1) == 8);
-    BOOST_REQUIRE_CLOSE(distances(0, 1), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 1), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(1, 1) == 2);
-    BOOST_REQUIRE_CLOSE(distances(1, 1), (0.20 * 0.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 1), 0.20, 1e-5);
     BOOST_REQUIRE(neighbors(2, 1) == 0);
-    BOOST_REQUIRE_CLOSE(distances(2, 1), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 1), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(3, 1) == 9);
-    BOOST_REQUIRE_CLOSE(distances(3, 1), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 1), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(4, 1) == 5);
-    BOOST_REQUIRE_CLOSE(distances(4, 1), (0.57 * 0.57), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 1), 0.57, 1e-5);
     BOOST_REQUIRE(neighbors(5, 1) == 10);
-    BOOST_REQUIRE_CLOSE(distances(5, 1), (0.65 * 0.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 1), 0.65, 1e-5);
     BOOST_REQUIRE(neighbors(6, 1) == 3);
-    BOOST_REQUIRE_CLOSE(distances(6, 1), (0.90 * 0.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 1), 0.90, 1e-5);
     BOOST_REQUIRE(neighbors(7, 1) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 1), (1.65 * 1.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 1), 1.65, 1e-5);
     BOOST_REQUIRE(neighbors(8, 1) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 1), (2.35 * 2.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 1), 2.35, 1e-5);
     BOOST_REQUIRE(neighbors(9, 1) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 1), (4.70 * 4.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 1), 4.70, 1e-5);
 
     // Neighbors of point 2.
     BOOST_REQUIRE(neighbors(0, 2) == 0);
-    BOOST_REQUIRE_CLOSE(distances(0, 2), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 2), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(1, 2) == 1);
-    BOOST_REQUIRE_CLOSE(distances(1, 2), (0.20 * 0.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 2), 0.20, 1e-5);
     BOOST_REQUIRE(neighbors(2, 2) == 8);
-    BOOST_REQUIRE_CLOSE(distances(2, 2), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 2), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(3, 2) == 5);
-    BOOST_REQUIRE_CLOSE(distances(3, 2), (0.37 * 0.37), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 2), 0.37, 1e-5);
     BOOST_REQUIRE(neighbors(4, 2) == 9);
-    BOOST_REQUIRE_CLOSE(distances(4, 2), (0.75 * 0.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 2), 0.75, 1e-5);
     BOOST_REQUIRE(neighbors(5, 2) == 10);
-    BOOST_REQUIRE_CLOSE(distances(5, 2), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 2), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(6, 2) == 3);
-    BOOST_REQUIRE_CLOSE(distances(6, 2), (1.10 * 1.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 2), 1.10, 1e-5);
     BOOST_REQUIRE(neighbors(7, 2) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 2), (1.45 * 1.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 2), 1.45, 1e-5);
     BOOST_REQUIRE(neighbors(8, 2) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 2), (2.15 * 2.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 2), 2.15, 1e-5);
     BOOST_REQUIRE(neighbors(9, 2) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 2), (4.90 * 4.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 2), 4.90, 1e-5);
 
     // Neighbors of point 3.
     BOOST_REQUIRE(neighbors(0, 3) == 10);
-    BOOST_REQUIRE_CLOSE(distances(0, 3), (0.25 * 0.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 3), 0.25, 1e-5);
     BOOST_REQUIRE(neighbors(1, 3) == 9);
-    BOOST_REQUIRE_CLOSE(distances(1, 3), (0.35 * 0.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 3), 0.35, 1e-5);
     BOOST_REQUIRE(neighbors(2, 3) == 8);
-    BOOST_REQUIRE_CLOSE(distances(2, 3), (0.80 * 0.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 3), 0.80, 1e-5);
     BOOST_REQUIRE(neighbors(3, 3) == 1);
-    BOOST_REQUIRE_CLOSE(distances(3, 3), (0.90 * 0.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 3), 0.90, 1e-5);
     BOOST_REQUIRE(neighbors(4, 3) == 2);
-    BOOST_REQUIRE_CLOSE(distances(4, 3), (1.10 * 1.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 3), 1.10, 1e-5);
     BOOST_REQUIRE(neighbors(5, 3) == 0);
-    BOOST_REQUIRE_CLOSE(distances(5, 3), (1.20 * 1.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 3), 1.20, 1e-5);
     BOOST_REQUIRE(neighbors(6, 3) == 5);
-    BOOST_REQUIRE_CLOSE(distances(6, 3), (1.47 * 1.47), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 3), 1.47, 1e-5);
     BOOST_REQUIRE(neighbors(7, 3) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 3), (2.55 * 2.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 3), 2.55, 1e-5);
     BOOST_REQUIRE(neighbors(8, 3) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 3), (3.25 * 3.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 3), 3.25, 1e-5);
     BOOST_REQUIRE(neighbors(9, 3) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 3), (3.80 * 3.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 3), 3.80, 1e-5);
 
     // Neighbors of point 4.
     BOOST_REQUIRE(neighbors(0, 4) == 3);
-    BOOST_REQUIRE_CLOSE(distances(0, 4), (3.80 * 3.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 4), 3.80, 1e-5);
     BOOST_REQUIRE(neighbors(1, 4) == 10);
-    BOOST_REQUIRE_CLOSE(distances(1, 4), (4.05 * 4.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 4), 4.05, 1e-5);
     BOOST_REQUIRE(neighbors(2, 4) == 9);
-    BOOST_REQUIRE_CLOSE(distances(2, 4), (4.15 * 4.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 4), 4.15, 1e-5);
     BOOST_REQUIRE(neighbors(3, 4) == 8);
-    BOOST_REQUIRE_CLOSE(distances(3, 4), (4.60 * 4.60), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 4), 4.60, 1e-5);
     BOOST_REQUIRE(neighbors(4, 4) == 1);
-    BOOST_REQUIRE_CLOSE(distances(4, 4), (4.70 * 4.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 4), 4.70, 1e-5);
     BOOST_REQUIRE(neighbors(5, 4) == 2);
-    BOOST_REQUIRE_CLOSE(distances(5, 4), (4.90 * 4.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 4), 4.90, 1e-5);
     BOOST_REQUIRE(neighbors(6, 4) == 0);
-    BOOST_REQUIRE_CLOSE(distances(6, 4), (5.00 * 5.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 4), 5.00, 1e-5);
     BOOST_REQUIRE(neighbors(7, 4) == 5);
-    BOOST_REQUIRE_CLOSE(distances(7, 4), (5.27 * 5.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 4), 5.27, 1e-5);
     BOOST_REQUIRE(neighbors(8, 4) == 7);
-    BOOST_REQUIRE_CLOSE(distances(8, 4), (6.35 * 6.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 4), 6.35, 1e-5);
     BOOST_REQUIRE(neighbors(9, 4) == 6);
-    BOOST_REQUIRE_CLOSE(distances(9, 4), (7.05 * 7.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 4), 7.05, 1e-5);
 
     // Neighbors of point 5.
     BOOST_REQUIRE(neighbors(0, 5) == 0);
-    BOOST_REQUIRE_CLOSE(distances(0, 5), (0.27 * 0.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 5), 0.27, 1e-5);
     BOOST_REQUIRE(neighbors(1, 5) == 2);
-    BOOST_REQUIRE_CLOSE(distances(1, 5), (0.37 * 0.37), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 5), 0.37, 1e-5);
     BOOST_REQUIRE(neighbors(2, 5) == 1);
-    BOOST_REQUIRE_CLOSE(distances(2, 5), (0.57 * 0.57), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 5), 0.57, 1e-5);
     BOOST_REQUIRE(neighbors(3, 5) == 8);
-    BOOST_REQUIRE_CLOSE(distances(3, 5), (0.67 * 0.67), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 5), 0.67, 1e-5);
     BOOST_REQUIRE(neighbors(4, 5) == 7);
-    BOOST_REQUIRE_CLOSE(distances(4, 5), (1.08 * 1.08), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 5), 1.08, 1e-5);
     BOOST_REQUIRE(neighbors(5, 5) == 9);
-    BOOST_REQUIRE_CLOSE(distances(5, 5), (1.12 * 1.12), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 5), 1.12, 1e-5);
     BOOST_REQUIRE(neighbors(6, 5) == 10);
-    BOOST_REQUIRE_CLOSE(distances(6, 5), (1.22 * 1.22), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 5), 1.22, 1e-5);
     BOOST_REQUIRE(neighbors(7, 5) == 3);
-    BOOST_REQUIRE_CLOSE(distances(7, 5), (1.47 * 1.47), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 5), 1.47, 1e-5);
     BOOST_REQUIRE(neighbors(8, 5) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 5), (1.78 * 1.78), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 5), 1.78, 1e-5);
     BOOST_REQUIRE(neighbors(9, 5) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 5), (5.27 * 5.27), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 5), 5.27, 1e-5);
 
     // Neighbors of point 6.
     BOOST_REQUIRE(neighbors(0, 6) == 7);
-    BOOST_REQUIRE_CLOSE(distances(0, 6), (0.70 * 0.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 6), 0.70, 1e-5);
     BOOST_REQUIRE(neighbors(1, 6) == 5);
-    BOOST_REQUIRE_CLOSE(distances(1, 6), (1.78 * 1.78), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 6), 1.78, 1e-5);
     BOOST_REQUIRE(neighbors(2, 6) == 0);
-    BOOST_REQUIRE_CLOSE(distances(2, 6), (2.05 * 2.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 6), 2.05, 1e-5);
     BOOST_REQUIRE(neighbors(3, 6) == 2);
-    BOOST_REQUIRE_CLOSE(distances(3, 6), (2.15 * 2.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 6), 2.15, 1e-5);
     BOOST_REQUIRE(neighbors(4, 6) == 1);
-    BOOST_REQUIRE_CLOSE(distances(4, 6), (2.35 * 2.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 6), 2.35, 1e-5);
     BOOST_REQUIRE(neighbors(5, 6) == 8);
-    BOOST_REQUIRE_CLOSE(distances(5, 6), (2.45 * 2.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 6), 2.45, 1e-5);
     BOOST_REQUIRE(neighbors(6, 6) == 9);
-    BOOST_REQUIRE_CLOSE(distances(6, 6), (2.90 * 2.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 6), 2.90, 1e-5);
     BOOST_REQUIRE(neighbors(7, 6) == 10);
-    BOOST_REQUIRE_CLOSE(distances(7, 6), (3.00 * 3.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 6), 3.00, 1e-5);
     BOOST_REQUIRE(neighbors(8, 6) == 3);
-    BOOST_REQUIRE_CLOSE(distances(8, 6), (3.25 * 3.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 6), 3.25, 1e-5);
     BOOST_REQUIRE(neighbors(9, 6) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 6), (7.05 * 7.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 6), 7.05, 1e-5);
 
     // Neighbors of point 7.
     BOOST_REQUIRE(neighbors(0, 7) == 6);
-    BOOST_REQUIRE_CLOSE(distances(0, 7), (0.70 * 0.70), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 7), 0.70, 1e-5);
     BOOST_REQUIRE(neighbors(1, 7) == 5);
-    BOOST_REQUIRE_CLOSE(distances(1, 7), (1.08 * 1.08), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 7), 1.08, 1e-5);
     BOOST_REQUIRE(neighbors(2, 7) == 0);
-    BOOST_REQUIRE_CLOSE(distances(2, 7), (1.35 * 1.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 7), 1.35, 1e-5);
     BOOST_REQUIRE(neighbors(3, 7) == 2);
-    BOOST_REQUIRE_CLOSE(distances(3, 7), (1.45 * 1.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 7), 1.45, 1e-5);
     BOOST_REQUIRE(neighbors(4, 7) == 1);
-    BOOST_REQUIRE_CLOSE(distances(4, 7), (1.65 * 1.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 7), 1.65, 1e-5);
     BOOST_REQUIRE(neighbors(5, 7) == 8);
-    BOOST_REQUIRE_CLOSE(distances(5, 7), (1.75 * 1.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 7), 1.75, 1e-5);
     BOOST_REQUIRE(neighbors(6, 7) == 9);
-    BOOST_REQUIRE_CLOSE(distances(6, 7), (2.20 * 2.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 7), 2.20, 1e-5);
     BOOST_REQUIRE(neighbors(7, 7) == 10);
-    BOOST_REQUIRE_CLOSE(distances(7, 7), (2.30 * 2.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 7), 2.30, 1e-5);
     BOOST_REQUIRE(neighbors(8, 7) == 3);
-    BOOST_REQUIRE_CLOSE(distances(8, 7), (2.55 * 2.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 7), 2.55, 1e-5);
     BOOST_REQUIRE(neighbors(9, 7) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 7), (6.35 * 6.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 7), 6.35, 1e-5);
 
     // Neighbors of point 8.
     BOOST_REQUIRE(neighbors(0, 8) == 1);
-    BOOST_REQUIRE_CLOSE(distances(0, 8), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 8), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(1, 8) == 2);
-    BOOST_REQUIRE_CLOSE(distances(1, 8), (0.30 * 0.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 8), 0.30, 1e-5);
     BOOST_REQUIRE(neighbors(2, 8) == 0);
-    BOOST_REQUIRE_CLOSE(distances(2, 8), (0.40 * 0.40), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 8), 0.40, 1e-5);
     BOOST_REQUIRE(neighbors(3, 8) == 9);
-    BOOST_REQUIRE_CLOSE(distances(3, 8), (0.45 * 0.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 8), 0.45, 1e-5);
     BOOST_REQUIRE(neighbors(4, 8) == 10);
-    BOOST_REQUIRE_CLOSE(distances(4, 8), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 8), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(5, 8) == 5);
-    BOOST_REQUIRE_CLOSE(distances(5, 8), (0.67 * 0.67), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 8), 0.67, 1e-5);
     BOOST_REQUIRE(neighbors(6, 8) == 3);
-    BOOST_REQUIRE_CLOSE(distances(6, 8), (0.80 * 0.80), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 8), 0.80, 1e-5);
     BOOST_REQUIRE(neighbors(7, 8) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 8), (1.75 * 1.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 8), 1.75, 1e-5);
     BOOST_REQUIRE(neighbors(8, 8) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 8), (2.45 * 2.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 8), 2.45, 1e-5);
     BOOST_REQUIRE(neighbors(9, 8) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 8), (4.60 * 4.60), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 8), 4.60, 1e-5);
 
     // Neighbors of point 9.
     BOOST_REQUIRE(neighbors(0, 9) == 10);
-    BOOST_REQUIRE_CLOSE(distances(0, 9), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 9), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(1, 9) == 3);
-    BOOST_REQUIRE_CLOSE(distances(1, 9), (0.35 * 0.35), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 9), 0.35, 1e-5);
     BOOST_REQUIRE(neighbors(2, 9) == 8);
-    BOOST_REQUIRE_CLOSE(distances(2, 9), (0.45 * 0.45), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 9), 0.45, 1e-5);
     BOOST_REQUIRE(neighbors(3, 9) == 1);
-    BOOST_REQUIRE_CLOSE(distances(3, 9), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 9), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(4, 9) == 2);
-    BOOST_REQUIRE_CLOSE(distances(4, 9), (0.75 * 0.75), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 9), 0.75, 1e-5);
     BOOST_REQUIRE(neighbors(5, 9) == 0);
-    BOOST_REQUIRE_CLOSE(distances(5, 9), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 9), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(6, 9) == 5);
-    BOOST_REQUIRE_CLOSE(distances(6, 9), (1.12 * 1.12), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 9), 1.12, 1e-5);
     BOOST_REQUIRE(neighbors(7, 9) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 9), (2.20 * 2.20), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 9), 2.20, 1e-5);
     BOOST_REQUIRE(neighbors(8, 9) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 9), (2.90 * 2.90), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 9), 2.90, 1e-5);
     BOOST_REQUIRE(neighbors(9, 9) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 9), (4.15 * 4.15), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 9), 4.15, 1e-5);
 
     // Neighbors of point 10.
     BOOST_REQUIRE(neighbors(0, 10) == 9);
-    BOOST_REQUIRE_CLOSE(distances(0, 10), (0.10 * 0.10), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(0, 10), 0.10, 1e-5);
     BOOST_REQUIRE(neighbors(1, 10) == 3);
-    BOOST_REQUIRE_CLOSE(distances(1, 10), (0.25 * 0.25), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(1, 10), 0.25, 1e-5);
     BOOST_REQUIRE(neighbors(2, 10) == 8);
-    BOOST_REQUIRE_CLOSE(distances(2, 10), (0.55 * 0.55), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(2, 10), 0.55, 1e-5);
     BOOST_REQUIRE(neighbors(3, 10) == 1);
-    BOOST_REQUIRE_CLOSE(distances(3, 10), (0.65 * 0.65), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(3, 10), 0.65, 1e-5);
     BOOST_REQUIRE(neighbors(4, 10) == 2);
-    BOOST_REQUIRE_CLOSE(distances(4, 10), (0.85 * 0.85), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(4, 10), 0.85, 1e-5);
     BOOST_REQUIRE(neighbors(5, 10) == 0);
-    BOOST_REQUIRE_CLOSE(distances(5, 10), (0.95 * 0.95), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(5, 10), 0.95, 1e-5);
     BOOST_REQUIRE(neighbors(6, 10) == 5);
-    BOOST_REQUIRE_CLOSE(distances(6, 10), (1.22 * 1.22), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(6, 10), 1.22, 1e-5);
     BOOST_REQUIRE(neighbors(7, 10) == 7);
-    BOOST_REQUIRE_CLOSE(distances(7, 10), (2.30 * 2.30), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(7, 10), 2.30, 1e-5);
     BOOST_REQUIRE(neighbors(8, 10) == 6);
-    BOOST_REQUIRE_CLOSE(distances(8, 10), (3.00 * 3.00), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(8, 10), 3.00, 1e-5);
     BOOST_REQUIRE(neighbors(9, 10) == 4);
-    BOOST_REQUIRE_CLOSE(distances(9, 10), (4.05 * 4.05), 1e-5);
+    BOOST_REQUIRE_CLOSE(distances(9, 10), 4.05, 1e-5);
 
     // Clean the memory.
     delete allknn;
@@ -521,18 +663,18 @@
 
   for (size_t i = 0; i < coverNeighbors.n_cols; ++i)
   {
-//    Log::Debug << "cover neighbors col " << i << "\n" <<
-//        trans(coverNeighbors.col(i));
-//    Log::Debug << "cover distances col " << i << "\n" <<
-//        trans(coverDistances.col(i));
-//    Log::Debug << "kd neighbors col " << i << "\n" <<
-//        trans(kdNeighbors.col(i));
-//    Log::Debug << "kd distances col " << i << "\n" <<
-//        trans(kdDistances.col(i));
+    Log::Debug << "cover neighbors col " << i << "\n" <<
+        trans(coverNeighbors.col(i));
+    Log::Debug << "cover distances col " << i << "\n" <<
+        trans(coverDistances.col(i));
+    Log::Debug << "kd neighbors col " << i << "\n" <<
+        trans(kdNeighbors.col(i));
+    Log::Debug << "kd distances col " << i << "\n" <<
+        trans(kdDistances.col(i));
     for (size_t j = 0; j < coverNeighbors.n_rows; ++j)
     {
       BOOST_REQUIRE_EQUAL(coverNeighbors(j, i), kdNeighbors(j, i));
-      BOOST_REQUIRE_CLOSE(coverDistances(j, i), sqrt(kdDistances(j, i)), 1e-5);
+      BOOST_REQUIRE_CLOSE(coverDistances(j, i), kdDistances(j, i), 1e-5);
     }
   }
 }

Copied: mlpack/branches/mlpack-1.x/src/mlpack/tests/allkrann_search_test.cpp (from rev 14992, mlpack/trunk/src/mlpack/tests/allkrann_search_test.cpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/allkrann_search_test.cpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/allkrann_search_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,272 @@
+/**
+ * @file allkrann_search_test.cpp
+ *
+ * Unit tests for the 'RASearch' class and consequently the
+ * 'RASearchRules' class
+ */
+#include <time.h>
+#include <mlpack/core.hpp>
+#include <mlpack/core/metrics/lmetric.hpp>
+
+// So that we can test private members.  This is hackish (for now).
+#define private public
+#include <mlpack/methods/rann/ra_search.hpp>
+#undef private
+
+#include <boost/test/unit_test.hpp>
+#include "old_boost_test_definitions.hpp"
+
+using namespace std;
+using namespace mlpack;
+using namespace mlpack::neighbor;
+
+
+BOOST_AUTO_TEST_SUITE(AllkRANNTest);
+
+// Test AllkRANN in naive mode for exact results when the random seeds are set
+// the same.  This may not be the best test; if the implementation of RANN-RS
+// gets random numbers in a different way, then this test might fail.
+BOOST_AUTO_TEST_CASE(AllkRANNNaiveSearchExact)
+{
+  // First test on a small set.
+  arma::mat rdata(2, 10);
+  rdata << 3 << 2 << 4 << 3 << 5 << 6 << 0 << 8 << 3 << 1 << arma::endr <<
+           0 << 3 << 4 << 7 << 8 << 4 << 1 << 0 << 4 << 3 << arma::endr;
+
+  arma::mat qdata(2, 3);
+  qdata << 3 << 2 << 0 << arma::endr
+        << 5 << 3 << 4 << arma::endr;
+
+  metric::SquaredEuclideanDistance dMetric;
+  double rankApproximation = 30;
+  double successProb = 0.95;
+
+  // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point
+  // (rank error of 3).
+  arma::Mat<size_t> neighbors;
+  arma::mat distances;
+
+  // Test naive rank-approximate search.
+  // Predict what the actual RANN-RS result would be.
+  math::RandomSeed(0);
+
+  size_t numSamples = (size_t) ceil(log(1.0 / (1.0 - successProb)) /
+      log(1.0 / (1.0 - (rankApproximation / 100.0))));
+
+  arma::Mat<size_t> samples(qdata.n_cols, numSamples);
+  for (size_t j = 0; j < qdata.n_cols; j++)
+    for (size_t i = 0; i < numSamples; i++)
+      samples(j, i) = (size_t) math::RandInt(10);
+
+  arma::Col<size_t> rann(qdata.n_cols);
+  arma::vec rannDistances(qdata.n_cols);
+  rannDistances.fill(DBL_MAX);
+
+  for (size_t j = 0; j < qdata.n_cols; j++)
+  {
+    for (size_t i = 0; i < numSamples; i++)
+    {
+      double dist = dMetric.Evaluate(qdata.unsafe_col(j),
+                                     rdata.unsafe_col(samples(j, i)));
+      if (dist < rannDistances[j])
+      {
+        rann[j] = samples(j, i);
+        rannDistances[j] = dist;
+      }
+    }
+  }
+
+  // Use RANN-RS implementation.
+  math::RandomSeed(0);
+
+  RASearch<> naive(rdata, qdata, true);
+  naive.Search(1, neighbors, distances, rankApproximation);
+
+  // Things to check:
+  //
+  // 1. (implicitly) The minimum number of required samples for guaranteed
+  //    approximation.
+  // 2. (implicitly) Check the samples obtained.
+  // 3. Check the neighbor returned.
+  for (size_t i = 0; i < qdata.n_cols; i++)
+  {
+    BOOST_REQUIRE(neighbors(0, i) == rann[i]);
+    BOOST_REQUIRE_CLOSE(distances(0, i), rannDistances[i], 1e-5);
+  }
+}
+
+// Test the correctness and guarantees of AllkRANN when in naive mode.
+BOOST_AUTO_TEST_CASE(AllkRANNNaiveGuaranteeTest)
+{
+  arma::Mat<size_t> neighbors;
+  arma::mat distances;
+
+  arma::mat refData;
+  arma::mat queryData;
+
+  data::Load("rann_test_r_3_900.csv", refData, true);
+  data::Load("rann_test_q_3_100.csv", queryData, true);
+
+  RASearch<> rsRann(refData, queryData, true);
+
+  arma::mat qrRanks;
+  data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose.
+
+  size_t numRounds = 1000;
+  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
+  numSuccessRounds.fill(0);
+
+  // 1% of 900 is 9, so the rank is expected to be less than 10
+  size_t expectedRankErrorUB = 10;
+
+  for (size_t rounds = 0; rounds < numRounds; rounds++)
+  {
+    rsRann.Search(1, neighbors, distances, 1.0);
+
+    for (size_t i = 0; i < queryData.n_cols; i++)
+      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
+        numSuccessRounds[i]++;
+
+    neighbors.reset();
+    distances.reset();
+  }
+
+  // Find the 95%-tile threshold so that 95% of the queries should pass this
+  // threshold.
+  size_t threshold = floor(numRounds *
+      (0.95 - (1.96 * sqrt(0.95 * 0.05 / numRounds))));
+  size_t numQueriesFail = 0;
+  for (size_t i = 0; i < queryData.n_cols; i++)
+    if (numSuccessRounds[i] < threshold)
+      numQueriesFail++;
+
+  Log::Warn << "RANN-RS: RANN guarantee fails on " << numQueriesFail
+      << " queries." << endl;
+
+  // assert that at most 5% of the queries fall out of this threshold
+  // 5% of 100 queries is 5.
+  size_t maxNumQueriesFail = 6;
+
+  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
+}
+
+// Test single-tree rank-approximate search (harder to test because of
+// the randomness involved).
+BOOST_AUTO_TEST_CASE(AllkRANNSingleTreeSearch)
+{
+  arma::mat refData;
+  arma::mat queryData;
+
+  data::Load("rann_test_r_3_900.csv", refData, true);
+  data::Load("rann_test_q_3_100.csv", queryData, true);
+
+  // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point
+  // (rank error of 3).
+  arma::Mat<size_t> neighbors;
+  arma::mat distances;
+
+  RASearch<> tssRann(refData, queryData, false, true, 5);
+
+  // The relative ranks for the given query reference pair
+  arma::Mat<size_t> qrRanks;
+  data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose.
+
+  size_t numRounds = 1000;
+  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
+  numSuccessRounds.fill(0);
+
+  // 1% of 900 is 9, so the rank is expected to be less than 10.
+  size_t expectedRankErrorUB = 10;
+
+  for (size_t rounds = 0; rounds < numRounds; rounds++)
+  {
+    tssRann.Search(1, neighbors, distances, 1.0, 0.95, false, false, 5);
+
+    for (size_t i = 0; i < queryData.n_cols; i++)
+      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
+        numSuccessRounds[i]++;
+
+    neighbors.reset();
+    distances.reset();
+  }
+
+  // Find the 95%-tile threshold so that 95% of the queries should pass this
+  // threshold.
+  size_t threshold = floor(numRounds *
+      (0.95 - (1.96 * sqrt(0.95 * 0.05 / numRounds))));
+  size_t numQueriesFail = 0;
+  for (size_t i = 0; i < queryData.n_cols; i++)
+    if (numSuccessRounds[i] < threshold)
+      numQueriesFail++;
+
+  Log::Warn << "RANN-TSS: RANN guarantee fails on " << numQueriesFail
+      << " queries." << endl;
+
+  // Assert that at most 5% of the queries fall out of this threshold.
+  // 5% of 100 queries is 5.
+  size_t maxNumQueriesFail = 6;
+
+  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
+}
+
+// Test dual-tree rank-approximate search (harder to test because of the
+// randomness involved).
+BOOST_AUTO_TEST_CASE(AllkRANNDualTreeSearch)
+{
+  arma::mat refData;
+  arma::mat queryData;
+
+  data::Load("rann_test_r_3_900.csv", refData, true);
+  data::Load("rann_test_q_3_100.csv", queryData, true);
+
+  // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point
+  // (rank error of 3).
+  arma::Mat<size_t> neighbors;
+  arma::mat distances;
+
+  RASearch<> tsdRann(refData, queryData, false, false, 5);
+
+  arma::Mat<size_t> qrRanks;
+  data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose.
+
+  size_t numRounds = 1000;
+  arma::Col<size_t> numSuccessRounds(queryData.n_cols);
+  numSuccessRounds.fill(0);
+
+  // 1% of 900 is 9, so the rank is expected to be less than 10.
+  size_t expectedRankErrorUB = 10;
+
+  for (size_t rounds = 0; rounds < numRounds; rounds++)
+  {
+    tsdRann.Search(1, neighbors, distances, 1.0, 0.95, false, false, 5);
+
+    for (size_t i = 0; i < queryData.n_cols; i++)
+      if (qrRanks(i, neighbors(0, i)) < expectedRankErrorUB)
+        numSuccessRounds[i]++;
+
+    neighbors.reset();
+    distances.reset();
+
+    tsdRann.ResetQueryTree();
+  }
+
+  // Find the 95%-tile threshold so that 95% of the queries should pass this
+  // threshold.
+  size_t threshold = floor(numRounds *
+      (0.95 - (1.96 * sqrt(0.95 * 0.05 / numRounds))));
+  size_t numQueriesFail = 0;
+  for (size_t i = 0; i < queryData.n_cols; i++)
+    if (numSuccessRounds[i] < threshold)
+      numQueriesFail++;
+
+  Log::Warn << "RANN-TSD: RANN guarantee fails on " << numQueriesFail
+      << " queries." << endl;
+
+  // assert that at most 5% of the queries fall out of this threshold
+  // 5% of 100 queries is 5.
+  size_t maxNumQueriesFail = 6;
+
+  BOOST_REQUIRE(numQueriesFail < maxNumQueriesFail);
+}
+
+BOOST_AUTO_TEST_SUITE_END();

Copied: mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_q_3_100.csv (from rev 14992, mlpack/trunk/src/mlpack/tests/data/rann_test_q_3_100.csv)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_q_3_100.csv	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_q_3_100.csv	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,100 @@
+0.339406815,0.843176636,0.472701471
+0.212587646,0.351174901,0.81056695
+0.605649993,0.45338097,0.623370668
+0.269783539,0.482031883,0.36535861
+0.725254282,0.477113042,0.042100268
+0.529287901,0.776008587,0.303809928
+0.098778217,0.318454787,0.983422857
+0.685345453,0.837942768,0.540406673
+0.503220972,0.268813629,0.41488501
+0.160147626,0.255047893,0.04072469
+0.564535197,0.943435462,0.597070812
+0.663842864,0.276972185,0.02208704
+0.077321401,0.032366881,0.826784604
+0.794220519,0.319582218,0.266025433
+0.466815953,0.864683732,0.684380976
+0.680962499,0.009554527,0.484176898
+0.257862396,0.875068776,0.326253946
+0.695503778,0.695095604,0.955586038
+0.569205007,0.662786497,0.036489177
+0.604542917,0.250714055,0.232826165
+0.928175028,0.871769923,0.327107027
+0.362809806,0.270846833,0.917535106
+0.567471988,0.09223176,0.018232595
+0.30294,0.197331083,0.676067984
+0.136497436,0.991079028,0.640906359
+0.490191642,0.321877535,0.210121475
+0.886240693,0.124811844,0.109638108
+0.487537807,0.474289999,0.34183089
+0.038698268,0.515865087,0.984297254
+0.437309222,0.534489172,0.792665419
+0.898099395,0.461121197,0.785225662
+0.256850927,0.840446806,0.056158684
+0.335408063,0.806637161,0.913551388
+0.11329872,0.670392847,0.333361274
+0.954403847,0.024104509,0.325578493
+0.824152332,0.614355433,0.271931013
+0.729647547,0.666093053,0.579723184
+0.25675029,0.94037263,0.530553224
+0.799877963,0.555666351,0.056606945
+0.213120693,0.763046224,0.341926361
+0.975873714,0.554796483,0.049489218
+0.422782321,0.375502502,0.875514176
+0.732474122,0.920181004,0.273895723
+0.288070185,0.878065303,0.57017629
+0.269706239,0.854626516,0.607709975
+0.615118638,0.006748605,0.00278243
+0.655373608,0.348029869,0.909502319
+0.358287814,0.419322455,0.362741982
+0.152473842,0.659459939,0.497284571
+0.930791658,0.934132013,0.150924236
+0.792977546,0.953203388,0.465884431
+0.971953827,0.268751729,0.220474277
+0.244730747,0.056636753,0.088649766
+0.873554351,0.305649442,0.91790044
+0.26662478,0.221646762,0.310857157
+0.659541537,0.93018384,0.139339275
+0.833616742,0.833734413,0.551027856
+0.43405195,0.874582065,0.996443541
+0.442896336,0.118977275,0.03127628
+0.388886541,0.976070927,0.294801481
+0.14757794,0.195944854,0.129778502
+0.73209291,0.551685931,0.218866346
+0.85393572,0.675733762,0.501776114
+0.804291505,0.746786474,0.94053733
+0.199998362,0.403471102,0.614783956
+0.302029244,0.084831174,0.043490422
+0.458371115,0.076068613,0.940418665
+0.122287089,0.867270578,0.612001352
+0.423331474,0.370629389,0.407480574
+0.400056969,0.919523609,0.940521669
+0.74852813,0.872400563,0.915423635
+0.614934326,0.67621724,0.382278246
+0.0184522,0.545825352,0.74127138
+0.937453855,0.175662201,0.666301896
+0.504358818,0.251308945,0.849159677
+0.397410107,0.973000161,0.648601332
+0.398342217,0.110698975,0.916968596
+0.464980239,0.683124011,0.070633362
+0.787030874,0.393777381,0.731973049
+0.612845512,0.893440416,0.475331995
+0.241219407,0.792282417,0.389574277
+0.465756798,0.552685716,0.092092299
+0.908028882,0.837528446,0.794160948
+0.552741674,0.898614081,0.764312365
+0.607116253,0.958698621,0.334887326
+0.322583246,0.541387861,0.879874555
+0.124522558,0.229074642,0.510214096
+0.049900273,0.471371867,0.367698395
+0.261657863,0.105228571,0.748191349
+0.216818324,0.700885804,0.34479269
+0.896337659,0.634574468,0.203599217
+0.961150989,0.920563011,0.795999477
+0.120635447,0.744570376,0.107177572
+0.696406743,0.788342315,0.173664558
+0.577700329,0.493151732,0.989211395
+0.270346683,0.586765585,0.208832269
+0.171412097,0.116618251,0.53141933
+0.596260532,0.819973735,0.531503373
+0.120665467,0.556332466,0.643268746
+0.546751646,0.563896374,0.079856633

Copied: mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_qr_ranks.csv (from rev 14992, mlpack/trunk/src/mlpack/tests/data/rann_test_qr_ranks.csv)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_qr_ranks.csv	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_qr_ranks.csv	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,100 @@
+797,104,105,552,469,788,257,26,42,565,621,640,78,670,595,28,733,714,337,809,278,284,429,92,468,612,449,496,234,110,85,8,150,199,174,819,76,743,716,600,642,647,235,277,292,81,128,446,212,75,467,806,838,753,301,708,151,323,213,535,273,786,651,181,427,474,27,362,828,381,524,375,200,271,342,67,608,205,664,790,486,413,276,587,424,685,214,7,137,118,23,861,17,732,321,328,772,80,182,684,333,179,436,525,722,577,589,349,187,217,758,329,262,593,258,710,372,300,416,652,750,351,655,164,3,471,19,767,49,221,238,518,885,385,397,693,198,634,557,129,254,532,550,835,746,345,215,796,222,675,196,546,638,580,696,153,850,209,163,694,854,158,692,867,403,832,117,763,404,426,616,399,601,868,456,393,418,177,592,377,636,659,514,628,485,679,239,444,721,737,757,144,411,180,896,56,246,202,366,253,442,170,145,545,874,63,453,310,100,367,70,77,688,816,846,89,15,434,6,148,673,751,690,237,352,34,373,95,282,327,852,13,649,114,102,785,646,259,502,648,448,774,139,668,2,126,152,609,127,388,249,686,571,161,160,368,
 729,794,526,760,464,143,748,359,804,374,36,255,66,801,603,707,624,309,555,335,830,635,111,122,203,529,241,447,261,572,484,54,69,225,405,762,831,480,894,414,521,172,438,369,516,350,898,131,734,759,306,155,396,82,567,51,48,304,274,761,791,9,884,515,883,627,226,764,216,862,727,169,483,415,162,562,798,827,540,44,614,88,702,475,826,845,224,86,789,607,64,229,299,171,575,24,841,519,522,877,899,395,458,147,305,156,800,834,599,31,99,166,314,364,778,263,303,500,534,585,508,297,58,428,98,389,491,260,149,814,382,848,390,681,718,735,121,116,268,730,869,472,73,597,12,793,663,781,863,400,588,72,223,620,645,459,626,60,220,715,527,644,307,108,71,402,386,285,662,554,512,623,824,586,346,94,886,736,879,617,725,452,598,39,190,115,547,146,859,671,293,481,505,840,194,749,811,613,712,706,219,860,361,50,817,218,178,625,371,676,357,312,654,783,820,45,272,878,279,360,661,441,542,206,517,744,432,493,590,14,488,201,583,189,717,876,723,875,563,65,799,829,594,822,185,175,591,615,842,509,643,142,672,825,70
 5,511,316,870,633,596,68,10,839,719,106,770,391,83,33,40,296,370,890,101,52,631,167,677,602,120,576,419,784,611,720,5,533,455,503,322,243,606,233,851,270,46,47,813,457,808,498,41,792,417,887,897,266,564,836,188,682,275,265,711,756,339,341,889,506,543,343,805,865,691,336,248,280,812,32,454,641,325,251,581,107,765,703,288,439,423,138,168,37,666,408,742,465,537,435,176,795,132,460,476,704,422,856,74,881,782,495,55,544,191,93,334,683,406,466,425,192,227,331,741,356,231,38,383,445,893,207,844,549,353,745,281,689,499,747,398,295,513,440,256,470,30,319,726,125,35,379,298,656,269,630,242,739,90,849,59,818,888,443,815,482,650,821,528,308,629,724,103,245,324,570,347,531,823,135,678,769,11,91,57,140,392,43,232,315,556,61,728,487,97,211,409,740,291,866,421,700,193,79,230,882,294,584,561,568,433,637,358,354,186,123,873,340,494,780,136,29,462,431,247,208,376,289,559,197,619,667,283,573,53,610,290,384,755,578,776,286,25,560,313,463,810,87,410,510,843,124,858,658,330,803,489,1,699,501,697,2
 87,332,900,569,520,365,880,497,895,437,109,380,21,582,119,523,318,695,837,4,787,348,775,558,632,451,687,657,311,320,738,210,204,18,731,669,551,864,892,240,618,134,250,891,773,16,566,184,355,236,477,857,574,553,653,777,228,344,478,363,872,622,195,771,252,605,660,461,579,302,802,401,267,530,639,62,807,244,326,420,548,853,165,754,536,541,473,430,709,674,507,20,713,113,338,479,159,407,173,779,387,84,130,871,183,492,317,112,833,450,855,412,698,539,504,22,604,665,133,768,680,766,141,378,96,701,157,847,752,394,538,264,490,154
+263,743,170,39,688,258,212,173,405,22,774,660,402,596,403,238,440,25,848,83,455,156,648,351,812,302,252,45,764,90,509,288,111,143,499,828,182,697,481,149,220,340,711,645,87,154,108,620,99,359,427,88,561,810,733,84,112,38,744,861,852,543,393,456,837,806,315,257,107,485,197,598,410,551,327,354,279,349,126,187,875,330,61,593,663,451,675,504,778,169,559,763,202,588,669,323,460,132,309,537,44,338,37,374,70,796,563,382,716,395,458,667,525,243,856,540,49,421,165,76,527,568,21,301,528,47,412,503,305,441,555,18,850,342,10,313,819,426,720,239,56,482,592,585,50,148,274,53,815,823,798,714,142,353,209,384,755,397,60,30,715,548,780,227,882,105,186,851,110,69,706,201,505,742,289,729,684,267,241,372,898,746,158,371,753,665,632,873,152,508,334,794,203,381,885,167,221,788,52,534,619,404,519,240,652,248,443,436,331,364,192,153,380,831,377,682,318,524,577,251,97,544,804,230,120,487,277,686,809,58,704,450,814,463,493,880,206,869,863,502,758,494,249,138,449,345,420,496,659,464,78,28,218,820,54,57
 5,123,437,888,476,255,556,344,625,845,881,636,807,179,74,724,506,839,7,583,401,459,130,523,247,275,689,367,510,295,24,846,256,387,538,705,92,89,325,572,457,618,245,121,34,690,36,895,67,638,434,399,375,631,467,554,413,307,805,166,347,668,571,465,254,721,35,250,134,46,394,824,282,64,576,447,627,215,172,141,466,737,498,834,843,727,109,835,300,552,756,520,829,217,428,5,507,642,896,566,386,693,29,723,677,854,647,292,535,333,430,287,392,666,767,199,692,140,836,591,643,606,871,317,536,348,549,745,91,115,185,626,335,557,362,322,630,735,196,226,783,847,801,605,2,358,611,608,676,271,11,622,409,624,356,484,587,864,474,102,122,787,357,553,268,297,518,687,701,722,424,12,180,790,23,768,312,176,62,514,19,607,604,521,303,266,259,781,131,695,900,595,281,63,406,515,649,491,601,417,284,157,146,472,707,461,42,136,27,709,868,93,135,698,71,95,171,754,785,826,623,296,681,228,462,773,584,438,234,224,600,581,802,183,363,759,336,674,818,730,661,775,96,411,479,237,190,82,513,874,489,899,343,32,235,308
 ,352,470,486,855,337,453,539,326,75,565,683,533,246,653,483,779,454,772,771,589,244,651,139,678,278,883,33,703,4,163,550,422,293,242,6,822,889,376,639,81,314,211,560,124,205,77,542,369,886,558,713,865,884,594,391,200,155,740,320,144,784,448,821,290,270,731,708,789,368,310,634,232,654,599,355,897,51,161,646,116,680,478,516,808,261,614,286,210,15,68,570,160,1,332,739,85,757,617,407,98,269,717,748,858,866,236,526,734,189,752,204,299,878,129,439,629,766,791,94,872,844,501,621,894,475,66,655,578,260,324,827,782,612,444,119,477,423,319,164,750,425,671,760,770,272,101,765,662,184,712,283,857,562,738,615,72,545,859,672,726,265,609,650,316,795,125,195,751,547,842,31,408,670,429,373,341,445,416,350,691,9,396,749,431,495,580,635,114,419,280,264,736,229,876,3,679,830,747,103,893,813,57,43,891,100,291,541,769,797,816,414,13,719,400,616,298,793,14,641,546,590,79,777,222,710,385,117,346,490,811,762,531,718,208,128,379,360,728,471,673,162,276,702,294,799,435,776,20,150,361,233,389,867,17,84
 1,792,231,725,862,613,610,574,418,694,398,567,188,446,838,133,306,512,370,800,285,532,40,147,193,832,432,637,480,16,321,442,80,633,388,597,644,657,383,853,833,468,602,113,586,860,656,273,86,365,825,175,685,564,127,219,194,511,253,517,877,892,55,699,433,817,304,26,415,664,198,500,177,65,732,8,390,311,225,214,159,887,118,696,329,178,700,579,530,339,41,803,522,879,104,145,213,207,840,106,181,137,216,469,569,473,492,151,366,573,223,488,741,191,262,582,529,603,890,628,48,168,497,59,174,786,378,73,870,640,452,849,328,658,761
+191,507,96,398,677,604,468,173,289,434,560,169,783,833,670,84,275,499,682,554,873,263,149,333,436,433,11,598,892,128,828,419,31,586,625,559,181,500,832,65,63,56,364,205,588,57,40,283,197,715,49,672,295,568,665,602,393,346,372,693,726,192,86,125,619,387,526,718,525,804,73,109,110,345,807,271,412,13,135,731,735,232,519,394,417,208,882,669,774,38,483,415,218,660,199,99,268,98,43,335,378,171,77,732,664,334,217,859,894,667,473,336,307,124,773,448,337,643,17,685,131,421,528,36,529,68,680,794,265,509,267,155,709,831,358,113,683,819,438,95,459,721,592,795,488,70,114,703,868,704,876,690,316,514,648,108,890,352,260,652,880,827,570,456,796,762,225,724,91,247,659,373,555,874,7,887,222,172,127,58,867,475,168,195,245,301,673,700,224,214,119,870,157,163,846,382,452,512,51,90,864,736,469,671,482,502,675,779,30,839,466,228,72,727,266,472,112,50,567,322,178,286,376,160,21,342,258,480,899,580,771,696,401,849,845,713,220,861,684,158,505,811,338,404,356,787,822,186,881,688,41,647,47,842,253,284,
 383,852,784,465,399,252,639,231,547,810,463,517,53,591,613,451,556,202,496,14,276,144,351,331,4,605,800,691,102,237,589,329,123,595,558,367,761,305,540,689,133,239,759,229,584,312,872,190,321,834,152,444,390,120,327,360,60,698,385,151,236,524,450,147,484,294,768,734,355,332,743,477,542,844,818,350,374,758,521,772,309,143,656,717,427,649,863,314,248,409,308,723,405,104,354,296,738,862,76,449,720,410,621,348,900,293,201,223,105,303,234,130,302,898,249,264,2,633,478,430,531,850,52,185,616,69,297,494,29,797,198,325,722,132,100,368,486,579,645,585,752,406,310,464,593,471,725,609,361,422,455,274,851,44,573,194,641,453,281,188,546,54,563,653,650,66,847,583,552,129,527,111,640,551,878,479,853,400,370,575,777,180,184,601,87,565,359,71,855,891,238,67,581,282,93,366,183,875,221,177,391,564,805,572,836,292,418,597,814,574,12,655,577,798,523,117,403,536,606,765,751,174,407,802,380,243,371,8,612,711,454,603,339,663,328,445,211,747,504,594,789,569,74,279,487,5,121,216,699,39,895,755,319,31
 3,242,692,78,340,754,745,189,661,261,678,829,728,816,145,492,187,446,85,520,756,362,432,886,126,837,657,767,561,493,377,533,634,55,19,23,241,897,753,614,298,16,59,146,627,22,763,397,285,458,830,447,668,840,748,306,83,97,537,635,571,429,408,869,706,20,457,291,347,510,92,582,381,25,694,788,18,843,259,543,835,141,793,215,193,676,46,244,553,103,530,600,618,140,442,10,413,485,871,545,801,204,35,541,610,716,615,159,815,210,662,532,739,330,776,26,162,857,437,646,290,742,889,251,138,854,535,317,515,423,712,164,896,697,809,156,629,45,24,240,212,246,167,481,476,702,203,142,491,161,6,235,566,823,856,402,737,686,474,757,518,885,62,273,730,27,638,539,280,879,624,632,506,311,411,544,549,443,386,179,226,508,440,388,785,176,94,516,420,607,341,416,654,764,33,719,137,511,826,666,81,841,636,148,707,786,165,708,461,884,596,808,357,288,701,136,256,395,522,431,590,630,106,435,389,599,230,651,257,28,631,623,501,170,893,48,323,42,467,206,34,695,343,61,272,182,548,269,562,620,82,760,153,375,803,576,
 674,749,1,729,578,304,790,379,626,538,369,227,15,498,497,426,154,534,353,766,324,687,428,318,116,733,658,489,209,196,80,490,460,824,166,414,791,858,349,746,740,79,866,9,470,813,611,587,315,637,679,207,877,88,64,75,254,134,744,792,780,817,557,396,825,617,32,344,439,775,705,622,107,503,233,513,250,200,363,424,37,770,838,462,806,219,213,270,812,750,326,365,769,714,320,101,122,644,628,441,300,550,115,821,392,277,262,3,175,883,495,287,255,118,741,89,278,820,799,860,681,425,848,139,642,781,778,299,782,384,865,608,710,150,888
+702,573,13,640,868,369,619,122,42,283,409,788,404,233,129,74,839,568,631,676,728,11,510,8,782,166,515,595,367,167,559,200,176,332,41,747,12,887,247,461,603,670,333,363,235,150,78,799,375,455,658,613,683,622,210,385,272,96,585,874,695,664,470,121,586,721,358,714,703,92,637,579,89,98,745,20,164,304,596,418,666,49,270,271,821,378,321,355,322,36,519,797,72,289,636,633,845,157,67,342,444,575,227,102,447,748,352,760,425,35,341,759,87,711,648,326,88,787,454,348,734,109,638,66,223,364,387,286,393,22,678,395,820,769,190,746,550,189,856,380,154,110,174,407,546,493,14,671,388,893,391,243,249,124,258,63,477,17,203,522,469,193,888,770,766,647,376,649,516,90,273,30,169,517,494,260,459,3,716,161,871,878,135,810,680,521,113,737,700,507,717,428,651,33,858,153,615,618,152,296,168,667,672,128,890,320,64,792,256,777,204,31,646,644,742,578,158,524,365,2,463,853,735,5,131,475,25,610,501,311,530,290,740,473,361,783,265,602,642,814,847,293,500,269,216,410,601,817,483,47,266,503,354,467,139,763,398,
 330,849,356,46,587,268,732,789,718,392,605,137,635,305,312,656,264,195,405,838,353,83,478,162,244,690,79,582,329,831,15,81,765,840,555,687,77,889,51,729,1,597,440,867,91,879,115,544,284,71,639,212,278,837,508,197,351,590,778,796,224,863,144,818,359,492,429,177,704,894,9,628,130,655,846,512,548,141,464,560,343,609,514,691,677,465,4,843,488,520,547,645,509,527,399,476,811,627,857,897,472,862,482,567,328,652,800,741,441,460,543,736,323,584,533,252,861,855,860,173,594,138,757,44,574,795,401,68,498,316,674,841,412,580,870,382,178,70,542,744,780,370,497,292,505,238,442,775,379,864,495,192,650,199,282,679,52,23,577,865,662,60,149,317,626,186,202,886,773,499,660,629,340,263,16,809,518,829,423,267,758,816,165,474,462,823,257,485,881,701,184,220,668,443,541,793,241,403,390,496,762,94,432,366,254,37,653,179,785,242,511,885,709,726,40,396,804,643,111,215,669,107,117,824,569,801,381,155,277,160,698,171,39,654,835,708,719,869,239,458,712,722,848,18,142,384,822,794,583,866,562,563,771,338,
 86,229,784,892,145,103,236,776,438,240,373,105,7,394,294,715,213,854,334,486,188,426,554,231,452,727,415,545,491,314,288,368,253,299,159,468,827,24,844,182,143,21,414,397,457,136,386,406,710,834,895,598,779,699,504,607,56,225,245,413,665,791,812,581,101,681,697,768,731,752,198,75,445,300,318,805,62,536,209,28,337,424,684,360,132,437,591,170,571,526,313,641,371,319,535,689,374,851,106,570,599,657,420,815,772,112,422,733,350,431,632,259,696,433,134,226,466,331,634,774,529,180,439,803,880,303,621,222,80,502,453,402,147,813,612,484,553,750,6,692,119,207,883,325,19,538,790,675,324,630,661,899,532,767,206,725,876,564,566,251,480,730,183,127,430,344,372,298,57,877,279,140,882,27,211,362,389,58,421,255,262,479,221,688,400,123,456,156,593,624,53,357,65,806,275,884,490,349,347,833,448,540,592,850,85,181,807,274,565,531,781,148,219,707,336,29,435,436,126,54,411,449,551,539,808,191,506,487,97,481,310,201,339,383,588,552,434,755,446,175,723,306,743,751,720,38,685,558,45,346,693,248,896,4
 27,620,307,217,898,749,287,114,828,76,875,798,234,151,73,706,93,754,43,276,589,120,335,451,549,232,891,61,345,825,125,616,301,250,172,308,417,246,208,842,832,556,534,309,230,852,900,450,116,55,32,537,673,471,617,327,623,739,187,686,104,713,830,302,663,297,753,606,576,69,214,604,377,600,205,761,561,34,764,611,659,513,826,738,281,291,146,572,802,108,237,625,694,416,756,84,523,118,315,608,95,528,82,10,218,872,59,185,194,26,408,50,836,614,557,133,525,285,196,786,280,705,261,295,100,99,419,228,163,724,873,819,859,48,682,489
+660,345,322,851,839,594,829,505,185,705,6,393,748,357,358,338,759,835,110,859,891,378,93,233,301,353,491,876,553,560,785,557,484,787,265,78,371,800,494,552,573,524,46,54,752,459,408,587,700,760,471,848,354,21,70,754,709,603,226,580,250,326,269,71,26,166,689,889,847,431,664,203,75,38,892,192,370,276,673,739,42,155,763,51,654,188,588,595,239,308,527,303,462,201,259,609,737,508,133,125,798,616,528,444,817,159,69,894,662,389,273,514,43,712,209,150,572,863,540,790,414,37,872,151,380,614,691,419,589,202,534,693,171,896,681,659,164,511,675,555,690,314,104,383,791,649,167,883,334,793,421,56,525,324,632,106,420,137,652,855,427,533,758,805,225,871,666,7,687,506,58,388,172,394,426,479,39,215,716,99,299,719,395,741,181,64,146,124,764,211,583,446,738,102,238,606,821,234,477,91,415,845,682,563,801,703,316,884,315,893,658,457,439,36,590,382,337,193,475,335,642,714,111,247,368,504,236,411,627,797,241,612,109,788,720,29,438,252,16,628,669,472,717,570,362,794,843,663,711,300,559,849,403,336,6
 17,615,645,598,344,254,348,442,474,482,96,176,320,148,418,844,30,174,10,692,82,248,704,530,105,708,232,33,879,243,608,665,404,377,144,783,727,726,886,213,831,305,369,282,885,750,796,582,268,567,107,556,73,732,11,231,735,599,323,53,807,667,372,333,770,277,406,677,854,786,676,537,841,386,875,428,857,694,607,804,581,728,34,267,4,8,168,860,291,289,657,12,485,145,824,434,809,412,275,165,246,826,867,823,781,216,519,114,568,522,655,520,640,507,476,518,621,139,430,575,806,740,57,184,249,585,468,257,432,812,379,810,19,579,877,297,443,729,149,684,596,20,97,312,240,828,639,161,178,116,747,792,769,544,463,473,218,23,14,198,480,674,671,500,128,648,721,355,309,44,813,636,852,696,83,777,385,373,900,744,644,825,261,493,643,604,564,774,449,547,359,304,490,220,710,492,260,108,543,489,245,397,775,868,453,325,548,699,535,881,224,80,465,861,830,895,862,387,41,278,160,221,576,244,402,512,488,169,779,392,542,452,50,374,455,447,86,814,200,153,736,212,129,865,529,713,458,332,597,686,59,274,266,836,7
 66,767,356,423,65,546,749,503,130,470,678,820,554,152,417,264,330,285,346,61,466,263,400,436,701,631,256,795,31,840,95,789,630,487,157,235,339,634,498,154,360,541,461,271,351,290,536,753,578,350,401,142,620,833,210,87,321,448,600,586,63,445,650,194,897,251,496,375,313,175,182,566,870,25,205,197,521,183,77,523,837,307,422,204,180,549,9,207,222,816,469,856,866,199,734,776,228,195,853,517,811,501,698,565,186,281,140,47,294,707,255,803,223,880,363,122,562,68,495,100,28,755,284,416,170,79,242,838,724,214,55,584,407,441,32,286,647,878,272,306,756,349,219,177,18,723,179,310,718,532,190,464,98,846,873,762,262,364,888,771,24,141,424,435,331,127,134,5,688,680,486,163,610,768,138,715,288,352,405,515,119,551,103,745,611,187,624,123,191,94,668,633,772,516,121,206,81,651,815,253,258,623,84,52,702,882,283,429,538,757,425,189,347,626,637,62,502,135,381,2,822,90,208,92,808,13,834,413,391,751,343,365,1,22,27,451,440,706,450,661,292,227,88,784,454,384,746,115,113,147,864,328,550,743,483,827,84
 2,3,89,287,858,76,15,270,577,298,641,802,112,302,327,48,602,725,136,296,101,481,329,819,670,376,778,318,72,697,593,574,293,731,390,410,117,229,341,773,237,143,230,618,460,656,869,433,467,558,366,126,780,437,217,497,605,761,49,887,361,173,66,730,409,545,398,478,799,156,158,874,342,695,722,340,850,162,685,782,832,613,196,898,85,629,396,67,638,399,526,818,118,672,17,571,683,311,765,45,622,625,601,295,619,742,74,60,367,131,592,456,679,120,569,591,132,280,319,35,561,890,539,510,531,635,317,513,646,40,733,899,499,509,279,653
+808,47,163,784,611,816,564,193,24,741,333,485,388,617,572,86,776,850,81,876,687,335,183,102,235,581,452,789,336,287,415,191,243,526,172,562,173,769,730,649,671,615,27,64,579,197,216,428,446,395,417,875,736,461,115,833,429,494,66,436,90,664,514,40,114,208,274,718,877,426,612,194,73,104,725,61,587,139,748,858,162,295,576,372,434,524,352,179,65,152,123,716,160,598,161,412,791,218,99,493,613,299,519,557,854,315,367,752,371,267,660,279,100,693,75,545,516,588,464,821,644,171,845,91,44,574,260,740,214,184,246,680,765,763,591,723,34,683,550,249,498,486,390,782,848,478,167,884,170,695,203,330,689,541,777,53,804,133,401,856,809,285,697,879,145,889,338,449,546,511,413,430,479,820,419,420,141,159,694,205,337,668,517,702,234,427,135,153,811,569,745,175,573,82,851,273,537,54,431,79,455,497,293,661,869,343,424,663,96,755,322,211,609,558,827,69,52,239,77,198,751,760,410,221,357,121,309,85,408,630,754,206,351,445,392,450,640,112,178,632,457,761,394,735,30,470,500,623,369,349,387,853,543,101,
 381,393,794,825,270,652,458,137,747,282,528,120,14,56,169,871,361,560,276,520,375,213,832,678,22,376,147,290,622,383,366,705,291,150,16,442,471,836,893,398,894,377,384,196,780,593,605,506,865,321,504,785,151,378,146,26,631,201,71,78,554,768,655,23,882,447,829,753,596,859,466,831,764,237,774,437,518,584,815,874,665,319,329,39,385,166,658,888,127,129,767,313,118,43,570,181,779,67,746,212,340,886,899,675,552,28,317,7,793,773,647,140,278,210,238,421,798,76,327,416,656,636,303,108,51,423,229,219,355,582,209,872,126,838,648,567,666,743,4,402,462,454,691,248,11,802,226,624,527,586,868,673,674,186,286,566,530,207,264,42,341,778,502,594,192,359,365,269,318,89,722,577,775,713,607,788,323,190,900,830,862,817,620,380,597,251,292,439,414,280,797,368,245,379,703,795,106,525,762,650,580,667,501,892,422,21,826,474,353,847,252,345,411,676,733,891,878,144,41,771,70,259,744,232,553,332,405,551,578,453,682,94,265,109,614,281,448,885,503,756,595,13,621,883,561,824,301,188,681,646,575,354,328,490
 ,806,861,639,534,124,841,619,662,5,110,842,852,254,601,418,111,17,18,155,177,846,45,68,638,399,734,499,467,227,714,559,796,787,97,364,346,441,507,262,284,268,786,342,48,122,717,509,864,616,37,749,134,867,897,95,225,715,199,712,463,84,701,803,128,738,813,488,538,185,610,700,679,641,49,215,684,174,306,272,456,585,515,217,629,535,304,168,316,36,482,158,844,728,606,618,759,302,35,870,223,589,544,783,460,711,15,742,465,440,314,331,531,10,704,633,119,522,228,275,29,87,828,142,200,1,143,189,895,477,707,344,512,685,255,433,432,739,731,182,391,590,288,231,3,98,708,31,88,556,247,438,307,363,563,790,397,699,103,890,887,136,643,476,600,692,373,187,326,807,339,297,222,487,626,406,801,154,625,729,117,20,195,8,637,202,132,389,360,25,505,669,242,473,508,549,224,634,571,757,83,19,407,706,55,719,839,289,472,698,489,356,32,74,857,523,271,721,12,131,156,696,105,157,149,592,244,542,475,657,521,484,116,298,58,165,727,565,834,257,233,362,180,263,860,176,256,642,635,46,690,849,324,814,627,92,720,77
 0,374,93,261,898,236,253,294,855,451,880,603,2,325,72,250,347,628,204,602,654,130,710,645,819,532,659,425,469,688,480,386,653,492,230,80,529,548,495,866,810,50,459,311,308,873,799,63,608,370,382,38,672,818,400,583,686,837,60,709,468,113,651,781,138,792,148,568,812,348,444,677,732,533,539,350,835,33,823,510,599,496,241,896,6,805,536,258,481,443,750,822,220,240,358,320,491,435,483,107,409,800,547,125,334,863,62,283,310,59,843,513,840,164,724,670,277,9,540,300,266,881,726,772,305,555,57,737,396,604,758,766,403,404,296,312
+238,734,236,24,588,248,139,203,460,46,792,655,354,603,432,280,365,22,857,38,322,213,687,403,807,341,269,13,720,126,427,277,160,101,535,842,233,606,475,170,218,343,749,691,81,197,177,583,98,307,430,49,564,828,766,73,103,85,753,843,853,556,437,527,847,806,282,142,66,491,189,630,488,607,208,419,308,393,124,150,877,394,65,644,617,496,647,470,780,239,540,759,232,612,684,310,398,176,377,575,40,325,92,386,54,799,613,244,659,424,494,646,584,204,859,576,91,323,192,64,521,623,2,367,538,86,374,500,304,489,537,45,850,205,44,283,830,423,653,243,83,507,637,573,43,143,338,12,812,773,788,748,173,390,198,447,727,463,89,18,695,519,709,165,880,52,181,861,109,120,743,242,549,719,309,704,732,329,202,439,898,660,210,318,763,708,666,873,108,547,326,784,171,446,881,183,155,790,114,580,619,319,462,241,560,216,468,313,373,231,188,196,387,845,358,677,360,561,558,298,110,471,815,287,190,482,331,680,777,57,714,426,829,389,431,882,235,863,869,454,686,487,212,153,472,272,335,441,596,499,113,19,249,818,90,
 526,128,413,887,505,296,553,355,611,852,879,652,809,225,39,765,550,851,42,624,443,410,157,574,214,332,740,257,544,275,63,841,289,444,442,633,88,27,378,450,493,625,295,50,47,605,87,892,104,673,418,478,328,689,512,484,396,356,820,123,314,664,578,384,305,700,69,174,94,74,382,767,315,26,563,351,565,209,122,156,417,769,534,848,858,741,61,836,352,492,778,508,839,151,436,14,509,656,896,586,302,570,30,631,707,840,679,274,503,311,425,266,399,650,733,195,722,191,819,497,568,658,867,369,498,362,569,718,72,186,129,674,327,429,407,345,562,756,187,227,800,855,796,635,9,344,645,640,713,220,23,542,406,614,368,523,641,871,517,152,119,745,364,592,251,253,536,701,744,626,391,8,161,798,32,760,353,56,67,457,20,629,591,474,290,263,206,770,158,692,900,581,336,76,411,545,683,464,589,456,306,117,77,477,711,440,70,169,1,721,870,144,80,597,3,53,228,774,785,835,648,279,702,256,453,754,609,363,267,230,598,628,794,219,379,771,259,703,825,649,682,783,51,409,422,258,247,102,449,876,516,899,262,36,182,349,3
 70,543,458,821,347,511,531,294,55,541,712,532,299,661,515,776,520,746,772,585,265,594,140,698,217,885,25,736,21,168,539,479,346,278,58,803,889,408,610,133,366,254,572,154,162,106,557,385,884,504,599,862,886,604,415,200,175,768,339,137,789,300,823,297,303,730,723,791,359,223,688,293,669,579,420,897,99,100,657,179,705,518,490,827,324,643,221,234,7,33,595,132,15,383,750,41,716,524,416,97,264,729,747,860,868,286,461,738,135,761,105,333,878,148,502,618,779,811,84,866,838,551,665,891,372,79,672,622,255,350,824,795,632,402,59,510,452,261,229,757,481,725,671,775,320,95,726,678,222,742,201,797,480,735,627,16,448,864,706,710,281,621,685,380,817,121,184,717,582,822,37,466,600,465,405,361,435,485,348,731,31,376,762,400,552,608,675,116,392,224,271,758,292,875,48,590,834,751,125,894,831,75,10,890,164,284,455,752,801,813,381,60,755,401,654,334,816,17,681,577,634,62,793,147,696,404,96,375,501,832,781,593,694,237,112,388,337,728,513,715,115,288,697,245,808,495,782,6,215,357,193,395,826,11,85
 6,805,276,602,865,667,636,529,451,642,330,615,250,476,846,145,268,559,414,810,301,548,35,136,240,787,459,676,428,71,317,469,82,638,412,639,662,663,316,849,844,506,567,167,525,802,651,285,118,397,833,130,670,587,166,211,146,571,138,530,874,895,68,690,421,804,321,29,473,693,111,514,159,78,724,5,445,273,178,141,172,888,28,737,312,226,739,522,533,342,34,814,467,883,131,134,260,163,854,127,185,149,270,438,486,546,554,207,434,528,246,433,764,199,252,616,555,620,893,601,4,194,483,107,180,786,371,93,872,566,291,837,340,668,699
+663,29,258,614,195,859,378,184,172,734,538,213,440,849,792,120,437,806,162,848,598,496,135,315,67,723,244,678,650,251,433,209,176,504,466,591,289,350,871,509,476,398,130,102,628,139,211,85,300,388,141,872,665,586,432,844,391,568,19,109,112,560,465,137,248,104,256,521,847,721,375,59,179,336,544,231,718,52,585,879,294,488,566,545,78,581,645,226,309,193,49,612,203,798,27,125,459,171,166,616,487,75,480,793,858,183,463,608,621,561,757,30,319,419,161,685,599,304,270,845,449,431,751,153,156,456,295,870,93,469,21,551,770,601,611,454,140,856,144,99,548,752,658,877,824,260,312,869,477,239,514,642,724,732,851,157,897,400,380,843,895,564,255,830,164,888,187,630,331,590,671,609,700,894,224,748,158,345,420,292,293,221,593,364,113,486,462,167,638,576,523,438,296,254,865,328,342,44,425,89,774,363,76,807,610,323,694,423,33,582,381,313,448,716,696,14,51,132,118,418,661,408,348,413,372,32,503,11,687,631,861,308,285,517,522,512,669,357,311,288,91,876,200,772,84,505,475,263,537,659,262,840,481,3
 47,393,60,785,892,149,747,647,1,846,35,510,217,45,69,124,855,625,695,399,457,615,100,567,632,207,198,126,573,483,679,116,660,74,324,107,154,105,784,885,579,797,674,131,396,709,446,174,580,881,346,556,883,321,145,379,10,219,64,40,337,362,511,451,148,768,528,749,701,565,875,474,762,301,482,633,745,447,170,802,890,761,359,403,3,549,410,644,874,422,334,453,445,8,182,335,12,667,13,853,314,175,767,866,525,147,16,643,56,683,570,340,41,119,28,17,744,720,39,220,88,218,201,574,355,53,94,472,68,77,498,215,893,204,775,298,550,533,341,87,478,653,617,777,66,15,733,277,717,781,742,786,575,227,38,613,371,738,330,392,264,473,664,121,390,495,501,417,70,677,384,274,233,690,479,727,795,681,426,900,783,736,803,834,79,230,402,96,360,110,163,889,386,20,443,764,715,7,600,532,864,623,654,358,857,714,71,891,430,491,750,634,327,325,584,281,873,835,188,133,728,97,624,854,80,691,618,90,547,199,338,809,257,520,34,697,552,450,800,412,826,160,191,825,852,279,527,508,136,589,267,627,189,404,442,708,731,670,
 769,169,735,181,831,111,269,684,860,516,808,725,242,54,9,18,246,743,266,6,740,604,603,810,427,382,656,672,706,833,194,365,344,409,507,592,250,555,540,291,48,210,832,373,887,689,5,801,290,789,842,310,280,655,23,535,619,387,822,811,47,578,827,273,703,26,571,676,421,385,240,282,828,368,278,415,526,458,816,302,838,577,42,439,397,4,326,117,790,635,787,370,705,249,31,818,494,177,796,668,190,756,103,753,492,539,424,142,524,72,587,713,216,374,406,596,81,349,711,108,500,63,129,247,829,416,763,553,712,646,607,675,746,441,595,46,223,252,460,95,73,354,286,236,214,353,25,320,155,333,369,332,464,637,361,868,758,377,729,804,502,588,680,228,562,837,202,639,534,127,622,572,452,434,788,791,58,152,55,168,626,82,468,83,383,234,629,760,62,241,719,794,306,673,493,307,316,165,232,780,225,557,782,186,546,839,134,702,86,229,776,542,606,536,37,303,343,597,414,470,128,471,351,436,180,821,339,389,376,515,253,299,886,484,766,57,151,150,61,602,754,50,43,305,666,238,730,819,429,878,329,106,265,722,541,405
 ,222,867,245,435,652,726,704,805,235,65,352,276,275,444,297,506,698,812,178,841,519,771,558,196,692,651,317,497,115,773,489,559,22,649,814,813,693,817,192,401,554,205,799,356,92,779,461,657,159,395,896,271,513,485,662,143,529,755,173,699,815,2,882,36,394,707,594,739,543,836,283,583,122,765,185,641,287,367,284,197,898,138,880,636,261,123,741,862,686,146,322,455,411,272,518,499,208,490,759,682,237,563,640,259,467,268,212,899,688,620,98,605,823,206,24,820,428,531,850,778,884,318,710,243,863,407,737,366,569,101,648,114,530
+325,722,105,635,886,180,767,385,271,317,208,533,819,364,164,214,705,497,691,545,893,88,284,193,701,45,254,726,829,348,860,584,228,696,390,368,178,849,372,143,241,327,392,313,583,277,139,746,544,810,435,525,156,273,412,377,589,272,617,875,793,152,53,121,567,600,729,855,517,485,434,382,74,136,882,188,44,203,309,387,663,9,596,60,809,21,811,765,686,82,751,349,353,133,546,571,673,331,43,33,612,637,110,297,480,531,47,891,854,411,50,753,122,532,775,48,200,870,275,486,318,125,643,52,618,218,778,255,628,234,704,315,432,885,341,463,706,391,828,490,458,242,134,233,404,440,28,651,773,890,808,243,90,81,266,96,492,129,441,565,446,708,871,475,826,597,588,398,447,101,184,99,92,416,196,736,289,68,540,10,880,838,18,668,504,120,406,742,473,58,329,822,611,78,562,516,759,692,76,182,578,862,806,304,783,693,236,883,295,889,592,270,190,328,298,724,336,240,721,162,176,713,423,35,25,680,19,744,872,626,206,749,481,848,827,560,32,812,593,621,846,316,694,128,539,818,866,665,867,306,283,561,46,795,381,74
 8,166,410,851,49,62,645,140,671,461,807,642,647,256,513,171,41,443,394,85,189,590,89,261,683,77,185,879,247,559,211,817,301,165,858,863,314,657,17,727,281,515,102,803,522,876,216,640,338,104,379,29,776,141,370,784,712,311,547,716,470,409,595,610,3,350,222,820,462,454,198,895,293,740,551,878,794,150,468,202,831,191,436,366,538,197,550,787,195,622,179,667,707,754,518,495,616,167,841,310,638,798,619,881,580,874,430,186,389,526,654,634,576,718,796,174,487,126,861,847,830,127,785,204,681,488,356,695,675,113,503,153,201,887,31,119,788,577,606,465,219,375,687,548,519,717,94,181,131,426,557,837,656,685,269,93,80,536,351,168,257,857,312,235,625,747,429,569,355,873,602,629,415,226,448,719,343,763,330,451,511,227,641,661,632,512,769,733,363,344,888,679,1,397,159,402,106,396,554,27,36,689,582,506,699,352,494,332,702,521,598,107,770,877,764,568,213,420,346,703,414,324,502,63,624,756,98,804,97,207,723,91,792,57,453,237,574,303,320,853,575,264,563,444,627,323,108,142,698,500,231,884,839,40
 1,477,24,248,79,319,894,294,238,684,388,489,752,170,507,123,658,469,728,40,479,700,660,70,856,209,403,789,672,650,130,439,192,710,38,13,26,282,845,781,340,529,117,239,183,115,175,413,163,579,72,802,431,772,790,732,169,496,232,376,424,114,177,633,896,373,285,73,630,210,322,393,843,249,7,145,768,39,782,148,758,408,161,245,34,674,419,2,514,799,357,566,731,109,553,445,51,605,549,825,869,438,296,417,160,690,433,501,5,833,510,741,646,834,30,762,225,15,730,535,478,383,821,844,367,246,850,678,552,135,61,449,69,832,244,400,542,777,337,173,715,71,528,299,262,836,644,217,520,815,308,221,250,824,900,864,305,649,664,652,608,124,662,87,230,267,14,286,258,614,774,276,868,556,16,766,347,86,65,666,157,620,482,474,711,581,670,54,466,84,369,734,760,335,229,6,491,259,859,771,677,405,599,572,342,738,842,42,260,835,743,688,800,333,287,300,253,428,360,361,586,345,371,205,653,280,779,603,144,613,100,541,326,395,64,558,66,288,437,737,527,268,291,456,399,655,659,292,147,223,601,11,252,615,594,898,609
 ,386,555,37,797,623,83,457,418,158,564,801,334,8,467,523,452,639,187,23,274,483,137,631,215,12,892,224,95,682,220,537,55,573,648,509,67,278,484,591,460,714,103,805,149,498,899,750,151,321,279,676,636,425,212,75,290,471,132,852,378,791,607,359,725,354,813,199,455,59,302,823,111,530,524,585,570,194,407,735,761,365,814,755,459,374,22,251,745,472,263,493,534,816,587,384,499,4,720,604,427,155,339,116,739,669,138,20,56,118,508,146,543,450,154,362,172,505,358,709,780,697,112,380,265,422,757,307,442,421,786,897,840,464,476,865
+658,648,212,728,888,196,767,389,214,327,191,779,556,2,21,322,855,536,525,616,796,132,482,140,774,101,620,682,274,420,663,427,419,532,107,463,215,889,19,499,614,714,350,394,374,409,320,838,613,634,738,470,485,304,144,317,510,250,624,868,668,515,399,247,417,698,585,809,633,55,732,609,211,135,821,178,113,480,603,253,483,98,442,149,856,264,273,527,310,260,680,636,325,59,686,766,850,415,237,193,626,749,348,25,361,694,254,822,382,99,152,815,138,780,574,146,225,849,602,312,684,105,669,245,381,497,581,33,646,76,788,506,507,829,324,772,490,27,867,635,328,6,38,73,464,672,143,615,283,896,301,63,229,52,159,218,20,93,426,467,26,232,891,696,709,486,638,289,673,200,77,94,36,39,591,125,413,130,782,238,814,885,188,840,679,321,110,649,731,334,710,379,773,155,518,390,768,628,315,387,41,791,802,97,882,552,13,851,475,833,414,258,604,256,644,670,400,550,529,129,450,860,601,120,290,665,89,711,339,448,124,457,623,572,437,514,241,443,428,827,864,32,721,236,408,559,718,842,488,23,500,456,386,401,376,
 828,329,67,820,156,75,723,103,798,571,607,522,577,402,537,109,136,418,469,74,519,826,355,192,707,343,92,799,10,745,392,832,198,267,843,866,468,592,84,861,18,761,123,671,625,887,240,568,356,314,49,151,784,167,460,862,717,421,265,755,775,734,359,823,175,622,377,629,291,383,521,897,118,735,53,763,863,360,326,154,612,373,523,281,296,429,563,342,148,835,295,687,453,783,681,588,598,115,677,617,831,880,637,884,560,364,410,540,742,789,659,695,720,800,179,474,558,435,865,878,873,68,416,368,819,182,627,811,594,302,282,300,512,875,332,494,871,424,363,172,239,336,777,508,538,502,230,22,147,713,543,881,697,168,664,45,248,455,189,185,546,874,689,61,307,509,701,69,165,892,813,586,726,262,365,137,150,685,452,759,423,17,806,837,347,683,667,830,517,58,812,786,227,259,501,582,288,754,12,272,306,703,715,64,524,65,473,210,705,78,643,403,655,893,674,688,285,385,553,600,48,87,702,106,161,836,372,854,465,108,396,90,746,160,121,446,795,597,297,883,305,91,654,765,839,139,366,422,848,504,589,781,712,5
 64,744,249,28,292,647,894,43,268,371,725,354,279,79,50,190,516,479,762,261,736,344,645,131,411,539,5,640,505,548,242,528,217,436,351,319,357,335,330,752,81,804,384,375,243,134,533,257,199,566,208,561,733,870,441,639,492,675,596,183,180,104,318,676,841,459,657,80,737,472,495,751,834,216,228,116,391,369,608,222,708,3,252,34,278,793,204,226,551,756,433,576,653,83,760,439,395,579,666,346,877,37,549,722,316,481,477,534,153,542,727,526,487,750,176,578,570,158,205,466,244,610,747,378,337,438,724,844,535,277,112,128,380,284,126,9,808,730,593,567,825,133,706,311,171,886,333,219,700,824,599,531,491,792,899,605,565,271,678,846,340,246,62,449,573,24,255,184,266,630,223,46,876,425,102,869,117,72,194,606,221,661,293,405,691,166,803,345,235,233,195,757,776,88,60,206,498,432,890,398,397,587,476,353,595,631,807,186,82,857,141,547,489,652,309,66,650,440,220,287,583,127,96,431,642,370,716,805,42,704,478,213,234,269,207,4,407,496,690,660,748,545,57,693,554,785,818,404,164,349,541,187,111,794,47
 1,898,511,294,224,352,879,619,201,47,740,15,801,853,341,275,231,557,299,816,54,163,169,367,85,621,430,251,895,16,145,847,303,753,122,445,162,544,209,8,7,817,530,454,447,331,434,770,900,575,71,263,35,451,787,30,562,388,651,741,270,797,11,632,520,286,758,56,778,611,590,44,14,729,119,739,358,771,580,197,743,769,790,662,764,618,323,100,177,461,845,31,70,656,641,569,503,308,699,181,493,458,280,406,170,202,276,852,157,142,362,174,40,86,810,584,513,95,484,462,1,555,298,692,203,29,338,173,412,51,393,313,872,858,859,114,719,444
+693,23,250,542,108,855,202,106,155,675,643,388,228,837,767,86,487,732,259,806,363,495,292,300,163,727,326,558,525,162,186,91,148,355,448,718,246,401,866,569,547,491,206,197,505,100,190,111,188,152,235,848,755,698,472,788,249,518,60,142,126,678,576,212,375,243,88,348,819,642,406,159,277,418,341,223,719,97,591,867,424,551,455,632,77,666,512,76,280,199,5,733,125,817,93,110,536,114,242,692,389,39,501,737,808,379,581,387,465,513,789,53,405,452,180,745,555,123,309,770,574,498,652,205,78,470,103,868,24,474,25,543,860,393,546,528,151,827,179,58,466,729,683,887,769,241,365,821,432,263,441,669,708,728,825,219,898,422,274,768,896,457,299,829,232,870,92,720,314,573,712,580,724,899,329,647,323,361,449,414,410,290,602,400,264,610,471,288,609,681,599,331,260,307,894,184,175,67,447,173,697,129,17,740,660,144,667,185,55,366,214,254,562,794,754,14,41,279,34,383,653,484,531,433,420,2,544,10,550,499,886,135,480,311,351,650,687,330,456,390,81,873,82,747,35,306,253,335,362,608,238,761,564,282,293
 ,66,763,889,255,787,623,11,844,70,663,281,27,121,85,823,682,752,548,398,658,181,625,634,248,80,170,626,266,651,87,616,141,268,119,46,62,757,863,604,831,627,269,391,552,373,133,538,900,267,679,874,416,47,479,37,257,12,45,402,215,577,588,83,795,584,842,674,386,851,381,812,318,446,509,668,195,216,798,882,705,134,557,26,664,507,750,862,377,303,560,575,1,211,187,28,592,3,875,409,349,775,888,445,94,51,529,96,726,671,408,6,44,22,52,621,731,107,276,113,182,237,618,357,64,116,392,166,153,367,209,883,360,807,124,638,617,423,98,339,554,710,853,167,31,644,105,779,780,800,786,485,245,7,526,482,756,478,545,236,443,661,130,489,524,372,213,149,614,435,287,302,578,517,811,703,595,359,893,746,792,707,841,139,319,240,65,150,210,117,892,473,49,534,670,772,56,704,633,834,691,695,194,839,622,50,891,324,428,635,586,515,364,431,283,815,785,145,229,833,138,583,830,189,685,519,157,665,140,442,759,128,587,38,696,488,594,810,571,872,171,154,854,824,396,601,461,156,589,333,748,353,481,217,659,730,713,71
 6,298,796,192,778,120,132,723,804,395,838,645,231,33,20,59,380,840,208,4,736,440,611,776,218,510,532,760,637,803,79,497,458,496,468,486,412,523,655,301,57,168,858,413,876,641,9,828,354,843,871,316,438,749,40,585,541,425,814,782,118,346,881,368,694,84,702,781,520,191,328,358,859,200,417,530,508,291,774,272,852,672,54,527,483,43,131,63,700,490,813,340,615,382,61,766,374,115,715,656,239,836,73,850,639,582,204,312,369,72,411,735,305,407,502,493,137,426,688,143,430,68,275,304,847,285,835,619,605,699,522,734,709,537,454,112,378,207,467,224,75,439,371,220,174,294,30,503,177,516,165,313,252,744,270,826,797,469,799,721,579,701,689,338,648,801,95,535,556,164,511,620,553,404,777,809,8,172,18,193,533,16,459,69,521,203,711,676,15,102,636,818,385,783,477,345,286,127,178,865,308,566,640,322,567,793,71,606,99,158,820,500,624,629,74,227,475,504,444,462,271,350,514,251,342,802,234,506,284,613,343,434,885,565,753,90,36,325,147,612,742,42,104,295,773,278,822,717,464,879,317,32,273,598,657,437,3
 20,890,427,559,597,791,686,864,160,101,429,198,460,332,310,539,741,857,89,861,415,762,600,196,662,714,399,463,109,790,370,494,13,722,805,765,725,878,226,540,421,230,849,352,29,739,397,596,201,347,897,453,568,549,654,247,356,706,244,816,738,19,877,48,492,649,607,743,376,856,265,476,261,673,183,677,146,221,296,337,884,176,869,628,450,136,680,845,631,321,122,590,297,233,572,334,336,403,764,593,225,436,690,315,570,327,258,895,646,684,222,630,751,394,21,784,561,419,771,758,880,262,603,169,846,289,832,451,344,161,563,256,384
+572,514,309,824,884,402,848,554,259,605,1,466,809,205,208,375,780,745,278,774,895,302,172,248,455,193,492,858,610,583,842,625,500,799,271,65,371,847,305,483,526,512,159,155,722,495,415,687,718,821,523,737,237,14,122,632,728,544,398,738,456,240,198,131,146,319,743,889,752,362,651,312,114,70,894,244,216,329,603,589,185,95,748,15,757,97,626,682,361,298,666,235,502,71,403,668,741,545,162,43,794,690,464,299,694,274,37,898,715,360,107,652,73,708,409,47,501,886,550,681,381,45,835,189,499,567,756,228,671,200,659,629,100,896,617,635,345,354,775,624,645,184,38,170,679,658,160,834,436,871,518,31,379,166,471,144,217,142,646,776,214,574,838,693,439,785,709,7,677,406,16,283,75,174,438,467,124,203,712,94,509,810,270,764,310,40,186,311,711,120,529,563,760,126,111,631,840,424,412,168,346,877,789,437,802,749,211,892,392,897,675,460,387,5,485,559,416,263,601,295,536,742,165,206,306,628,154,585,676,770,67,678,195,832,767,82,285,425,133,663,790,265,777,428,477,826,872,703,784,226,569,769,313,476
 ,608,716,497,405,548,96,225,581,269,602,115,388,474,324,470,744,6,59,64,664,26,301,674,418,171,766,257,19,888,161,669,570,590,391,231,859,833,611,831,116,779,220,457,250,879,740,866,511,137,575,51,365,77,816,32,341,803,702,401,153,827,630,357,447,704,164,281,573,860,653,654,394,883,356,864,364,880,772,449,650,451,806,52,396,9,85,104,758,422,286,656,22,613,317,841,549,750,556,86,373,293,762,818,804,865,382,616,252,454,473,660,640,706,606,618,538,493,289,432,733,855,820,28,353,320,673,475,337,566,814,383,665,74,440,890,183,336,786,308,680,553,3,29,463,397,759,700,54,78,21,647,765,839,655,481,450,88,36,90,267,430,584,792,479,125,649,763,444,277,101,863,672,819,661,17,683,408,370,873,633,552,734,105,594,685,642,634,822,577,588,143,516,615,145,623,342,376,42,504,349,132,260,813,793,395,487,330,688,508,857,224,188,434,853,875,878,795,420,158,169,352,199,421,358,258,515,619,109,837,351,399,564,24,571,297,427,87,729,215,39,828,326,25,787,558,695,423,332,507,730,69,296,489,861,691,69
 2,207,290,103,435,852,334,222,565,591,697,607,35,350,272,480,413,517,83,359,400,562,268,754,547,149,829,150,817,23,717,468,593,141,196,262,582,586,333,315,520,441,340,363,102,510,597,472,490,219,328,505,773,380,246,213,551,533,532,135,254,496,367,899,119,498,236,458,129,121,557,881,91,191,53,620,180,238,453,845,192,419,68,99,662,56,151,366,846,522,796,851,63,736,707,221,372,778,609,867,393,604,600,76,445,80,92,177,781,348,815,390,882,204,307,541,48,527,253,113,670,491,540,292,157,461,768,727,81,20,513,273,521,2,201,637,874,355,304,808,275,335,279,60,800,322,323,726,684,230,484,127,869,893,830,194,452,843,714,136,41,369,338,245,79,140,4,535,720,525,147,751,739,62,746,288,173,227,636,181,648,229,698,705,256,701,108,287,27,568,731,825,431,30,179,66,595,854,411,410,638,55,187,644,862,486,318,377,836,442,374,506,494,578,46,433,276,417,49,791,134,233,163,812,50,849,503,223,771,284,426,8,106,44,280,344,592,528,735,384,300,61,696,534,530,782,57,152,58,811,251,339,761,580,885,801,13,
 176,266,805,212,18,241,488,175,546,844,232,243,385,148,598,753,123,138,10,542,130,807,539,255,868,210,12,732,543,641,118,723,429,524,34,98,239,719,128,316,197,667,459,555,891,587,303,537,282,294,798,218,242,404,560,699,110,887,261,386,72,621,579,347,596,443,724,89,84,876,139,710,686,446,797,234,612,823,850,614,407,870,209,448,264,117,721,321,343,747,249,755,93,576,689,202,788,190,599,478,519,291,643,713,112,33,331,167,389,325,627,247,482,469,178,414,182,156,622,856,378,314,531,561,462,327,639,11,783,900,657,465,368,725
+175,809,248,112,806,65,355,313,502,27,671,689,542,384,236,359,494,17,863,21,581,150,678,392,838,157,316,115,736,224,645,433,238,245,505,747,264,750,253,130,202,346,740,691,137,290,214,731,246,527,530,2,400,709,694,12,242,89,800,884,874,431,335,526,837,826,490,386,33,397,265,677,466,541,477,429,136,471,116,29,865,272,143,485,767,330,681,650,788,260,714,628,322,367,748,480,497,271,370,387,158,531,88,228,6,801,482,521,730,383,267,771,528,298,870,360,78,610,254,24,484,532,54,364,648,107,574,252,504,425,703,70,733,479,62,327,843,230,784,399,120,333,456,289,14,266,287,11,815,862,805,591,59,207,58,444,439,404,192,13,402,566,824,92,890,1,344,777,218,75,563,139,338,421,339,651,700,286,296,373,898,786,101,455,760,572,619,877,129,379,293,813,323,418,778,295,372,832,105,596,515,586,693,111,624,389,325,612,483,512,310,237,342,716,247,789,473,577,701,273,67,580,764,226,156,661,220,795,793,124,437,584,802,578,576,852,99,869,855,565,822,232,415,51,602,460,567,579,718,380,196,15,176,836,169,
 704,43,167,894,280,162,702,131,734,797,888,745,834,315,8,597,329,811,109,443,498,428,84,571,413,347,590,535,391,449,46,873,324,491,706,807,39,3,234,432,363,680,262,181,147,794,80,817,187,525,188,401,570,603,609,662,614,464,796,318,326,623,675,336,180,536,36,343,16,140,225,861,288,146,470,605,724,69,10,64,625,669,641,766,828,575,7,841,341,549,672,684,850,361,588,56,665,376,897,600,275,511,132,812,762,849,719,170,440,398,618,469,573,765,696,96,752,223,871,713,737,508,867,445,658,388,627,787,203,213,18,635,171,715,268,251,687,775,276,208,666,728,833,720,40,522,427,420,495,135,98,725,607,611,371,311,552,840,547,141,85,839,368,507,331,423,616,620,685,781,529,71,201,632,23,699,350,4,26,354,20,385,705,608,406,430,409,816,274,394,900,726,231,52,255,638,519,422,407,291,159,305,49,395,782,190,161,185,68,642,853,160,229,773,34,45,283,756,630,857,553,114,738,117,467,814,457,601,249,93,698,489,854,87,362,668,209,637,640,804,722,561,31,476,461,244,285,79,598,820,534,899,499,48,138,179,219
 ,513,320,880,173,550,646,227,9,613,478,436,307,753,634,831,468,604,791,727,103,692,106,520,410,876,104,546,41,47,670,396,278,221,83,821,891,345,569,166,450,301,314,183,30,55,683,172,889,365,543,866,883,441,560,164,154,711,128,42,825,589,649,337,142,785,582,653,374,488,655,256,417,686,366,893,91,294,481,206,459,352,663,759,235,721,453,348,32,153,349,263,38,357,792,44,757,749,284,74,369,514,803,746,827,163,644,744,282,799,309,145,878,191,393,636,790,772,66,885,851,615,659,896,319,195,447,458,200,204,823,647,487,451,216,587,463,465,174,763,548,657,779,783,351,222,829,643,292,673,442,881,667,592,676,19,408,846,493,606,211,500,533,340,708,28,358,712,492,872,100,306,679,448,193,152,626,503,544,732,76,595,717,594,454,639,501,73,621,452,186,540,241,808,82,751,847,780,239,848,819,95,81,895,94,118,695,697,835,844,250,77,617,332,707,378,758,97,633,538,631,197,729,353,735,194,261,328,554,741,742,518,472,168,53,524,555,743,568,583,90,434,769,403,674,486,593,25,151,119,334,557,887,61,776,
 774,270,537,858,551,545,405,299,517,564,654,198,539,830,215,416,462,212,622,419,279,149,57,121,868,317,496,556,86,475,243,182,629,562,438,446,509,302,723,856,435,652,217,390,879,761,122,148,300,842,277,377,559,113,205,144,558,375,381,882,859,22,798,184,864,308,50,321,516,312,259,297,125,755,37,474,240,382,356,257,892,5,739,110,102,682,690,411,134,63,810,656,860,199,269,155,304,845,178,72,108,281,523,506,510,414,210,426,258,127,412,754,126,123,585,660,424,886,664,35,60,233,177,133,818,165,189,770,688,599,875,303,710,768
+398,477,304,800,843,491,835,540,307,659,48,214,859,479,391,333,618,752,305,767,898,367,55,329,294,269,289,861,825,554,877,683,395,837,446,15,396,721,588,330,343,284,155,104,804,417,353,520,696,850,293,789,113,13,279,718,744,608,306,650,456,89,73,112,172,183,781,889,733,643,481,143,102,128,894,298,286,188,467,715,230,144,803,32,648,54,834,762,529,255,677,80,512,211,240,513,559,480,121,47,784,604,379,530,776,119,5,897,865,574,159,506,125,561,462,97,565,869,364,782,157,126,830,135,582,441,816,436,651,352,528,575,67,895,671,425,397,631,628,523,722,404,174,365,706,535,171,845,679,786,740,186,389,302,612,134,551,243,669,820,522,764,719,637,438,831,687,61,577,426,148,380,204,455,231,751,46,245,569,31,496,658,266,611,142,1,369,296,616,38,317,743,673,151,131,694,821,374,338,84,668,876,737,619,624,788,415,892,259,896,734,490,175,62,309,516,355,96,664,386,434,548,36,241,229,590,216,541,866,822,208,779,69,880,863,71,261,597,161,429,685,510,741,448,487,870,888,501,874,432,450,818,191,657
 ,639,583,484,667,471,149,320,453,408,419,27,443,458,299,382,760,110,115,50,655,123,129,459,332,239,736,147,130,893,376,533,538,444,460,203,832,750,586,849,181,633,428,226,311,886,713,795,570,165,580,6,635,85,777,77,253,663,686,308,281,802,421,136,521,544,154,145,560,881,756,703,264,819,495,856,665,890,621,407,748,573,848,2,292,49,180,23,783,641,371,420,4,555,392,814,383,730,493,224,435,108,640,690,799,806,314,839,210,310,242,447,603,666,468,449,811,384,190,276,630,765,689,139,525,248,489,646,156,357,823,316,785,25,319,879,98,179,606,324,774,711,22,64,288,348,771,766,70,258,100,539,778,723,598,726,225,220,7,91,366,475,469,680,250,285,770,824,232,578,223,755,461,827,503,39,747,705,504,883,629,351,787,323,377,474,738,505,838,361,494,387,563,442,103,724,212,237,10,263,688,83,194,793,759,661,515,589,712,605,854,476,107,301,868,792,885,763,393,150,78,341,431,625,173,346,727,418,18,745,185,556,695,109,526,350,622,3,617,43,94,716,430,189,773,315,482,562,234,403,537,37,111,571,875,67
 5,585,167,500,29,257,775,567,213,691,412,780,790,184,642,295,486,345,388,19,182,546,502,347,871,406,433,852,192,840,26,720,550,697,24,87,138,596,813,280,507,268,326,267,373,202,349,725,534,423,244,427,322,623,532,236,90,378,360,674,265,372,498,256,899,101,277,340,297,20,33,321,864,133,127,170,754,57,287,485,846,472,414,270,41,508,168,106,278,842,452,809,858,187,644,732,79,313,746,801,808,656,514,400,68,483,58,34,178,853,153,847,402,887,222,358,375,44,749,228,221,609,457,753,283,56,518,649,731,82,74,704,169,772,114,465,401,872,176,116,700,327,163,260,146,638,440,363,654,602,51,318,9,857,867,878,63,627,844,543,238,59,707,195,92,275,75,76,614,709,769,336,632,796,117,542,437,303,252,634,197,594,291,739,699,470,572,8,390,17,701,692,798,620,201,132,40,547,735,579,497,553,105,251,558,873,409,328,576,761,729,381,647,339,615,217,218,219,499,88,794,271,399,52,810,11,855,254,385,728,118,584,66,162,21,652,209,531,331,742,166,137,249,626,413,335,660,16,206,35,829,233,524,653,599,833,826,
 53,344,140,672,141,12,488,282,362,342,758,198,152,492,86,684,613,274,160,120,581,272,805,473,207,797,411,60,536,552,466,196,768,681,439,30,334,549,568,95,394,45,836,325,359,851,645,454,595,478,356,714,517,65,290,370,587,81,891,527,416,93,708,464,607,545,235,702,200,312,882,247,593,757,227,807,262,424,791,817,445,354,884,246,670,273,14,564,610,557,710,124,828,99,636,591,177,841,205,693,410,662,300,815,509,158,42,215,199,698,463,405,122,337,678,28,368,451,193,812,860,422,592,511,717,600,566,682,72,601,900,519,676,164,862
+647,107,186,395,136,824,84,44,193,574,739,451,158,839,762,58,446,626,442,725,252,425,405,287,349,718,274,402,554,75,151,41,78,201,449,820,176,416,848,490,479,460,348,310,367,45,123,169,79,91,251,772,784,795,548,723,113,406,179,316,326,714,587,276,526,409,37,187,743,632,296,265,295,463,198,237,697,118,521,825,578,543,285,691,133,690,518,74,394,156,16,801,73,834,203,80,497,46,250,735,220,17,401,728,729,498,627,248,467,478,808,111,444,360,391,776,445,59,234,672,603,544,537,215,109,358,69,862,6,470,42,419,887,241,415,472,333,806,261,20,313,744,734,883,674,139,342,726,517,356,499,742,650,730,769,253,897,427,134,652,896,439,376,767,454,809,26,830,190,481,778,541,754,898,289,682,434,325,357,430,616,355,563,336,390,688,514,485,540,717,577,423,148,319,899,97,71,219,334,263,724,62,13,692,670,61,661,103,48,229,117,162,550,861,747,68,31,331,51,321,584,469,625,382,339,8,507,57,585,347,888,120,593,246,288,798,643,484,601,383,163,868,24,685,43,202,157,323,363,619,131,649,515,412,161,92,706
 ,874,471,807,604,32,826,135,783,476,82,291,39,738,756,777,662,240,712,233,617,576,293,21,170,710,143,666,50,536,329,206,152,28,104,676,782,608,817,635,338,343,397,212,175,429,900,140,741,859,435,15,545,70,256,1,34,516,89,552,642,137,786,570,857,583,239,787,235,802,396,386,335,671,124,258,759,835,633,100,629,56,781,623,813,791,492,279,561,656,14,399,81,36,473,18,878,610,411,751,880,266,141,146,607,207,698,689,361,4,10,22,116,660,683,244,196,278,194,267,673,513,65,149,345,255,280,197,147,837,447,789,90,637,615,436,236,227,466,799,885,340,88,527,66,827,819,840,753,311,260,5,533,458,775,532,669,271,332,598,247,465,549,275,125,221,658,504,317,283,443,432,854,600,648,307,870,653,800,602,847,213,315,164,30,64,351,47,894,677,87,500,575,773,102,763,640,832,715,667,77,761,618,129,879,167,301,503,638,641,273,257,292,702,708,93,377,865,327,622,790,303,639,486,286,720,108,389,719,174,634,159,644,450,686,768,624,889,249,262,875,740,380,599,387,127,519,322,845,393,681,119,567,665,707,699,3
 64,804,344,760,173,160,695,727,381,852,646,199,95,40,188,418,863,330,29,709,428,558,821,106,655,374,818,530,757,99,511,438,457,318,555,597,489,696,205,53,132,856,305,836,568,33,816,547,841,873,475,611,785,38,542,441,502,792,737,282,230,890,314,659,209,765,844,487,96,420,312,871,238,417,711,407,142,811,172,866,701,60,620,452,115,49,25,580,308,831,231,501,379,178,664,422,128,700,581,185,858,182,884,774,564,181,424,228,192,243,731,495,297,520,494,290,538,612,369,524,121,372,523,829,138,851,668,562,684,588,815,748,510,272,168,400,144,404,366,110,506,426,352,154,165,105,566,130,589,72,408,211,805,298,733,797,609,838,758,560,750,746,341,755,745,27,565,572,328,362,636,571,398,779,796,9,232,2,309,384,3,525,63,551,277,766,591,7,35,596,849,350,867,346,370,437,254,86,893,461,455,505,531,488,764,67,654,264,306,810,371,705,628,166,191,579,337,493,477,359,180,613,112,433,793,101,482,284,736,462,474,882,509,680,94,12,431,208,679,663,19,222,223,842,294,855,606,403,860,217,23,388,468,780,535
 ,281,886,573,614,630,812,687,869,122,189,375,226,592,214,242,556,749,877,52,853,245,703,569,304,657,770,378,320,85,803,216,512,11,771,833,794,693,892,410,559,413,150,846,440,76,713,269,582,385,225,895,483,491,480,590,302,195,721,448,881,645,83,864,177,459,553,621,788,210,850,153,324,373,557,218,631,54,98,204,546,822,300,843,594,528,171,678,823,534,464,114,752,184,126,529,200,496,270,722,522,183,392,694,365,595,259,268,891,605,675,368,586,704,453,55,814,732,421,651,716,872,145,539,299,828,155,876,456,224,354,508,353,414
+87,758,341,551,858,150,754,564,518,318,245,326,859,451,292,442,452,374,704,342,900,290,285,473,615,113,216,683,876,506,886,705,375,741,606,176,440,684,425,96,122,161,515,386,664,445,331,635,584,852,336,364,3,191,571,337,669,416,644,817,793,14,15,310,590,531,786,844,279,641,307,365,256,345,879,463,108,309,167,314,657,154,661,118,731,12,866,833,778,287,788,76,562,174,527,526,383,491,230,33,623,642,178,438,410,390,71,895,889,617,35,687,324,353,800,60,359,855,249,478,93,312,543,242,739,225,838,278,685,487,678,272,116,887,431,234,747,489,697,555,574,389,251,199,282,417,232,508,839,831,861,362,111,194,284,300,446,380,561,498,387,812,742,165,806,428,646,306,408,231,274,270,197,344,183,813,316,297,360,106,837,690,92,483,414,84,602,702,253,7,101,867,546,296,169,655,743,714,185,302,692,870,802,403,427,762,421,883,412,892,699,501,73,213,30,753,520,228,792,436,115,450,262,244,128,732,198,763,897,676,136,828,343,881,869,392,43,846,585,393,772,319,717,147,681,857,885,479,893,502,355,500,3
 2,848,533,673,123,398,805,31,218,666,172,607,238,808,728,680,434,339,252,58,381,462,201,240,241,75,499,710,221,311,880,437,550,210,735,541,400,847,820,173,492,144,261,480,373,349,787,522,816,367,212,507,42,397,200,780,294,512,640,745,465,648,698,204,146,730,186,57,20,207,841,384,567,6,836,528,686,682,888,651,59,328,313,865,171,549,308,573,34,325,840,477,299,193,708,751,724,552,411,689,114,823,217,239,289,608,835,638,896,553,26,85,334,713,677,596,668,854,61,523,214,799,756,691,266,825,402,577,675,333,575,701,293,396,255,13,877,5,19,566,670,720,620,187,162,603,639,454,794,25,271,102,119,572,711,696,791,139,177,163,464,582,388,133,770,148,456,736,807,371,695,532,761,430,598,247,112,441,803,569,539,215,74,471,283,536,482,749,537,797,594,470,267,864,633,44,468,2,460,41,104,634,4,9,700,298,659,768,327,570,534,612,663,455,181,776,774,650,340,448,516,49,715,592,377,419,175,748,632,16,723,89,304,815,226,789,120,643,132,190,121,97,759,703,237,330,263,280,542,248,126,511,265,180,868,86
 0,281,188,11,404,203,18,853,385,459,790,95,420,834,196,656,378,738,589,693,155,67,785,722,131,890,109,517,827,628,662,77,363,202,804,51,56,46,391,884,694,560,166,233,429,444,79,189,320,277,665,21,801,39,258,829,667,8,521,103,556,583,153,124,610,899,64,206,195,591,50,68,184,818,423,141,110,843,81,726,323,765,529,394,264,10,630,519,72,581,810,525,474,718,130,458,433,90,653,332,872,811,579,160,351,22,766,142,315,82,875,376,782,725,832,36,755,209,125,821,600,587,211,795,878,557,288,842,223,616,17,156,604,1,874,268,554,254,764,352,145,613,275,447,509,432,658,740,485,493,773,159,286,170,814,882,891,47,771,488,208,645,37,750,27,23,405,137,303,229,671,849,496,783,614,100,467,580,152,29,734,406,679,627,535,752,709,618,63,649,62,472,737,746,514,250,138,236,301,721,830,767,457,317,647,243,688,777,164,348,779,819,733,845,24,395,426,54,548,595,415,576,544,586,260,674,257,798,407,235,611,55,706,338,524,192,597,45,135,424,781,379,295,443,205,513,578,538,91,399,53,530,151,227,510,707,871,60
 5,335,672,127,273,540,158,622,52,346,86,712,504,88,660,435,609,503,418,28,182,652,140,637,98,38,851,413,107,466,356,497,66,654,769,619,40,357,599,220,99,760,48,863,259,69,873,809,276,505,490,729,545,369,143,80,149,224,291,850,547,784,354,366,716,370,796,105,329,222,409,824,83,469,621,449,494,461,134,719,727,321,744,601,593,382,94,219,626,624,305,347,453,862,475,563,476,78,775,625,588,65,495,358,826,269,368,117,157,361,484,322,179,422,70,486,168,629,481,631,856,558,129,401,439,565,822,350,568,246,559,898,757,636,372,894
+836,145,152,648,587,755,370,108,31,576,516,710,82,492,469,101,819,751,274,835,296,266,441,72,501,543,548,549,61,220,94,42,258,260,75,789,104,829,562,667,717,740,218,283,297,187,221,564,327,121,572,806,840,673,174,689,236,320,254,603,248,803,666,191,333,483,97,442,852,226,642,436,212,213,410,58,547,300,745,760,378,347,311,513,528,660,50,11,32,188,99,857,73,610,375,458,842,182,223,623,424,317,489,387,704,607,560,393,40,113,694,437,210,714,197,634,351,422,514,611,796,265,709,203,4,537,52,637,172,130,356,588,870,440,404,787,148,472,674,275,279,382,430,752,769,465,217,808,59,779,35,394,614,495,626,161,721,150,246,702,742,34,790,873,324,825,253,658,509,417,478,330,491,774,541,171,399,167,715,366,567,776,503,757,517,639,116,380,795,726,809,17,532,164,890,110,364,224,413,287,249,262,272,449,888,134,309,409,216,425,120,114,754,734,861,151,86,485,14,123,719,831,678,237,400,131,316,170,81,341,783,10,638,95,49,713,631,126,405,762,552,641,273,653,13,138,179,739,36,247,352,686,615,39,235,
 481,737,671,506,696,388,255,662,457,785,278,66,250,176,814,474,630,550,379,446,415,867,661,80,261,280,398,307,299,406,613,518,55,98,340,510,786,838,411,897,269,605,158,466,456,636,346,894,209,698,619,277,281,302,156,703,168,144,185,397,823,820,7,891,496,879,655,264,730,268,862,813,119,556,232,207,690,797,804,486,67,586,178,596,335,812,854,76,74,849,544,173,157,429,293,654,109,770,407,584,886,899,460,578,186,88,165,824,859,720,135,245,291,414,141,801,295,392,570,668,716,381,159,136,534,45,451,571,332,233,781,344,858,500,683,763,818,111,133,214,635,826,511,118,647,37,753,519,685,872,448,725,198,71,705,527,426,536,20,231,772,625,729,190,91,102,482,189,181,782,676,558,728,771,592,132,62,881,765,883,627,579,551,722,38,328,208,621,271,768,577,403,473,470,844,285,708,851,421,691,711,329,868,204,51,712,294,180,680,184,640,439,362,775,794,847,107,251,871,259,200,553,498,484,85,602,743,565,561,512,2,373,242,555,100,693,885,748,843,682,18,672,853,701,865,143,270,649,746,802,573,521,201
 ,732,860,688,377,322,875,723,471,83,1,864,699,15,651,219,105,48,106,339,353,889,23,128,575,43,744,412,192,480,445,718,663,677,5,554,487,540,355,57,566,139,869,354,127,90,750,539,777,468,112,767,290,887,898,146,497,837,314,758,244,155,628,759,357,384,877,609,467,401,799,850,780,454,199,308,731,3,494,523,326,334,395,160,617,679,420,303,431,202,276,137,706,453,633,589,574,477,205,827,12,590,318,766,530,821,54,863,735,464,33,599,238,92,391,643,306,559,371,44,228,230,792,323,65,64,389,348,896,292,807,459,263,764,79,545,310,817,455,374,583,582,252,507,68,234,811,46,53,493,376,684,383,622,350,816,70,845,6,839,893,312,773,257,692,832,361,325,504,697,239,69,196,657,367,461,866,63,585,736,84,96,183,89,416,149,87,447,568,16,665,433,241,336,298,595,313,828,475,805,78,27,349,856,215,670,598,535,427,526,488,142,166,47,876,363,331,815,175,25,365,490,140,93,390,372,515,286,700,557,402,632,9,499,222,337,538,629,800,408,122,618,385,304,846,227,479,644,810,103,822,681,338,727,612,26,788,525,59
 1,154,396,900,531,452,194,882,360,895,581,129,418,8,546,153,659,206,650,756,29,695,434,793,569,733,315,594,778,342,450,664,267,56,117,669,502,345,878,880,163,656,22,343,892,841,30,476,211,243,177,604,749,620,608,738,830,240,423,305,284,834,606,282,646,288,687,724,359,419,358,741,522,289,597,675,60,855,369,444,524,505,848,125,645,520,533,593,256,600,747,508,24,624,162,462,463,193,319,195,791,321,124,41,884,147,435,386,115,707,368,874,428,761,438,529,77,432,563,19,798,652,616,229,301,28,580,225,784,833,443,601,169,542,21
+291,341,337,193,63,732,130,223,459,527,753,170,510,888,812,225,46,460,605,493,499,532,343,540,267,688,81,324,844,176,516,306,135,370,694,691,377,38,881,234,175,138,506,394,501,152,207,37,117,384,59,623,546,730,735,635,252,467,295,218,538,449,385,403,634,353,278,229,484,826,60,192,416,609,296,479,671,124,219,762,683,597,402,680,48,570,824,434,690,255,227,552,288,832,190,4,75,165,330,659,204,34,270,815,639,368,569,393,804,704,725,89,596,54,618,711,505,110,72,657,258,663,358,299,463,177,398,866,120,673,62,238,783,339,430,108,588,860,49,58,443,829,790,876,526,44,445,556,809,92,817,823,573,737,742,389,900,604,239,576,898,744,65,433,608,669,107,813,66,494,825,615,779,897,102,882,425,490,53,410,668,52,522,14,266,599,734,592,189,554,210,765,19,483,872,319,116,397,262,294,869,251,104,757,166,281,798,197,125,342,359,367,230,834,401,263,198,201,379,539,364,64,502,500,259,167,587,253,864,437,868,495,478,594,643,731,543,763,682,51,76,878,106,603,328,519,456,24,710,787,109,571,305,720,272
 ,27,558,886,515,724,652,119,793,77,640,666,362,457,155,548,795,714,660,224,747,144,171,399,544,111,188,780,318,805,12,381,277,466,348,100,71,468,616,633,315,792,133,520,436,148,36,472,891,256,619,877,523,91,630,209,5,134,161,706,105,150,322,491,323,531,614,441,444,717,347,534,87,606,244,853,400,20,574,748,662,448,566,183,774,750,631,598,788,529,126,632,146,627,82,68,286,191,856,727,206,275,452,221,61,307,871,382,405,301,45,142,78,50,103,884,427,297,127,187,8,16,758,766,196,17,625,157,137,271,213,781,485,528,95,470,340,47,480,469,658,770,839,250,290,391,378,719,850,806,386,289,11,101,810,156,789,536,679,561,465,311,93,145,718,559,420,97,855,692,33,18,371,115,802,557,867,586,701,471,414,535,865,67,30,496,31,249,162,96,894,751,73,428,611,514,153,648,254,893,572,518,140,464,822,435,885,241,512,361,841,590,172,357,23,577,423,261,517,674,508,820,816,205,651,761,136,551,2,181,728,564,700,349,612,689,560,352,408,845,41,583,879,489,80,141,600,163,304,21,759,185,786,373,338,284,575,79
 7,375,487,151,821,390,545,303,646,707,854,837,388,383,220,242,415,589,654,212,670,768,264,887,345,721,380,726,366,676,477,369,300,279,346,849,602,697,280,173,194,334,818,132,775,568,215,693,712,509,431,729,647,555,56,222,601,703,764,595,320,387,801,88,686,195,581,672,131,98,582,325,843,620,273,772,446,226,883,321,880,567,35,760,395,245,179,158,432,326,814,42,421,237,351,407,769,25,833,308,26,746,504,796,678,537,562,236,424,462,331,636,656,118,547,800,453,702,310,521,827,363,344,677,374,214,733,695,713,476,858,831,859,112,274,129,178,1,513,248,333,661,69,638,396,70,154,355,74,454,149,123,591,579,655,524,317,741,749,892,293,482,835,335,785,650,128,842,755,174,418,649,114,645,771,685,200,426,99,578,404,147,778,9,417,584,684,653,90,85,723,862,360,777,233,28,716,580,79,863,642,199,461,553,475,799,22,874,503,644,481,392,819,283,327,488,664,276,698,705,309,211,593,247,164,807,94,246,621,767,626,530,899,282,440,40,202,217,160,811,336,84,139,6,708,525,740,507,406,840,15,268,143,439,7
 76,752,203,473,565,617,828,442,784,533,3,376,287,549,563,422,7,709,665,861,313,836,228,486,450,113,791,738,32,356,10,743,354,794,159,687,870,889,235,803,637,350,739,121,497,122,411,736,419,745,607,39,896,265,292,169,216,413,257,847,624,838,613,180,873,314,168,316,696,857,312,808,29,451,182,412,455,240,83,86,55,585,681,542,851,550,438,13,846,830,260,409,498,722,372,43,492,429,622,447,511,629,365,699,208,541,610,184,458,895,675,232,332,298,782,302,269,875,754,756,474,628,890,243,667,641,848,285,852,57,329,231,715,186,773
+775,193,250,846,792,666,745,395,79,701,80,532,579,355,381,230,833,849,38,880,816,356,171,124,337,429,572,852,315,497,613,403,441,672,121,316,274,841,498,652,669,650,18,64,660,394,373,616,647,618,547,867,588,182,12,776,623,566,165,580,133,541,443,52,19,224,530,848,879,309,697,267,68,22,855,107,451,292,739,774,31,199,673,161,635,383,352,391,43,257,379,552,344,333,271,620,821,436,138,304,738,569,582,400,818,300,209,863,412,233,430,503,26,761,71,326,551,790,599,778,603,34,872,154,179,651,508,487,489,118,501,703,469,868,646,740,42,493,681,513,611,284,149,510,832,648,164,888,101,799,168,73,612,370,657,76,482,87,577,854,504,328,791,873,132,882,590,128,674,521,123,382,245,499,524,268,108,169,766,172,262,755,465,789,278,228,35,112,836,421,706,177,724,70,548,476,730,142,507,117,272,715,581,549,878,578,252,831,266,864,526,359,601,206,742,244,217,314,264,219,704,801,291,214,420,378,234,281,363,705,424,401,249,619,522,180,550,59,25,694,645,520,634,643,192,637,678,717,485,203,562,845,533,
 106,542,605,700,627,319,423,362,367,559,483,325,77,158,93,361,871,103,347,104,653,152,330,823,632,23,626,238,62,793,191,598,684,408,232,88,676,670,795,891,261,892,213,467,205,850,719,772,558,585,502,321,583,100,638,20,163,757,479,235,2,734,773,586,131,877,369,658,711,727,802,602,707,847,263,853,294,702,713,712,839,591,546,174,195,105,8,437,884,66,170,768,127,365,30,749,399,812,289,439,113,387,887,899,769,736,136,241,55,708,691,714,402,557,456,453,306,725,139,463,573,794,760,98,33,189,615,297,336,491,721,360,829,60,732,825,461,610,797,39,545,481,162,350,351,135,824,455,385,239,296,856,743,787,448,231,608,308,109,83,67,411,750,662,631,65,490,574,415,153,6,822,679,826,753,301,764,181,220,900,796,808,809,338,536,687,428,539,656,516,512,472,247,464,342,671,665,242,323,699,406,434,564,689,889,324,147,617,633,440,875,94,201,511,782,838,895,885,307,21,553,99,116,594,332,450,340,529,396,756,509,567,210,95,251,528,293,280,883,419,413,735,40,259,886,636,828,349,335,663,728,287,398,194,
 680,810,859,514,393,119,731,733,496,57,229,805,817,341,288,282,183,156,176,302,130,690,63,273,515,462,709,211,659,51,783,299,806,668,258,329,354,447,604,216,198,222,720,471,197,236,449,609,786,596,215,571,49,803,896,37,115,561,422,692,500,5,527,716,190,860,544,592,417,317,431,460,677,813,13,237,377,290,327,91,505,741,246,358,311,390,537,4,305,160,686,380,857,814,348,737,767,346,129,876,253,771,409,763,621,442,111,432,218,366,506,375,667,84,827,495,56,628,134,256,47,1,820,185,157,78,146,140,894,649,452,144,486,589,175,122,200,747,837,318,427,748,322,303,102,10,781,29,184,696,474,389,488,255,759,866,576,525,145,893,881,9,371,260,584,565,125,188,61,718,595,226,96,625,695,225,819,137,433,556,372,54,454,14,685,480,36,614,286,45,270,629,531,683,446,212,240,339,655,840,53,69,600,343,11,744,865,275,457,554,698,207,81,120,784,606,48,661,85,221,17,779,16,82,159,729,114,723,535,444,693,484,166,46,3,72,418,568,788,459,519,405,276,58,858,397,416,762,368,41,410,861,353,630,752,320,815,807
 ,92,7,357,898,151,110,143,765,269,835,780,44,364,141,148,494,746,86,435,285,331,445,754,751,492,770,254,204,758,575,593,426,644,178,310,312,248,243,870,534,28,404,384,466,834,869,223,475,478,277,27,785,518,386,597,688,844,50,843,279,90,298,726,345,587,313,607,830,186,167,800,477,682,639,425,851,75,798,710,777,642,202,897,15,641,470,187,654,295,570,842,196,458,126,473,664,388,640,24,523,722,543,208,407,862,32,150,414,74,622,438,811,173,675,560,265,155,283,89,334,890,624,538,468,555,97,540,563,227,804,874,517,376,374,392
+449,609,239,781,886,301,834,504,270,505,30,455,836,262,190,328,754,662,457,701,895,230,184,241,545,114,390,828,768,512,870,630,413,795,337,120,318,853,338,343,401,418,238,192,708,429,313,723,678,841,472,669,159,48,234,548,711,459,485,825,617,162,103,115,292,420,778,885,665,434,562,314,83,84,891,236,128,278,483,513,380,34,734,1,799,23,766,767,527,216,737,215,467,68,445,628,715,479,109,3,759,694,319,298,625,344,6,897,822,409,43,709,78,635,581,11,412,882,440,622,299,64,790,124,561,441,803,223,681,222,693,518,163,893,532,549,515,384,804,570,597,205,51,173,576,572,101,792,611,880,699,89,255,122,397,117,302,143,583,730,283,656,857,593,627,736,692,102,596,284,45,213,57,247,326,606,156,145,644,26,743,818,153,739,367,25,274,499,616,42,427,733,729,104,218,607,827,541,273,166,466,878,808,392,789,770,226,892,354,896,682,414,276,61,373,636,395,228,684,264,399,735,217,134,183,664,92,659,820,753,86,756,259,862,821,219,165,631,290,621,823,268,777,295,517,850,877,691,855,257,471,720,182,648,
 547,749,372,408,728,37,152,604,211,618,189,591,551,465,400,663,31,14,169,569,18,246,615,265,208,772,176,54,888,199,629,443,707,377,207,867,858,495,787,50,750,249,451,198,864,687,872,424,267,502,22,379,29,813,47,362,802,741,371,300,805,543,329,525,641,65,250,447,861,578,601,275,887,358,839,462,884,793,311,573,376,843,69,417,93,240,94,697,612,269,613,35,647,500,819,533,672,575,88,620,261,706,798,765,874,461,801,308,320,396,585,660,704,587,655,700,363,361,297,809,859,824,36,568,282,683,501,322,600,791,279,605,80,306,890,81,221,788,430,696,537,27,95,542,458,698,752,20,105,15,546,725,846,679,586,356,71,17,224,312,353,453,830,382,170,677,796,419,422,194,868,634,779,556,33,614,564,387,845,521,464,676,139,592,675,668,580,817,619,514,196,774,637,39,552,237,381,16,425,452,38,138,794,727,460,579,340,640,463,815,357,304,289,848,873,854,726,366,248,175,507,285,388,394,172,574,666,55,832,232,333,654,19,690,195,456,97,649,193,79,851,448,75,716,494,645,402,244,369,718,174,243,757,866,584,59
 5,98,281,72,334,879,323,231,639,491,633,714,58,439,225,566,437,602,32,349,550,608,179,842,415,251,837,360,784,13,623,368,674,66,87,140,492,769,538,351,480,305,303,309,74,383,531,370,534,127,565,431,763,582,446,144,523,403,497,242,186,374,473,899,149,398,164,516,112,132,468,875,142,91,53,732,96,487,364,831,272,342,113,28,673,178,49,428,849,478,738,826,44,686,626,123,474,703,760,871,432,484,526,59,557,147,197,76,833,386,807,506,876,107,519,423,7,643,365,245,559,653,742,325,168,689,724,695,46,5,508,157,719,40,280,567,856,332,233,783,200,393,286,126,811,481,296,657,775,202,385,131,863,898,865,171,554,800,661,310,24,524,212,188,136,62,60,433,713,680,201,816,710,12,755,330,125,129,670,181,651,324,638,745,410,705,41,375,8,509,761,814,411,73,82,167,488,860,589,540,558,206,339,535,838,667,204,341,852,594,520,671,391,490,121,317,331,421,141,748,210,287,160,782,99,847,511,187,744,180,496,77,203,21,405,209,469,486,776,407,266,135,598,493,563,751,85,161,70,762,137,293,721,599,889,764,106
 ,336,158,786,355,10,335,416,177,498,840,260,119,435,258,560,717,154,56,52,539,111,773,406,130,881,220,4,712,442,590,67,702,544,529,9,155,345,650,185,503,116,780,350,482,894,688,254,476,288,470,758,277,191,256,438,603,110,883,315,571,229,536,642,359,722,321,632,63,151,869,100,646,652,477,740,227,510,806,829,522,588,844,294,426,148,133,747,404,307,658,327,810,252,528,624,90,797,352,553,347,475,235,731,685,118,2,214,150,436,271,555,291,346,444,146,454,253,378,746,812,263,348,450,530,610,316,577,108,785,900,771,489,389,835
+676,52,355,780,314,845,590,368,228,819,293,152,596,784,748,252,479,861,35,876,778,553,78,341,6,685,318,829,615,444,576,386,347,708,446,269,399,336,844,567,519,385,66,53,776,315,360,148,504,550,199,889,507,288,273,869,589,704,13,55,25,419,374,146,59,10,451,749,871,709,476,56,184,244,763,275,695,138,664,885,58,445,752,371,156,457,641,358,230,310,179,370,369,670,24,264,474,361,213,458,691,253,580,773,883,49,300,797,637,581,651,96,238,503,61,533,710,505,381,875,339,296,852,210,245,573,462,826,277,437,126,688,455,796,750,488,71,835,180,276,716,696,496,822,857,421,327,893,356,222,439,447,755,684,854,188,856,354,548,882,855,599,240,837,20,896,409,287,493,673,471,636,595,847,284,703,74,366,508,249,16,226,610,436,37,274,362,9,719,435,517,367,472,251,586,500,551,18,514,93,726,547,236,820,542,521,657,618,142,783,543,456,390,405,654,73,183,119,217,466,724,388,123,427,426,163,492,80,655,788,732,441,89,669,644,165,672,185,86,299,144,841,430,795,191,681,661,302,613,606,428,879,489,246,555,
 169,810,880,1,630,633,101,815,100,202,50,108,14,278,881,397,563,121,626,463,140,538,666,203,420,200,378,693,605,272,753,7,415,168,328,195,824,897,525,754,619,117,432,846,625,265,698,616,510,352,867,266,350,219,92,294,239,166,173,569,523,280,206,739,509,546,785,761,888,652,697,282,535,803,717,623,225,799,894,807,497,181,85,248,151,394,890,271,382,401,207,134,94,544,129,801,128,744,48,139,769,817,735,242,29,530,47,671,475,391,190,311,161,70,701,743,17,340,60,321,262,418,170,159,177,537,98,65,711,353,895,122,738,480,477,495,323,68,643,742,334,465,12,62,836,443,528,648,541,794,759,301,192,593,342,634,198,112,270,578,730,137,363,403,640,582,116,584,227,304,298,830,570,461,853,597,481,900,831,662,865,733,120,268,526,263,558,67,359,828,38,103,400,834,631,63,383,469,827,498,607,564,877,713,114,872,614,612,858,501,64,425,781,324,898,868,337,51,473,15,520,848,43,705,650,77,376,357,364,816,307,373,31,722,598,216,802,218,566,214,186,621,878,290,516,592,260,665,308,258,174,57,628,804,768
 ,609,757,147,646,160,818,150,332,677,884,556,627,700,320,113,106,11,189,527,205,110,745,660,659,690,617,87,813,442,814,838,289,267,317,392,667,502,8,571,411,412,164,333,718,460,891,764,105,741,84,687,765,153,27,483,143,588,723,229,789,823,3,771,565,322,699,19,343,402,407,585,154,313,675,404,250,76,645,680,721,440,706,448,149,209,365,36,539,285,863,806,653,513,821,243,21,859,482,305,790,746,312,536,115,429,171,529,534,75,728,82,786,674,41,468,297,587,28,172,787,5,379,124,81,39,805,604,568,393,774,579,491,424,663,422,792,102,212,408,512,33,145,204,256,175,316,522,79,176,292,155,577,309,591,387,345,892,712,132,518,736,490,406,532,237,295,849,431,583,467,90,782,485,380,434,734,740,208,187,224,133,772,261,348,215,257,231,410,825,235,464,760,601,326,306,635,331,196,157,423,377,104,679,870,2,608,832,283,624,40,178,720,694,416,486,44,396,135,770,286,413,91,683,136,649,127,777,540,330,389,247,130,201,843,494,808,167,344,88,107,438,809,211,45,449,375,233,478,873,470,864,484,255,220,83
 9,234,223,279,811,30,259,554,611,658,668,398,95,372,319,54,594,414,433,620,561,338,758,725,798,559,197,656,450,349,639,254,678,682,524,158,459,686,727,707,511,97,281,603,351,702,303,162,779,602,647,72,545,860,182,560,531,731,131,756,714,32,291,851,42,866,23,384,812,506,600,762,751,452,747,69,850,232,629,499,572,417,4,899,109,874,632,118,194,715,842,800,22,453,125,549,454,515,689,46,642,775,767,325,638,574,221,335,346,241,886,729,557,26,622,833,141,111,737,99,562,887,791,862,487,793,193,840,575,395,329,766,34,692,83,552
+94,741,255,17,622,274,237,267,506,70,757,495,575,700,507,302,243,16,852,21,600,259,580,469,751,346,135,106,850,153,660,396,127,273,648,767,290,498,615,47,76,182,707,637,230,193,158,497,124,503,305,84,397,763,788,121,213,152,704,816,858,380,297,483,839,738,422,314,28,667,72,514,447,606,407,459,310,316,15,239,870,379,188,588,561,381,818,639,826,218,617,584,307,624,608,249,263,187,345,485,91,319,35,515,122,701,502,488,830,577,442,596,581,90,867,509,151,424,78,171,347,632,20,329,642,10,557,579,361,574,493,4,784,419,99,133,838,572,568,227,192,612,654,616,37,85,333,51,869,710,863,758,144,416,279,421,795,505,149,79,762,714,631,62,886,112,220,840,49,129,726,299,556,764,175,834,643,357,88,368,898,562,173,210,649,594,735,865,14,400,167,860,116,449,849,295,241,783,57,499,768,492,517,369,384,367,576,474,335,457,326,271,222,811,201,698,374,413,663,376,29,332,706,306,109,521,343,699,873,191,693,611,734,652,686,859,174,891,857,321,650,587,280,148,542,508,573,327,801,625,67,83,119,861,157,4
 68,98,543,882,453,341,531,387,530,787,890,692,797,215,43,727,484,814,50,618,337,242,66,610,282,262,721,473,638,236,18,809,382,444,528,633,36,80,378,293,609,476,348,225,46,585,134,871,161,554,548,439,394,662,478,389,455,344,829,184,156,475,677,223,254,526,33,386,199,162,253,702,418,97,722,578,470,131,203,235,629,658,496,820,854,599,58,872,411,328,694,532,851,208,385,6,537,641,897,431,160,392,73,635,690,894,668,139,325,177,465,304,373,597,853,82,666,105,790,456,480,661,888,354,405,523,451,626,183,159,251,604,195,525,284,190,417,755,360,388,754,812,723,640,19,500,550,679,665,89,68,461,425,774,211,534,555,846,601,217,22,689,205,655,440,443,403,806,760,551,275,61,42,733,95,847,466,136,30,289,71,682,477,353,463,231,363,664,143,719,899,519,257,180,270,467,570,287,749,359,206,200,31,659,752,553,118,281,45,802,825,60,245,538,107,12,264,732,653,823,739,401,592,286,671,656,458,352,130,323,717,623,796,212,547,645,120,533,761,590,744,771,24,265,261,383,185,23,340,836,372,900,471,3,52,269
 ,487,454,298,792,464,512,680,138,128,728,697,695,331,703,511,729,428,560,819,619,278,805,32,772,393,880,123,646,7,196,674,351,228,169,77,879,881,539,406,75,358,300,540,48,258,154,565,339,893,336,408,884,874,436,365,55,313,785,370,110,742,552,724,163,342,657,571,678,198,318,685,234,651,740,292,896,142,238,756,209,716,395,427,821,246,621,355,260,26,150,583,69,39,272,715,9,837,518,591,11,165,628,778,798,822,252,688,605,334,766,301,288,877,44,445,789,753,817,8,864,889,558,564,895,221,141,569,586,426,216,885,779,731,247,189,402,311,219,268,644,486,712,559,813,375,59,696,524,126,607,322,782,705,567,746,38,285,866,620,824,145,441,725,312,793,155,244,841,669,776,146,429,433,582,415,320,504,489,377,747,102,452,815,362,404,687,589,250,430,291,409,748,240,831,13,501,868,794,101,878,827,5,115,887,147,391,462,848,810,856,233,93,765,232,636,432,791,54,720,683,527,132,713,308,546,460,114,226,647,807,769,522,803,108,41,309,446,595,399,750,27,276,613,172,708,513,684,53,178,412,113,479,800,92
 ,828,832,181,410,833,603,743,349,536,450,317,598,168,593,804,277,179,630,366,781,390,549,104,63,164,759,563,634,303,81,248,438,197,777,414,544,711,773,166,780,855,364,770,96,350,775,718,371,207,520,842,86,745,420,56,64,34,516,324,672,875,876,125,675,535,808,170,2,490,737,296,494,103,204,602,25,481,117,224,202,74,883,140,730,437,194,627,435,691,434,1,736,670,862,229,87,214,356,843,256,100,283,294,676,315,545,491,111,448,681,330,266,673,65,398,472,566,709,892,786,40,186,614,137,338,835,482,176,845,423,529,799,510,541,844
+471,637,318,789,887,232,846,557,323,469,38,531,812,107,108,406,794,627,425,649,890,255,276,269,586,95,488,817,620,568,855,650,492,783,286,116,361,863,163,396,465,494,285,274,663,507,395,782,726,825,567,583,187,59,195,460,724,437,533,837,602,225,183,212,298,457,784,881,617,308,639,410,171,121,888,280,115,397,525,376,340,85,705,21,824,76,632,747,448,319,756,246,506,13,526,718,755,544,215,33,762,752,374,206,542,391,64,895,744,336,46,758,123,701,556,17,389,885,532,539,370,86,767,240,564,499,802,91,733,210,751,554,103,893,523,604,490,230,831,658,581,114,32,57,545,656,169,735,500,884,572,50,253,87,292,218,82,162,616,651,74,560,865,574,593,624,739,62,668,310,15,214,34,56,427,418,242,211,708,130,680,847,194,787,420,77,235,477,646,98,476,623,775,166,94,621,842,562,347,270,301,872,835,290,806,763,150,891,446,896,678,426,358,16,378,675,470,345,686,284,408,773,267,190,278,721,124,697,709,727,6,731,312,834,785,184,188,543,272,696,849,118,805,275,555,819,866,750,807,179,549,647,266,570,57
 5,798,344,223,704,42,145,679,131,700,198,551,578,481,482,597,18,25,172,603,22,364,654,316,252,799,305,44,883,127,716,438,734,379,302,871,867,459,714,81,736,165,536,245,850,719,877,405,110,540,68,205,102,839,89,432,830,778,451,268,821,592,375,527,641,117,241,423,845,473,601,281,889,331,829,313,874,820,299,445,315,822,120,493,70,208,106,608,517,303,671,80,707,456,841,615,673,642,9,553,360,702,759,764,879,513,664,367,348,421,669,722,754,682,728,519,359,414,407,828,870,852,39,484,382,749,441,422,670,791,366,461,157,317,894,146,291,816,429,659,452,27,36,589,512,672,742,29,31,3,535,720,860,737,466,428,37,92,222,328,353,468,854,458,142,626,779,521,271,177,873,715,757,613,14,561,393,355,769,487,450,614,43,681,743,643,677,823,685,587,35,690,713,132,486,259,479,58,462,248,90,176,809,676,332,595,158,661,435,810,238,324,384,832,880,813,687,413,293,155,514,203,258,474,156,478,729,109,856,343,254,619,45,703,192,373,144,640,262,19,861,417,2,662,576,691,363,354,394,770,136,350,653,858,590,5
 98,126,197,173,341,882,213,306,606,505,550,612,4,304,294,584,508,648,134,326,496,657,152,780,436,100,826,309,761,20,611,295,655,160,200,247,503,625,509,287,510,399,402,368,26,464,388,342,585,99,498,398,732,515,400,175,607,444,431,224,122,334,520,897,88,491,135,580,143,129,538,875,178,201,5,667,216,390,362,833,128,387,12,83,745,141,147,489,853,552,694,815,11,740,600,250,516,674,652,876,288,497,609,52,559,93,186,125,808,447,797,522,868,104,472,501,72,530,385,229,569,644,605,380,265,618,695,711,47,24,404,207,566,10,153,635,851,433,346,818,244,453,357,138,840,424,349,725,804,289,485,209,864,900,843,196,504,753,660,263,23,327,296,239,67,167,48,352,746,534,154,836,683,51,786,307,79,105,712,257,717,337,622,771,320,765,139,356,30,419,801,838,321,7,180,119,528,869,524,518,634,97,322,571,811,645,249,236,862,415,529,610,371,483,71,369,392,411,151,741,193,251,264,792,140,844,579,101,776,282,439,65,228,96,161,297,442,582,793,480,381,84,594,577,638,800,78,220,60,710,219,164,768,633,892,73
 0,75,273,277,748,351,61,231,403,112,454,857,335,233,412,283,558,772,133,69,1,565,40,777,383,189,886,148,8,760,449,689,53,692,416,591,28,55,170,665,113,455,221,684,434,443,898,688,185,475,234,430,795,73,300,329,502,628,202,878,199,547,137,463,693,182,738,409,630,66,63,859,49,723,629,546,706,279,541,827,848,596,573,781,330,260,174,217,796,261,191,666,372,803,226,537,698,149,774,339,548,338,401,311,631,699,168,54,333,227,204,237,588,365,377,325,256,511,111,314,636,790,243,159,495,440,563,181,599,41,814,899,788,386,467,766
+167,795,172,186,841,81,458,290,441,6,623,637,648,470,276,289,518,41,851,71,755,102,586,347,821,127,257,255,812,201,743,455,175,346,507,713,217,784,356,65,157,308,669,612,232,235,137,718,273,626,465,56,359,657,666,26,298,68,759,883,866,368,260,415,818,789,546,559,73,485,251,593,353,468,651,366,104,363,90,85,860,202,228,408,778,264,772,678,796,162,720,587,300,376,684,453,515,236,268,329,225,513,4,296,55,750,384,710,815,424,254,758,444,301,864,325,43,700,189,83,419,466,138,266,640,48,645,327,503,404,675,27,725,665,53,320,832,335,792,370,166,372,437,357,18,250,199,114,839,873,836,579,5,200,92,341,571,345,197,77,525,650,842,140,887,97,364,761,209,11,547,111,330,533,267,737,621,219,303,271,898,806,20,482,711,502,611,865,155,318,274,845,340,333,803,321,462,814,15,495,604,686,717,164,658,463,350,733,388,690,360,215,285,692,245,773,398,481,712,253,16,597,721,152,45,649,156,783,857,231,477,642,751,707,682,831,32,876,833,549,828,332,464,7,573,596,698,576,808,406,142,76,89,852,169,687,3
 ,305,895,265,129,664,161,701,762,884,726,811,261,51,564,291,775,105,400,386,448,12,511,461,243,558,671,413,427,2,863,312,394,754,824,14,115,180,521,392,624,205,365,178,823,44,835,163,452,307,311,617,527,529,670,618,379,779,389,324,569,653,401,96,519,1,512,75,173,222,877,297,282,560,729,732,40,82,63,702,591,568,741,807,526,70,856,315,545,599,655,844,446,536,69,634,405,897,509,358,630,208,837,727,879,652,145,418,381,608,476,537,745,786,60,694,131,871,749,756,467,870,352,635,432,541,760,302,125,110,538,168,793,190,184,704,744,355,281,628,714,809,667,64,575,387,440,472,176,151,752,590,672,314,309,457,820,510,112,49,850,319,484,416,520,539,660,647,816,505,154,192,607,46,764,354,194,8,378,57,430,662,592,478,390,508,797,238,493,900,685,128,80,234,557,454,396,542,223,99,373,120,489,776,306,188,191,185,661,829,67,377,813,203,103,229,708,609,843,580,187,668,84,555,802,383,636,153,116,724,425,848,31,412,598,283,565,631,817,705,581,95,422,486,269,183,10,595,805,434,899,627,34,181,118,27
 5,391,322,888,244,473,659,246,58,676,488,516,242,739,572,810,343,606,798,699,72,794,61,574,531,862,211,500,35,30,679,294,170,117,50,861,885,375,561,74,362,247,326,108,98,17,641,158,886,393,633,868,874,397,504,123,198,677,141,9,790,763,644,279,121,746,524,616,337,594,585,139,426,734,263,890,38,403,544,150,498,286,638,736,126,656,550,313,78,288,344,278,42,256,757,94,819,788,380,39,328,491,785,735,804,79,728,681,407,777,492,106,875,122,304,709,747,748,62,881,867,548,566,896,420,239,423,395,287,146,858,625,535,442,367,501,361,497,109,716,474,605,801,781,310,237,826,563,216,589,556,894,768,554,688,124,483,834,460,697,135,447,532,227,663,19,382,782,487,872,174,249,689,449,196,133,620,410,523,695,107,610,730,583,342,614,439,113,629,514,241,543,130,791,24,787,855,780,221,849,800,66,226,893,13,179,731,769,822,854,272,47,601,295,639,369,719,160,603,530,528,280,654,480,691,224,299,240,570,703,696,409,602,87,28,456,588,680,475,577,119,374,740,429,632,402,567,100,54,193,351,551,892,144,7
 53,770,159,643,838,469,582,417,317,552,615,578,91,522,799,258,431,438,171,619,411,316,230,22,37,882,338,443,562,36,436,233,252,674,517,385,494,584,348,722,847,336,738,134,435,891,771,148,147,331,830,323,506,471,23,165,177,459,553,451,880,853,29,774,293,859,248,52,284,534,479,277,292,195,715,93,399,262,450,445,218,889,182,683,220,25,600,673,499,207,88,767,723,846,210,270,59,414,827,212,33,143,214,622,540,428,334,101,339,421,132,433,693,86,213,490,613,496,878,742,149,21,349,136,206,825,259,204,765,706,766,869,371,646,840
+757,212,196,344,292,750,90,66,175,440,759,698,6,690,612,134,646,523,464,671,20,307,562,210,549,647,449,241,182,111,1,25,173,51,249,866,145,653,693,571,608,649,399,441,141,132,181,425,131,3,481,663,851,833,432,566,57,246,336,514,369,822,722,342,573,585,14,87,712,349,450,475,352,424,49,198,636,310,587,695,637,488,127,718,360,760,153,18,244,220,62,873,68,781,419,288,707,108,318,772,167,163,390,494,546,705,725,39,99,240,797,340,408,496,365,782,297,98,376,458,784,484,412,296,67,392,5,765,53,309,253,402,892,60,263,655,334,577,499,142,157,557,660,829,598,271,326,581,268,567,222,669,596,622,618,303,838,327,104,478,842,129,607,801,486,682,75,841,305,375,733,383,686,857,477,338,561,274,491,489,719,593,510,520,592,788,347,569,605,798,745,170,282,321,899,41,92,324,348,405,415,22,100,463,837,21,468,58,219,48,30,112,716,862,825,177,118,527,43,214,610,701,795,319,380,81,434,178,191,147,863,17,766,12,27,850,658,345,664,619,381,753,64,616,71,15,4,560,35,407,231,461,601,234,113,329,670,746,60
 0,799,474,207,738,374,859,465,152,384,136,659,735,775,770,206,678,435,796,603,265,55,316,666,26,487,239,480,519,121,226,107,304,672,656,538,876,437,580,251,155,225,373,279,900,114,814,709,439,70,533,224,476,54,164,444,123,720,823,102,858,568,885,517,29,617,130,845,597,204,230,372,7,493,761,726,456,2,755,223,815,628,861,721,294,180,767,752,124,357,137,237,398,110,852,632,621,831,896,201,333,276,256,311,786,828,547,72,80,199,346,300,741,396,332,482,389,495,629,386,185,388,126,470,521,94,208,694,528,827,161,744,742,676,269,46,203,821,884,550,209,397,13,835,730,826,808,216,473,97,217,650,704,609,769,184,221,642,467,661,394,50,16,455,395,430,539,504,281,536,865,414,339,160,777,620,868,428,764,460,559,28,187,24,590,148,855,748,320,553,353,834,312,820,812,572,774,732,82,749,331,165,785,120,158,361,416,794,354,86,501,492,687,117,442,886,400,411,589,535,541,172,537,810,287,506,524,61,604,278,576,200,811,832,800,887,471,197,840,700,595,783,189,257,534,558,878,591,724,11,522,758,743,48
 5,457,860,540,555,233,45,804,532,85,817,358,190,146,168,366,497,889,215,140,626,59,625,654,19,734,193,836,447,657,36,645,526,554,243,227,731,260,847,286,171,135,830,433,710,417,150,803,505,881,893,362,708,854,245,648,213,404,706,697,453,33,895,500,552,431,849,880,689,119,409,368,843,47,551,762,280,69,615,159,805,778,284,586,490,267,32,91,452,166,793,343,363,508,308,644,128,313,413,623,378,874,188,890,848,529,10,651,40,238,74,711,509,429,544,176,377,479,635,443,252,186,512,525,871,103,864,683,264,768,270,792,515,715,138,385,584,317,302,570,179,462,677,254,139,258,306,754,299,751,65,578,8,869,133,624,870,588,853,446,679,846,614,426,763,633,56,228,393,556,174,631,790,218,703,779,44,247,79,295,232,42,330,275,688,194,809,351,89,88,341,802,379,883,325,582,283,195,192,894,445,483,285,675,418,574,242,335,315,211,856,250,602,787,291,101,630,236,371,293,503,125,723,37,684,680,162,641,122,756,451,518,739,599,702,322,23,662,421,565,728,151,454,382,875,272,877,436,370,771,359,34,579,273,
 813,410,403,898,717,674,391,872,513,891,290,277,438,115,737,83,427,406,747,867,38,807,169,713,583,511,466,780,594,248,298,776,93,229,106,806,727,563,816,897,364,714,78,266,882,639,84,542,154,355,367,328,844,691,543,611,692,387,73,469,459,888,472,262,729,314,627,498,531,665,63,818,301,144,606,420,205,773,109,149,350,668,652,323,685,545,696,422,401,673,502,643,9,819,96,255,507,31,548,116,740,289,183,76,839,337,613,356,259,791,423,824,530,681,448,634,156,638,789,105,516,640,736,143,261,202,667,95,879,699,52,564,235,575,77
+571,591,175,784,888,326,822,432,188,484,41,595,769,178,118,275,826,676,449,736,885,150,256,136,622,92,470,814,623,464,831,546,387,727,204,270,231,877,248,415,502,542,223,215,617,386,280,775,654,786,564,680,325,134,144,534,647,385,493,852,613,320,210,83,316,498,706,873,720,283,636,397,40,24,883,142,108,313,561,496,398,8,656,10,828,91,620,671,413,181,684,409,377,43,500,673,804,425,67,32,725,694,337,205,605,462,36,890,728,262,81,750,22,713,562,28,340,875,491,579,472,13,787,93,466,471,734,184,642,100,712,543,348,889,478,664,473,276,842,576,521,107,12,179,608,612,33,792,494,894,567,26,266,68,357,66,258,37,540,700,243,519,878,702,638,733,658,170,631,246,21,138,19,227,411,459,213,62,721,29,774,862,148,799,455,110,165,530,699,152,558,604,753,30,418,525,816,538,278,191,311,861,802,297,859,691,116,886,351,891,590,314,416,133,523,615,346,322,599,159,457,818,368,54,197,633,25,650,719,679,124,652,393,808,742,345,202,560,328,739,848,220,748,308,435,788,849,773,781,131,469,696,257,552,481,
 778,402,343,763,74,86,616,201,686,352,586,507,467,367,695,18,31,245,555,4,312,760,332,128,735,189,15,874,90,663,456,761,260,154,860,865,544,791,14,840,129,563,102,837,672,881,354,482,437,117,300,9,801,23,342,838,704,339,242,795,670,514,421,783,58,454,460,823,568,537,431,896,224,827,304,864,833,394,580,305,782,153,400,146,230,238,724,516,168,759,96,630,451,821,554,677,553,120,635,381,810,871,737,879,450,692,295,453,569,693,632,674,609,705,545,447,389,334,839,872,858,7,511,255,744,369,405,690,746,244,589,99,448,893,177,349,844,379,588,407,75,221,621,426,688,661,95,42,47,667,683,866,660,443,477,27,34,298,211,261,528,856,509,60,556,709,499,273,119,882,729,754,649,125,581,414,251,850,557,637,653,89,681,767,559,602,780,722,495,193,797,682,61,489,390,406,103,583,318,121,217,764,772,303,535,293,596,358,819,219,430,327,812,884,843,765,284,241,376,510,166,302,483,130,433,756,180,847,309,269,549,1,678,187,306,222,770,355,208,867,350,72,758,601,777,277,237,410,796,330,366,768,832,628,70
 8,155,186,82,513,887,235,173,531,624,610,572,51,285,145,515,401,640,38,566,446,587,160,757,488,147,790,399,745,85,641,363,574,139,132,207,439,634,611,212,659,317,279,233,104,438,518,319,503,190,550,607,857,526,505,310,547,508,383,163,172,403,517,895,336,486,111,573,267,301,597,868,94,69,77,603,158,529,290,805,171,265,76,106,710,140,55,420,824,424,731,800,39,717,606,194,465,749,626,876,291,548,592,185,501,329,333,59,766,504,752,461,855,126,520,475,5,497,356,199,629,669,619,272,225,687,830,643,161,3,378,264,584,35,162,707,834,395,344,809,123,485,232,64,863,388,214,675,785,353,408,249,845,900,820,360,429,811,803,296,112,375,321,371,50,56,63,423,668,533,87,854,645,6,836,203,97,182,618,114,627,259,593,698,281,740,127,263,53,422,741,806,286,48,57,331,480,880,512,452,565,372,299,582,817,732,183,268,853,445,492,594,551,428,45,476,324,294,149,711,115,169,218,751,167,815,639,135,726,287,359,98,174,20,292,289,539,536,715,527,335,49,689,479,644,789,229,71,206,743,105,282,762,532,898,718
 ,156,247,195,869,436,16,200,598,78,697,851,228,137,307,361,468,771,46,80,101,444,109,738,474,164,892,113,17,794,392,648,73,625,396,490,52,84,216,776,384,458,234,651,362,666,899,614,192,382,176,427,779,240,323,315,541,701,88,870,198,577,380,506,662,288,723,442,665,11,65,841,122,685,575,578,730,141,646,798,829,570,657,835,252,364,143,226,793,254,253,703,419,747,347,434,655,79,714,365,463,417,373,157,585,807,44,2,236,70,370,196,716,374,440,338,239,404,151,441,600,825,274,271,391,412,524,250,522,209,846,897,813,341,487,755
+358,573,369,787,862,351,846,622,370,616,49,255,867,322,293,433,631,717,321,710,897,377,122,368,340,202,347,854,794,626,882,730,495,840,453,14,467,736,412,331,343,309,212,169,789,520,432,602,741,864,365,713,78,16,261,639,775,608,385,678,507,83,98,178,186,240,816,889,668,557,536,230,159,155,894,345,221,291,466,594,218,144,805,51,701,63,809,793,541,327,739,59,597,118,316,610,561,584,191,50,798,688,396,431,709,151,42,898,849,542,97,605,153,595,493,61,544,879,437,728,165,135,812,216,641,483,835,280,723,337,633,585,4,895,660,448,446,486,674,627,731,305,124,187,645,612,224,808,642,799,727,128,326,225,489,208,303,257,704,770,284,756,743,533,468,759,745,31,634,418,91,356,134,231,295,692,115,281,599,110,469,684,248,648,201,28,342,308,598,54,304,747,715,200,5,729,841,450,372,167,564,885,790,522,579,817,334,893,375,896,766,546,192,17,245,609,463,166,716,419,407,567,75,266,269,681,217,629,843,819,82,804,102,878,860,52,226,587,157,477,734,323,788,379,588,874,888,555,873,374,538,769,203,65
 4,669,663,403,473,494,87,277,576,278,517,37,460,551,350,488,698,69,71,67,680,94,219,441,306,285,782,239,107,892,302,632,516,510,519,289,852,795,514,802,160,525,363,290,335,884,742,821,562,12,636,26,459,126,822,108,359,700,750,421,274,826,417,133,589,456,149,72,515,881,672,726,180,827,506,853,577,891,666,312,647,497,861,40,394,41,161,24,703,615,410,422,35,650,425,833,503,725,607,93,414,158,552,539,806,829,395,803,294,250,210,499,690,735,591,553,754,319,264,349,670,796,724,114,511,341,586,646,241,430,834,389,679,95,233,886,100,176,630,386,780,683,21,1,339,443,753,800,39,152,46,455,777,758,687,693,254,139,64,89,409,502,442,718,275,260,773,837,310,490,228,776,531,818,526,7,714,640,528,838,560,259,752,183,465,535,764,613,847,423,596,181,500,547,123,682,148,325,22,244,537,76,154,820,696,593,592,383,744,621,842,408,113,355,872,810,869,712,482,198,30,382,371,491,247,286,706,485,43,785,236,458,721,103,603,292,600,34,521,79,8,751,481,80,711,360,470,559,313,393,590,20,172,504,880,638,5
 24,130,404,116,179,786,444,298,719,352,720,774,86,550,353,578,454,475,96,104,570,611,265,866,388,300,865,168,832,18,689,439,733,84,131,175,618,772,271,484,235,392,373,451,99,391,601,492,534,142,415,215,472,527,220,65,496,354,653,262,256,402,317,899,15,328,272,378,33,19,332,876,174,188,73,768,121,238,498,857,336,480,132,55,614,147,137,376,859,565,767,856,105,677,722,138,390,705,779,830,558,479,487,23,549,2,45,177,858,209,851,474,887,162,357,428,88,732,287,222,566,505,737,366,127,509,530,762,32,68,662,140,738,62,362,416,875,273,173,748,338,234,348,156,656,476,435,694,671,92,399,60,871,870,877,48,644,807,449,214,27,604,194,77,193,136,57,508,760,740,299,665,781,111,532,461,199,164,707,263,686,324,749,757,452,655,66,440,29,652,755,828,556,101,185,10,575,761,580,543,628,13,268,554,863,413,318,457,811,667,447,658,242,619,163,204,307,548,109,784,267,387,129,823,56,868,301,270,765,146,606,58,190,85,445,229,464,438,791,223,232,189,563,529,420,699,3,251,6,792,253,346,691,675,836,815,44
 ,315,211,513,150,53,424,196,288,213,801,276,197,540,112,702,661,249,119,38,651,141,814,397,195,813,330,47,581,572,574,120,778,643,568,36,205,406,501,9,426,90,825,400,243,855,695,367,624,434,381,746,279,117,296,380,545,143,890,429,436,25,649,571,427,617,258,673,170,207,883,125,657,763,282,771,320,384,824,839,523,344,848,297,512,246,74,635,518,398,685,171,844,81,664,659,184,845,227,697,329,625,364,797,462,206,70,283,252,478,411,361,182,311,583,106,471,314,145,783,831,333,401,582,676,623,405,708,11,620,900,569,637,237,850
+662,438,37,776,877,542,761,205,44,536,155,587,709,400,260,61,823,754,404,813,881,87,152,43,584,190,333,799,671,261,789,345,161,666,132,464,72,874,495,399,488,522,105,91,597,146,88,714,518,716,461,796,483,296,126,663,524,306,326,840,567,427,214,9,291,443,583,864,808,337,595,248,3,22,873,31,198,103,592,696,425,32,618,90,774,167,655,553,327,33,527,608,148,263,353,560,815,196,2,144,669,544,247,308,735,451,97,887,742,215,267,651,17,690,508,174,283,851,358,692,528,35,804,6,276,391,634,449,450,74,593,503,649,885,437,675,378,471,822,367,446,230,112,490,718,481,7,849,502,890,591,145,325,180,525,4,644,27,381,781,629,491,872,802,638,834,489,363,540,202,160,122,138,626,289,582,123,13,698,18,809,855,142,779,376,185,130,520,736,243,620,603,673,1,777,350,746,411,150,55,439,826,704,406,880,577,186,870,109,886,448,125,435,389,665,460,100,191,432,65,499,820,415,25,86,445,42,492,766,657,454,535,420,773,705,516,255,572,342,720,812,493,624,413,203,743,819,747,764,171,285,770,226,513,312,694,526,
 635,762,258,114,440,408,589,509,599,302,349,118,795,137,183,307,452,92,140,798,344,38,613,39,107,860,162,510,472,730,99,21,811,833,654,861,64,884,177,487,36,836,612,869,284,825,254,228,578,5,707,45,110,817,545,98,209,722,711,606,233,853,83,689,504,792,731,426,623,895,129,806,405,835,800,559,767,372,713,187,165,293,269,434,827,511,51,785,153,444,382,758,334,700,322,428,699,295,865,898,693,867,268,748,120,580,676,667,436,505,421,610,648,573,227,151,821,858,843,84,515,52,661,252,259,637,682,73,771,53,633,879,220,390,846,219,485,383,242,538,579,213,725,519,290,235,270,782,650,854,468,462,447,176,47,374,77,141,601,837,484,76,469,622,356,341,95,878,680,757,640,370,656,501,124,892,658,780,719,319,615,740,430,419,697,688,281,568,839,569,57,551,563,195,237,672,550,212,292,674,847,359,365,614,473,234,831,275,500,173,786,882,871,828,82,134,628,423,201,486,379,188,422,710,271,801,210,384,417,54,594,239,249,299,845,402,549,852,199,364,830,576,807,179,62,414,768,564,265,824,790,678,788,24
 6,279,29,684,888,388,34,380,733,737,539,301,357,26,317,158,543,23,765,352,387,257,751,523,332,723,477,729,272,677,506,418,104,78,135,330,681,670,163,749,143,60,56,361,321,724,324,274,373,588,787,894,517,565,476,331,530,323,121,328,555,412,891,664,395,178,455,416,546,616,842,46,16,351,514,85,643,206,750,354,93,343,192,598,168,40,217,753,175,775,783,250,659,642,94,297,803,625,862,401,619,470,441,340,631,480,81,703,453,695,300,838,231,512,371,19,497,211,166,701,641,653,79,113,715,876,532,407,75,397,347,646,223,287,732,816,208,245,755,59,398,48,63,866,280,50,602,712,355,218,262,797,900,784,548,313,863,868,316,320,533,310,496,170,11,189,585,507,586,101,844,621,68,856,108,251,339,424,14,431,128,571,537,256,632,111,115,197,475,605,727,309,286,15,596,396,875,474,311,394,687,236,590,829,752,133,429,805,554,369,531,726,346,136,561,127,119,147,685,89,116,102,679,181,760,630,305,636,238,224,204,106,24,617,264,647,348,581,482,154,131,769,232,556,744,459,12,457,791,49,558,706,303,896,739,
 304,225,70,897,465,66,241,759,164,841,810,69,58,139,377,318,728,71,207,410,222,360,686,607,157,889,182,149,778,282,498,253,552,386,240,194,294,392,832,702,393,221,639,159,814,899,463,288,244,184,335,734,627,273,278,541,756,20,857,298,574,668,611,529,570,645,409,708,67,229,818,366,604,521,534,763,28,721,717,772,458,683,883,117,609,156,193,738,338,466,741,375,660,478,277,547,80,652,314,336,557,362,30,566,850,10,41,96,8,691,216,793,266,479,456,169,172,329,575,600,859,385,562,200,433,442,467,368,494,848,893,794,315,403,745
+357,623,218,30,465,370,64,141,391,102,827,687,197,642,496,241,397,77,834,136,146,227,701,358,793,423,310,1,588,85,247,184,144,34,474,865,201,589,542,255,304,408,711,665,38,162,164,537,61,166,431,143,703,850,728,156,46,88,677,810,818,668,544,514,841,805,165,45,178,452,219,618,483,602,71,364,390,372,211,256,863,438,22,714,538,607,508,318,691,229,382,828,176,702,641,276,453,128,375,673,16,250,157,414,120,817,689,83,491,368,613,571,584,243,825,678,115,194,216,110,617,629,23,363,400,137,224,597,204,459,437,93,882,68,56,355,782,461,605,191,53,546,683,696,134,147,345,70,742,708,686,770,265,470,284,429,792,448,49,59,775,393,659,309,857,142,109,874,121,177,783,278,610,800,347,620,735,324,239,490,894,628,290,334,753,779,616,856,199,651,421,655,151,435,895,105,72,732,169,576,580,170,331,281,635,106,485,163,336,80,96,154,487,868,506,570,297,585,404,270,213,516,837,308,231,352,365,569,637,19,809,279,839,223,273,890,343,829,860,486,603,579,117,258,360,139,174,455,403,493,113,57,339,737,60
 ,450,248,497,869,632,346,458,468,553,873,855,541,773,186,135,794,646,859,37,676,464,510,261,530,118,337,762,112,554,237,131,815,238,401,307,520,203,104,441,601,495,627,289,4,36,512,108,900,74,764,492,502,208,705,446,442,277,305,796,62,389,752,466,540,378,814,150,55,189,43,551,700,275,6,524,179,532,342,236,212,245,802,460,862,849,821,175,785,314,566,812,385,801,79,371,47,388,767,888,621,424,731,14,519,626,763,624,411,625,344,315,185,329,581,631,323,684,210,772,419,526,698,835,326,454,287,575,692,17,180,230,694,482,286,527,457,572,663,99,190,842,880,784,545,35,205,755,706,795,354,12,484,302,513,434,606,679,872,443,155,225,664,430,578,161,133,528,647,716,574,394,8,222,847,69,667,292,168,171,611,52,704,565,481,188,215,84,745,123,788,899,518,407,101,563,498,777,582,594,587,422,51,196,428,592,550,31,138,11,682,871,195,15,539,26,149,187,747,845,803,612,348,695,335,366,717,719,295,333,298,447,661,718,311,325,819,398,769,864,586,590,831,153,449,511,226,249,198,463,889,564,897,119,111
 ,301,473,396,562,619,771,383,462,377,420,116,387,789,489,272,547,425,715,559,833,662,471,356,412,246,721,86,881,5,811,65,269,376,557,406,359,63,707,883,367,710,167,321,214,699,206,268,173,445,536,866,670,750,830,878,733,353,300,152,729,433,262,760,130,870,341,369,680,807,846,427,114,660,327,776,418,477,893,127,27,671,158,774,633,415,826,374,577,100,181,42,3,697,145,40,432,669,132,573,417,399,202,274,823,634,884,877,361,291,746,48,652,21,436,858,200,558,501,734,797,183,836,768,472,666,875,535,29,791,681,232,478,749,832,630,476,7,499,515,228,244,743,410,712,654,693,267,92,622,744,220,786,90,738,294,820,504,78,598,853,799,653,379,736,709,413,838,221,103,604,568,790,20,548,643,402,505,500,317,439,252,656,24,259,688,340,614,521,766,148,282,126,271,804,330,891,73,556,781,636,107,898,806,140,2,879,217,350,351,657,751,727,552,66,757,525,595,260,824,9,644,531,638,18,822,50,713,488,58,467,395,844,756,615,730,328,234,362,207,741,517,725,235,240,648,233,854,469,843,33,257,475,193,280,77
 8,10,867,780,322,754,861,722,600,674,494,787,263,560,306,373,851,97,266,549,534,852,209,650,13,264,332,724,480,759,440,75,288,591,28,543,320,740,720,658,426,885,808,599,409,182,690,758,509,349,98,380,798,125,761,640,254,293,253,567,39,533,848,896,122,596,503,739,386,82,523,726,25,639,159,41,723,32,392,384,95,76,192,876,87,672,381,312,765,479,507,416,94,816,303,886,91,124,338,67,840,81,316,160,251,319,593,522,609,242,405,608,283,555,748,313,285,649,456,645,892,451,44,299,561,89,172,685,444,54,887,583,129,813,296,675,529
+294,546,113,73,452,589,90,66,362,239,772,466,461,824,679,92,250,248,766,331,527,261,502,390,621,540,61,149,825,18,523,199,6,187,605,818,145,474,787,115,129,203,590,512,233,19,28,323,10,346,168,450,608,809,731,416,84,173,528,688,745,545,394,366,768,632,224,227,352,709,49,381,341,572,333,335,516,108,119,586,838,439,158,660,377,535,778,451,729,76,356,711,110,760,430,60,303,20,215,630,51,74,64,670,429,641,580,438,783,581,657,391,533,81,782,673,208,244,21,426,432,614,176,185,464,31,380,780,96,567,255,54,876,383,138,180,724,741,443,23,171,716,721,820,308,4,264,384,832,612,826,786,355,602,571,301,894,483,42,344,889,672,539,402,828,514,32,870,7,214,789,392,684,891,95,851,569,288,79,324,892,488,287,151,548,652,691,798,134,570,284,793,24,367,897,130,82,619,53,365,804,319,268,573,541,175,669,334,98,401,170,125,299,871,459,487,121,322,453,316,193,338,700,273,78,251,397,484,869,204,854,456,702,560,596,874,363,855,821,272,481,790,69,399,314,421,468,240,719,666,1,337,202,792,56,263,361,791
 ,827,662,472,282,655,329,815,844,485,654,27,370,771,658,796,26,687,186,389,221,503,70,99,752,359,696,40,140,678,269,270,304,431,296,471,493,582,671,388,290,283,15,425,178,900,50,661,770,413,150,634,249,285,192,101,765,52,242,578,498,518,343,732,211,328,534,97,537,622,410,112,761,448,349,437,585,427,470,668,258,845,831,726,449,836,326,400,706,267,754,63,135,103,281,822,888,378,436,722,58,463,497,886,501,373,495,132,201,62,111,393,859,318,509,16,642,317,376,704,858,117,229,482,306,486,104,34,617,542,500,357,423,320,407,593,271,454,803,883,600,418,165,315,718,781,784,398,86,354,153,740,218,690,555,830,490,191,195,536,222,643,386,311,245,810,694,475,172,142,88,835,297,849,408,609,278,566,286,811,321,265,339,29,184,550,3,880,898,302,293,342,521,252,685,428,848,526,403,55,385,701,575,800,47,231,188,797,799,25,206,455,414,310,83,624,794,705,743,647,473,467,644,520,597,167,107,549,579,651,623,405,551,682,440,588,877,462,606,867,353,213,375,382,38,124,257,875,305,899,336,147,295,476,
 639,374,576,674,663,348,522,372,434,659,823,728,198,511,276,561,395,751,708,358,499,736,156,843,256,868,157,753,137,496,492,371,220,179,77,861,857,564,562,13,114,127,749,33,615,300,313,607,865,627,710,841,853,631,109,163,350,720,618,406,592,489,864,100,517,491,686,785,230,159,591,152,807,616,254,893,155,120,829,91,847,557,212,795,237,404,161,39,223,146,744,22,162,210,543,274,763,351,695,174,45,775,613,879,840,340,559,525,260,598,241,513,833,30,479,737,610,755,196,764,862,360,480,878,565,46,748,650,531,415,872,834,788,292,154,226,253,85,243,529,291,664,515,698,219,9,505,544,11,611,144,689,595,707,636,368,563,839,757,860,232,603,774,228,814,460,48,816,665,645,160,554,506,530,638,583,238,347,105,625,128,189,758,131,458,558,697,412,169,93,538,842,177,881,35,445,801,646,2,896,742,71,262,850,216,629,259,856,667,747,532,106,779,379,446,309,739,87,675,637,424,67,693,166,494,676,17,246,547,813,681,508,887,182,298,102,209,519,235,759,275,41,444,75,808,417,802,279,164,717,43,236,699,20
 5,852,776,94,733,777,626,746,599,649,713,141,422,123,469,750,183,89,628,574,873,190,756,65,325,277,633,656,725,247,80,57,653,116,730,148,680,819,837,396,882,762,409,703,8,640,692,524,577,139,594,734,36,885,419,133,126,207,411,234,735,817,895,369,457,769,635,181,136,584,805,225,727,14,197,507,200,345,307,59,68,12,846,552,604,712,327,587,280,738,683,122,648,510,866,118,5,289,266,767,194,364,387,143,620,504,477,556,44,330,863,478,447,553,217,601,435,332,812,884,714,312,433,806,37,442,723,715,72,890,420,465,677,568,441,773
+159,425,373,379,317,672,431,396,494,564,556,12,790,859,780,319,31,535,549,519,832,536,160,567,190,589,30,602,894,342,813,548,228,662,759,362,459,65,863,155,84,17,398,277,713,268,280,76,327,719,4,671,221,465,725,682,521,573,304,276,550,143,137,322,517,209,588,629,472,851,71,85,324,518,724,504,569,93,183,774,578,464,639,474,144,306,887,698,776,288,445,179,444,721,134,79,20,310,271,403,441,194,279,826,723,148,308,794,891,798,540,153,488,68,645,511,563,467,75,756,34,559,528,259,626,208,701,830,336,699,166,300,427,753,553,32,604,858,89,199,631,812,694,809,532,130,386,663,856,196,875,737,486,673,749,331,886,576,434,691,881,855,104,328,595,740,332,603,161,484,709,614,678,873,26,896,242,453,74,247,606,69,400,43,118,302,763,483,192,257,57,853,156,404,609,554,409,402,278,195,880,646,351,791,39,593,792,625,158,758,610,490,45,624,169,393,301,56,592,586,287,7,198,443,226,350,508,385,900,679,742,738,211,836,844,468,387,818,545,2,187,838,366,539,477,806,801,8,879,803,202,696,168,823,458,11
 3,476,866,432,534,613,224,727,94,312,669,460,408,256,580,650,524,412,383,615,50,36,289,523,372,141,666,732,793,112,382,262,574,337,401,255,407,715,527,129,804,22,520,743,333,216,551,664,420,320,861,375,368,487,241,61,365,231,689,376,40,46,617,131,361,249,423,775,778,541,263,201,692,533,874,773,59,416,768,695,762,284,232,557,651,293,612,835,566,3,371,309,642,354,123,406,338,729,705,37,163,210,456,265,330,899,345,205,54,18,339,292,152,150,898,285,240,116,251,151,80,641,800,238,51,764,52,78,572,274,816,295,281,442,229,122,24,482,710,788,530,577,171,348,526,659,452,779,608,252,515,98,286,870,16,687,315,461,616,542,254,172,14,711,769,716,29,867,656,119,9,583,99,544,658,885,684,787,440,136,647,814,41,6,718,140,596,81,234,841,712,121,264,717,233,128,347,42,890,313,298,417,447,854,547,847,451,634,570,839,325,162,677,142,752,439,374,394,307,463,828,824,86,599,843,95,239,175,77,745,741,571,418,529,797,244,215,102,600,125,649,777,501,1,25,704,165,261,15,435,28,761,734,370,213,355,807,2
 25,188,258,825,380,730,132,733,845,739,862,415,500,303,266,245,204,746,353,591,884,197,857,683,582,635,457,436,648,681,138,147,135,450,892,428,772,33,200,250,410,653,106,786,594,329,513,714,193,170,784,497,220,107,120,728,693,686,507,260,805,466,19,637,164,235,321,13,429,481,248,697,811,108,654,509,561,864,411,810,290,109,668,253,270,531,297,560,627,675,139,543,90,343,426,869,236,852,275,38,437,584,455,377,395,820,72,726,514,703,473,618,103,359,871,390,652,299,503,878,388,176,685,191,448,446,525,822,246,889,688,842,5,621,64,27,126,499,115,364,568,47,707,469,212,269,82,88,174,496,305,834,218,781,620,114,670,478,895,124,146,789,219,619,640,367,883,751,206,636,491,10,720,676,522,413,399,294,565,579,389,817,105,173,638,414,747,316,363,795,771,272,454,323,91,796,667,214,630,597,230,708,438,422,802,237,893,510,766,223,506,750,73,314,607,495,502,690,755,157,489,334,605,23,757,318,66,744,581,538,335,897,154,356,49,492,58,70,760,282,185,101,92,381,479,421,644,340,799,111,480,283,643,
 562,748,117,207,349,391,833,133,765,177,182,344,203,657,326,623,63,702,475,706,512,731,485,369,311,243,785,537,11,433,67,585,598,850,291,424,829,876,110,449,655,97,872,149,180,267,587,736,558,782,601,184,877,55,217,83,178,296,660,840,611,575,674,273,848,397,35,384,622,819,680,665,127,661,60,552,471,100,346,357,87,462,808,505,837,430,189,62,860,815,341,222,767,493,546,167,352,722,516,632,358,735,392,846,44,470,405,145,419,888,700,48,186,181,827,96,360,849,590,868,628,555,865,378,783,754,831,498,633,21,770,227,821,53,882
+835,188,205,768,740,692,586,247,66,622,300,717,227,283,325,193,862,792,165,848,497,264,378,72,498,449,651,711,21,349,251,185,367,408,38,619,172,870,375,715,753,760,143,237,399,307,306,684,514,291,659,818,771,467,45,705,382,380,258,658,191,739,625,164,194,436,268,675,860,120,743,434,174,117,627,77,465,360,780,712,216,270,454,345,671,568,40,133,9,249,235,794,183,400,396,611,871,316,219,488,591,490,561,275,725,547,429,609,60,80,560,541,124,800,122,470,392,647,621,654,774,138,801,218,59,655,208,457,331,67,494,698,755,670,496,820,90,330,756,415,369,229,238,557,785,617,195,836,1,825,2,176,597,361,579,152,455,96,377,750,481,53,834,881,236,827,416,391,676,427,259,296,318,528,615,50,319,158,802,324,421,822,478,823,495,506,28,273,832,626,819,8,706,134,815,253,580,210,469,267,95,463,435,379,894,303,179,635,297,650,263,202,745,484,846,220,186,493,114,137,744,857,578,215,439,266,260,248,30,486,573,126,544,224,145,512,599,32,232,808,686,461,464,623,109,289,344,804,107,129,501,737,633,12,3
 53,616,720,531,441,559,321,354,549,558,642,160,125,199,290,826,262,479,365,533,277,450,879,691,62,443,323,198,530,153,572,687,535,118,130,550,674,797,847,313,897,140,644,161,652,620,763,395,831,327,567,468,204,472,170,213,803,328,241,58,601,841,787,49,893,438,844,700,417,713,381,828,856,127,723,104,384,778,764,775,466,217,446,245,359,147,704,852,6,91,858,374,293,79,634,398,746,221,571,239,581,892,900,640,722,201,10,150,816,843,789,287,409,424,510,35,798,286,487,636,796,809,211,47,212,679,82,480,614,520,305,736,261,829,708,629,734,851,98,255,231,412,639,517,163,732,180,587,302,476,876,600,817,340,27,731,357,308,351,31,269,790,719,752,71,181,254,548,46,63,840,761,699,795,562,662,17,84,887,777,884,707,355,645,786,151,492,386,672,402,534,393,515,433,521,814,334,566,838,228,604,681,536,883,116,97,552,445,240,791,39,503,526,554,839,833,869,203,168,799,196,64,459,509,413,68,661,638,730,605,444,42,222,265,519,88,574,890,690,688,779,22,406,868,749,878,159,338,701,811,613,584,326,372,
 781,874,618,276,282,854,782,358,101,55,867,718,52,403,108,146,112,178,366,299,873,14,225,507,85,762,182,364,284,595,543,742,656,69,516,475,563,460,5,423,94,864,452,209,167,575,646,726,482,200,677,141,885,898,51,332,759,425,776,272,43,529,729,337,606,793,695,376,419,702,735,805,689,110,315,527,48,473,309,368,546,184,246,370,583,553,121,387,234,477,274,773,630,442,727,682,485,206,849,16,738,214,788,668,697,70,728,555,405,155,585,373,105,590,565,175,667,285,25,169,73,821,278,4,103,342,230,896,462,685,298,244,716,3,304,136,837,657,418,594,733,250,500,113,100,845,19,119,669,474,637,502,539,577,866,192,765,11,865,895,132,593,78,703,767,166,311,280,696,401,13,74,709,508,339,882,54,448,643,226,102,336,56,537,317,7,603,504,20,513,432,394,556,256,343,312,665,588,853,18,33,524,678,92,748,724,453,414,428,680,23,139,41,872,456,135,810,173,87,207,653,44,34,352,569,362,489,714,407,589,648,26,281,106,252,295,663,812,523,294,612,410,123,861,346,540,766,673,83,694,754,347,598,751,156,830,660,
 356,29,426,899,389,310,65,877,233,891,741,131,420,37,404,257,769,89,545,505,148,525,602,784,551,807,187,390,824,431,592,532,397,15,242,522,279,149,886,806,81,610,61,458,888,875,115,383,292,157,93,747,511,596,649,770,850,189,641,162,177,631,632,350,491,320,721,783,243,197,570,576,693,388,607,757,75,855,582,666,664,385,859,76,538,483,447,710,128,471,813,430,154,411,271,628,422,333,190,288,772,335,171,86,889,99,301,451,111,518,322,880,371,758,363,499,142,223,341,36,842,608,440,329,314,24,437,348,542,863,683,624,144,564,57
+509,312,226,131,140,716,5,86,311,354,823,510,144,832,738,155,293,345,657,446,110,358,551,366,534,671,229,122,614,66,151,98,97,79,535,863,214,321,810,341,338,378,554,513,185,89,145,235,24,83,271,532,767,853,689,514,43,252,401,468,578,707,599,425,727,587,54,19,484,640,189,414,435,595,28,323,642,225,315,653,779,568,129,761,209,701,560,166,572,208,138,814,128,836,376,103,360,71,327,763,53,42,261,686,488,643,703,58,505,497,788,238,574,203,616,789,296,14,170,458,596,646,224,302,259,205,117,834,29,543,158,221,888,34,228,324,573,755,288,36,180,742,778,870,441,84,385,416,661,342,623,809,542,696,638,369,891,504,73,379,887,464,340,565,683,561,16,878,95,352,829,481,768,895,277,730,602,364,199,492,807,325,485,217,544,766,629,706,299,724,478,563,63,436,899,96,1,454,242,428,739,27,64,604,567,44,682,18,165,33,91,171,503,882,634,265,149,437,204,331,415,363,752,390,287,118,517,255,644,148,881,184,731,195,268,874,570,688,784,310,245,833,8,559,194,136,105,275,361,647,94,371,442,597,106,164,549,
 820,681,791,569,174,760,254,847,708,286,540,101,475,819,781,806,112,765,304,506,452,460,9,250,792,30,713,70,319,522,247,295,39,176,479,494,610,673,666,421,347,125,65,188,279,900,108,782,804,523,17,675,239,212,55,152,698,10,418,677,300,633,550,843,383,92,598,126,722,349,373,82,695,75,249,620,651,518,134,747,227,860,795,830,547,670,314,477,774,135,615,7,146,215,157,875,802,483,564,793,74,175,353,719,427,592,635,253,87,22,107,257,720,548,445,183,420,160,241,759,718,193,201,333,357,396,51,162,660,605,684,37,624,555,348,461,154,362,850,893,516,292,244,116,827,825,855,575,120,220,72,588,406,776,639,822,398,267,410,307,404,631,222,109,301,737,655,273,233,163,246,877,344,729,332,618,443,711,318,845,289,282,172,56,26,462,52,884,848,219,508,377,704,263,801,594,813,700,612,13,500,619,329,840,69,240,190,735,797,213,67,236,343,429,150,583,869,571,705,692,463,591,489,408,740,77,322,611,305,725,386,566,447,771,585,693,892,258,451,879,465,320,476,334,186,339,270,880,444,852,57,303,472,649,6
 58,480,733,400,697,328,278,562,487,419,865,669,264,294,218,393,521,846,530,197,627,430,382,837,46,824,133,842,269,613,230,557,440,422,187,654,783,512,662,169,181,192,844,223,685,423,202,762,757,769,786,687,794,775,139,389,309,668,728,581,496,59,889,274,617,391,800,862,399,6,590,335,866,317,455,854,280,23,817,179,872,717,153,777,456,306,11,76,284,90,826,102,251,407,411,392,520,132,659,381,161,864,405,890,856,537,207,546,100,424,41,672,723,206,603,558,526,714,368,606,674,297,527,744,667,40,851,745,470,625,710,859,773,417,49,290,426,78,351,519,276,652,394,552,231,62,266,637,142,694,2,359,211,816,439,413,664,785,849,787,482,749,796,403,839,580,15,630,645,450,156,676,501,459,743,736,104,356,47,528,177,48,650,114,608,438,803,434,45,3,531,868,355,885,178,285,622,457,50,898,665,243,196,734,395,680,88,732,507,533,709,216,790,577,372,248,751,119,628,579,499,31,746,20,498,753,21,471,380,835,641,600,876,431,493,167,35,541,316,770,448,85,350,124,867,433,873,298,346,798,113,127,412,198,86
 1,702,291,805,754,715,699,741,691,818,68,384,336,313,756,159,147,626,721,883,130,838,60,538,502,337,678,812,283,200,115,780,99,593,123,799,841,808,536,896,621,589,432,143,772,409,260,636,191,586,609,80,886,556,370,326,367,469,25,726,679,897,449,272,811,397,387,281,656,821,32,828,81,168,486,256,330,495,4,12,137,748,529,524,758,525,648,210,690,750,262,632,173,858,141,61,491,111,712,182,576,388,237,365,584,490,663,234,374,871,539,582,545,453,607,553,232,815,857,467,308,601,831,121,402,515,764,93,894,375,38,511,474,466,473
+774,405,88,584,783,542,431,108,55,391,537,801,115,283,266,122,845,586,506,711,361,107,579,27,733,368,596,456,58,187,186,77,245,190,22,805,36,880,307,614,690,745,354,429,154,194,173,750,324,174,687,630,797,706,196,463,189,155,485,831,534,772,647,235,526,704,164,483,738,42,665,597,221,203,469,38,366,409,668,505,593,241,197,467,747,599,31,116,160,145,296,849,54,464,598,591,851,180,215,563,367,465,393,169,478,753,553,452,63,8,564,674,202,730,451,545,177,581,544,384,803,227,590,204,73,480,137,424,279,40,585,491,859,495,234,779,380,225,830,352,129,201,310,559,594,501,139,654,158,878,114,326,436,294,394,178,514,80,179,500,528,6,874,820,624,642,291,697,522,237,420,150,338,582,595,68,541,81,731,359,818,856,341,795,700,657,92,641,740,681,787,134,600,140,887,71,434,471,304,410,89,382,482,206,896,157,133,551,306,488,84,37,741,723,824,407,167,606,170,24,605,854,768,118,317,312,182,426,109,217,652,60,762,123,53,791,492,328,589,815,770,414,344,449,121,131,233,807,94,87,339,490,561,211,142,
 692,562,419,775,570,209,466,444,675,827,554,263,484,191,661,440,521,678,287,357,515,861,547,117,325,301,350,399,149,523,468,765,11,151,567,748,640,679,271,897,100,742,49,379,425,813,175,894,135,686,363,238,435,316,286,812,323,223,288,441,816,842,93,883,376,870,493,218,481,156,804,886,10,498,59,292,821,659,587,254,159,649,330,651,472,794,718,219,18,858,608,371,377,494,462,540,284,626,685,691,881,899,408,782,412,183,320,755,847,758,297,346,459,650,69,705,499,401,809,810,835,308,360,207,721,1,610,760,276,181,536,437,781,696,627,715,862,293,51,29,639,808,735,300,497,95,670,369,611,829,340,836,362,21,727,375,453,694,35,74,667,826,743,111,19,104,636,96,216,860,763,432,710,728,396,86,2,784,603,872,438,413,732,806,23,439,246,798,280,583,825,628,417,249,785,454,684,841,200,622,607,351,786,32,268,460,222,34,571,119,773,403,302,855,634,746,79,415,853,509,98,285,682,282,4,788,716,720,557,272,70,309,530,365,3,736,865,778,800,837,128,578,739,756,863,13,274,546,817,832,662,780,244,612,814,
 574,163,390,846,867,229,153,41,833,470,14,535,46,56,248,265,623,395,888,168,335,381,62,656,257,210,672,319,677,529,457,91,568,461,507,220,132,777,17,875,305,199,48,602,525,531,270,290,617,552,879,898,353,724,802,473,702,52,208,427,575,613,477,857,648,273,635,790,838,776,566,255,261,609,45,508,734,165,327,224,78,474,632,621,386,355,406,345,176,555,374,496,620,418,503,433,725,72,767,99,658,616,764,256,850,796,321,106,749,166,295,385,487,569,549,329,20,423,314,695,633,198,172,524,653,892,247,744,411,44,676,144,518,162,834,422,532,645,688,105,699,143,267,876,192,30,504,664,752,430,712,442,890,147,839,33,713,891,475,709,120,644,819,259,311,527,476,275,47,97,843,230,347,884,12,402,576,240,126,313,214,269,298,112,625,588,67,631,195,421,445,83,489,253,840,388,869,258,193,372,852,383,601,455,793,264,277,693,82,416,262,844,213,278,792,331,5,479,400,141,39,516,332,619,299,811,333,428,638,7,556,315,358,322,577,680,550,239,761,519,242,766,303,707,722,799,103,789,511,226,486,671,127,882,3
 73,655,236,404,900,726,458,85,873,185,895,719,252,349,16,717,43,729,113,510,683,50,520,364,660,448,864,136,539,828,212,580,513,171,25,251,618,337,188,866,877,392,669,28,336,885,893,232,250,76,57,398,637,543,703,517,708,771,289,446,124,565,848,389,548,397,592,698,604,228,281,343,573,572,146,757,538,64,823,450,512,560,759,689,260,378,348,646,754,75,342,643,701,125,751,65,502,334,130,533,61,663,110,66,9,889,152,387,356,101,443,161,868,615,673,184,629,231,243,737,26,666,447,370,148,90,205,318,138,769,871,558,822,15,714,102
+184,650,401,703,830,310,823,627,470,529,120,173,871,464,371,445,419,596,476,558,900,408,139,466,358,220,247,819,864,593,886,758,440,832,605,26,502,586,509,212,201,171,321,240,796,485,412,503,689,867,268,604,20,49,441,559,775,588,448,665,637,25,46,251,325,273,824,874,481,698,367,217,223,272,894,443,231,274,296,524,370,189,790,87,643,42,863,833,719,341,771,12,623,178,332,492,344,557,234,51,753,639,319,522,642,159,48,897,882,671,98,569,261,406,658,74,528,860,316,691,68,254,736,252,740,354,855,350,717,469,592,437,5,895,617,262,606,587,577,573,734,423,235,250,501,478,275,723,798,746,834,270,285,279,462,276,433,364,681,712,404,831,631,318,618,669,714,102,490,388,192,399,214,334,190,820,156,342,416,115,602,564,224,450,199,32,532,432,390,27,150,840,600,287,15,748,816,549,311,195,733,880,791,566,328,822,456,885,365,896,787,581,90,64,99,670,486,135,781,487,280,357,73,312,230,705,266,682,884,808,123,839,108,888,881,103,168,757,300,313,686,410,776,317,660,877,891,389,890,511,444,715,127
 ,793,654,589,305,530,580,85,320,575,293,451,40,633,645,459,465,567,163,86,132,614,166,182,233,207,411,773,228,216,892,435,537,398,518,591,351,837,768,352,718,202,260,496,222,407,865,657,769,536,21,615,22,516,180,806,188,403,571,754,426,458,784,232,56,699,211,142,8,397,876,619,710,71,759,597,817,724,893,544,204,562,483,870,53,427,111,330,6,561,780,500,242,66,666,601,792,460,609,640,130,608,122,298,255,752,795,473,872,381,125,76,329,704,706,543,519,851,186,323,288,656,726,611,213,711,372,468,739,208,369,815,373,625,140,106,869,50,79,439,514,810,744,63,31,347,512,663,825,36,267,75,248,741,649,688,812,138,205,93,174,551,513,286,659,152,414,818,847,259,687,387,693,368,767,340,37,655,794,628,755,417,92,685,290,376,374,813,535,841,361,531,278,661,505,109,664,57,335,24,101,692,45,97,789,495,722,696,434,709,647,782,620,157,284,856,732,821,538,499,308,1,506,565,526,241,297,803,420,19,728,151,461,807,177,676,271,707,30,282,39,28,668,634,161,547,226,258,632,294,281,418,43,117,684,879,46
 7,303,91,494,137,59,756,507,380,799,167,651,843,158,701,415,674,493,508,118,17,735,652,264,887,249,472,859,309,805,34,570,379,804,55,100,116,568,861,366,612,94,331,402,480,114,283,542,452,585,119,613,65,203,721,343,14,442,200,690,436,277,306,377,899,3,219,304,382,9,4,181,848,291,185,113,836,88,405,475,835,510,484,245,35,548,314,128,425,845,560,683,828,148,534,638,104,474,533,858,785,672,315,353,16,680,11,70,172,875,175,853,607,873,144,527,299,124,826,396,395,375,621,842,454,155,673,263,743,23,126,725,69,846,153,539,243,849,257,112,636,378,236,428,295,498,653,497,583,675,58,326,52,850,829,889,7,763,702,198,400,29,766,105,18,345,147,149,424,745,838,446,624,770,136,324,595,244,133,742,349,679,477,708,762,646,572,47,590,38,648,749,801,629,191,187,33,457,641,750,697,541,54,430,392,827,504,301,482,764,814,578,786,95,576,322,83,383,635,209,747,431,563,145,788,96,854,221,327,713,81,729,146,333,131,616,134,302,362,809,179,206,346,348,488,384,556,13,356,10,738,256,360,550,730,802,777,
 121,525,169,229,237,89,610,61,391,60,737,363,165,662,162,731,491,394,107,84,695,183,772,269,154,765,449,78,393,515,455,129,778,779,584,41,336,599,265,2,603,44,866,337,77,811,774,413,630,553,555,622,386,72,194,227,338,210,878,579,598,67,582,594,479,677,141,520,253,355,868,143,523,761,246,694,421,193,783,797,385,453,800,429,540,225,80,517,667,438,521,197,862,160,678,545,170,844,359,720,215,644,409,852,239,307,110,238,339,574,447,164,218,176,626,82,546,471,289,857,751,292,489,554,716,760,463,700,62,422,898,552,727,196,883
+629,173,309,829,649,766,747,424,205,788,151,180,752,672,612,248,598,851,58,870,883,466,5,297,67,517,320,866,713,480,779,491,365,799,406,149,381,573,768,499,481,383,16,2,812,345,344,308,611,740,238,882,374,140,215,843,689,673,52,291,133,296,247,51,21,15,619,858,860,664,507,34,78,134,876,236,531,109,637,859,40,283,802,193,372,278,733,525,299,252,360,265,412,476,48,392,563,408,118,266,759,404,508,688,869,25,141,892,762,543,459,241,126,574,165,340,662,756,396,863,289,175,867,125,336,546,645,711,426,359,275,684,302,889,730,504,127,771,394,385,729,560,333,694,839,487,229,895,444,538,540,292,646,519,809,96,780,259,615,880,772,669,495,828,122,896,526,162,551,582,303,518,418,746,260,710,1,277,581,110,167,453,477,554,23,119,314,38,724,264,479,502,593,160,429,577,725,82,448,12,687,783,470,753,661,666,534,837,154,885,644,450,330,237,569,192,207,53,370,405,659,506,37,322,335,312,357,211,770,830,524,595,19,822,773,75,514,298,29,398,391,750,602,704,269,818,833,425,778,503,449,878,387,366,6
 01,342,739,838,142,443,496,201,698,198,97,148,188,41,305,871,233,380,20,667,280,91,576,555,159,591,139,231,846,482,397,701,161,410,112,625,473,785,897,369,775,511,145,350,886,699,558,655,469,527,189,824,138,572,88,81,488,419,184,146,718,530,240,281,735,358,432,734,844,874,693,578,624,490,852,681,831,427,705,881,737,707,42,95,108,83,244,884,379,343,465,63,268,137,716,203,819,232,544,153,86,782,835,801,545,69,685,33,571,423,463,338,464,273,196,743,651,13,315,285,586,484,258,249,152,317,549,66,169,800,323,887,10,634,765,321,400,493,89,712,722,179,284,71,102,840,594,334,475,349,754,806,535,348,636,319,458,50,24,256,520,683,389,347,310,708,717,128,539,168,575,407,850,596,271,841,623,456,900,808,608,856,562,217,395,628,368,728,174,417,703,197,216,255,825,501,72,209,433,774,331,461,709,873,676,213,826,682,605,879,452,18,388,845,618,898,865,337,11,328,64,446,804,45,559,677,195,225,588,300,741,436,220,183,592,583,84,797,131,382,468,228,437,875,329,568,553,221,600,445,147,117,212,811,
 796,751,447,660,30,541,478,738,101,454,641,872,663,441,652,272,202,136,105,55,440,287,218,606,792,607,565,767,46,842,250,823,777,435,150,199,286,650,640,49,509,409,386,166,324,516,434,868,696,182,564,155,616,790,245,35,332,214,528,697,185,658,748,28,888,402,326,550,77,208,257,414,791,65,204,471,542,144,85,589,807,610,413,515,270,290,124,234,62,736,339,862,849,460,609,827,157,60,854,617,599,731,700,375,353,194,276,68,390,721,59,821,135,864,497,87,451,156,647,22,111,757,123,510,114,3,172,816,691,384,227,745,439,604,254,552,467,855,79,164,579,422,32,129,106,462,224,301,613,261,92,304,43,764,695,781,263,421,894,719,90,325,706,393,295,399,121,163,813,557,653,371,311,814,306,505,401,566,570,361,120,373,115,787,438,352,377,116,243,230,803,430,656,702,420,222,186,633,590,293,235,483,251,74,671,890,104,494,755,537,657,98,316,638,680,288,415,36,411,31,820,226,364,8,769,17,798,177,643,665,246,431,107,54,61,784,403,749,219,521,80,57,313,793,274,130,580,223,170,294,877,355,794,597,367,58
 5,853,103,206,200,832,9,94,489,536,512,614,626,47,267,351,7,635,532,327,442,376,416,587,795,726,428,513,529,253,474,620,354,485,744,548,242,262,522,639,714,362,143,176,715,341,642,678,318,670,603,556,100,675,776,99,472,500,723,27,861,627,113,191,834,178,817,187,346,815,356,455,848,567,533,763,93,857,190,621,686,742,457,76,899,73,836,492,14,363,654,761,810,6,648,44,584,523,378,786,26,668,692,732,279,720,630,132,181,282,171,847,631,561,4,547,789,39,158,622,56,679,893,690,805,486,758,307,760,632,239,498,891,210,674,70,727
+496,141,233,583,331,832,432,236,252,704,516,88,637,867,795,114,305,763,303,806,802,480,58,373,75,670,98,718,839,259,663,346,134,608,576,487,314,289,880,360,309,201,163,81,692,129,172,54,312,563,30,861,493,513,518,828,445,577,59,199,282,385,293,119,321,86,404,645,798,810,223,12,144,343,714,287,659,3,436,876,387,418,630,481,102,433,831,440,507,150,198,442,273,767,13,69,318,178,112,502,505,91,377,822,854,117,344,776,833,672,683,42,329,277,371,604,589,435,133,849,256,413,740,101,337,339,490,868,157,527,34,465,680,758,603,284,315,873,132,89,601,790,644,870,769,176,270,860,698,301,751,661,642,708,842,138,898,405,391,840,897,748,245,731,349,882,243,599,250,533,676,594,687,893,79,865,108,334,281,173,450,192,495,239,46,370,567,286,497,416,347,685,242,237,829,406,403,139,322,32,857,536,193,821,458,448,741,588,10,752,472,351,247,682,525,124,74,21,302,431,530,261,229,368,235,115,457,123,869,688,838,511,200,738,742,485,561,579,379,146,135,877,290,705,196,694,690,142,791,721,186,835,324,5
 78,400,62,702,892,294,674,612,25,824,16,411,407,161,156,103,827,606,620,361,420,586,11,396,489,280,285,35,587,666,728,76,573,130,388,106,311,187,697,878,522,654,730,29,389,792,409,248,565,864,354,422,887,265,262,353,15,171,165,28,451,393,342,266,323,615,419,602,627,722,874,508,611,348,548,652,841,657,136,699,883,755,574,291,14,529,471,492,858,636,383,283,362,78,365,380,9,616,83,830,491,47,623,784,545,254,72,853,93,519,384,182,122,159,22,27,871,585,36,110,160,240,179,575,558,33,45,596,6,40,566,166,890,153,626,441,392,364,231,191,595,727,562,720,63,77,710,446,614,782,691,650,591,216,96,777,167,717,244,386,363,477,526,151,181,553,634,564,5,801,437,269,121,711,338,656,780,834,499,899,712,568,794,836,23,126,531,68,484,70,147,886,556,17,307,772,554,2,474,352,888,473,501,399,807,809,238,891,438,539,760,744,299,197,684,298,879,775,213,168,592,209,719,863,19,649,761,66,395,219,158,803,467,498,162,633,667,328,673,228,762,183,359,812,811,118,376,582,60,454,152,551,48,593,617,624,597,54
 0,797,97,569,292,846,131,460,517,856,724,787,818,255,194,43,65,145,590,464,92,693,823,453,848,572,427,695,580,653,800,398,185,177,225,488,815,332,640,366,184,39,241,778,214,881,665,67,715,470,625,732,524,355,482,7,381,678,466,786,736,71,771,735,109,681,20,414,542,227,456,272,175,789,584,120,504,510,546,852,308,837,425,31,494,260,26,449,127,765,686,745,276,689,95,90,756,734,258,847,544,87,651,275,675,417,452,646,53,655,211,701,618,378,217,310,773,140,421,605,263,754,116,52,444,707,426,658,500,783,475,820,668,814,264,671,1,73,215,428,38,104,382,220,410,267,295,100,154,64,202,469,424,713,459,538,855,607,463,631,875,335,402,726,128,557,804,274,816,613,174,660,503,317,523,753,703,170,169,107,296,629,189,621,61,212,372,515,781,143,327,766,788,206,598,412,279,535,367,188,747,345,443,813,313,479,844,204,851,218,476,619,532,643,356,55,394,350,600,483,571,44,512,278,547,80,805,340,180,514,509,320,224,896,326,662,8,306,56,4,647,639,37,18,226,560,268,622,808,336,872,251,221,369,743,528,
 521,99,785,257,358,749,552,729,648,253,94,208,401,246,506,203,559,609,774,300,817,543,664,429,297,737,581,190,468,49,700,555,733,57,537,826,859,541,725,375,205,770,125,638,415,288,768,486,709,330,333,895,105,374,325,520,111,669,819,357,679,799,51,885,155,195,635,570,779,677,793,207,632,41,746,234,455,341,397,164,319,894,230,884,534,149,82,825,862,610,113,549,447,439,210,408,628,304,550,641,723,232,750,461,271,390,137,222,900,696,430,50,434,845,84,85,850,478,757,843,716,889,316,764,462,866,423,706,249,759,148,739,24,796
+795,133,165,465,365,786,170,48,105,527,690,656,18,672,608,78,696,652,388,763,96,316,485,160,482,647,462,390,191,118,13,10,175,122,222,842,115,689,709,603,639,653,320,362,233,109,174,428,176,16,469,760,847,802,359,661,94,304,266,491,297,816,694,274,470,500,12,221,799,373,492,422,293,356,177,130,635,272,651,759,522,459,215,657,384,726,157,1,168,190,28,869,41,761,368,312,739,90,269,729,265,161,438,513,659,628,658,167,106,238,788,327,345,561,289,750,353,183,415,573,770,423,555,251,21,451,3,768,42,275,247,481,891,208,349,678,254,610,509,136,226,543,599,833,706,326,287,722,232,596,186,593,638,609,673,246,844,281,135,615,846,120,634,841,412,785,88,805,369,424,670,411,648,865,475,347,473,248,557,440,633,614,532,576,516,731,292,471,685,775,754,124,357,267,897,45,163,253,385,342,429,51,93,520,863,27,463,158,166,188,40,95,714,836,837,113,54,480,11,193,662,721,734,299,404,43,417,117,212,249,860,5,699,29,34,818,663,276,544,627,408,767,84,660,22,36,32,580,46,409,260,601,602,164,141,339,71
 6,780,521,791,484,162,747,366,831,398,59,308,101,751,664,745,688,278,612,401,823,640,203,77,280,583,92,467,258,550,468,83,150,139,334,727,776,511,888,425,539,237,303,307,433,340,900,129,781,738,391,85,457,145,512,38,98,361,205,743,815,33,877,551,885,597,107,715,184,856,650,195,372,402,35,517,797,800,514,6,687,149,755,519,852,809,241,140,784,681,67,279,223,210,507,50,850,530,566,867,898,306,381,207,250,235,806,832,579,37,79,178,321,311,771,332,338,461,455,533,563,317,127,410,108,430,489,187,196,774,452,845,255,718,733,698,192,68,252,783,879,487,125,523,4,825,703,814,838,319,525,58,214,643,677,531,684,119,245,700,476,655,358,60,24,427,394,350,589,534,420,595,849,528,330,128,858,704,876,540,742,447,574,26,197,47,545,154,855,665,296,526,450,839,261,798,821,591,746,725,144,824,343,75,811,180,179,510,396,720,386,204,567,671,778,81,352,883,324,395,645,478,558,189,501,787,354,508,575,23,538,227,600,199,764,868,762,882,494,114,826,796,598,810,200,242,584,586,861,542,631,39,625,812,72
 8,499,406,872,556,585,148,15,827,654,66,803,379,143,57,86,322,437,892,131,65,644,70,666,620,44,630,315,819,554,708,7,590,497,537,300,211,642,263,851,305,111,89,828,456,782,477,72,813,431,884,896,291,604,848,229,675,262,335,719,736,389,152,893,506,562,378,830,874,695,231,336,348,829,25,503,667,328,153,592,142,793,744,284,490,466,206,71,56,582,290,772,419,474,483,239,741,91,377,445,682,414,870,104,886,817,529,9,578,100,147,202,713,432,460,486,169,295,405,711,375,217,102,442,444,887,159,857,613,325,766,256,735,498,730,268,346,547,393,298,493,99,403,686,173,82,333,282,710,301,692,137,637,19,864,64,748,881,488,835,449,668,834,565,387,691,701,69,224,370,536,277,581,808,181,702,789,20,182,52,216,329,31,273,294,622,116,779,436,76,138,397,773,363,875,400,636,225,110,234,889,355,559,443,577,441,621,286,331,240,132,873,318,535,794,219,55,524,344,313,257,439,220,632,97,641,679,236,619,62,676,371,453,737,607,752,309,14,594,380,496,790,121,421,454,862,218,871,571,383,801,434,8,611,413,749
 ,341,399,899,623,587,382,878,505,895,367,198,426,53,649,103,479,376,724,854,17,807,270,757,588,541,464,732,626,302,314,765,156,213,49,777,697,548,843,894,285,669,74,283,890,683,30,570,185,374,288,416,853,629,568,646,740,323,201,472,392,880,572,230,756,264,624,605,495,618,171,822,360,228,552,546,134,804,172,243,407,569,792,244,723,560,606,435,418,705,616,553,2,758,112,310,504,73,446,151,769,351,146,80,859,271,549,364,209,820,448,840,458,707,502,564,63,617,712,87,680,674,753,155,337,123,693,126,866,717,194,518,259,515,61
+675,254,338,852,781,676,808,490,203,762,32,323,755,439,436,317,745,851,48,868,885,422,55,263,185,415,456,879,562,552,776,535,465,798,303,77,381,747,576,568,573,500,30,38,785,433,405,494,699,761,395,867,361,42,95,807,731,643,146,449,160,324,282,71,9,98,665,882,858,489,641,153,90,66,887,227,437,241,692,803,14,231,792,103,545,246,590,554,225,309,461,279,452,304,176,543,712,492,154,186,802,550,551,514,846,105,101,895,666,429,342,406,70,706,138,233,618,836,521,838,376,78,878,169,345,613,669,512,536,264,445,727,194,896,730,627,117,589,579,515,728,378,175,480,833,614,223,889,310,719,402,120,583,391,716,118,523,191,656,869,525,541,685,828,126,884,636,22,679,540,124,451,272,496,390,511,27,260,711,125,161,629,446,717,123,85,187,51,782,250,572,403,729,131,267,598,795,151,493,64,473,825,603,633,766,707,373,870,271,891,661,467,413,72,594,302,301,164,410,357,680,681,69,297,379,424,299,321,621,816,336,582,57,789,742,16,488,206,4,558,561,555,701,630,327,796,835,591,718,353,546,865,417,290,6
 23,524,700,697,205,334,401,347,547,371,68,110,252,89,393,861,80,265,3,713,150,218,688,569,114,690,228,83,866,322,549,709,281,386,149,746,644,772,893,286,820,363,295,318,886,765,743,622,291,578,137,652,108,698,31,180,684,533,285,46,794,647,333,294,780,330,404,733,850,840,704,566,769,421,873,486,839,605,664,847,651,720,39,213,13,7,199,877,262,311,599,24,392,104,797,358,829,343,356,92,204,823,854,826,722,147,506,76,588,502,604,463,586,428,366,539,653,91,414,448,751,678,122,152,235,499,485,195,332,812,380,853,20,606,842,325,444,677,112,702,637,49,132,196,181,841,607,239,283,189,777,809,726,484,482,431,307,41,2,226,509,710,557,466,184,667,737,284,344,60,750,574,857,693,130,824,411,394,900,787,635,845,351,389,571,597,517,771,337,527,458,167,382,268,770,510,198,145,522,559,298,441,775,876,508,258,648,724,570,883,274,35,464,856,768,898,871,385,23,280,96,276,670,171,471,537,369,207,749,384,615,409,107,273,516,477,79,814,182,216,655,190,224,874,481,691,495,313,619,610,52,238,148,821,8
 00,790,396,498,62,556,650,577,127,432,687,849,560,249,472,287,261,234,240,73,443,237,331,505,715,649,339,793,6,848,141,815,705,438,177,257,341,663,478,65,398,503,462,248,348,364,528,819,631,278,470,86,620,817,162,29,335,370,601,626,74,518,714,121,892,288,460,447,212,193,208,532,844,37,243,296,501,200,25,567,834,372,435,305,242,469,19,253,159,791,430,863,862,300,734,811,230,134,860,504,752,565,740,526,251,221,166,33,340,703,179,806,163,880,418,58,553,109,507,53,34,786,170,377,157,50,142,837,744,275,113,634,434,420,84,350,596,872,217,270,739,383,144,173,40,638,168,312,725,416,165,425,75,831,813,763,269,349,890,773,15,211,479,440,320,209,158,28,753,657,491,236,483,799,222,668,315,423,474,459,129,497,88,783,544,219,538,140,197,139,741,564,759,580,214,247,81,673,756,215,220,593,93,36,738,888,155,475,617,708,455,128,277,632,674,119,487,99,387,1,832,116,256,61,804,11,827,328,476,754,329,368,12,21,44,530,450,757,375,608,210,178,143,805,400,292,735,136,135,192,875,355,642,736,427,748
 ,855,10,94,289,843,26,43,326,575,365,624,764,87,314,319,18,612,695,201,354,172,457,399,818,723,412,696,374,133,640,616,519,360,758,407,352,174,316,397,778,259,102,232,611,442,658,801,362,531,584,419,82,774,529,188,513,592,779,47,881,426,106,54,788,308,639,293,453,822,244,255,864,408,682,760,245,859,183,686,767,810,581,100,899,59,721,454,45,542,468,609,830,56,645,5,585,662,346,784,17,646,671,660,306,625,732,97,111,367,156,694,520,659,63,587,672,115,229,388,8,563,894,602,600,534,689,266,595,654,67,683,897,359,548,202,628
+815,255,94,615,720,668,399,82,23,489,518,772,97,416,387,77,836,688,375,795,342,184,488,27,612,465,558,517,66,189,139,39,229,224,31,802,46,862,464,632,711,752,269,324,237,170,179,665,316,146,607,761,823,698,180,592,207,245,345,760,370,798,655,197,419,580,112,470,814,145,649,490,201,199,450,28,466,318,716,662,482,290,268,485,648,625,50,42,80,138,190,858,37,547,471,507,853,163,198,584,392,371,427,301,610,692,541,437,58,45,634,539,196,732,312,583,279,491,512,519,804,240,666,183,8,503,79,548,211,72,456,531,872,480,320,789,253,384,779,294,210,308,376,680,705,472,162,770,107,842,73,367,532,410,528,147,653,99,205,618,669,14,846,860,474,777,265,689,504,321,452,247,422,717,554,132,448,105,734,348,740,830,423,784,591,646,93,509,781,710,806,68,555,125,890,74,393,319,352,314,192,313,361,347,892,131,238,481,239,462,88,54,759,745,845,256,95,526,62,48,671,849,750,165,351,208,248,280,110,295,749,26,718,111,52,774,561,228,486,792,691,545,297,559,34,134,217,783,69,176,331,602,574,113,181,572,6
 61,568,675,639,304,330,567,553,811,409,136,346,158,771,458,576,606,332,408,442,871,596,70,287,277,377,356,235,446,542,664,11,91,451,638,738,791,335,897,200,677,86,440,436,762,271,895,161,697,524,244,339,302,203,780,231,159,230,413,820,834,16,889,429,880,571,254,630,212,839,866,41,530,166,264,776,758,744,389,104,603,225,624,404,810,808,149,24,856,565,252,258,453,357,588,182,721,546,619,886,899,434,714,275,152,221,800,855,755,204,283,355,520,119,769,378,372,724,768,794,350,261,143,621,6,508,678,309,187,696,374,832,599,654,746,851,193,87,117,640,827,620,194,575,51,725,457,656,859,405,797,262,40,722,460,420,614,13,142,736,763,747,144,44,96,540,151,191,835,739,499,726,767,502,114,10,865,700,882,549,506,643,778,18,364,220,742,263,709,754,494,433,382,824,338,703,847,336,660,663,333,844,122,135,616,260,98,641,157,735,403,343,831,756,816,65,306,870,366,153,454,570,396,32,719,733,642,536,412,12,341,365,469,33,729,884,775,833,787,47,637,817,743,868,56,250,585,788,821,597,693,223,683,84
 0,629,289,325,867,825,379,85,4,852,601,9,594,148,53,123,160,467,353,888,76,218,484,57,707,354,202,573,402,712,598,582,17,544,459,515,293,103,701,63,874,315,128,43,695,523,687,380,188,708,418,885,898,251,604,822,369,737,154,177,537,682,468,447,876,609,383,500,801,843,786,510,213,274,684,7,483,647,249,334,327,100,563,658,497,329,381,278,307,127,644,421,569,587,498,476,296,796,38,706,233,723,556,807,133,864,782,397,61,681,206,185,395,566,431,534,340,30,298,266,764,475,129,84,439,505,894,270,790,425,173,730,116,533,257,829,445,432,595,627,172,586,71,234,854,106,19,487,516,731,386,672,398,873,108,841,5,799,893,390,757,215,673,828,317,303,513,600,242,60,140,785,311,411,878,15,496,667,137,81,226,126,344,214,92,522,562,25,650,323,305,388,209,550,273,838,424,848,168,90,349,863,286,635,538,702,337,426,581,118,276,150,869,291,310,809,227,3,415,444,124,55,435,360,552,299,773,463,407,626,2,521,259,328,477,589,765,455,169,704,430,281,819,243,579,685,813,75,818,611,282,631,636,49,861,461,6
 23,195,373,900,633,449,141,881,288,896,651,171,368,1,628,89,699,155,577,741,20,622,400,751,501,826,241,560,805,285,492,593,219,35,164,645,441,292,877,883,267,657,29,322,891,879,109,385,130,156,272,608,679,659,551,728,812,246,443,236,417,850,511,391,543,428,694,676,300,363,362,674,529,222,690,613,36,837,406,478,525,652,803,178,535,438,578,686,186,493,713,590,59,715,101,473,401,167,414,115,753,232,67,22,887,121,394,359,78,605,284,875,495,727,326,564,120,358,670,21,766,557,527,174,216,102,479,175,793,857,514,748,83,617,64
+614,241,371,841,728,701,804,528,264,786,55,219,790,518,505,347,632,846,56,858,886,483,47,325,104,445,395,879,653,590,801,594,467,820,374,38,430,613,656,536,519,405,53,49,816,442,419,380,712,787,316,870,289,36,171,828,762,705,124,310,147,250,245,114,20,51,700,880,845,592,596,107,139,135,885,290,470,231,659,827,17,278,815,131,436,233,691,606,281,341,439,176,496,330,133,492,599,516,204,205,805,522,567,603,852,43,102,896,747,524,344,322,138,637,148,246,679,811,476,849,288,151,875,216,386,616,713,568,545,336,369,734,108,895,768,549,137,682,440,501,773,450,242,511,831,600,273,887,362,576,471,188,615,434,763,172,586,269,698,877,583,639,539,794,94,884,650,26,649,601,183,517,311,537,340,612,28,312,644,158,72,494,466,625,66,68,271,37,756,221,477,463,689,201,166,660,795,142,507,75,573,821,585,727,629,746,451,859,262,892,726,525,339,70,523,283,314,120,422,413,662,548,27,348,388,408,346,296,717,840,332,643,22,818,785,3,489,237,11,432,437,620,708,669,351,830,842,481,779,427,553,874,391,32
 4,673,417,718,758,109,327,459,306,597,295,24,99,261,78,406,856,123,276,5,740,210,193,575,564,191,699,236,145,869,394,510,731,184,449,206,721,556,777,893,326,739,433,209,373,890,772,630,685,174,622,112,733,165,683,71,200,569,530,297,97,791,559,222,333,692,343,299,744,862,848,750,495,640,508,872,589,843,490,655,850,722,760,31,217,21,34,143,871,305,372,468,30,366,122,792,317,819,334,359,64,146,767,775,826,623,152,580,95,540,377,527,438,591,382,291,646,626,74,399,321,663,555,187,195,256,398,571,157,232,829,404,861,41,563,812,293,378,538,141,764,735,61,92,113,203,844,664,227,331,211,741,822,610,453,578,352,345,60,2,292,574,684,415,370,266,743,776,225,418,130,627,469,864,642,110,839,509,473,900,789,529,851,397,298,443,675,482,793,223,533,485,81,309,272,802,425,182,121,402,658,277,410,783,857,608,270,710,751,638,883,350,7,444,867,667,898,855,414,42,190,88,356,738,105,521,641,255,170,680,349,690,460,167,235,552,570,48,770,103,175,532,252,249,865,376,579,577,318,617,506,18,178,87,834
 ,799,755,383,588,86,457,502,657,186,493,611,854,647,279,572,337,274,243,179,96,304,287,308,543,780,619,403,806,8,853,134,814,742,479,169,248,319,706,554,23,491,355,458,267,396,363,504,837,694,282,461,84,515,716,199,12,253,328,561,719,149,562,732,79,894,208,384,499,156,125,126,428,833,77,265,302,566,194,13,621,838,447,480,342,224,387,62,263,160,798,441,866,868,320,695,823,215,129,847,582,674,661,724,462,212,244,91,9,361,757,98,835,192,882,421,58,526,154,602,65,73,778,128,424,207,50,106,771,765,240,164,736,393,497,115,420,488,876,181,220,676,431,80,226,89,487,229,360,704,338,93,400,45,817,715,797,173,409,888,670,40,198,581,390,234,284,189,52,781,671,584,307,335,825,258,513,385,464,472,456,196,484,144,803,551,294,474,118,268,140,782,544,753,668,254,275,33,687,628,257,259,605,39,63,723,889,69,514,696,635,547,136,303,560,729,197,389,111,452,19,836,202,329,59,813,14,832,218,534,754,280,429,32,57,76,618,407,748,323,631,116,159,228,784,392,214,665,85,213,150,878,381,693,678,454,604,
 863,16,163,285,759,10,67,401,446,423,478,720,117,315,379,6,688,624,286,357,180,503,416,824,711,411,558,448,162,531,666,455,368,788,500,353,177,365,486,702,161,119,185,707,426,541,686,367,607,651,512,100,752,593,132,498,546,745,83,881,520,90,15,807,260,714,238,375,810,300,313,873,412,636,796,153,860,251,609,769,800,550,44,899,101,774,475,35,435,565,681,809,29,697,1,652,634,364,808,25,725,654,737,354,730,598,168,155,358,230,761,595,542,46,557,749,82,247,465,4,648,891,633,677,587,766,301,672,703,54,535,897,239,645,127,709
+112,681,222,15,549,381,190,203,485,123,757,458,562,764,600,239,197,75,834,98,603,280,541,476,693,421,70,116,858,85,641,366,59,271,653,771,265,461,709,38,50,142,674,579,260,114,90,429,63,489,235,204,456,774,777,236,182,172,647,759,832,411,311,460,819,694,384,306,101,711,24,466,422,599,412,445,375,241,16,371,866,407,194,619,492,430,828,594,812,169,544,615,261,686,538,156,231,113,310,540,64,234,25,605,242,665,527,502,839,610,532,516,571,43,853,574,181,374,23,282,338,631,54,297,601,1,530,685,292,589,413,3,804,438,110,99,805,671,505,137,205,672,690,712,104,20,324,157,870,659,867,773,213,509,386,394,851,520,107,175,831,731,561,134,876,256,149,847,4,158,754,346,623,835,106,855,608,349,42,350,898,508,198,152,593,607,738,849,18,446,154,856,47,436,879,269,187,730,39,457,795,474,448,470,392,330,636,451,253,472,307,243,214,829,248,634,315,370,613,372,48,302,695,316,74,450,368,632,886,216,753,580,713,645,678,860,230,884,846,270,569,692,212,233,496,522,560,266,790,658,10,176,118,857,120,3
 82,170,676,869,537,385,453,511,455,781,882,630,748,136,131,749,556,796,28,649,278,244,87,581,215,193,743,475,677,141,41,751,369,400,473,552,89,211,428,351,655,426,347,272,11,517,160,893,117,583,669,439,333,656,415,335,378,267,821,124,132,484,628,291,285,587,68,402,332,146,325,651,452,91,760,557,405,226,352,322,591,648,431,826,850,633,179,878,418,312,696,463,830,151,317,13,477,722,897,390,199,490,55,555,624,895,614,184,339,119,388,227,295,518,871,128,602,37,726,389,423,687,883,294,336,542,379,550,166,95,396,576,273,480,319,196,377,708,363,447,762,837,670,567,53,479,618,728,714,150,67,403,359,785,174,616,551,838,577,232,44,621,167,667,465,437,343,822,744,500,206,83,14,765,165,859,483,320,81,344,139,741,410,298,471,135,327,596,65,797,899,442,254,255,326,393,611,300,799,398,252,145,111,705,703,679,86,299,80,814,806,21,251,487,217,76,207,700,691,789,755,529,531,355,689,584,498,284,84,420,698,639,740,287,578,643,188,534,798,523,715,811,102,200,250,414,109,33,286,844,328,900,468,22
 ,82,323,570,425,362,737,568,482,644,173,247,735,750,736,309,650,449,668,417,620,792,539,361,800,40,810,373,880,147,684,31,308,629,337,209,138,69,885,874,573,424,27,296,259,638,8,397,210,499,434,891,404,497,881,872,493,277,52,356,768,478,195,688,553,775,93,409,582,597,704,162,281,654,202,720,725,263,896,155,218,791,178,780,441,357,818,238,547,318,183,73,159,657,17,71,229,662,60,836,459,660,35,78,675,734,823,820,289,663,554,340,721,314,364,873,6,462,788,707,801,34,842,889,513,526,894,304,100,640,622,504,264,888,794,772,219,192,341,268,144,279,585,440,710,514,786,348,9,627,512,49,588,288,733,702,604,727,127,334,863,664,854,140,481,756,290,793,258,177,848,683,723,164,486,416,586,524,408,443,467,305,716,108,376,807,274,406,652,625,329,365,228,495,787,220,845,5,454,861,752,29,892,803,2,180,877,168,510,387,865,763,841,313,94,782,245,565,427,770,57,724,680,488,105,706,293,501,563,58,208,637,802,742,519,852,97,88,224,383,546,345,758,62,186,536,96,739,503,719,121,171,559,51,435,747,13
 0,833,827,125,515,808,612,761,395,609,525,246,548,129,566,778,275,103,642,433,817,360,646,77,122,185,697,626,666,249,72,153,533,191,784,354,595,766,813,189,809,840,353,769,32,419,729,673,464,201,575,816,36,824,401,56,46,45,491,321,718,868,887,223,592,661,746,126,19,543,779,303,598,30,225,545,66,469,133,163,143,12,875,301,699,572,240,590,367,732,558,7,701,635,864,221,26,237,358,825,257,161,342,262,682,331,535,521,61,432,776,391,283,617,79,506,444,507,767,890,783,115,276,717,92,399,815,606,148,862,380,528,745,564,494,843
+773,19,285,785,373,848,561,286,151,797,312,288,438,726,700,199,647,865,17,882,686,491,125,240,77,689,396,804,402,375,412,276,325,626,297,395,306,529,801,660,640,531,45,65,705,270,321,234,482,417,291,890,669,359,190,863,508,649,12,148,3,574,480,121,55,73,331,713,881,578,570,114,162,200,712,197,694,163,742,878,61,397,688,389,230,541,440,229,110,262,117,568,275,671,69,320,661,310,198,509,677,252,604,706,875,156,349,732,430,429,697,141,196,627,11,579,665,494,442,861,511,245,854,188,135,620,319,795,232,317,159,720,629,744,714,641,14,781,296,267,645,624,457,809,866,464,280,893,211,363,251,381,755,666,838,155,833,266,492,873,839,403,394,871,8,897,361,337,548,648,435,584,572,835,365,530,104,292,633,260,62,379,625,576,115,354,243,23,782,545,675,212,525,204,746,392,540,1,519,96,593,469,221,768,754,401,564,590,139,728,427,346,542,476,775,35,137,192,119,344,765,586,231,358,432,122,441,41,444,730,752,282,185,502,465,253,708,84,85,455,224,812,378,790,105,550,535,445,406,493,419,870,565,11
 6,490,228,821,864,44,687,601,91,800,157,332,20,37,5,242,883,376,610,181,616,431,194,729,719,129,371,215,336,617,506,308,758,78,295,112,314,247,842,898,501,862,518,225,335,806,643,353,655,771,436,451,841,239,318,206,63,415,201,138,101,557,691,467,103,846,536,741,789,673,879,589,792,446,400,783,581,513,348,826,891,767,347,250,58,284,128,552,894,147,272,608,259,102,26,553,146,799,81,757,47,236,857,888,718,311,10,329,27,763,667,537,152,278,182,113,515,791,34,362,145,423,390,370,80,134,257,380,158,166,662,315,892,140,805,486,569,634,512,16,522,632,387,583,88,28,829,303,619,618,597,852,733,425,174,399,479,628,226,154,175,498,779,233,504,300,497,447,186,422,165,454,416,808,681,554,837,407,334,900,845,796,851,703,217,404,374,274,470,183,333,813,74,144,426,794,753,83,478,657,750,595,692,533,889,575,36,859,563,507,856,356,161,452,725,471,896,880,264,42,658,2,384,815,123,684,481,179,495,420,437,778,176,341,18,721,449,324,867,351,683,330,86,646,885,421,711,468,249,717,453,377,263,72,527
 ,820,834,682,690,167,780,273,764,93,208,788,876,368,651,562,246,40,56,38,216,743,95,59,737,458,738,611,516,99,770,523,814,832,172,339,366,462,637,309,71,433,639,405,133,254,747,520,884,740,54,769,39,818,874,66,68,642,169,696,630,153,774,830,32,709,727,414,674,67,496,573,567,580,106,304,710,238,305,98,603,631,638,352,693,534,202,177,382,31,475,235,860,766,672,591,802,298,7,872,281,372,699,786,385,664,33,598,269,544,360,180,635,15,734,702,22,538,294,393,13,108,822,6,218,64,109,24,877,556,680,388,679,685,299,413,555,605,751,142,307,485,443,107,89,164,424,75,227,558,100,293,323,248,549,461,408,571,210,895,840,97,615,594,602,588,456,244,301,847,369,383,342,189,731,473,609,290,724,759,150,130,203,57,736,214,222,265,327,131,484,772,219,428,678,599,322,448,654,503,90,60,411,521,50,735,855,52,600,793,326,450,4,70,816,659,340,650,30,268,136,749,205,279,124,653,187,582,256,748,546,434,241,255,87,213,787,587,831,220,261,195,149,345,849,209,120,547,514,173,606,868,439,853,559,168,355,810
 ,277,143,313,886,92,271,410,776,592,823,466,49,391,207,126,487,524,328,670,622,237,756,698,825,614,316,566,474,510,607,302,707,612,343,118,526,644,621,817,695,29,386,398,357,827,472,76,739,517,543,21,623,843,283,636,656,798,111,715,613,9,418,836,53,844,25,505,824,463,539,704,760,500,676,178,850,160,761,489,577,477,48,899,46,858,652,191,287,596,811,819,94,289,193,460,483,528,585,43,551,807,701,258,459,762,170,338,364,184,869,668,745,79,723,777,223,51,663,132,367,887,784,828,409,716,82,803,499,488,532,722,127,560,171,350
+762,168,142,433,363,782,145,22,108,498,715,640,21,717,631,57,664,622,428,743,127,304,476,169,491,642,423,359,270,81,30,3,121,105,245,849,93,676,735,568,597,615,336,368,214,68,133,410,129,15,446,746,841,815,404,650,71,282,277,523,351,809,674,263,511,519,5,202,773,409,458,413,288,373,178,135,629,237,607,756,582,456,192,670,371,725,231,6,230,158,28,864,23,777,362,273,716,58,246,737,225,123,401,543,652,637,662,182,191,253,793,316,361,514,346,758,328,172,367,573,752,440,530,223,26,412,4,795,20,299,222,445,891,209,321,641,300,647,501,95,198,586,625,845,680,278,272,703,306,605,262,636,616,618,681,227,861,290,100,598,863,175,628,828,464,772,60,822,315,399,701,403,668,876,437,424,474,232,508,427,698,604,507,542,524,739,332,522,645,764,729,207,309,255,899,32,131,276,339,326,473,56,90,534,850,16,485,165,136,193,33,80,682,852,827,120,41,462,14,188,624,696,744,287,358,36,407,132,305,228,867,9,706,52,67,832,643,357,600,601,398,796,63,646,17,50,46,557,103,432,211,588,572,240,111,314,692,80
 3,576,798,475,157,755,345,842,452,89,340,66,734,691,753,718,234,634,366,807,606,212,54,243,620,101,495,215,517,488,83,147,134,324,705,761,515,884,454,528,220,297,258,425,312,900,98,784,763,379,69,467,137,489,29,77,411,170,719,808,49,873,537,885,570,110,707,156,846,653,201,335,444,48,496,776,800,510,12,688,141,788,579,848,801,313,149,760,694,65,327,180,176,471,45,855,603,545,851,897,268,375,213,348,238,789,823,541,27,55,153,311,392,747,334,292,470,443,516,590,390,99,380,122,408,481,163,161,771,460,837,244,700,710,679,219,70,251,805,882,493,130,487,1,824,728,818,826,285,503,51,266,608,689,535,720,140,217,667,472,619,381,82,19,402,447,385,585,494,387,554,856,504,405,146,854,675,871,531,770,435,549,24,160,35,552,106,868,738,286,499,448,834,239,802,806,654,741,709,112,812,382,107,819,148,171,482,441,745,333,185,559,665,751,59,377,883,364,430,658,465,555,229,500,778,323,469,587,43,564,248,591,221,769,853,757,888,492,155,838,767,569,794,199,195,548,561,870,529,714,42,594,791,722,53
 2,384,860,578,610,154,31,814,644,118,817,420,126,86,84,329,429,890,194,79,635,152,627,673,39,683,296,820,521,690,13,577,468,502,264,301,684,281,839,254,87,72,835,415,779,461,74,810,490,880,896,369,660,844,190,639,252,378,726,724,394,173,894,466,566,376,833,875,661,196,356,320,840,53,478,732,303,124,649,114,813,740,256,540,450,206,61,34,560,265,790,374,451,455,247,721,174,365,479,648,370,869,150,889,825,506,25,583,97,183,189,699,480,416,477,233,319,438,677,417,307,104,449,518,881,117,857,626,341,748,343,766,556,704,241,322,526,344,284,497,94,421,678,226,78,283,294,695,250,686,115,655,40,858,116,733,878,546,843,520,638,831,609,360,723,685,44,298,395,553,249,589,799,203,702,783,11,177,38,242,302,18,325,261,612,151,785,436,64,109,396,804,330,879,347,617,291,164,179,892,400,513,431,633,422,632,267,406,271,208,859,289,584,765,218,62,562,310,350,293,434,181,651,88,623,687,186,592,102,711,397,457,792,575,730,275,7,595,353,544,759,85,414,419,865,216,872,550,352,811,389,2,630,383,786,
 391,355,898,657,599,426,874,536,893,331,200,388,76,672,92,442,393,727,862,8,816,236,736,567,565,484,750,596,269,274,768,128,259,37,781,731,611,830,895,342,656,144,235,886,693,47,581,166,386,337,372,866,614,533,602,712,318,187,509,439,887,563,224,774,295,593,574,512,663,167,821,308,205,547,525,139,775,143,204,354,621,787,260,742,538,613,418,459,713,580,571,10,797,91,257,483,75,486,138,749,349,119,125,847,279,558,317,197,836,453,829,463,671,527,551,73,666,754,162,659,669,780,113,338,184,708,96,877,697,210,539,280,505,159
+742,207,136,368,347,766,111,16,132,455,744,655,22,725,638,61,643,572,474,702,113,285,506,185,535,640,394,297,298,62,26,2,116,79,267,856,99,665,733,538,570,600,365,388,184,63,122,406,105,9,431,710,841,827,435,612,49,248,311,558,393,806,670,289,566,561,1,165,737,410,419,421,301,387,141,161,623,242,568,732,641,451,158,687,362,727,257,10,277,156,44,866,23,785,372,259,698,48,254,746,186,124,359,543,607,671,678,151,212,266,787,327,370,477,398,769,296,150,336,528,752,456,463,222,51,361,4,791,21,308,225,390,892,177,283,622,342,646,508,92,173,589,652,847,635,246,274,659,344,618,305,667,592,621,654,243,865,300,78,549,863,197,639,811,523,736,42,842,280,360,730,379,675,875,418,442,511,232,476,429,756,608,484,517,553,758,353,582,606,772,711,247,278,275,899,17,106,318,309,343,493,43,101,510,845,8,496,133,148,162,18,69,674,861,821,176,54,468,33,193,593,686,775,284,331,53,397,180,332,191,869,12,739,55,77,850,628,404,658,590,403,786,45,619,32,39,37,545,128,438,187,536,554,293,91,315,664,792,
 633,795,467,181,750,349,852,507,126,374,64,694,721,765,753,202,656,354,789,579,241,38,244,653,81,513,204,472,537,93,169,131,330,672,719,514,880,453,539,217,238,216,415,281,900,80,798,760,382,65,504,167,478,29,89,450,129,696,808,85,858,527,884,530,83,676,121,840,660,206,282,447,40,498,759,768,483,11,720,170,810,631,853,764,356,160,751,724,90,373,149,190,423,67,855,673,560,837,897,218,364,250,386,273,770,820,518,35,47,159,325,414,723,358,268,505,422,509,615,444,118,366,137,413,502,119,144,747,481,826,221,699,701,668,264,57,237,814,886,532,179,440,3,829,740,828,812,233,497,59,291,594,705,559,763,175,203,630,485,610,400,74,13,401,461,417,577,482,335,515,860,457,428,152,831,634,862,471,783,436,542,25,143,20,573,95,867,797,294,495,399,825,258,807,800,663,743,700,87,779,384,163,817,112,154,426,464,782,307,142,552,602,713,58,408,885,402,445,645,488,540,234,526,784,303,454,563,72,587,292,567,219,788,838,773,887,494,200,849,731,557,778,199,194,512,551,876,534,777,27,544,762,712,521,39
 6,854,596,598,183,52,803,599,153,824,420,134,125,114,355,439,888,240,110,625,178,597,693,24,735,239,830,466,669,31,584,465,490,224,337,734,287,836,230,102,76,834,377,755,424,107,805,562,879,895,416,715,843,196,613,228,411,718,695,427,145,893,452,555,391,835,877,648,171,378,314,846,82,479,781,269,98,666,109,819,748,265,591,437,227,41,28,500,214,796,328,392,448,288,677,210,345,475,611,341,872,198,890,844,499,34,603,70,220,146,689,546,375,486,260,352,480,636,459,346,139,458,588,878,97,857,650,321,738,380,794,575,692,201,334,524,316,271,533,123,446,679,272,88,245,312,717,235,716,96,662,50,859,164,684,873,604,848,547,626,833,637,350,754,657,30,322,412,583,209,595,790,215,703,776,15,205,36,286,252,19,357,256,624,189,799,395,66,94,371,813,323,883,304,614,339,208,157,894,443,469,363,688,389,620,261,430,317,255,851,249,617,761,251,68,605,263,369,310,449,138,685,60,647,690,155,586,127,749,434,470,801,556,697,270,5,616,351,581,728,86,425,376,870,236,874,487,333,802,348,6,651,329,809,43
 3,340,898,704,627,441,871,541,891,306,226,367,104,714,75,409,405,722,868,7,816,195,709,550,578,492,767,585,231,262,771,103,290,46,793,745,632,815,896,385,661,168,211,882,708,84,564,135,381,383,324,864,629,501,576,681,338,147,525,491,889,516,253,774,326,574,519,522,683,120,823,279,174,569,462,166,757,115,172,319,682,741,302,729,520,642,407,460,706,529,609,14,818,71,223,473,56,548,117,726,320,130,140,839,295,571,299,213,832,432,822,489,649,503,565,108,680,804,188,601,644,780,100,313,229,707,73,881,691,182,580,276,531,192
+417,659,337,779,888,204,847,575,355,454,45,494,826,124,121,432,766,604,445,614,892,271,275,297,580,105,474,815,670,583,863,685,501,791,319,97,388,853,170,374,428,451,303,288,686,518,412,770,734,840,543,551,138,49,223,439,738,452,538,829,626,173,156,230,300,447,796,884,582,334,617,403,195,142,890,312,117,398,481,362,347,104,723,30,820,71,678,780,498,335,776,185,531,20,517,710,720,560,228,31,772,763,370,216,521,373,66,896,782,366,39,759,146,676,574,19,395,885,512,528,336,112,758,251,602,479,813,99,748,239,756,530,72,894,520,568,516,234,819,672,595,135,54,47,508,651,194,707,535,880,615,69,237,101,284,235,87,197,637,635,80,601,860,511,611,593,751,58,658,306,34,225,50,48,413,468,238,231,684,134,674,830,186,764,408,74,268,478,613,88,423,671,769,196,52,647,844,576,351,280,323,879,838,292,761,786,171,891,470,895,704,460,322,13,326,699,496,327,719,313,380,745,241,211,279,740,137,721,750,736,2,762,286,849,806,162,169,572,281,669,843,120,808,263,581,832,871,732,823,214,544,632,244,607,
 587,789,309,210,703,35,153,693,122,698,154,561,608,497,499,569,36,26,165,616,41,363,603,289,282,801,307,63,886,149,714,424,727,416,318,872,866,425,688,96,662,199,506,267,850,716,875,415,61,556,56,198,127,842,109,458,817,787,476,291,824,547,339,557,567,119,167,406,852,446,622,227,887,359,827,344,882,811,258,421,310,836,115,504,75,217,84,570,549,330,621,83,729,489,841,627,654,663,8,555,349,641,689,774,878,524,705,389,299,371,640,741,767,691,726,552,321,427,402,822,867,837,60,515,400,744,484,419,652,794,384,436,164,262,893,125,254,797,467,694,487,28,15,579,532,655,771,16,44,3,475,724,856,752,505,396,46,103,209,361,378,429,845,422,174,661,795,500,305,213,869,692,754,586,9,550,435,391,739,453,385,610,51,665,717,683,679,831,664,598,33,690,713,130,490,208,480,42,401,264,82,151,810,628,360,629,148,677,472,799,270,294,383,833,873,805,645,440,304,110,522,232,256,455,158,513,712,93,854,317,252,666,62,722,181,410,123,573,229,6,859,463,4,623,536,639,390,369,377,753,108,338,657,865,562,55
 3,111,212,183,277,877,218,325,649,437,526,660,7,328,315,620,525,653,140,250,533,687,147,802,405,126,835,298,775,14,597,276,701,150,187,226,502,673,495,316,438,397,426,394,18,443,365,343,612,91,509,331,644,537,393,132,619,411,461,248,118,296,514,899,53,469,139,577,114,94,492,876,207,206,5,708,202,387,376,834,143,407,23,76,746,161,145,503,858,564,680,816,17,730,596,236,523,633,702,874,308,457,600,27,591,65,155,128,821,430,807,541,870,102,483,477,90,565,399,246,529,656,650,409,269,634,624,725,25,38,431,166,606,21,179,590,851,434,320,812,257,442,386,163,818,473,382,715,800,260,482,180,868,898,857,141,540,733,592,283,10,358,266,184,92,178,55,340,765,571,190,825,696,59,747,341,86,98,737,285,735,364,631,788,356,768,129,392,24,433,803,839,345,12,193,95,510,862,554,545,636,77,346,542,809,642,247,233,861,466,539,648,314,491,100,332,414,450,160,743,222,287,265,792,136,848,546,113,778,259,486,79,242,116,176,273,404,578,804,448,381,107,548,589,630,783,57,243,32,700,220,152,760,668,889,73
 1,81,301,278,667,348,67,261,342,133,375,855,357,224,456,274,584,757,157,68,1,594,37,781,353,175,883,168,11,742,464,681,43,711,471,618,22,70,201,609,73,488,189,728,441,372,897,718,192,493,255,462,785,78,272,302,459,585,215,881,219,559,106,449,706,177,749,379,605,89,85,864,40,709,646,519,695,311,485,828,846,588,563,755,354,253,172,200,784,290,188,643,368,814,205,558,697,144,790,350,566,293,418,329,675,638,203,64,324,249,191,245,527,367,352,333,240,534,131,295,682,773,221,159,507,465,599,182,625,29,793,900,777,420,444,798
+45,632,316,126,436,495,302,329,560,306,694,183,714,838,687,304,30,217,774,198,745,413,377,580,517,501,16,320,893,211,758,515,133,483,737,611,395,185,804,39,9,14,616,493,511,189,181,229,169,636,81,361,256,657,796,406,355,367,559,599,777,206,161,433,743,528,542,453,167,823,4,279,408,608,583,539,461,154,22,550,808,456,422,579,317,336,881,681,841,233,573,354,391,693,375,98,29,213,305,475,223,199,109,724,439,449,420,656,886,731,531,352,592,2,828,552,364,426,11,505,113,635,208,287,662,49,649,748,331,673,301,87,637,607,315,3,781,794,270,152,428,755,704,735,232,48,378,327,882,438,888,779,300,600,566,405,874,598,276,380,861,843,310,111,829,429,235,773,42,308,750,496,650,854,33,891,476,440,5,295,857,246,266,28,389,469,792,762,18,312,24,878,65,473,769,443,286,647,123,353,867,589,437,634,104,502,726,553,209,619,498,392,64,753,105,596,339,194,653,537,101,66,487,402,122,455,454,590,899,447,732,698,522,789,814,739,248,879,780,62,396,770,291,333,558,691,711,73,870,751,86,386,94,869,299,238,
 247,785,765,529,520,368,603,272,605,847,622,665,200,257,723,545,677,168,641,141,34,125,613,297,159,730,614,756,112,144,597,534,419,458,416,156,382,489,100,747,187,467,514,128,348,344,818,277,445,775,442,362,623,369,134,412,263,810,224,7,193,672,75,296,349,177,617,533,345,178,417,610,259,850,683,182,231,521,508,713,510,366,738,815,446,289,880,551,59,586,432,809,221,216,139,460,700,873,180,51,171,218,414,563,900,565,102,107,8,410,254,212,358,896,116,484,60,562,226,201,679,875,280,151,682,207,323,363,174,588,491,158,466,205,96,124,668,581,642,674,727,478,544,219,612,540,757,658,83,252,196,347,860,36,639,464,728,643,400,67,409,27,718,646,615,153,868,744,258,53,293,1,669,376,889,624,471,176,120,346,782,197,88,631,129,485,350,136,830,887,294,225,479,170,285,482,77,872,313,202,268,149,822,688,764,264,499,253,855,645,63,468,265,424,143,318,627,481,715,827,671,324,465,817,351,335,175,50,587,759,633,661,372,719,459,68,290,701,309,733,801,186,40,35,601,132,84,82,709,135,894,626,115,43,
 282,699,341,150,555,703,504,725,52,444,842,740,840,398,638,431,547,343,338,825,524,448,876,46,852,575,821,373,593,157,434,702,204,142,106,243,897,767,706,131,95,292,370,625,17,574,379,477,423,862,166,164,871,791,288,179,20,577,778,571,274,557,678,621,13,535,418,394,518,15,337,630,210,689,807,147,859,325,387,848,314,800,334,220,798,214,470,435,250,244,371,655,31,251,127,594,140,877,326,795,72,26,561,721,667,664,321,784,322,572,680,516,381,831,10,430,864,628,787,76,763,895,532,383,866,97,271,541,602,686,165,898,766,844,23,384,192,108,99,403,385,462,685,222,803,457,71,513,269,57,390,388,546,813,374,802,267,90,833,582,890,80,245,799,240,742,401,275,885,741,527,393,509,117,690,595,421,492,494,319,707,328,427,845,155,260,696,543,554,360,284,660,788,230,710,114,203,863,771,103,824,772,41,407,776,273,648,303,892,716,846,138,283,797,74,519,576,697,236,746,752,342,278,584,452,227,651,146,92,729,736,708,463,884,78,130,118,490,298,195,793,70,184,340,47,591,556,585,330,242,652,38,525,568
 ,357,754,835,110,188,670,548,839,145,692,228,160,530,137,659,629,474,37,695,425,768,486,663,249,148,191,506,720,618,56,241,91,549,399,851,359,526,811,865,32,640,816,172,856,79,163,523,684,604,397,705,786,55,853,190,85,6,19,441,488,812,826,806,411,500,760,654,25,119,606,819,503,609,44,451,307,237,538,21,234,215,12,783,507,666,712,311,415,173,832,675,93,536,734,761,404,61,262,578,749,472,162,564,356,820,69,569,497,89,480,849,570,54,450,58,676,255,512,837,836,858,281,365,805,239,620,834,717,332,790,121,644,567,722,261,883
+631,610,14,673,884,324,703,190,65,305,296,754,612,244,116,90,837,579,627,685,840,12,387,21,779,93,418,678,571,225,734,312,173,496,101,641,31,887,265,374,490,597,303,294,369,164,79,804,439,633,603,620,553,453,217,404,390,139,566,879,747,521,309,74,522,680,507,810,693,182,595,474,37,54,836,27,96,252,508,424,652,7,402,154,833,242,524,516,415,24,606,721,132,213,588,625,835,202,23,212,527,604,177,131,478,683,216,849,648,108,232,782,48,694,681,206,117,839,389,413,638,57,679,26,330,331,570,260,466,34,709,381,763,847,245,704,569,238,856,411,254,114,110,341,515,476,3,732,518,896,556,185,194,84,266,32,445,10,276,572,432,368,890,756,792,671,448,532,501,83,211,25,100,444,388,414,362,2,700,56,873,876,78,803,628,353,146,749,674,336,642,594,664,9,821,261,692,622,109,227,272,796,766,161,885,460,81,852,249,850,333,72,510,503,658,616,174,398,483,13,386,843,647,1,76,541,5,649,690,435,391,454,659,676,584,727,170,667,587,791,854,284,591,241,286,624,769,805,687,86,273,557,250,585,222,788,348,365,
 853,237,28,598,231,743,708,764,442,586,153,634,224,183,552,321,105,318,820,271,89,573,98,166,811,91,582,313,838,51,64,828,858,486,751,22,878,87,675,4,729,485,880,123,848,168,366,306,18,725,130,277,844,592,200,370,660,748,738,308,842,53,762,337,669,450,263,596,897,43,714,246,798,845,407,536,157,654,392,350,469,447,555,686,580,20,824,349,561,567,720,494,542,446,357,819,502,841,892,549,877,470,730,322,531,753,718,509,528,537,760,506,456,458,207,868,864,861,106,646,126,774,148,463,789,534,55,520,226,576,872,269,419,863,408,328,171,382,640,777,393,535,443,342,175,301,740,459,867,548,345,539,120,163,621,97,40,488,869,578,58,300,491,547,267,187,888,768,583,618,461,401,406,61,832,464,790,480,233,761,802,315,473,615,813,293,410,883,713,70,285,546,397,363,741,317,256,262,600,778,198,504,359,346,102,719,247,745,179,656,889,785,744,66,358,728,645,155,243,617,69,264,823,384,829,283,159,423,88,757,115,129,500,817,599,605,874,298,361,731,668,831,62,103,323,816,733,438,875,717,529,755,228,1
 07,128,699,895,165,94,377,726,477,412,281,209,8,452,314,736,99,812,433,533,124,657,440,248,623,696,538,372,499,288,425,236,133,186,204,643,822,71,808,140,137,35,297,339,449,141,421,291,759,794,891,651,775,564,479,498,138,234,178,367,650,860,737,471,60,670,558,663,666,814,151,19,320,465,201,800,82,655,235,41,282,268,707,326,46,420,701,219,607,639,215,636,417,210,513,698,568,866,188,495,540,497,493,750,691,38,632,672,526,467,770,158,716,378,47,383,434,332,590,797,662,192,340,827,862,399,436,112,172,354,614,299,181,783,724,405,409,780,6,644,127,156,882,396,33,543,807,563,289,475,776,899,723,661,327,773,857,519,385,375,351,613,149,45,335,338,457,462,80,881,395,52,870,73,136,255,482,49,487,279,355,574,292,715,258,180,295,229,653,702,118,278,15,752,287,886,581,429,379,799,430,481,682,851,50,195,834,426,575,626,711,189,176,608,334,92,360,512,135,104,311,550,403,665,781,143,565,347,208,376,280,95,394,274,505,492,562,695,364,147,689,325,742,772,602,30,551,609,16,316,710,352,898,523,4
 89,343,122,894,705,167,169,786,68,846,826,218,67,144,635,199,765,44,162,437,223,259,545,441,125,893,77,230,815,150,593,203,373,302,356,270,220,257,825,784,577,371,511,196,818,900,554,111,119,63,544,706,427,451,251,530,712,113,801,152,758,795,344,688,304,787,468,559,29,184,739,275,589,310,735,601,39,722,677,746,455,830,793,290,319,85,422,806,191,239,619,637,611,697,160,517,42,484,560,193,416,142,11,400,855,36,75,121,17,431,59,809,514,428,205,380,329,214,771,472,767,221,307,134,197,525,240,253,629,865,871,859,145,630,684
+729,433,45,431,720,554,258,25,84,301,668,783,67,473,378,58,790,483,628,625,260,89,604,54,749,428,503,302,212,60,135,21,126,65,115,851,15,852,462,528,602,682,454,484,55,85,81,691,167,90,614,555,807,789,366,415,56,79,521,822,622,781,650,269,659,730,70,330,664,166,546,583,255,304,327,68,410,343,570,505,724,295,74,571,687,642,162,97,303,86,257,866,10,599,587,470,810,63,197,638,193,347,276,264,419,777,615,329,172,66,637,633,296,626,572,632,117,445,418,328,787,355,451,177,101,361,78,549,165,129,511,364,889,353,133,713,496,358,785,222,39,342,472,672,509,360,141,553,344,859,289,518,413,384,400,188,700,145,51,408,698,71,850,766,722,578,151,806,376,176,575,159,474,734,516,261,586,92,624,381,865,828,336,712,711,718,234,732,644,709,741,274,453,173,896,9,262,535,211,421,259,251,387,237,888,47,247,409,238,354,13,4,707,811,801,399,112,581,163,29,530,818,809,121,252,253,204,420,283,100,761,48,804,95,64,858,479,515,714,758,733,544,192,439,106,62,149,746,152,202,198,392,506,367,33,612,512,533
 ,821,649,239,416,517,629,861,680,280,560,88,573,594,606,768,150,497,476,836,486,180,179,254,529,256,284,395,375,782,5,148,460,683,566,596,333,891,219,715,59,225,249,754,109,900,30,737,487,294,306,450,272,747,232,161,469,267,757,840,128,872,382,879,405,111,459,44,798,871,26,334,207,199,763,634,565,241,110,719,313,769,645,823,654,407,27,832,697,315,507,331,386,393,243,731,796,670,854,898,227,728,440,391,380,723,833,673,218,210,371,613,265,657,540,279,803,735,779,464,547,155,646,14,574,743,125,91,531,508,767,576,630,674,834,379,7,32,751,867,745,325,372,38,739,539,716,778,187,774,266,139,669,498,536,784,98,34,580,795,684,236,2,31,584,285,369,824,686,275,592,808,300,286,17,736,527,863,341,563,681,748,3,311,120,791,146,725,876,567,404,184,776,432,742,813,383,653,590,185,721,147,314,577,83,11,422,310,827,288,160,815,526,663,24,502,878,593,263,365,676,318,61,771,740,598,488,305,122,452,558,373,37,780,841,800,860,794,213,727,661,699,837,19,183,456,755,873,641,862,134,494,753,579,248,
 412,843,857,322,168,72,793,411,73,671,182,43,273,233,631,423,892,293,319,403,138,568,468,93,786,174,756,401,458,104,569,447,467,118,324,839,76,868,194,142,20,692,414,537,215,270,656,695,874,897,538,805,812,388,623,35,368,489,542,647,362,886,562,321,639,817,864,726,406,370,229,717,107,499,829,102,171,430,23,648,666,543,552,356,402,195,75,438,206,617,475,291,478,477,627,190,694,203,564,501,819,338,885,849,345,96,750,57,377,220,520,689,435,397,132,500,490,595,706,390,181,556,760,883,103,802,513,80,665,359,679,346,788,244,492,610,551,87,708,143,396,853,323,22,351,640,762,312,744,282,881,130,855,123,609,884,651,773,337,597,820,446,316,677,455,131,208,230,830,114,441,870,69,480,603,169,157,205,320,137,201,281,522,607,144,710,164,308,297,124,660,226,880,240,835,429,292,217,893,525,482,317,842,216,348,582,277,495,385,825,116,471,764,374,6,616,228,278,158,545,170,703,156,797,444,250,601,52,696,461,442,550,519,608,463,136,759,493,424,705,196,678,585,846,153,844,394,186,561,541,77,877,
 235,772,417,339,899,792,557,242,869,299,895,589,298,309,46,775,1,618,231,559,799,16,635,191,600,434,848,245,655,765,113,465,588,50,154,175,688,532,389,838,894,523,667,105,223,882,887,246,307,18,140,514,491,701,693,449,619,704,349,290,268,675,890,326,534,504,620,636,485,335,481,189,662,426,49,752,398,99,770,287,350,427,816,611,363,457,352,690,685,214,443,524,738,108,831,8,357,340,36,658,12,621,94,40,42,875,209,466,271,127,591,178,847,652,605,224,643,221,437,826,119,548,448,510,41,82,332,436,28,856,845,425,814,53,702,200
+740,62,349,819,390,840,665,380,203,825,224,218,569,695,686,259,601,869,18,884,761,544,93,285,47,669,402,852,471,479,546,378,394,721,335,241,381,453,794,653,616,480,54,66,766,345,387,229,579,555,269,889,537,234,182,867,628,709,38,99,19,450,412,142,32,41,451,770,880,618,578,100,172,197,775,246,679,185,734,876,23,397,751,307,233,445,519,315,149,310,195,384,364,590,69,344,595,393,220,424,739,301,644,710,877,80,273,805,521,497,625,147,198,626,25,485,711,582,466,872,414,236,868,222,210,658,433,764,309,343,183,741,396,811,752,599,36,779,260,333,720,612,408,762,866,517,300,894,231,294,281,312,749,649,845,177,795,283,600,882,800,495,327,863,6,896,464,206,589,683,353,621,523,786,354,558,75,331,635,250,1,313,633,557,74,253,255,4,778,431,617,248,574,225,513,512,638,26,566,98,606,587,276,787,673,533,570,680,178,796,556,446,462,297,717,83,204,159,200,423,758,511,131,401,460,192,454,87,502,791,662,389,92,632,584,117,689,89,35,400,212,798,482,793,186,671,659,411,522,510,490,881,539,151,593,
 242,818,859,11,609,610,134,780,153,181,17,91,21,306,886,291,526,84,691,367,191,660,706,158,477,238,275,714,505,348,769,49,372,160,379,258,846,897,486,814,530,175,391,860,703,346,707,540,543,322,837,243,410,168,107,404,267,199,94,656,643,329,169,799,514,585,806,750,883,682,735,368,483,832,608,645,311,810,890,784,474,164,102,171,76,375,893,157,334,515,173,161,40,641,179,828,150,681,9,190,826,857,765,303,50,350,55,724,551,506,226,360,223,125,549,767,42,405,112,427,356,320,71,184,254,475,140,129,737,373,891,111,760,550,491,565,441,52,646,701,263,365,57,70,856,425,489,552,468,831,783,409,239,467,426,572,176,64,221,577,768,208,449,296,613,576,170,438,156,413,399,850,678,371,861,439,421,900,849,729,865,651,193,363,496,326,596,128,422,754,2,154,416,829,687,106,347,554,743,507,648,640,888,622,88,847,666,604,871,355,60,484,792,436,898,878,339,43,457,16,388,823,95,685,561,135,369,455,428,789,244,292,45,713,525,213,844,245,492,293,133,518,887,377,642,548,286,716,420,207,230,5,657,833,81
 7,634,698,155,702,227,763,139,270,745,879,459,541,594,295,96,116,46,196,571,137,121,725,559,726,567,647,31,824,374,839,838,249,282,341,440,697,336,10,488,493,465,188,325,675,534,885,755,113,728,22,738,820,68,15,499,201,676,700,152,748,830,27,773,531,415,674,65,337,376,508,668,115,318,605,314,271,20,664,719,603,443,607,435,216,130,370,63,592,308,870,821,586,627,836,277,37,873,338,386,718,781,406,504,77,362,138,527,481,120,731,58,804,672,14,547,268,456,30,97,822,12,240,119,90,8,848,661,536,321,732,624,319,302,535,532,813,144,264,520,498,73,145,148,342,105,289,623,118,211,357,163,652,385,538,398,256,895,774,59,469,597,553,442,417,252,214,853,478,434,351,141,788,432,494,340,692,727,232,165,266,86,782,279,235,284,261,174,361,809,278,528,712,487,332,247,699,448,109,104,500,274,48,742,874,7,629,802,358,472,29,108,757,715,288,563,61,352,85,803,205,299,103,733,114,690,194,730,631,382,298,167,78,180,759,560,827,237,359,132,146,305,843,257,101,562,328,202,429,875,473,842,588,251,280,85
 4,162,136,316,851,28,219,430,684,580,723,503,82,407,262,53,598,529,330,614,458,323,705,756,815,591,265,575,366,461,677,324,650,704,395,189,419,581,602,771,470,39,304,501,418,747,383,143,736,615,573,33,667,807,228,630,637,790,123,776,620,13,215,855,81,835,44,463,841,444,476,772,708,545,744,122,864,209,722,583,663,509,3,899,67,858,655,126,272,619,812,834,51,403,72,568,542,524,694,24,654,797,746,317,564,688,187,290,392,217,862,693,670,56,696,801,166,110,636,34,452,892,777,816,516,753,124,808,611,287,447,785,79,639,127,437
+693,10,330,678,185,862,428,270,218,788,469,205,446,828,784,194,450,837,82,863,601,542,134,339,25,737,315,733,573,341,411,271,285,559,453,480,349,305,864,578,515,414,108,98,673,241,316,100,381,393,191,882,647,484,353,858,455,637,5,33,29,540,472,175,156,55,301,567,860,702,426,76,221,322,585,264,735,118,642,886,165,494,635,505,81,582,593,242,236,283,70,544,288,770,21,192,465,269,232,599,560,153,552,789,871,144,436,623,549,563,748,26,309,459,75,665,660,332,345,859,437,387,809,222,178,517,317,854,167,463,46,634,674,626,675,479,78,849,143,183,625,743,620,865,843,340,355,880,370,172,421,574,760,740,853,209,890,390,451,861,888,527,204,841,53,896,281,493,407,648,618,644,689,887,292,694,152,376,461,323,91,197,639,380,86,438,409,65,676,565,554,337,365,278,801,384,395,8,485,115,732,368,114,816,583,371,691,424,95,603,422,379,460,629,713,9,125,163,131,442,709,386,254,445,431,62,522,6,609,679,835,325,201,497,500,366,701,215,188,298,66,869,284,799,126,511,476,272,488,641,352,857,516,237,462
 ,90,814,892,27,741,669,18,844,45,398,92,42,23,216,870,547,687,266,523,592,155,577,670,224,274,196,504,492,662,187,715,13,364,160,180,96,817,894,600,783,661,148,427,751,508,171,646,832,419,507,879,335,208,327,47,235,119,113,244,417,532,405,164,766,575,710,757,611,883,536,767,225,496,686,716,448,181,819,895,796,346,328,35,449,268,591,884,295,363,443,367,39,112,394,58,730,43,834,135,193,779,848,614,147,12,501,54,706,562,372,88,189,79,19,680,752,28,324,24,229,207,528,212,127,129,478,102,59,566,319,897,198,785,296,570,572,321,61,510,672,518,681,34,22,791,308,682,746,697,808,652,230,89,568,383,724,307,249,261,520,714,80,402,466,519,435,109,627,310,239,267,753,526,656,826,617,440,900,820,728,836,810,93,250,413,177,396,72,265,874,145,37,470,805,717,40,551,530,845,622,671,412,868,696,57,889,491,535,807,558,200,404,636,247,885,851,277,104,664,32,576,852,69,721,608,60,513,245,389,821,233,487,3,739,561,378,811,347,754,158,173,775,867,312,529,541,231,650,275,481,223,162,458,764,763,688,7
 74,202,729,111,831,151,256,703,873,482,761,698,303,51,44,2,257,692,199,20,771,546,654,759,457,214,708,621,769,846,206,362,375,447,597,477,106,564,502,373,121,290,812,432,893,742,30,800,149,776,818,184,140,628,77,602,658,302,823,833,15,589,758,329,725,14,509,612,439,406,217,338,794,326,313,211,606,498,778,377,806,571,73,336,425,16,369,203,827,684,755,430,768,291,11,839,418,186,787,719,263,707,71,663,359,594,397,128,588,49,631,726,103,434,392,538,50,251,756,17,374,94,132,87,825,474,722,514,731,657,486,605,711,452,651,84,258,311,495,67,120,293,240,179,276,423,7,286,252,279,403,227,441,569,320,877,749,234,683,750,533,550,638,282,471,850,294,556,503,56,677,586,408,429,786,797,105,190,124,154,685,142,391,138,360,226,587,798,117,304,734,736,361,539,579,280,213,141,334,645,157,632,822,52,615,840,168,640,38,159,781,630,525,555,41,342,248,666,348,444,136,531,262,475,169,815,410,399,351,416,195,289,872,521,803,122,210,133,107,534,795,139,36,357,595,255,668,842,473,876,388,161,166,780,4
 33,297,300,847,146,385,610,704,699,773,273,83,400,287,176,490,344,483,705,744,246,830,598,802,613,137,690,607,333,580,182,762,553,499,74,616,777,772,712,727,116,382,506,314,782,238,85,792,512,655,97,454,891,260,584,524,700,170,590,738,64,548,838,4,878,1,420,765,596,695,604,824,356,643,101,813,228,659,350,415,358,63,899,123,881,667,220,150,720,855,747,99,318,299,464,354,557,537,130,543,793,723,306,545,624,259,456,343,253,898,718,619,68,649,829,219,48,790,243,489,866,804,875,401,745,174,856,467,633,331,581,31,653,110,468
+356,459,385,787,799,527,829,609,369,682,71,138,866,536,448,403,525,762,261,756,898,450,69,414,212,313,283,862,833,612,879,710,456,845,540,1,492,604,625,330,317,242,157,117,823,482,419,432,702,856,250,781,84,16,303,730,774,663,275,507,406,72,90,148,142,131,794,886,717,679,466,130,143,182,894,364,328,216,458,721,167,210,821,85,562,87,841,778,559,323,662,32,588,234,202,495,445,557,179,83,791,602,429,601,783,75,42,897,868,642,173,437,175,520,422,119,630,858,370,801,112,176,827,199,622,483,826,480,652,423,493,603,9,895,701,363,378,665,516,554,763,463,220,368,704,552,247,843,670,672,749,217,435,350,646,194,553,304,699,824,529,790,596,580,362,825,690,46,579,500,159,461,244,447,227,773,67,318,533,99,335,535,319,547,108,13,421,226,581,63,265,752,648,221,34,726,819,331,393,113,689,872,724,664,453,807,490,889,293,896,768,577,146,49,249,498,409,98,669,485,452,430,18,314,279,605,288,521,867,838,195,798,33,883,869,22,297,574,128,343,592,551,751,499,548,876,888,418,877,511,505,822,214,647,
 678,522,517,675,339,154,389,440,444,353,2,382,478,264,441,761,125,133,37,680,149,139,354,352,287,745,192,150,893,436,539,575,329,561,259,812,687,589,847,241,476,504,158,395,890,718,716,632,48,641,23,651,136,766,118,280,572,676,347,285,797,348,81,567,420,203,78,587,885,772,741,225,712,586,855,692,892,519,411,757,629,853,11,300,44,155,17,767,631,455,302,21,555,371,802,381,740,512,219,336,95,544,506,804,735,299,830,228,277,152,402,616,666,465,396,818,374,169,309,503,694,585,171,497,294,427,686,134,269,832,384,786,70,276,865,110,161,474,322,806,748,40,29,207,349,779,785,80,290,105,477,793,639,608,750,191,258,54,60,431,570,469,564,215,338,805,839,197,620,253,661,404,834,486,41,771,723,595,873,634,245,800,344,301,391,776,523,840,256,550,383,388,405,137,758,172,232,31,187,705,102,204,795,734,698,528,614,738,668,851,542,52,333,870,697,884,744,479,144,24,291,494,657,132,407,765,307,36,706,200,613,703,140,473,400,674,5,530,30,57,617,468,178,754,257,375,637,281,428,439,4,101,415,878,66
 7,545,186,576,93,185,659,621,271,711,342,788,813,188,677,367,502,361,326,82,88,565,509,392,875,410,472,860,129,846,43,722,583,708,66,122,156,649,811,160,597,151,377,312,449,206,357,733,606,434,246,358,223,424,510,141,65,372,341,715,296,412,532,211,900,38,262,401,239,12,10,267,854,162,190,166,775,96,183,573,849,531,501,284,73,467,170,145,274,844,526,808,863,209,624,755,109,292,737,809,742,691,514,390,55,496,7,8,237,859,107,861,408,887,251,289,386,106,777,218,231,600,379,747,320,77,417,513,759,76,114,743,164,770,120,534,316,871,174,111,656,416,124,310,177,491,464,443,650,541,39,337,14,850,789,880,25,655,837,399,205,64,728,193,58,308,127,89,638,720,782,397,489,816,153,387,537,334,272,645,254,615,305,769,688,515,546,45,446,50,739,671,784,673,208,198,3,594,644,571,524,578,20,240,563,874,278,398,626,719,746,355,628,266,660,248,168,233,582,97,803,311,470,79,817,26,857,163,433,736,121,640,74,180,86,654,230,543,315,760,115,135,282,593,442,270,619,6,273,27,831,295,560,623,636,729,836,
 47,351,181,471,94,59,558,184,425,196,725,229,201,568,56,727,566,332,189,104,635,286,815,484,243,684,488,91,438,618,451,222,796,700,487,68,360,591,457,19,373,62,842,365,238,764,643,538,658,569,325,685,518,61,306,345,549,123,891,590,346,15,731,426,633,475,213,696,255,340,882,252,598,792,147,810,327,359,780,814,454,235,881,260,683,324,28,481,653,599,695,92,835,51,681,607,236,848,165,732,413,707,376,828,366,224,100,263,268,693,556,298,103,321,709,53,394,508,116,820,852,460,627,584,753,610,611,713,35,462,899,380,714,126,864
+492,733,251,685,893,107,790,453,301,274,164,730,702,18,19,380,829,438,622,487,849,142,455,208,779,52,551,678,470,461,780,558,437,616,200,363,271,885,21,386,497,594,412,419,430,444,340,840,639,744,688,367,321,241,229,248,579,262,686,882,756,365,288,276,482,694,697,837,477,136,658,600,233,170,852,247,63,484,476,166,554,87,504,112,860,157,456,683,460,280,767,452,394,13,693,759,815,462,245,116,637,769,302,58,300,649,186,856,598,188,67,834,172,725,690,78,223,867,544,281,546,130,614,261,532,429,714,6,706,141,811,432,353,857,322,681,621,54,868,655,373,31,49,8,366,647,156,520,459,894,500,90,148,26,114,250,5,140,472,401,2,383,890,518,772,381,677,253,635,176,74,101,22,3,517,264,411,158,728,199,843,876,129,814,653,243,201,698,619,213,560,581,763,189,342,480,792,705,275,389,143,841,836,102,853,654,60,870,510,863,527,314,466,183,441,753,465,505,671,185,341,835,528,134,252,739,91,775,564,508,35,628,567,726,633,454,146,623,478,795,872,9,757,150,534,696,804,819,691,92,493,396,283,587,415,83
 8,221,40,845,72,70,760,37,805,458,715,643,648,440,410,100,68,398,464,62,490,758,258,266,746,346,105,844,64,738,315,846,278,320,865,879,345,479,65,803,85,717,160,713,615,888,238,375,393,210,32,153,820,184,524,858,770,481,358,771,675,607,506,720,119,414,296,723,228,423,332,897,193,727,147,833,861,226,227,128,751,318,584,260,359,298,420,530,214,782,255,748,588,801,700,523,687,28,755,553,740,827,634,889,638,591,495,370,590,737,729,735,734,813,344,329,599,400,873,878,871,84,583,406,816,293,601,812,645,319,209,304,330,887,215,357,862,541,463,242,178,230,778,603,474,644,122,12,82,521,545,875,750,313,549,15,222,446,290,212,402,880,572,124,428,640,666,179,236,891,785,565,629,161,328,282,240,548,348,576,385,7,798,817,491,692,743,826,542,4,847,802,162,254,324,604,194,611,83,159,192,732,557,154,656,20,515,268,657,173,606,364,703,892,620,555,349,434,371,680,131,75,676,76,291,839,256,855,382,88,568,93,800,106,218,361,661,471,171,883,436,48,513,695,777,205,368,334,832,399,516,828,781,448,5
 96,138,59,285,433,895,55,337,535,556,299,450,29,139,239,646,563,786,237,540,512,722,77,632,403,50,731,547,571,149,445,135,610,279,257,277,338,539,766,155,699,362,426,303,42,447,168,169,651,99,670,526,818,608,665,327,689,451,234,263,44,206,709,869,286,570,56,749,339,347,642,851,265,204,41,577,309,659,216,742,51,289,10,180,807,259,177,618,799,501,503,672,23,718,397,333,650,537,561,884,108,417,667,181,630,335,449,109,711,684,631,613,784,94,664,494,133,369,543,323,473,796,586,427,431,788,754,574,152,89,191,244,488,110,80,741,752,582,475,823,145,679,387,217,874,468,287,668,848,502,507,408,825,900,764,390,424,569,762,418,132,175,336,395,66,231,174,182,682,388,121,881,457,71,850,207,24,95,708,272,716,391,413,761,292,810,273,352,144,197,793,808,127,36,190,384,392,886,566,552,589,374,443,498,626,831,151,69,866,295,652,660,435,311,111,486,519,312,317,573,203,187,421,663,343,765,774,17,704,377,351,224,331,198,39,310,360,673,745,701,529,104,536,595,783,806,284,219,225,485,163,45,773,602
 ,898,509,269,326,316,824,625,167,137,550,38,641,854,409,232,350,538,379,794,113,86,98,469,11,636,305,165,896,57,97,822,308,736,47,511,306,624,123,14,81,724,355,592,354,522,416,585,899,707,61,307,103,575,768,1,467,297,525,617,294,830,79,719,425,246,791,27,821,499,496,53,46,776,33,710,404,747,514,267,597,787,809,609,789,531,407,73,120,405,842,118,43,559,627,721,483,372,674,126,605,533,356,270,195,249,439,797,202,117,325,220,25,96,712,580,378,115,422,562,30,578,489,612,125,16,376,211,593,34,442,235,859,877,864,196,669,662
+60,588,381,242,354,530,406,433,579,430,614,79,810,839,727,343,17,330,700,290,827,506,249,618,317,517,51,470,895,318,823,590,218,625,788,399,483,92,830,86,43,12,542,376,650,278,274,162,288,728,58,462,159,522,787,523,499,507,451,417,707,111,125,391,658,328,627,571,250,848,52,195,374,586,682,565,492,175,84,626,711,458,574,500,229,257,889,746,831,296,570,174,490,678,254,112,7,305,302,371,352,239,203,793,552,252,308,759,893,804,465,256,556,39,779,474,491,481,68,624,45,617,336,295,703,134,729,772,378,718,251,188,435,704,454,11,733,829,173,223,569,795,694,734,326,116,407,449,880,268,884,755,342,622,635,394,870,620,411,521,858,866,171,143,739,538,322,666,119,396,714,558,652,840,54,894,332,486,42,264,757,131,312,34,234,309,807,655,75,215,21,878,132,473,578,554,380,576,213,285,875,669,439,717,10,600,775,621,225,719,610,505,36,645,66,546,358,136,690,598,164,13,273,453,191,460,494,540,900,599,685,774,294,842,859,573,282,865,681,25,281,803,365,393,581,802,806,40,882,799,180,527,107,862,4
 36,201,304,822,631,459,555,315,629,205,353,801,605,583,279,344,679,477,537,303,623,123,2,182,616,375,194,699,710,792,155,248,420,602,429,469,323,238,504,503,22,796,97,534,653,247,261,471,636,401,300,818,425,419,566,335,95,446,291,781,327,8,71,702,26,301,177,280,735,628,498,140,246,693,408,868,778,110,253,593,589,794,329,324,634,745,269,359,872,604,5,440,422,764,310,212,259,456,667,819,101,32,55,348,321,480,899,495,93,30,18,437,313,220,258,898,152,356,118,370,185,133,673,856,297,124,768,151,190,518,265,675,369,147,479,179,76,56,637,691,751,562,582,293,501,341,697,423,753,584,90,404,144,350,873,24,651,351,591,684,513,121,263,14,736,756,716,106,871,726,168,38,445,50,544,516,886,698,557,271,53,493,783,127,48,725,183,592,200,228,815,825,222,231,608,126,237,333,15,879,244,207,382,224,849,683,805,403,607,397,861,447,135,611,181,563,235,395,541,255,638,832,742,204,520,852,208,214,199,72,659,808,601,595,432,800,276,61,149,560,206,738,749,275,20,1,687,192,157,47,514,85,845,723,211,69,
 267,758,283,87,346,763,487,786,44,568,864,706,860,457,642,413,415,286,142,821,489,497,885,94,854,676,708,533,455,284,508,747,165,154,115,363,897,613,767,28,178,306,448,577,80,644,485,452,383,820,81,41,846,660,170,189,59,680,760,585,325,409,784,416,33,567,287,217,289,9,421,587,243,647,837,141,777,441,525,855,414,782,245,202,743,233,386,536,319,366,529,632,100,388,114,510,230,881,272,836,137,62,389,709,461,466,334,833,176,689,662,643,361,752,74,372,876,548,741,150,677,891,511,270,813,46,410,385,543,789,160,896,705,844,3,531,163,70,128,478,226,463,661,98,797,526,166,390,145,103,232,482,349,851,193,824,373,19,771,443,890,83,122,798,240,674,484,360,887,769,314,547,475,23,740,603,400,524,496,339,686,476,467,841,169,196,720,412,664,367,347,748,754,260,512,221,117,850,766,197,671,715,120,561,633,338,722,277,892,670,834,91,424,780,37,442,648,612,377,744,790,241,426,428,575,96,692,266,73,791,654,656,384,883,99,198,113,551,158,161,785,109,236,216,82,379,553,398,468,299,696,88,564,357,5
 19,646,817,139,57,509,444,843,63,731,78,186,472,184,712,450,596,65,721,387,688,559,657,392,210,227,316,765,539,29,355,104,515,545,867,364,405,814,869,16,434,773,108,877,153,67,311,701,663,528,761,730,130,847,102,138,35,64,368,606,835,750,641,535,402,812,572,31,219,609,816,630,580,105,594,167,362,549,27,320,307,77,649,619,639,776,337,262,129,853,732,187,331,809,615,532,146,292,695,668,597,209,672,431,857,4,550,438,148,502,863,640,6,298,89,762,172,488,838,713,874,418,427,828,340,724,826,770,464,665,49,737,345,811,156,888
+477,752,149,595,892,92,738,359,270,218,295,762,659,71,8,300,820,386,723,449,836,38,498,161,814,7,482,591,552,350,770,462,335,509,216,533,181,883,48,336,443,560,461,447,349,345,247,832,517,697,656,346,400,394,310,222,466,167,713,889,803,423,304,267,599,757,610,807,454,160,586,597,213,187,829,210,12,424,421,168,701,20,399,153,853,197,520,641,534,186,747,592,316,61,712,708,813,358,192,155,521,719,220,30,275,734,242,842,640,171,87,827,177,670,772,107,125,849,453,250,578,148,528,207,496,339,664,34,616,121,791,347,565,840,238,649,690,55,866,551,289,32,82,76,325,539,80,478,571,894,594,170,88,3,72,219,146,98,367,360,133,403,893,513,828,378,570,439,530,73,157,13,24,141,456,364,469,78,680,174,877,876,44,798,703,332,257,785,553,279,542,650,693,144,619,384,739,749,180,390,225,819,817,43,863,561,37,858,435,845,429,232,470,371,481,760,393,499,642,102,299,831,627,40,162,704,10,776,667,410,165,583,683,709,602,666,94,737,620,789,870,41,681,95,485,636,778,808,722,81,380,351,252,668,315,824,19
 3,79,868,93,1,740,22,801,625,802,623,718,341,387,204,90,549,356,86,448,771,217,273,663,285,182,821,59,672,253,860,214,286,850,873,313,459,5,825,64,736,69,628,492,886,140,695,301,309,56,119,781,243,480,851,731,402,458,696,658,674,486,763,46,556,240,655,228,326,385,897,132,638,208,811,856,233,249,54,730,408,538,428,502,422,411,624,151,799,357,727,678,751,643,432,633,130,835,559,766,854,519,887,644,721,501,382,622,714,677,653,685,812,445,318,609,319,882,871,867,114,717,343,805,262,590,822,535,229,234,342,366,879,236,354,861,577,389,198,320,441,809,589,398,575,223,63,178,525,433,869,702,365,524,21,266,611,283,109,368,881,546,137,370,562,645,268,306,890,774,473,555,328,278,388,195,564,307,629,331,57,796,810,419,600,671,839,427,124,884,788,112,196,374,568,296,626,150,194,183,631,532,175,669,65,396,185,581,265,744,281,612,891,569,511,255,494,537,754,190,42,707,4,302,843,329,841,334,27,563,106,818,31,206,465,687,554,373,880,464,191,484,675,787,139,288,280,823,613,506,874,750,392,576
 ,134,19,290,504,896,23,312,512,557,274,474,128,176,154,634,518,806,241,689,566,705,17,654,362,135,661,724,472,272,379,96,584,292,230,245,244,646,834,126,758,264,355,224,99,377,179,85,608,111,782,605,848,729,786,413,621,418,164,337,18,188,755,859,489,508,2,769,451,503,615,826,311,129,136,579,294,804,108,660,117,189,101,231,780,381,110,601,756,395,431,582,67,630,330,308,679,488,606,875,97,375,596,321,648,550,635,28,692,733,536,632,743,53,775,404,120,412,593,420,430,833,699,401,460,846,784,455,282,115,147,261,604,248,127,748,684,545,467,790,39,728,348,287,878,531,226,567,847,558,407,490,783,900,759,522,444,529,794,572,259,293,317,487,118,184,314,145,580,476,131,888,372,36,857,201,11,89,651,254,639,437,327,716,369,779,305,353,239,138,767,765,77,143,103,603,303,885,662,588,471,652,544,414,540,864,47,25,852,397,715,732,491,221,199,500,514,258,425,468,260,212,438,548,442,694,793,6,598,361,338,363,405,227,163,276,333,607,688,746,497,169,505,493,797,773,446,203,383,415,62,51,726,527,
 898,416,440,426,256,855,745,235,200,618,14,753,838,409,156,324,665,297,768,100,66,271,391,52,523,291,104,895,33,166,815,211,682,50,406,352,543,209,83,152,741,585,686,376,541,322,673,899,711,9,215,60,657,710,123,495,246,475,574,298,795,91,800,691,202,792,49,837,463,417,16,105,725,75,614,323,777,434,237,587,735,761,507,844,515,452,68,35,483,830,142,26,479,706,698,676,284,573,45,510,637,269,263,122,158,436,816,205,116,251,173,113,15,742,617,344,70,450,526,84,764,516,547,74,58,277,159,647,29,340,457,862,865,872,172,700,720
+805,45,290,817,499,824,619,311,117,793,250,395,405,582,588,198,761,862,10,882,680,447,162,189,138,632,483,823,276,411,394,282,376,615,201,397,295,684,725,702,703,628,41,80,682,316,348,361,531,419,401,885,692,325,105,850,523,614,55,228,12,613,513,114,43,123,351,745,883,435,666,175,147,141,736,160,644,204,787,864,40,370,679,345,349,521,317,199,57,277,146,608,279,550,132,431,764,344,190,470,704,343,630,585,865,197,350,746,319,329,650,216,143,716,1,515,636,565,528,846,590,182,858,188,104,673,314,727,291,224,231,757,605,772,700,726,2,696,439,341,612,480,367,762,860,539,260,890,101,522,142,288,748,566,797,139,760,200,498,871,767,310,546,878,15,893,426,287,622,616,339,510,471,771,458,365,124,261,720,266,78,530,595,699,174,363,152,35,826,534,742,115,625,165,714,386,589,26,532,121,423,496,294,709,833,421,446,646,179,755,422,335,610,403,800,70,156,244,113,308,789,710,269,326,460,163,389,81,303,718,687,251,211,453,387,227,698,22,62,581,331,758,448,785,106,495,508,577,324,378,476,867,59
 7,56,484,334,816,812,86,638,524,153,765,237,357,6,50,20,285,880,304,537,161,642,362,249,795,731,92,437,232,254,639,384,406,780,145,259,111,402,373,849,896,442,879,393,320,305,808,688,489,623,751,454,443,788,209,390,149,96,558,236,164,47,620,768,542,82,872,500,766,794,658,869,560,806,606,340,801,424,511,488,827,881,728,332,255,99,225,75,538,891,63,219,717,234,148,4,621,206,821,116,697,23,315,874,898,744,441,44,186,38,792,737,652,185,353,248,192,346,804,74,430,226,561,535,298,19,155,381,313,212,256,674,337,877,133,825,579,573,677,664,16,474,533,333,516,158,53,838,301,559,481,509,868,753,575,213,289,556,527,203,130,119,462,798,368,592,208,438,429,271,292,95,609,543,820,754,477,828,265,280,900,848,837,847,576,321,540,338,371,482,284,392,747,71,214,434,779,784,136,461,729,611,574,693,571,892,436,37,803,572,463,859,221,172,491,730,635,895,884,270,42,670,13,262,773,184,629,372,278,497,541,494,732,125,283,59,689,356,347,876,413,627,473,51,518,886,536,791,398,299,741,587,374,342,54,5
 26,836,856,669,568,169,802,410,690,87,151,831,863,281,529,414,217,48,89,94,202,782,46,97,694,354,776,452,512,77,783,472,832,813,137,379,400,487,634,180,93,336,722,459,154,242,691,580,873,706,90,759,8,845,889,14,67,665,230,749,545,85,733,830,76,721,707,517,598,131,514,564,667,660,83,318,626,177,352,69,553,659,469,358,549,525,300,102,388,66,519,268,857,786,569,681,799,355,36,875,181,505,555,809,485,637,24,551,274,502,322,240,607,18,750,676,11,600,275,273,25,61,843,28,107,65,140,17,888,567,651,328,570,701,168,327,399,711,781,194,383,602,404,171,91,103,578,32,196,641,176,366,396,293,593,617,377,599,127,894,870,49,548,408,645,633,330,258,223,834,425,247,243,306,723,418,735,210,657,743,170,109,245,33,734,246,120,380,360,84,451,738,286,506,563,468,323,428,683,662,29,31,479,465,21,778,853,88,557,739,450,296,9,34,841,649,229,708,52,222,98,774,122,187,159,685,178,601,375,675,604,490,173,191,58,183,671,624,844,307,302,272,195,238,861,253,193,661,486,129,562,866,432,811,668,167,507,815,
 215,64,364,897,108,239,297,814,467,851,586,60,416,144,135,457,647,235,631,520,218,695,724,835,603,464,449,409,653,594,407,655,596,220,157,475,493,456,855,686,3,440,309,417,854,640,79,672,478,427,5,705,777,359,663,719,839,112,740,466,7,385,822,110,790,73,584,840,382,391,715,713,591,654,257,852,128,807,547,656,552,68,899,27,810,618,205,420,444,769,842,134,267,166,445,554,501,544,30,503,818,643,241,369,829,126,312,412,150,819,583,796,118,763,712,263,72,504,100,264,887,775,770,433,648,39,756,492,415,678,752,207,455,233,252
+577,64,341,616,177,857,423,294,260,768,483,111,539,859,810,205,332,813,158,845,697,549,96,397,13,735,220,736,737,342,519,343,248,590,531,450,386,214,877,474,420,305,145,98,707,230,289,43,373,475,102,873,544,481,452,853,470,634,20,27,107,451,394,182,213,40,376,579,838,790,334,32,228,366,611,325,731,73,535,881,234,491,652,499,49,506,741,357,379,262,126,458,329,787,5,128,346,259,222,550,534,117,487,826,863,93,404,688,718,646,734,7,350,362,183,643,659,358,254,861,330,428,778,212,263,456,408,867,174,514,23,555,623,672,677,377,166,868,77,154,633,795,648,871,825,266,372,870,526,127,584,613,738,756,860,219,897,435,448,858,896,666,135,794,144,887,272,512,348,614,650,656,712,892,203,815,129,403,364,275,172,119,591,271,48,400,501,124,570,488,432,498,300,307,781,427,396,55,439,92,821,431,130,840,436,424,753,467,71,649,471,411,360,619,599,54,131,91,218,480,631,261,215,446,381,90,527,47,771,706,842,426,161,620,638,383,657,378,247,193,46,875,285,777,181,606,566,176,654,711,311,855,442,402,
 464,51,779,894,75,726,683,16,849,8,371,208,103,74,202,854,574,671,280,493,592,85,437,596,273,281,155,553,554,727,137,669,11,418,167,209,82,772,882,582,667,730,67,453,776,473,134,637,817,422,468,886,344,224,363,53,153,146,101,351,405,416,298,246,651,518,608,724,668,879,545,690,169,557,673,808,525,104,775,889,800,459,297,31,465,365,503,872,462,417,318,367,61,217,385,29,695,72,836,243,113,675,770,575,118,36,709,80,605,434,257,108,190,58,2,814,685,26,245,21,165,132,561,368,112,63,558,45,14,567,287,893,198,710,322,485,466,211,125,573,739,521,678,10,62,763,395,647,780,700,729,628,157,94,704,268,746,288,274,352,536,622,52,286,528,602,502,42,745,393,163,168,748,429,635,819,758,492,900,782,607,827,833,30,151,490,136,441,24,240,880,241,9,419,811,618,15,496,415,874,546,597,414,846,788,140,891,486,569,789,682,196,345,662,189,878,824,290,138,578,87,670,864,25,728,714,17,457,197,303,830,369,507,44,723,645,336,725,258,751,99,267,799,848,200,409,593,194,560,178,469,139,277,522,713,674,625,8
 07,179,617,88,851,171,384,587,866,612,783,793,333,121,68,3,235,580,340,59,761,708,551,823,505,269,719,581,732,843,320,295,316,375,559,664,141,630,392,331,115,321,805,355,888,744,60,769,251,680,720,339,188,516,41,484,701,399,820,803,18,655,722,231,742,1,449,529,323,407,256,313,798,463,239,293,586,515,831,391,829,494,37,413,387,22,406,206,809,698,764,359,754,226,39,804,576,156,841,639,186,676,160,609,356,542,513,69,621,120,660,702,195,353,388,692,89,349,696,79,552,133,97,201,740,472,693,517,791,563,679,626,792,328,658,34,170,238,504,33,148,361,150,299,324,374,12,210,192,233,421,207,562,479,440,862,615,337,653,844,444,455,703,244,497,847,301,715,583,35,699,556,283,495,796,765,147,227,123,232,687,162,508,84,302,326,537,812,122,310,784,767,338,511,510,199,370,242,282,641,236,538,822,95,571,852,143,773,105,296,691,603,598,438,66,410,292,642,433,520,100,524,255,500,83,828,389,314,461,454,253,279,890,445,752,65,252,70,57,604,721,109,4,265,532,306,610,839,447,876,315,216,142,774,460,
 412,237,766,149,390,705,588,750,661,229,110,354,380,175,523,249,543,686,760,308,832,568,755,540,106,749,589,225,548,116,757,564,644,86,565,816,835,585,694,221,304,663,250,684,204,173,806,533,717,191,382,895,184,489,425,594,164,601,802,159,547,834,6,884,28,319,716,600,762,624,818,284,665,38,797,264,530,347,398,270,114,898,185,883,627,180,76,801,865,689,78,430,335,482,291,509,595,187,572,743,759,327,681,477,309,443,276,278,899,747,478,56,541,850,152,81,837,312,640,856,785,885,401,786,317,869,476,632,223,629,19,733,50,636
+479,293,289,139,36,750,13,122,366,433,816,399,194,861,783,187,217,403,616,476,125,452,498,436,414,712,216,157,645,103,182,133,118,131,590,831,282,202,846,355,335,330,530,482,276,111,185,145,42,114,219,570,730,833,707,572,92,341,345,321,508,649,566,428,680,501,79,25,502,715,156,346,455,610,39,389,685,221,334,717,738,605,196,761,110,695,613,204,583,263,117,768,177,852,313,57,281,99,364,760,82,23,306,746,555,560,686,73,554,574,801,161,596,165,576,797,382,1,164,540,522,660,267,343,297,232,141,858,33,599,94,258,880,51,307,287,539,809,174,37,270,786,799,876,491,71,439,463,675,201,643,821,587,743,700,402,898,550,119,456,895,537,208,545,612,604,24,870,86,434,832,553,793,897,256,777,551,429,160,505,726,207,535,138,461,741,653,629,295,706,421,585,38,474,899,147,11,393,296,400,787,29,30,657,425,81,737,10,166,49,146,246,458,879,602,236,170,375,223,416,426,269,678,459,327,93,564,222,682,225,885,235,646,255,338,848,601,659,749,244,135,862,14,603,224,190,129,183,417,711,107,451,450,594,158
 ,89,584,855,571,802,623,128,795,178,814,640,283,483,123,516,826,791,774,148,782,290,406,480,495,16,275,803,48,756,40,376,391,324,331,12,75,507,541,642,578,722,329,424,176,88,72,358,900,155,764,838,543,9,667,240,108,44,153,688,15,348,598,337,561,577,813,432,144,641,186,689,192,467,104,753,91,143,635,710,593,168,716,220,845,781,807,568,661,397,365,754,102,591,6,106,252,137,878,752,411,494,703,105,66,326,733,398,562,567,200,69,20,65,180,762,544,388,195,285,58,126,776,691,214,120,427,311,298,96,209,721,580,651,3,620,528,239,441,231,473,840,889,405,284,305,149,824,849,859,542,167,101,53,634,353,805,626,784,453,351,410,188,349,665,304,151,251,778,664,134,169,226,234,871,430,769,419,638,486,637,404,867,210,193,249,41,50,340,67,893,788,142,526,475,672,238,785,518,851,696,618,22,504,687,333,868,115,336,230,770,734,241,113,109,409,437,203,546,839,511,747,755,371,632,565,292,718,19,332,671,350,742,320,615,533,732,532,625,891,132,468,884,489,278,369,442,206,372,179,869,384,804,87,344,43
 8,655,725,477,684,245,759,360,323,512,556,490,873,727,325,294,213,312,519,806,536,173,669,493,385,860,84,789,191,829,314,648,273,538,444,415,257,683,702,586,575,205,199,250,856,229,736,500,184,773,714,720,692,650,735,744,100,367,420,670,767,611,412,62,883,247,663,310,766,830,339,2,592,377,872,373,443,817,356,47,850,248,877,705,85,772,485,288,18,97,342,130,835,76,319,390,359,407,552,32,731,392,124,857,387,881,819,569,262,454,162,395,78,694,656,211,609,614,488,704,380,517,674,316,484,668,595,83,843,758,559,621,728,864,812,328,80,264,368,31,435,422,300,654,254,547,301,60,181,579,136,636,7,189,261,779,487,446,582,765,841,823,471,697,818,413,828,624,26,676,690,302,233,698,357,527,780,757,95,396,43,525,253,45,679,54,588,470,800,524,27,4,608,874,401,875,228,152,619,462,61,896,633,268,265,627,465,740,21,771,466,514,658,291,810,521,354,322,724,159,644,622,464,70,713,46,381,790,28,445,448,820,628,597,886,423,509,127,52,440,299,792,431,77,279,63,853,472,863,362,408,827,64,140,237,274,8
 47,708,308,723,681,709,748,677,745,763,17,378,370,383,693,242,90,662,739,887,175,854,98,549,531,197,729,815,198,277,68,798,154,631,112,796,865,834,457,888,600,548,499,163,719,227,266,699,280,639,581,56,894,497,394,318,347,469,34,775,617,892,523,212,844,317,352,315,701,836,74,837,59,260,379,309,386,447,5,8,121,647,573,513,808,563,607,116,751,794,286,558,215,825,218,55,534,171,652,272,589,492,303,460,481,520,666,271,418,882,606,496,478,449,673,503,243,842,822,529,363,630,866,172,506,510,811,150,890,259,35,361,557,374,515
+502,656,278,772,893,191,835,509,290,412,66,625,777,54,64,387,826,601,467,633,878,206,344,233,668,77,522,793,546,526,828,611,464,723,237,220,321,874,95,416,495,555,313,315,597,474,374,812,689,803,629,534,270,112,175,403,677,375,576,854,644,289,245,225,348,543,744,868,618,226,662,471,181,117,880,259,84,424,528,323,390,71,638,38,845,108,556,700,425,295,749,347,445,5,587,740,805,506,218,49,730,764,363,135,465,484,97,886,674,266,46,796,123,728,586,30,339,877,550,450,451,79,741,242,524,485,761,47,712,157,778,525,216,885,444,660,501,147,853,658,499,68,18,29,498,663,153,686,443,892,510,33,229,51,236,214,42,141,579,603,35,463,876,599,648,581,711,115,673,267,14,158,15,22,468,345,293,172,733,151,752,863,171,810,503,142,188,540,664,152,529,588,780,162,207,573,831,608,331,305,221,861,840,219,843,721,86,889,457,887,626,377,420,67,434,684,447,398,659,240,410,819,364,154,274,713,88,714,634,652,9,680,397,801,715,281,180,533,330,760,858,72,787,252,520,783,844,799,757,125,530,596,285,541,514,8
 20,316,148,773,45,102,697,87,748,300,593,590,519,454,577,25,31,262,575,19,411,722,307,241,779,311,39,871,78,727,413,788,332,287,867,873,439,665,56,794,111,620,195,821,685,883,353,234,481,122,138,106,837,99,446,850,769,449,275,817,650,477,483,699,116,337,399,813,400,549,335,897,269,816,231,859,847,292,393,256,800,190,507,130,248,193,591,475,260,743,140,707,472,836,646,641,642,11,613,430,750,822,731,884,535,614,394,386,512,709,706,747,692,767,419,376,461,414,852,875,862,28,482,385,789,370,488,739,746,355,391,204,354,895,183,341,848,442,598,369,69,101,670,518,632,687,55,8,13,569,676,870,734,382,493,16,134,291,284,301,466,865,521,109,553,717,580,211,174,882,762,701,643,60,489,327,298,735,455,536,563,10,736,791,584,682,804,758,582,12,763,751,146,409,309,511,98,547,160,126,201,790,672,253,605,104,623,371,781,179,415,388,807,888,782,678,380,325,268,558,149,178,551,121,384,786,173,855,366,184,589,34,732,161,302,235,683,357,76,872,404,2,645,636,753,294,361,395,811,250,418,719,839,578
 ,637,145,132,212,407,890,144,296,565,559,469,537,1,222,265,594,504,694,168,426,459,675,127,698,448,57,802,372,704,59,592,257,627,217,228,272,437,567,609,223,616,392,401,342,26,470,329,279,606,107,531,479,806,508,478,263,639,476,360,210,83,306,583,891,176,532,89,640,239,230,607,869,192,198,6,621,261,462,310,814,75,350,4,124,776,164,156,516,838,517,651,785,7,745,560,280,544,657,604,881,205,491,647,94,561,199,286,113,768,545,742,523,849,100,515,505,80,431,422,243,571,690,574,378,322,681,756,666,82,27,319,246,496,24,93,695,830,487,402,832,194,539,358,150,860,417,312,708,827,373,494,283,851,900,815,288,436,718,737,299,58,251,326,318,41,187,73,308,720,441,114,857,622,40,833,255,48,105,691,254,702,338,566,766,277,792,197,334,62,352,795,834,247,3,177,232,486,879,497,492,630,208,346,572,775,726,215,165,864,351,548,610,428,423,53,435,421,362,200,688,170,202,317,754,213,824,671,65,759,333,383,103,249,128,90,314,438,628,771,568,427,63,619,585,696,809,163,196,120,655,189,129,784,615,898,
 669,139,271,297,818,433,81,166,490,70,570,856,349,238,368,367,480,798,91,74,17,513,21,738,381,186,894,85,23,808,406,703,43,635,356,602,50,20,110,716,227,473,276,612,432,538,899,679,137,405,159,452,797,37,365,328,527,653,224,866,131,595,258,396,729,118,770,456,617,44,32,842,36,724,562,631,661,264,600,823,841,624,649,725,340,185,155,282,825,182,136,654,453,765,304,460,693,143,710,379,458,343,324,273,554,774,167,52,336,203,133,169,667,429,408,244,320,500,61,389,564,755,209,92,440,359,542,119,557,96,846,896,829,303,552,705
+839,36,213,699,471,819,407,172,60,678,485,599,153,589,577,129,772,817,135,863,350,355,337,127,328,625,545,639,114,269,141,90,282,348,145,702,183,736,668,685,712,686,134,198,427,215,264,438,366,179,512,857,821,609,169,784,300,446,121,398,81,764,641,177,217,326,142,507,871,317,626,315,202,209,456,97,628,256,755,833,239,402,429,525,396,654,132,27,20,227,41,820,138,653,257,414,803,223,222,624,514,273,563,527,809,464,548,451,103,216,723,296,208,684,59,647,493,383,528,737,740,267,775,212,7,598,87,719,170,199,260,642,842,503,537,752,38,607,553,259,390,496,463,796,829,484,258,856,43,620,44,408,700,584,741,174,777,201,313,798,788,123,649,885,158,869,268,581,546,533,509,441,558,816,534,248,298,229,687,360,331,631,583,690,378,591,149,218,812,698,787,21,543,186,882,187,386,74,491,225,339,265,195,590,875,194,409,394,180,467,204,196,710,672,851,46,79,405,10,207,759,765,568,292,449,70,384,62,131,481,794,47,518,178,140,587,688,35,272,664,404,730,275,729,18,224,230,638,89,323,389,785,632,16,
 307,368,791,774,291,720,502,166,747,330,670,111,17,107,191,853,482,657,436,475,490,351,847,708,72,266,271,392,346,377,358,689,316,139,91,278,373,832,874,489,895,352,501,235,586,536,523,479,890,283,652,734,279,246,277,96,605,130,126,115,426,805,754,1,891,557,870,726,349,822,359,861,674,221,627,319,237,576,835,859,619,100,521,102,531,243,766,879,30,146,806,499,92,50,439,226,716,56,783,220,508,888,899,556,445,71,88,77,834,836,663,93,231,233,276,219,826,184,413,375,572,603,406,63,128,442,151,353,420,422,270,848,285,860,430,679,743,732,29,240,340,592,780,345,39,731,80,735,578,680,877,561,614,147,155,659,596,376,419,52,320,790,473,675,232,206,182,385,242,165,650,610,655,718,721,707,190,159,896,818,883,738,633,432,623,125,299,252,476,288,807,338,280,519,617,844,203,667,824,552,696,733,369,886,309,9,799,374,287,760,228,500,480,465,643,850,866,175,160,846,106,249,676,363,588,188,443,693,513,566,630,5,388,85,637,210,615,889,651,828,559,14,677,872,629,841,251,274,694,645,703,515,293,24
 7,778,862,715,517,281,867,549,604,66,15,855,801,83,665,312,171,13,58,192,327,881,12,51,661,112,757,498,250,324,569,682,739,767,11,541,504,567,468,67,361,238,840,399,113,154,769,570,843,594,49,793,143,887,898,42,314,815,244,753,362,136,714,814,214,421,864,579,573,263,744,813,727,457,167,332,742,22,477,342,435,401,495,236,662,669,311,245,454,101,294,173,779,562,671,593,673,459,82,852,34,494,452,786,516,810,8,830,611,542,75,472,321,23,486,695,164,580,381,119,104,168,823,152,37,33,301,176,897,364,802,483,393,762,86,550,387,771,555,297,538,554,329,365,55,197,697,19,105,530,234,597,379,551,372,666,110,811,24,868,893,211,748,336,692,795,410,318,460,781,255,124,241,469,510,520,825,137,660,770,57,99,162,40,547,116,98,367,544,26,640,575,185,334,431,621,347,751,564,701,25,4,380,797,109,711,705,325,526,648,391,205,48,6,878,492,344,792,84,95,284,585,150,157,305,455,423,343,574,644,437,613,45,434,156,310,634,646,837,333,118,506,306,322,854,200,335,608,758,120,789,776,411,808,602,31,616,63
 5,522,108,397,900,371,425,261,880,461,894,535,69,447,32,412,254,618,253,681,725,68,746,524,831,622,565,416,595,691,453,400,709,357,117,78,658,571,440,876,865,54,612,94,370,892,704,3,600,308,341,65,606,804,560,636,722,838,193,487,415,122,745,717,161,749,133,656,773,424,474,444,768,532,417,462,761,76,845,382,470,540,304,884,64,756,601,448,497,354,706,782,356,53,505,262,488,539,286,189,302,827,466,181,148,873,163,433,418,144,800,511,858,295,763,582,458,28,529,395,73,849,728,724,290,450,2,683,303,713,750,478,403,289,428,61
+583,707,208,669,888,141,755,385,248,262,226,778,579,1,4,318,845,438,632,518,796,104,519,160,802,71,597,631,344,398,697,443,396,502,142,496,212,889,2,426,554,671,413,434,334,394,302,841,582,654,740,370,451,336,203,244,480,211,685,881,749,482,366,277,510,744,605,794,528,75,692,650,230,172,816,196,79,484,530,182,594,90,402,164,860,241,326,572,392,252,720,636,317,59,722,762,837,401,238,184,576,751,303,11,284,736,258,819,444,115,127,828,174,757,674,140,181,849,561,250,663,135,600,254,420,429,613,10,655,98,798,425,523,824,278,747,591,9,871,630,293,3,63,56,372,649,144,517,371,896,390,100,175,32,103,237,25,110,397,384,27,273,892,617,770,389,627,341,643,159,101,72,44,46,557,178,458,130,761,232,854,882,149,827,714,329,161,733,667,310,659,465,759,176,536,383,756,703,275,408,81,793,812,65,873,540,15,853,483,829,410,247,568,287,575,730,411,559,590,129,379,856,648,114,261,702,78,750,419,405,119,492,670,606,477,588,188,562,525,820,870,8,706,177,450,567,728,833,546,42,457,369,331,497,342,83
 2,259,36,850,134,54,746,62,808,620,715,592,657,393,427,143,122,487,415,87,521,811,299,229,699,338,126,792,28,742,314,852,204,289,847,872,382,481,70,848,34,766,121,640,570,887,194,602,327,312,22,165,783,201,490,862,729,436,333,741,753,734,414,797,145,604,304,625,221,343,453,897,124,687,82,772,863,291,249,105,656,399,555,335,377,423,454,446,163,826,323,719,552,769,700,507,646,102,768,638,803,865,577,886,634,464,468,466,713,773,682,695,724,815,239,395,624,404,875,877,874,94,532,373,821,197,653,825,549,286,216,332,433,876,297,442,868,506,350,162,268,364,804,563,452,524,218,33,156,637,476,878,716,215,642,41,271,531,225,170,459,880,660,96,307,514,710,120,219,891,807,511,672,279,296,198,169,578,365,718,351,16,813,831,363,675,665,839,491,55,857,795,199,206,439,615,294,726,29,246,263,678,623,85,608,35,431,193,639,128,704,361,628,893,589,601,285,445,538,684,91,53,731,73,186,846,357,855,421,68,455,106,781,117,139,467,758,612,306,883,367,108,543,754,822,137,346,360,843,550,593,834,708,4
 70,681,209,13,308,587,894,21,301,416,664,280,325,86,77,191,585,522,786,272,721,424,686,89,471,461,31,645,614,486,255,441,157,493,339,300,316,290,417,791,92,787,340,388,243,111,474,183,155,622,173,677,688,861,558,725,460,689,529,167,240,66,253,738,835,456,633,52,767,469,499,723,830,264,213,112,448,353,717,180,679,18,235,51,269,799,276,200,611,752,428,478,607,76,732,368,374,651,573,422,879,45,463,701,305,564,503,598,125,584,748,505,566,735,136,680,512,171,260,535,311,527,790,479,381,473,784,818,489,274,123,116,320,378,168,39,789,696,616,542,817,113,739,337,217,885,406,224,662,842,619,501,513,782,899,658,548,319,581,823,430,242,107,400,539,58,251,234,195,626,283,83,884,386,93,867,146,48,153,652,245,673,358,349,711,231,801,345,281,233,154,765,771,74,84,192,537,375,890,498,472,545,533,435,520,551,838,148,47,859,205,644,599,580,265,109,610,495,228,347,516,179,133,462,603,409,693,809,17,668,447,257,282,321,227,12,359,407,690,676,763,553,95,618,547,800,806,418,189,354,449,166,69,774
 ,504,898,437,348,295,330,864,698,222,88,705,7,776,851,391,256,267,635,288,805,80,131,187,376,64,571,355,207,895,14,158,836,266,745,99,412,214,565,210,19,38,788,534,556,432,380,403,743,900,647,40,236,49,544,764,30,560,322,596,683,298,779,26,727,595,223,777,24,814,574,500,50,43,709,97,712,315,780,485,220,694,760,775,629,810,515,387,60,132,488,844,57,37,569,691,621,586,292,666,150,475,541,270,328,138,202,309,840,185,152,324,190,23,61,785,641,440,67,494,509,5,661,352,609,151,6,313,147,508,20,362,356,869,858,866,118,737,526
+642,238,260,836,786,715,800,432,158,757,59,286,764,534,487,236,721,846,83,867,888,396,17,228,183,436,378,873,655,488,802,507,384,797,327,132,338,746,668,515,519,454,8,3,784,360,334,461,633,759,342,876,374,84,131,821,705,610,116,477,205,317,242,18,21,87,630,880,857,539,578,91,29,44,886,179,453,143,646,831,48,198,783,111,524,233,699,547,265,230,438,313,397,368,130,483,700,419,68,194,785,495,500,556,851,94,79,894,751,463,375,381,40,648,193,253,595,830,451,842,357,69,874,85,343,552,665,587,486,261,401,691,296,893,710,584,151,679,560,446,711,447,224,563,829,546,157,889,404,740,505,185,568,423,745,45,669,172,601,872,653,597,704,827,197,887,579,92,603,516,192,442,310,621,323,611,2,210,656,61,281,622,417,684,93,80,229,98,760,237,533,489,678,73,415,561,780,152,428,11,557,823,574,680,775,694,426,871,177,892,623,418,376,168,592,274,221,97,405,335,631,643,71,248,318,389,264,304,744,815,435,586,63,814,763,72,470,300,27,518,545,632,650,627,282,812,837,549,769,402,475,866,372,362,572,480,7
 07,766,267,364,407,303,593,337,117,190,226,88,321,863,129,285,16,658,180,128,683,529,86,635,125,121,869,371,484,690,297,359,76,737,626,768,895,268,832,409,246,270,884,731,735,594,465,522,150,738,57,659,20,110,637,499,201,89,765,609,325,280,791,293,460,717,849,848,673,565,792,421,862,553,844,582,670,859,654,734,28,140,53,38,234,882,352,275,581,25,355,145,777,290,813,295,450,209,146,826,870,808,726,114,625,36,570,491,551,412,531,370,336,664,628,41,340,469,741,647,154,247,144,456,490,127,302,804,309,865,1,613,843,294,410,651,99,706,649,101,243,188,142,835,598,266,358,254,779,803,712,430,540,385,349,12,24,208,472,693,550,414,212,675,730,217,440,78,753,521,850,636,211,825,520,392,900,787,645,845,445,351,526,596,449,758,320,457,567,322,347,213,776,509,123,162,506,676,284,425,755,878,559,251,739,688,537,883,353,60,388,852,772,898,868,328,7,344,112,345,724,124,473,589,354,206,723,319,639,437,115,273,510,501,82,822,170,324,638,204,331,877,429,689,482,222,576,577,138,166,311,824,796,7
 88,394,535,10,562,696,619,66,452,687,853,605,333,536,223,244,165,218,22,496,269,288,512,770,604,444,793,52,840,189,809,728,448,120,184,276,614,583,136,427,504,379,159,289,433,466,839,618,231,498,175,640,838,250,75,346,301,558,620,105,542,722,102,896,380,390,462,174,216,258,493,834,15,161,373,530,126,118,527,820,476,377,403,227,416,50,186,106,781,365,858,855,356,685,807,147,108,856,571,750,616,714,458,308,225,263,74,315,736,153,810,160,879,431,119,485,65,566,35,54,774,219,494,104,9,245,841,709,330,122,672,422,538,156,439,564,864,133,202,702,350,109,107,33,629,203,255,660,411,137,348,55,819,833,795,292,387,890,789,58,257,588,398,329,271,77,64,761,600,575,259,503,799,215,663,326,467,497,420,67,443,81,767,511,277,492,96,195,163,749,517,732,599,307,169,178,612,756,287,235,528,240,49,703,885,232,441,671,695,554,139,341,641,624,181,464,47,367,4,817,135,272,14,794,6,818,299,523,720,262,382,37,19,13,677,400,752,306,580,176,100,207,806,332,252,698,199,95,256,875,298,716,692,393,773,84
 7,51,149,196,861,39,30,391,585,408,681,743,34,241,312,26,590,634,220,369,278,413,474,805,719,383,727,424,167,602,569,455,399,742,478,291,200,406,508,778,363,148,182,697,361,701,828,366,555,543,459,113,747,666,141,468,541,762,5,881,502,164,191,801,279,729,305,395,811,249,339,860,471,607,754,214,854,134,667,748,798,514,171,899,43,771,434,23,513,532,682,816,42,662,46,544,591,316,782,31,615,652,661,239,686,733,56,90,283,103,790,525,644,32,548,718,62,173,481,70,617,891,606,708,479,713,314,674,608,187,657,897,386,573,155,725
+508,124,337,670,368,827,566,370,290,751,402,47,700,846,765,202,348,809,170,839,847,542,26,415,19,641,157,793,820,398,714,460,258,704,575,312,411,274,874,428,367,220,99,46,764,244,296,70,458,634,63,876,426,362,462,853,578,643,42,102,171,317,254,110,169,18,504,733,824,796,331,1,147,308,785,338,639,41,499,878,207,440,724,412,107,404,822,497,466,240,247,314,396,691,3,149,340,316,145,445,620,186,470,807,872,29,267,838,832,668,615,56,295,364,251,530,647,545,229,869,195,389,801,139,390,447,580,849,280,531,72,565,487,825,678,334,219,868,118,197,681,746,588,843,805,304,318,877,625,242,692,571,659,673,848,156,892,427,510,867,889,741,198,732,191,895,394,431,384,602,576,619,623,882,123,850,49,388,373,175,224,164,533,302,6,246,526,120,568,365,363,629,371,245,635,520,532,81,417,36,837,621,279,831,430,561,719,660,60,815,587,463,235,502,500,114,143,24,357,490,596,257,83,420,325,185,486,117,857,768,747,585,65,781,774,270,582,476,200,153,126,866,423,723,248,749,742,166,795,687,329,865,359,507
 ,523,95,725,894,109,609,618,64,800,33,218,265,168,77,210,854,492,557,183,555,506,32,399,536,277,419,87,489,735,682,174,630,51,468,138,406,206,730,893,512,611,701,23,453,852,543,268,633,690,477,341,885,249,386,285,52,201,261,96,361,521,377,165,353,595,457,483,675,789,883,613,579,309,599,739,826,726,141,693,890,777,628,158,45,375,336,378,871,562,442,255,228,129,260,496,54,694,131,745,305,34,617,710,650,272,58,810,68,519,344,234,196,292,86,43,859,604,21,199,88,289,190,493,455,92,75,627,5,22,669,281,897,93,608,518,385,369,215,144,666,762,422,538,15,79,776,537,514,713,592,648,686,237,176,757,184,653,173,188,395,558,590,119,194,516,697,640,17,743,391,266,155,786,421,501,830,792,552,900,738,509,841,780,37,135,612,167,600,27,287,863,333,44,327,818,503,14,383,326,879,438,495,535,836,799,223,886,572,614,828,676,98,298,770,303,896,814,328,90,448,104,658,862,2,655,766,35,315,310,205,808,488,450,108,642,679,181,656,122,610,182,351,705,842,132,379,624,140,525,178,354,48,382,698,688,616,52
 4,784,76,505,208,840,150,494,515,873,729,680,798,332,192,78,38,121,464,435,115,684,829,498,794,657,231,778,465,728,806,459,161,193,262,598,772,112,644,291,301,101,346,706,311,887,711,97,661,322,559,636,432,151,407,57,436,727,410,759,740,25,833,581,160,665,8,300,405,243,583,209,225,689,603,116,294,597,654,813,413,761,392,71,393,288,39,570,239,821,773,662,400,752,105,61,791,712,307,845,601,163,528,241,480,221,474,685,16,734,172,787,607,213,319,286,756,73,343,645,133,671,134,31,282,664,563,550,444,802,469,760,546,771,269,755,9,69,323,491,4,137,313,179,380,356,424,84,74,152,89,593,397,736,347,544,875,564,330,513,858,358,320,638,146,429,823,416,788,589,94,737,479,264,547,717,663,252,189,203,238,720,297,569,125,159,381,425,817,236,456,783,677,250,403,527,283,467,345,342,517,230,534,861,111,539,844,276,819,142,433,591,622,560,349,55,471,212,695,443,556,30,626,136,646,40,779,475,187,540,376,222,180,891,366,683,53,414,20,11,584,667,127,12,335,409,284,481,855,408,864,360,321,299,812,3
 72,446,148,699,80,271,702,485,696,551,352,85,263,452,82,605,293,529,586,632,401,754,651,674,472,233,716,484,211,574,128,637,652,709,130,461,763,834,549,541,273,162,775,227,573,374,306,769,594,703,216,451,888,67,439,387,577,91,748,790,204,449,835,59,880,100,217,707,548,708,753,731,339,721,10,804,275,478,473,522,278,113,899,177,884,567,66,103,803,856,672,28,606,232,554,350,454,718,154,631,649,758,324,767,437,259,355,214,253,898,715,418,13,482,851,50,106,811,256,744,870,722,881,441,797,434,860,553,511,226,816,62,750,7,782
+311,258,349,261,49,779,188,255,441,597,717,114,537,887,828,242,61,551,510,574,536,581,257,558,185,718,96,413,845,228,524,332,181,432,701,638,405,12,888,264,206,141,422,315,582,191,241,19,180,415,58,693,505,691,724,698,305,542,224,123,424,409,357,362,575,236,302,274,561,839,93,150,386,603,342,469,697,122,259,807,618,607,466,668,24,572,826,429,664,273,211,471,320,832,140,27,77,208,313,647,268,60,324,834,710,254,545,436,808,747,749,59,584,84,549,715,573,139,110,734,227,649,435,290,438,232,408,876,143,683,50,293,741,384,498,120,499,874,13,82,512,838,784,878,595,85,447,636,788,40,798,806,627,770,790,367,900,621,289,650,898,765,21,467,493,748,153,768,112,556,809,657,785,895,113,879,337,494,81,379,554,14,557,42,197,563,745,461,234,526,215,750,71,459,842,365,173,288,308,251,875,270,97,793,130,327,811,225,126,380,394,395,220,796,387,218,209,175,341,579,398,55,383,508,286,158,612,207,864,513,865,492,353,625,671,661,586,704,623,48,41,883,147,653,304,565,480,26,742,794,162,648,321,692,3
 36,18,620,891,339,746,687,92,819,51,577,592,292,345,187,626,775,729,599,278,752,129,168,433,514,154,199,766,356,814,45,443,182,485,319,101,46,534,694,656,281,804,89,539,518,212,17,544,866,309,594,886,488,111,615,193,2,142,172,673,165,161,250,449,306,546,588,500,501,783,406,533,36,642,322,860,420,5,624,800,712,456,489,167,733,695,604,658,756,541,105,600,128,580,127,68,366,184,855,643,171,275,412,283,39,238,861,310,411,263,67,148,107,62,69,880,454,230,164,102,4,3,753,703,205,11,654,116,78,338,246,829,418,527,103,455,328,29,401,525,699,738,799,170,243,468,392,707,847,789,416,372,1,108,815,151,791,479,614,568,515,351,47,149,732,611,450,76,856,670,8,30,445,155,772,635,867,619,776,548,382,622,870,44,25,523,66,280,86,144,894,640,53,431,675,491,121,629,231,893,583,521,198,538,833,370,889,297,570,437,835,458,210,421,6,659,487,285,427,633,388,818,844,146,690,782,73,504,15,201,780,564,696,247,651,725,478,350,316,821,10,560,868,569,75,138,639,186,346,20,686,163,681,402,397,317,601,820,3
 25,452,72,841,355,547,307,719,744,849,846,399,326,203,176,373,520,631,189,700,777,303,882,381,645,457,702,434,740,451,331,291,277,410,836,460,736,233,213,200,344,817,177,824,632,194,714,644,464,376,680,559,507,64,244,655,682,787,641,229,425,763,98,728,135,522,630,132,145,552,333,837,628,256,677,503,276,881,360,873,566,31,716,390,202,221,190,517,407,812,87,497,226,260,463,762,22,852,358,57,730,430,751,609,571,590,174,482,385,391,662,585,159,531,803,364,665,369,377,802,314,265,596,354,271,731,688,769,472,850,810,862,106,348,109,169,32,550,183,300,637,28,613,404,118,94,266,104,368,195,63,608,511,652,605,282,684,739,890,299,423,831,312,754,705,179,840,757,83,490,660,79,663,786,709,204,400,115,530,476,160,767,16,371,578,666,713,95,119,773,858,359,711,287,9,679,540,124,823,598,252,567,393,519,827,33,872,396,610,465,453,801,267,262,496,617,352,689,720,249,272,509,294,99,825,152,235,634,721,589,477,899,298,484,52,219,156,134,795,375,100,80,43,669,495,706,591,428,859,65,269,70,529,73
 5,722,216,426,442,602,830,403,797,462,23,323,301,562,446,473,38,727,676,848,334,843,295,535,475,54,805,737,35,414,34,759,417,792,157,672,871,885,237,755,587,296,760,166,448,56,347,781,470,774,543,88,896,222,330,196,253,363,318,853,532,778,678,131,884,223,178,389,708,857,378,816,74,528,117,486,440,248,125,137,91,439,761,474,869,593,343,7,854,851,335,279,483,646,419,90,502,481,553,506,555,685,374,743,192,516,606,214,444,897,723,217,239,329,822,245,240,877,667,764,576,674,892,284,726,616,863,340,813,37,361,136,758,133,771
+437,700,44,208,810,240,324,88,274,35,682,752,380,459,284,138,677,152,814,264,556,22,644,176,829,212,354,171,630,54,512,202,76,137,325,832,43,843,371,232,352,509,636,600,42,93,40,739,154,372,560,196,645,772,583,96,92,3,712,879,835,633,450,367,792,803,310,410,305,319,361,638,316,408,480,198,182,359,268,186,846,200,52,524,768,452,558,446,661,61,563,791,83,497,693,455,702,78,205,500,119,427,47,225,109,806,538,535,613,221,424,743,390,431,826,488,6,593,259,74,657,418,175,192,417,108,395,409,333,265,642,84,856,510,8,533,763,300,818,278,12,332,464,525,160,241,127,224,714,878,685,581,106,235,146,271,646,234,39,113,627,399,863,442,873,231,216,825,223,11,592,53,388,652,375,569,662,97,434,315,898,842,81,615,754,651,472,855,356,547,530,694,364,238,886,85,330,753,32,492,451,515,609,103,838,217,277,602,323,540,120,31,519,799,561,673,250,568,522,73,181,747,807,69,72,511,126,680,708,57,653,383,819,436,415,874,179,817,833,679,821,400,311,114,378,329,458,681,588,299,89,102,242,737,19,683,168,3
 66,891,441,110,598,290,707,850,861,590,764,118,213,623,447,811,33,457,438,696,169,384,304,219,578,483,346,404,64,864,86,285,660,796,199,258,201,798,298,709,68,204,123,816,2,896,18,639,345,294,478,537,430,736,463,267,706,292,567,760,461,722,174,784,77,273,156,16,552,882,91,206,394,520,775,289,226,51,454,701,479,794,785,741,281,758,128,738,690,551,777,355,489,122,501,597,890,635,668,862,117,820,656,782,586,422,689,548,445,340,474,731,622,317,674,150,872,765,790,482,822,248,667,180,596,788,131,41,209,570,487,725,403,421,800,650,101,71,732,841,823,572,87,320,607,494,632,491,60,786,462,469,508,382,531,844,328,9,253,849,521,379,153,256,601,539,571,845,624,90,360,756,49,612,142,405,166,704,67,502,715,699,194,339,297,828,134,629,900,675,222,25,549,541,641,666,453,428,313,228,376,308,643,402,45,15,188,550,860,94,190,840,244,314,59,670,813,797,448,184,724,112,312,824,611,637,288,111,513,449,789,105,189,742,619,733,801,834,555,678,303,584,713,62,140,143,703,869,564,899,387,165,465,322,
 195,416,649,887,207,347,420,554,104,426,608,358,82,604,443,781,397,836,659,580,161,566,260,546,296,867,80,672,100,147,466,432,276,243,7,729,885,191,779,58,245,65,529,193,214,20,526,381,866,728,859,812,876,671,468,335,27,595,252,178,776,591,839,407,151,744,734,802,559,499,536,136,605,507,370,892,1,233,498,14,585,493,628,710,185,599,368,155,135,158,490,327,46,353,692,282,634,769,255,229,396,716,664,857,854,148,475,761,172,669,309,263,852,211,348,485,697,691,262,858,773,411,614,883,745,75,665,471,98,392,735,684,444,655,230,532,514,527,28,755,331,557,848,654,116,220,787,711,215,717,406,895,543,771,481,275,770,808,663,562,343,698,518,239,721,130,218,594,373,877,36,321,830,257,295,336,433,302,385,587,17,429,589,575,505,425,618,34,503,391,95,631,129,871,38,837,759,640,157,889,740,183,159,893,29,173,687,616,750,749,610,5,577,565,573,145,726,79,496,369,579,144,727,283,783,287,210,413,338,746,647,439,582,251,249,470,386,767,517,545,374,280,751,504,793,293,762,121,48,326,414,334,894,66
 ,805,676,197,870,851,553,435,730,269,827,621,486,139,306,831,37,528,344,337,748,177,467,115,237,167,881,266,576,686,4,440,393,55,476,377,574,523,506,648,865,780,542,495,107,757,897,620,149,10,187,766,363,617,625,162,365,412,419,389,349,853,888,56,720,350,815,423,164,286,534,291,460,318,26,774,124,246,544,341,362,270,884,301,606,261,99,688,719,357,247,203,795,477,868,23,254,132,170,804,21,272,24,63,351,778,342,401,125,227,484,70,705,723,307,133,603,473,456,880,516,236,141,398,13,50,695,279,30,847,809,626,875,163,718,658
+512,705,257,722,893,133,808,473,285,329,126,706,719,19,26,381,835,498,554,546,856,163,419,211,751,59,549,727,464,489,792,571,441,656,200,314,280,883,37,410,505,597,374,382,484,453,354,838,670,764,680,424,316,198,199,304,623,299,646,873,710,351,278,252,420,649,707,848,537,148,675,563,219,146,861,238,81,460,514,226,476,89,545,92,852,151,459,683,425,282,757,422,417,10,657,758,821,482,233,101,678,774,330,77,360,606,162,865,604,201,62,825,152,735,643,64,259,871,562,340,525,111,673,247,510,445,720,13,708,136,800,474,306,866,367,693,570,79,863,663,415,31,27,11,421,662,158,598,427,895,472,58,183,32,145,231,7,132,515,475,5,397,887,567,724,440,696,202,659,207,43,117,18,2,511,265,372,164,739,192,819,875,149,822,613,215,186,641,654,205,572,558,777,179,294,500,807,667,300,364,144,846,840,128,851,679,63,880,492,869,551,335,458,139,450,728,449,465,660,197,378,839,461,142,264,730,96,750,568,565,23,635,507,742,650,395,167,577,414,791,868,22,771,191,521,718,816,820,700,94,508,467,295,541,438,
 836,261,70,827,65,84,738,54,790,408,658,621,605,437,477,73,50,350,504,38,456,762,281,241,759,338,82,849,52,741,356,832,286,307,862,879,390,566,61,809,86,694,173,756,653,889,275,327,423,193,56,137,829,153,491,855,772,466,317,788,685,586,479,731,120,401,339,753,288,457,348,897,208,768,154,843,854,256,287,170,763,273,559,210,301,269,488,483,223,784,217,733,530,815,689,587,672,21,697,517,760,837,677,888,603,569,435,393,590,740,721,737,726,802,343,357,544,418,867,881,870,51,523,406,813,305,574,794,684,332,272,268,352,891,220,359,860,494,497,274,138,190,752,573,538,655,108,8,49,560,600,877,745,322,539,14,195,391,276,240,434,876,579,112,442,665,648,171,204,890,787,630,652,127,388,271,244,634,398,592,436,3,786,817,501,698,766,810,564,1,823,789,165,303,333,584,168,609,93,157,203,755,622,172,627,45,550,296,712,160,532,380,744,892,690,619,355,392,341,633,124,104,640,95,302,830,236,859,389,116,561,68,779,125,234,323,692,433,141,882,411,20,585,691,785,229,366,365,833,349,487,793,801,509,
 631,147,76,260,431,894,83,319,526,583,361,455,12,150,239,624,536,765,218,516,470,703,98,637,430,36,754,463,629,123,503,182,607,262,248,279,377,520,709,166,687,379,416,311,34,468,227,214,632,109,616,527,826,548,601,318,681,480,270,230,60,246,664,878,254,582,71,715,312,310,645,857,232,209,24,581,293,593,245,776,44,309,4,169,796,216,174,589,812,499,575,717,17,734,454,326,615,602,540,884,122,446,674,161,595,290,400,113,716,647,669,578,814,102,608,502,118,368,490,277,524,767,547,407,396,746,773,618,135,66,225,249,447,80,74,743,783,552,451,831,159,638,370,187,872,428,291,699,844,448,506,375,841,900,775,369,413,644,770,362,115,176,346,384,41,222,131,228,701,385,107,874,519,53,847,213,30,105,702,258,714,363,462,761,266,806,251,328,119,242,795,818,155,16,194,331,429,886,522,513,612,313,399,533,686,799,177,97,864,283,611,626,439,353,90,485,471,324,267,628,184,180,387,704,292,781,748,29,729,373,347,178,289,175,40,325,402,666,749,668,493,85,591,596,769,811,243,206,196,557,181,75,780,599
 ,898,580,221,284,320,834,553,140,129,543,39,636,853,383,237,342,469,409,803,100,91,67,478,15,682,345,185,896,57,72,828,344,732,46,555,297,614,106,9,78,736,315,531,334,528,426,594,899,688,88,337,110,518,782,6,432,321,535,651,263,845,87,671,358,298,778,48,805,496,542,42,25,798,33,723,444,713,588,255,620,804,824,625,747,617,376,103,130,371,842,121,69,610,576,725,412,404,695,134,642,452,386,308,235,250,443,797,188,99,336,212,47,114,711,529,403,143,394,534,28,495,486,676,156,35,405,253,556,55,481,189,858,885,850,224,639,661
+29,790,306,87,686,183,359,367,573,93,682,419,717,668,458,370,201,43,846,21,745,280,528,527,730,269,136,216,874,255,785,535,219,409,694,635,362,459,557,35,50,119,716,616,339,278,232,513,244,670,277,63,229,658,788,115,340,228,733,818,862,234,196,504,824,712,578,450,7,695,83,494,444,594,572,523,246,333,15,188,852,343,303,483,600,259,851,748,845,274,713,386,414,507,609,288,191,283,347,356,218,402,62,511,126,643,398,659,867,641,307,627,571,89,870,385,213,567,105,199,224,601,78,344,731,52,700,485,465,610,559,39,611,587,177,84,844,546,569,319,290,574,581,466,37,153,342,67,881,718,882,708,96,360,236,443,715,529,264,108,678,796,604,2,883,86,338,776,111,165,672,300,474,665,162,847,595,379,91,320,897,540,141,206,602,456,765,849,16,265,73,880,197,460,703,423,363,804,92,492,786,657,637,354,254,508,568,634,378,618,453,353,129,705,61,764,451,374,760,433,19,258,614,321,121,631,324,766,893,302,532,729,660,781,787,800,103,890,839,267,685,501,401,102,652,677,723,286,853,625,147,117,79,879,263,
 515,56,464,872,316,309,599,294,545,675,885,752,810,296,36,671,358,761,148,534,314,125,45,646,406,273,684,642,620,295,40,806,468,493,655,688,17,75,332,110,615,430,383,352,140,628,207,753,262,410,480,424,525,623,536,395,576,412,833,298,80,329,746,70,202,297,42,548,179,268,82,704,503,214,756,725,462,55,139,237,749,551,558,757,838,418,34,884,489,225,596,626,854,323,441,54,636,477,896,366,47,170,189,687,719,898,691,44,174,156,577,417,434,624,868,26,674,130,794,495,486,607,888,405,429,619,426,592,308,227,208,564,58,647,176,85,369,784,479,471,650,683,710,693,74,654,388,593,522,10,181,469,538,822,143,442,487,808,669,281,9,696,133,667,570,598,390,816,762,553,253,158,49,588,132,855,552,81,27,100,114,584,467,311,605,304,510,632,243,608,899,563,204,231,95,499,422,150,737,230,97,325,4,699,803,452,245,361,116,813,782,88,377,549,144,8,341,732,432,834,754,368,555,247,736,639,310,411,99,292,802,560,825,173,622,512,24,400,589,597,792,676,14,215,151,457,233,30,301,739,299,900,640,20,5,157,476,
 428,112,797,436,566,773,38,137,811,580,720,387,777,585,751,393,326,842,692,221,850,18,743,561,858,242,491,48,146,771,260,190,118,164,891,860,590,251,124,420,372,389,65,198,178,653,210,889,127,193,886,857,256,408,32,382,791,276,59,742,709,518,138,291,661,399,470,122,438,681,238,505,819,239,887,205,371,728,284,630,270,478,807,217,656,502,348,68,272,455,123,90,226,747,11,866,579,612,6,185,427,821,644,740,212,795,539,473,801,439,200,875,64,392,830,767,814,3,864,894,617,526,895,60,266,381,506,498,94,892,702,726,167,315,407,249,275,287,603,556,707,514,836,447,142,741,413,180,496,454,789,815,373,809,51,104,848,435,837,77,271,698,285,727,113,364,863,679,780,252,357,330,645,337,203,629,530,484,778,195,575,831,403,312,734,440,279,550,415,448,663,240,724,71,482,878,828,192,812,829,25,220,873,159,355,542,861,827,871,69,175,735,107,664,533,755,166,738,711,488,261,649,449,472,394,235,160,722,744,768,475,775,66,12,327,586,524,391,721,1,346,606,211,543,554,490,98,194,322,169,613,805,187,774
 ,840,184,186,799,520,763,152,516,223,376,633,155,680,750,384,209,621,248,666,519,421,222,23,106,769,562,509,257,163,282,317,318,820,521,404,662,770,57,583,859,250,835,149,134,779,798,334,293,544,843,154,651,335,53,46,13,517,463,673,876,817,145,714,461,826,101,28,446,701,437,351,168,305,547,76,541,41,345,313,109,869,131,759,380,161,531,445,706,375,22,697,783,823,336,171,182,500,832,350,33,331,349,772,172,565,425,135,481,591,328,120,638,31,416,397,648,690,865,841,72,128,537,241,396,856,431,289,758,365,689,793,582,497,877
+750,273,162,327,407,694,113,42,170,371,758,739,2,625,537,120,695,485,535,621,35,249,583,183,641,568,448,226,206,83,11,17,163,34,229,869,103,736,616,540,588,662,435,461,96,118,157,504,130,3,518,593,848,841,423,494,37,197,391,668,463,823,711,329,624,667,8,124,682,297,455,521,334,398,85,175,553,310,555,613,692,438,87,697,452,738,158,27,269,191,115,876,40,753,475,317,748,86,291,751,153,205,346,434,478,756,710,63,125,203,768,427,388,517,442,759,237,172,373,392,792,456,382,272,70,364,6,717,64,270,312,367,892,98,223,672,387,505,606,160,105,499,611,805,543,278,279,532,296,707,247,642,526,544,534,280,815,284,58,426,818,117,723,788,579,617,76,847,294,309,712,315,628,845,483,313,578,236,515,467,802,700,454,562,656,785,321,660,587,787,742,215,302,289,899,26,119,389,300,421,375,39,173,390,859,10,415,132,232,91,19,59,722,863,826,248,129,549,65,171,556,747,812,267,340,134,370,253,224,110,850,15,796,9,24,865,585,402,709,676,498,706,74,541,81,5,12,619,47,356,217,413,558,275,71,396,603,685,72
 1,775,411,264,680,444,868,550,204,447,128,598,718,744,791,180,633,439,809,547,263,61,295,640,41,437,265,431,644,82,221,190,405,615,594,484,880,377,638,212,144,214,491,228,900,75,806,646,400,122,524,244,551,94,169,466,140,731,839,126,864,513,885,468,29,536,84,840,732,156,227,330,23,577,725,669,383,7,769,252,820,664,862,683,333,149,794,761,178,418,164,271,368,152,836,724,653,843,897,184,440,322,293,336,771,842,569,109,107,238,425,287,713,443,301,608,492,589,581,445,194,460,89,509,610,69,181,614,539,817,255,719,727,740,306,28,147,819,884,639,251,357,4,831,689,813,799,187,565,141,209,661,659,596,795,182,168,607,584,673,366,32,1,497,376,424,663,552,254,533,861,352,326,127,749,554,866,365,726,529,620,14,218,25,686,142,837,827,385,510,288,832,341,811,816,519,752,696,90,728,277,216,734,92,102,335,395,825,323,67,623,457,655,88,472,887,474,379,514,586,473,148,636,803,355,502,449,72,561,363,508,159,814,835,808,883,574,222,833,670,629,801,145,243,493,626,881,612,804,16,489,754,703,419,4
 50,857,690,479,233,46,800,471,78,797,308,161,198,201,451,488,888,250,199,545,60,580,602,13,781,166,834,401,566,45,630,506,522,200,258,793,225,856,259,176,99,810,404,645,345,195,776,600,877,895,432,774,851,276,627,155,409,648,632,523,68,893,516,481,495,852,879,699,174,416,332,829,52,530,807,230,55,557,121,782,762,343,597,446,307,44,80,410,146,763,348,311,507,359,609,151,414,350,573,399,867,242,890,860,477,18,702,30,282,73,665,599,403,512,177,430,501,590,538,292,210,542,647,875,77,855,649,219,743,299,783,476,745,135,422,591,358,245,635,188,464,757,283,108,261,397,779,286,772,93,730,21,870,139,572,874,637,846,417,652,849,563,393,764,548,53,234,360,687,138,564,830,192,643,741,62,239,112,305,189,66,320,328,677,202,798,285,143,131,274,784,339,886,281,691,331,235,193,894,486,453,260,767,354,500,314,319,372,266,853,208,570,786,316,56,654,211,362,268,525,116,735,38,733,604,167,634,111,766,470,511,693,559,666,347,33,714,441,531,708,165,527,428,872,257,873,381,318,720,384,36,729,240,82
 1,433,380,898,770,657,361,871,458,891,349,290,394,101,778,43,459,369,705,858,31,780,150,675,528,674,412,765,658,207,324,737,49,220,133,790,684,520,824,896,429,716,79,256,882,773,137,469,100,298,436,338,822,704,503,595,681,386,95,420,546,889,406,337,671,408,622,465,487,618,54,789,303,97,679,378,196,777,136,179,353,755,592,342,601,482,715,496,351,582,480,701,20,844,48,262,462,22,605,57,698,231,154,51,854,304,571,325,241,746,344,838,576,650,374,651,185,567,828,106,490,560,678,104,213,246,575,50,878,760,123,688,186,631,114
+484,664,24,648,890,271,731,224,114,288,284,656,739,329,151,93,808,519,679,634,873,27,330,69,754,66,317,699,758,222,814,409,146,575,211,546,54,877,349,239,360,457,336,274,443,160,56,789,454,740,496,570,405,413,312,391,455,163,573,881,788,376,175,67,555,654,613,840,628,332,488,415,35,79,859,68,62,187,395,421,691,7,472,102,831,116,722,652,563,22,673,591,182,192,535,560,795,195,14,118,531,588,100,202,478,631,119,874,805,233,150,774,65,608,766,129,124,853,299,444,491,82,660,17,445,236,685,293,507,99,702,318,672,871,243,580,653,326,850,407,314,179,125,335,461,418,2,706,696,894,734,232,123,76,265,34,525,41,305,557,498,537,888,644,825,655,480,508,433,60,219,39,97,497,272,629,319,8,616,25,883,864,33,760,556,247,260,770,564,200,493,752,620,23,791,340,720,662,52,177,442,836,785,213,863,553,148,870,207,872,419,101,367,474,501,666,194,309,600,48,283,813,554,4,29,589,6,698,828,504,368,618,595,797,742,693,89,782,619,728,855,327,624,172,372,743,827,765,815,174,218,544,110,730,238,773,255,41
 7,862,153,37,602,198,707,640,810,529,626,145,568,217,115,518,311,96,227,762,159,137,606,47,193,849,164,526,240,842,108,77,843,861,398,719,20,851,167,592,21,775,466,878,128,830,190,246,375,13,751,131,275,832,641,186,462,676,623,615,423,799,16,633,258,764,470,313,435,897,113,721,406,844,837,300,510,168,769,324,357,464,512,426,643,726,64,772,292,596,657,727,471,494,502,322,846,397,803,884,547,880,506,838,356,384,611,621,549,534,513,737,715,339,463,109,869,860,854,117,756,112,723,286,400,763,578,42,523,178,422,882,136,270,845,479,434,291,347,565,750,440,503,567,241,205,248,617,485,858,569,528,402,104,105,612,185,70,373,866,429,130,436,622,468,432,257,885,683,586,499,408,411,610,152,826,399,684,482,253,700,759,450,453,688,801,263,430,893,692,19,323,393,371,249,598,465,132,138,625,705,351,607,396,370,165,713,389,704,95,716,889,792,668,84,381,609,690,285,278,536,51,439,811,252,820,154,181,574,83,784,72,251,404,757,467,517,868,420,366,661,538,779,143,53,210,786,674,334,891,793,456,6
 37,103,171,75,540,896,228,120,516,577,483,614,268,359,30,543,352,736,49,741,582,576,88,806,328,354,712,725,571,290,451,245,561,106,44,74,189,798,829,169,732,81,133,61,237,225,458,134,473,191,807,687,875,761,783,414,452,364,214,325,155,279,646,887,638,362,58,651,425,533,527,833,183,3,282,647,87,824,80,701,345,55,307,149,680,388,9,437,753,220,566,678,180,559,412,94,541,635,745,865,315,387,449,394,597,663,649,11,768,603,636,550,809,86,771,261,26,581,475,410,481,821,804,234,277,852,834,428,342,85,294,203,781,316,304,686,755,344,289,749,12,579,158,196,867,520,73,492,819,441,204,386,796,900,817,524,486,735,823,590,303,548,199,460,215,15,337,301,500,675,157,876,448,32,848,173,111,166,545,71,509,365,378,630,438,681,142,295,208,267,677,724,197,297,1,682,231,879,711,552,343,777,505,390,718,856,31,226,839,639,645,748,558,188,242,446,355,170,374,515,223,209,244,572,361,729,717,162,542,201,348,379,331,63,521,144,403,424,642,627,287,221,585,310,703,714,495,57,447,599,5,321,650,427,898,539
 ,477,459,45,886,694,121,320,670,107,802,818,235,18,259,605,264,697,98,91,416,298,230,551,346,46,895,139,176,780,141,522,135,431,490,385,184,266,392,767,709,665,229,708,122,746,899,659,127,161,147,632,658,487,350,126,401,601,92,835,262,794,776,341,710,363,812,338,489,40,250,787,216,514,382,667,562,78,583,695,747,383,841,800,358,369,38,353,790,333,256,530,593,738,689,212,469,10,594,604,254,308,206,28,584,822,59,43,50,36,511,90,733,476,302,269,276,377,306,778,671,744,156,380,140,280,669,273,296,587,847,892,857,281,532,816
+533,252,273,180,49,767,15,103,332,456,815,437,141,850,778,170,275,444,580,526,88,432,501,389,418,716,244,173,591,99,131,101,126,121,538,846,258,251,835,396,366,364,502,460,254,108,187,168,48,72,241,605,765,838,675,593,76,331,320,319,462,698,595,407,666,498,54,26,552,680,204,348,430,584,34,350,695,221,367,736,711,596,188,762,128,717,542,146,518,246,81,797,155,848,315,74,336,94,352,769,97,28,326,732,574,569,699,53,485,529,812,163,564,216,525,804,370,1,193,545,566,654,300,325,237,265,98,856,25,557,93,291,883,44,317,340,492,795,203,45,250,773,786,876,527,95,422,504,620,225,588,813,600,747,706,369,896,523,116,480,895,472,243,607,568,637,23,869,120,441,827,541,787,897,289,735,544,405,212,507,702,239,543,194,463,755,630,609,344,731,493,509,62,448,899,127,12,353,314,383,761,16,21,664,510,60,715,4,159,41,125,222,505,879,658,199,142,387,166,378,479,321,696,439,339,66,556,185,619,215,884,174,673,196,277,847,625,613,729,294,151,859,10,627,176,148,89,232,341,685,129,476,489,524,154,100,6
 11,852,548,814,623,123,800,189,821,608,233,443,117,554,819,799,768,162,777,303,490,513,449,13,272,790,33,738,55,408,373,297,306,8,77,547,576,652,656,693,347,399,171,109,90,355,900,150,782,836,530,6,663,219,153,30,140,657,19,409,636,284,635,587,834,470,122,674,179,746,229,424,130,720,56,181,682,734,589,115,718,198,840,760,820,616,612,357,433,759,78,537,14,112,292,114,878,721,440,563,779,124,75,302,671,361,618,628,247,52,18,65,183,710,590,363,217,285,82,167,763,646,197,143,365,322,312,92,208,741,565,713,5,651,567,296,381,200,434,844,889,400,249,329,110,833,839,863,601,175,138,42,586,393,801,633,783,391,334,464,206,390,649,264,119,271,749,642,178,211,235,286,874,454,724,368,690,520,703,425,865,231,234,202,50,35,349,68,893,766,149,536,477,725,227,798,571,830,722,653,24,562,659,281,867,118,311,262,737,740,261,105,152,447,500,182,521,864,478,712,757,374,647,514,307,748,40,356,681,295,733,290,631,491,750,599,665,891,165,403,882,535,318,451,398,210,417,224,870,415,781,58,375,508,691
 ,707,471,745,255,751,330,268,572,573,406,872,689,304,245,186,299,515,832,469,139,686,402,436,845,59,780,201,837,342,684,213,553,461,452,259,622,688,539,632,220,184,228,862,263,754,506,160,793,677,770,764,610,719,775,106,426,392,641,774,645,394,47,888,283,678,309,785,851,380,2,558,371,873,316,458,802,351,46,831,230,875,728,96,752,495,267,11,83,362,135,842,113,337,412,327,467,487,51,701,446,158,866,335,885,824,578,195,466,133,343,67,714,634,240,602,549,450,676,438,483,614,288,481,638,669,79,858,758,531,661,672,855,789,376,85,266,401,57,423,431,269,644,301,496,270,80,169,598,161,662,7,223,191,803,414,497,655,742,853,796,512,739,805,420,825,650,22,624,667,310,226,697,427,486,784,776,64,359,36,482,257,29,639,63,597,411,810,516,20,3,585,871,397,877,242,205,559,385,70,898,604,308,274,617,468,743,31,727,416,445,726,298,788,570,324,287,704,172,621,579,457,71,705,38,419,791,43,484,372,817,603,583,880,465,555,144,32,459,305,772,503,69,278,104,861,435,868,382,413,829,102,107,253,279,841
 ,668,323,792,683,700,708,744,730,811,37,345,379,333,692,214,132,648,753,886,134,857,111,592,550,218,709,818,248,276,87,809,147,582,91,807,854,823,528,892,546,575,421,177,771,256,209,694,260,626,532,86,894,522,429,360,410,453,39,756,577,890,534,190,843,293,388,354,687,826,61,849,84,236,395,338,346,511,9,17,157,643,606,475,806,581,615,145,723,794,328,560,156,822,192,73,540,136,640,238,629,473,282,377,551,494,679,280,384,881,594,561,474,499,670,517,207,828,816,455,404,660,860,164,488,442,808,137,887,313,27,358,519,386,428
+430,195,341,286,6,819,149,221,390,612,736,176,405,883,832,217,111,579,450,627,393,557,276,504,179,750,151,395,772,206,382,251,181,371,662,690,375,48,884,346,271,208,386,307,523,177,235,25,162,297,89,737,613,727,689,735,259,529,190,92,333,519,453,351,528,234,223,226,623,813,147,172,384,566,257,427,738,131,344,830,562,617,431,701,9,631,754,305,572,272,128,571,266,852,127,34,153,186,322,698,255,33,376,829,743,279,580,327,719,700,782,37,553,144,443,758,556,77,152,740,323,646,473,298,336,269,287,882,95,660,26,347,792,285,507,198,413,869,24,72,481,835,789,888,641,105,459,668,713,28,723,804,664,781,811,357,900,576,264,675,899,693,32,574,412,771,116,780,140,559,816,661,799,898,173,856,355,484,142,414,479,35,581,79,210,600,694,416,315,601,312,650,78,455,872,304,125,232,349,253,859,188,49,796,227,246,800,156,117,275,326,366,309,825,521,158,180,201,242,532,488,109,438,514,334,97,616,138,803,478,881,380,399,496,561,688,636,629,577,94,17,885,102,697,231,435,358,66,622,773,178,670,404,587
 ,308,8,666,892,292,775,704,62,842,44,619,500,224,295,175,672,777,763,590,288,756,164,256,515,474,106,212,766,252,802,40,505,154,436,289,46,7,597,733,680,444,787,122,512,471,216,2,537,889,284,647,887,506,65,598,165,21,82,146,633,136,238,352,359,460,573,681,558,410,806,379,639,29,593,311,841,290,22,687,828,730,332,542,135,746,674,667,715,676,492,191,618,80,480,104,53,409,118,871,570,209,418,563,282,5,200,798,268,525,389,114,91,71,41,50,853,555,211,193,74,3,15,751,638,185,23,583,145,87,303,245,849,423,637,51,545,432,69,330,452,673,760,837,167,197,508,291,765,858,822,534,372,12,64,757,222,812,516,605,490,502,454,27,219,705,530,356,98,827,642,18,68,457,213,809,651,831,554,818,595,527,634,874,54,61,422,56,220,101,132,894,567,38,485,684,603,112,685,338,890,640,596,171,614,807,267,893,274,517,463,805,489,239,368,13,678,564,261,391,712,325,786,851,169,717,725,75,582,10,254,790,429,708,184,692,679,547,495,406,857,11,462,879,626,134,225,592,196,425,60,731,205,620,294,476,434,657,815,34
 3,578,47,845,320,420,437,748,652,863,824,378,236,163,129,402,644,531,121,744,686,397,878,283,625,442,755,482,768,340,400,363,364,411,764,441,695,342,230,182,318,848,218,846,649,141,770,568,602,541,594,518,611,52,335,632,648,814,696,204,300,823,160,747,120,604,702,207,100,511,365,861,509,316,653,513,233,876,339,880,621,20,699,446,174,166,161,550,377,836,115,526,270,214,546,665,1,838,451,83,779,328,795,643,586,447,199,408,302,324,711,503,203,551,741,319,635,465,301,720,262,280,499,510,244,778,710,742,565,785,821,854,187,310,119,215,39,535,192,258,606,58,520,367,137,57,337,123,428,139,36,467,608,560,645,440,654,774,875,398,536,826,345,759,749,133,776,734,70,475,691,157,615,810,767,130,374,73,464,477,96,709,14,439,487,716,714,55,84,753,864,387,762,329,30,584,424,126,850,533,317,540,348,548,833,4,843,321,486,591,466,791,383,228,433,589,361,656,683,265,247,538,229,148,840,143,314,549,729,539,497,895,388,569,59,155,189,159,784,483,88,85,63,732,468,769,599,461,867,86,202,45,522,745,
 671,248,575,445,610,801,544,797,609,19,281,354,472,469,421,67,707,728,865,260,862,278,607,543,31,794,761,76,415,42,793,373,739,110,724,868,877,369,820,493,385,669,183,585,43,243,788,449,752,458,107,897,277,407,263,350,362,249,844,448,808,703,90,886,170,237,456,722,855,306,847,93,491,150,524,396,370,99,108,124,394,783,417,873,630,392,16,834,860,401,299,360,659,381,103,552,403,498,470,628,677,353,655,293,494,624,240,419,896,726,331,241,426,817,296,194,870,658,682,588,718,891,273,706,501,866,313,839,81,250,113,721,168,663
+741,78,129,780,634,821,609,203,50,753,314,324,561,744,653,59,700,847,115,879,828,343,61,138,167,563,303,822,629,288,615,274,193,646,290,446,179,718,812,509,514,442,22,14,696,148,163,328,420,527,259,885,616,377,204,843,464,518,39,394,150,488,354,10,118,121,375,792,876,592,481,64,26,92,820,77,572,38,676,874,190,272,672,318,359,401,630,325,217,87,182,577,187,628,65,308,708,201,33,400,656,263,429,683,867,195,268,846,675,402,613,230,82,581,166,474,530,671,333,849,455,168,853,30,143,469,410,790,233,266,200,623,715,845,626,589,101,784,452,214,570,578,395,815,844,373,116,891,371,681,445,374,673,554,814,19,863,161,397,873,860,497,639,871,220,894,341,415,449,480,417,435,479,855,267,690,51,147,587,97,382,564,444,601,120,312,256,162,761,428,608,391,485,58,826,348,575,66,345,9,668,641,331,742,825,427,503,756,28,834,404,250,433,519,751,85,35,94,174,248,697,662,279,209,265,135,304,103,725,731,758,363,237,685,620,378,565,298,178,470,390,818,392,733,74,669,709,476,658,447,310,869,396,297,383
 ,311,771,866,302,602,454,91,770,196,405,226,57,60,108,878,361,495,238,501,360,72,749,582,46,379,43,327,759,461,289,691,260,210,7,472,438,810,895,357,881,465,232,208,841,573,576,515,857,338,376,842,89,388,124,3,525,240,27,155,571,670,463,107,854,358,752,734,750,875,489,764,747,339,804,633,712,468,778,887,719,484,228,11,346,207,513,890,335,172,651,243,114,127,580,88,775,69,754,316,177,865,898,706,536,24,642,4,722,659,487,153,286,146,180,710,743,23,221,366,599,540,329,278,13,313,364,81,245,667,152,889,49,777,721,424,496,643,37,498,586,387,661,170,18,816,355,544,585,548,837,714,593,173,505,384,534,117,247,104,362,729,434,416,269,491,492,134,499,144,684,426,808,611,549,817,567,287,900,813,807,832,704,252,450,386,234,521,291,244,830,453,175,277,765,720,25,412,632,794,456,547,524,886,595,84,858,478,406,856,421,273,295,760,699,896,877,131,31,695,83,399,803,113,546,522,293,403,517,301,739,255,282,136,596,422,317,868,342,728,520,96,677,883,385,740,380,80,588,502,483,186,439,664,786,82
 3,538,644,36,766,604,748,8,264,772,870,477,635,590,95,68,16,111,67,776,192,76,638,687,654,655,591,257,773,471,785,800,239,224,211,307,490,553,285,381,678,258,17,123,724,370,880,647,41,723,251,824,893,254,241,584,106,597,543,158,732,789,70,840,767,334,542,90,462,594,500,701,48,122,698,356,159,336,443,679,674,227,705,408,235,213,219,15,551,128,850,783,617,528,774,151,32,872,467,569,711,738,330,649,86,692,367,365,516,191,680,56,797,579,184,389,160,508,29,142,788,189,451,6,42,292,884,486,652,315,660,558,535,431,568,600,787,55,216,507,300,119,5,110,619,137,102,482,246,281,197,231,640,791,627,562,276,892,859,202,566,717,448,532,440,75,332,819,353,552,323,423,716,347,726,261,657,707,157,20,181,52,694,249,299,305,225,99,414,745,271,473,624,598,139,555,510,703,253,125,337,702,93,666,864,309,418,769,459,614,73,242,806,529,349,574,2,205,133,735,176,280,40,645,169,650,320,713,493,319,262,294,71,79,831,419,799,149,322,222,47,350,829,100,165,539,526,53,606,862,275,835,533,145,730,811,344,
 206,140,897,194,198,441,782,504,848,556,1,223,164,188,411,512,284,537,663,183,737,693,779,430,636,494,407,550,457,283,625,559,432,63,436,648,686,827,763,132,296,560,218,838,795,156,682,398,466,98,607,861,229,458,541,781,12,793,605,185,610,809,109,839,171,393,796,352,523,768,736,437,631,215,836,44,746,506,621,372,270,899,34,852,475,141,369,612,802,798,126,425,326,368,409,351,618,112,460,762,637,105,545,805,54,236,199,45,882,557,755,62,622,757,130,21,688,321,511,888,727,833,306,689,212,801,413,583,665,851,340,531,154,603
+515,601,139,122,630,388,113,86,304,95,769,767,120,517,399,185,621,159,797,245,161,132,698,236,811,392,418,43,445,65,199,102,127,10,332,870,100,776,450,355,443,548,644,633,2,126,112,664,85,111,551,211,751,834,590,163,27,38,673,846,786,732,585,468,803,807,114,107,320,306,372,656,438,498,128,252,369,419,342,247,848,384,3,650,666,613,361,239,558,175,397,854,90,618,680,396,672,93,343,648,46,329,171,305,131,826,667,138,366,218,583,655,487,425,768,637,59,313,312,88,722,525,101,326,325,196,173,509,212,330,530,150,888,134,32,532,707,351,744,221,7,429,566,626,204,229,264,168,598,828,533,660,259,395,237,382,695,341,28,91,685,241,810,488,840,213,115,863,209,116,690,187,522,721,465,466,710,225,422,476,894,782,257,531,770,756,479,844,373,681,574,528,273,368,899,45,130,699,158,545,424,200,410,191,820,71,365,248,350,154,42,68,602,855,642,552,240,622,364,156,302,708,841,216,228,379,288,559,489,1,759,193,843,147,170,887,371,746,835,661,718,492,155,249,300,76,136,632,308,359,137,87,409,615,25,
 572,293,433,875,611,258,501,437,640,876,829,494,733,157,226,709,612,849,48,578,506,703,323,435,146,336,668,143,426,338,167,831,119,346,420,654,290,202,387,799,362,714,184,12,79,684,55,900,39,753,414,447,271,614,451,636,303,281,696,117,575,812,380,739,378,850,186,35,190,9,658,830,141,62,370,176,693,428,267,152,194,785,469,842,802,823,282,665,192,738,777,432,723,169,453,108,401,715,880,688,670,864,49,677,607,616,568,537,749,518,328,214,400,653,471,448,676,238,821,619,701,581,765,297,580,144,617,761,15,133,234,647,596,463,554,547,750,606,24,67,814,877,801,508,83,135,734,591,745,535,23,682,340,353,560,521,634,862,334,66,347,780,562,460,57,72,604,490,584,752,561,37,385,833,73,503,162,316,232,760,74,599,675,651,82,279,81,800,129,711,898,592,417,58,659,519,758,717,464,600,481,84,376,278,529,485,21,47,80,520,873,217,16,731,105,299,106,689,868,763,475,269,727,275,215,789,726,474,412,219,354,563,704,276,178,818,620,798,865,741,483,773,292,593,705,96,235,250,643,890,628,895,97,203,491,
 496,289,527,735,847,296,393,283,603,123,246,712,335,183,495,421,724,524,869,544,478,331,295,363,567,69,872,8,784,118,254,311,569,452,415,40,549,885,223,815,166,287,124,663,284,274,110,455,539,839,794,866,754,874,774,434,441,52,605,408,317,755,195,879,472,307,713,819,861,582,227,564,298,720,322,504,891,70,56,526,78,686,641,523,742,383,553,125,145,98,18,623,266,60,482,646,265,449,594,256,319,398,816,555,889,882,337,207,781,13,589,53,457,832,285,500,345,687,702,315,822,635,413,671,867,747,30,783,610,99,541,587,771,484,657,44,540,576,394,153,764,358,609,806,571,172,177,691,775,272,790,160,853,222,836,381,205,788,813,778,493,480,791,573,403,793,230,104,458,442,837,5,486,808,260,462,502,301,374,263,557,11,270,534,477,629,407,736,75,339,198,151,719,294,892,94,748,678,538,142,897,729,233,31,884,179,268,505,497,694,627,692,36,631,649,550,140,766,33,516,390,639,41,796,63,792,423,109,536,262,805,674,556,577,405,349,467,201,787,542,586,411,243,716,416,858,375,838,77,208,454,344,224,857,
 19,852,662,348,871,859,669,459,795,386,856,456,499,310,251,851,22,461,430,510,827,121,597,34,367,352,825,360,700,638,51,402,546,6,389,318,706,595,507,652,893,737,645,277,197,809,860,470,261,29,242,725,255,679,697,314,444,446,512,92,391,824,896,103,625,436,740,513,181,440,588,50,608,253,4,772,89,309,565,165,174,286,878,188,579,333,280,757,624,356,357,206,817,231,883,26,210,324,20,804,14,404,64,164,180,779,439,543,244,327,514,189,730,743,427,182,683,431,511,886,321,148,291,473,54,61,570,377,17,881,762,220,845,149,728,406
+69,633,389,470,654,421,673,528,540,480,361,67,858,771,606,396,134,465,620,401,889,467,163,568,311,368,90,707,894,455,875,717,312,784,755,157,500,267,770,103,68,32,424,290,769,371,332,282,486,840,100,534,23,245,687,543,670,554,438,513,704,12,34,306,501,276,779,805,352,828,148,169,294,434,848,522,358,189,139,602,573,319,731,273,393,107,891,827,811,310,706,18,557,462,263,255,97,422,251,191,580,406,231,732,614,171,142,874,898,788,260,378,409,156,757,246,516,759,138,684,3,447,542,256,756,208,832,642,553,658,388,288,146,859,539,63,711,787,313,373,676,692,493,538,403,257,336,597,862,479,879,564,308,472,578,330,795,515,552,637,764,863,342,193,715,617,523,379,265,391,494,495,458,720,71,883,221,415,162,164,713,283,258,179,183,117,741,555,184,70,22,876,317,377,236,680,656,556,239,217,851,836,651,693,87,767,698,834,277,861,742,548,11,344,29,611,423,92,775,562,194,108,116,385,186,588,381,613,900,753,412,839,168,882,878,309,206,843,504,98,456,690,600,357,639,860,868,140,895,736,286,641,85
 ,850,547,349,296,762,601,248,461,425,482,287,149,758,645,524,366,459,443,262,305,460,397,109,38,170,530,604,181,491,854,695,298,300,439,623,384,723,550,278,624,353,62,726,106,481,820,437,505,511,279,507,110,754,291,655,383,360,272,618,351,688,587,47,6,740,51,207,19,324,847,652,622,54,487,686,667,844,865,268,212,595,558,856,154,369,367,589,77,464,857,575,42,219,533,730,585,302,413,541,400,768,58,96,79,576,574,476,899,427,60,1,101,572,508,355,362,892,120,325,166,492,411,304,468,831,326,244,794,126,232,718,301,682,238,84,773,65,27,175,593,792,789,293,264,292,499,506,801,192,565,314,112,590,343,519,864,20,446,205,370,661,526,161,420,21,636,817,825,128,841,607,374,130,640,127,247,596,873,710,689,328,13,603,608,203,135,803,320,783,226,363,638,786,334,136,668,41,253,121,4,846,104,111,632,339,833,721,709,561,664,631,813,271,174,799,402,750,365,453,414,56,583,782,701,177,407,849,269,57,426,61,599,830,394,646,346,797,99,105,33,252,386,737,502,387,55,49,705,213,185,158,227,48,806,845,3
 16,124,147,702,196,16,545,712,431,815,46,634,867,469,835,436,675,448,442,178,10,807,560,380,897,115,781,819,535,719,204,405,451,804,59,89,80,475,893,488,748,2,223,348,478,341,122,621,484,509,233,776,15,50,826,503,24,285,83,727,669,441,307,372,880,133,66,452,299,53,86,31,714,450,202,382,855,74,644,471,747,793,457,579,95,331,584,155,395,763,429,532,743,392,270,518,72,489,359,884,531,810,197,151,150,733,176,225,242,869,118,816,660,824,243,681,132,234,871,474,628,222,666,888,490,182,780,88,594,159,322,798,73,890,463,791,44,766,167,37,335,433,199,449,498,230,778,520,337,517,43,180,93,744,635,887,28,829,544,39,650,200,870,45,9,663,173,418,466,570,886,685,435,700,295,94,725,430,250,653,419,510,619,610,647,808,318,75,703,190,694,566,615,745,529,209,218,327,315,837,777,338,340,616,214,760,559,321,665,521,881,643,838,40,497,626,7,398,674,404,582,662,739,165,649,224,785,102,546,485,25,796,399,514,240,842,81,216,201,729,114,141,648,198,345,261,254,131,473,145,629,266,567,259,672,592,678
 ,376,749,113,64,347,241,800,5,627,8,428,408,144,734,280,697,215,609,229,390,659,440,612,211,172,536,683,289,129,444,235,303,708,852,477,195,671,821,76,137,738,26,885,210,14,571,774,563,591,724,679,333,746,35,123,78,143,284,818,790,716,329,569,483,735,630,30,354,445,677,814,364,275,722,153,537,496,52,581,586,187,551,751,549,728,281,125,274,822,657,323,237,853,375,625,297,220,812,527,691,188,699,410,866,36,432,249,152,417,809,577,17,228,91,752,82,512,772,525,877,605,356,761,454,765,823,696,598,350,160,872,416,802,119,896
+25,735,255,92,647,287,348,314,533,135,695,380,710,744,557,304,166,90,839,80,765,277,480,507,679,338,65,244,882,195,780,495,127,413,692,661,333,445,670,4,17,78,671,569,381,199,150,444,185,648,207,171,263,681,789,214,323,236,672,796,848,251,170,439,814,663,545,467,67,732,31,418,400,583,596,484,301,249,1,326,851,356,328,518,540,279,864,714,843,206,653,429,371,595,535,216,159,219,289,403,189,334,27,594,238,604,404,676,877,657,393,564,558,47,860,446,220,541,35,290,197,597,115,275,688,8,669,614,399,608,476,21,680,618,176,57,832,656,526,241,311,650,635,611,88,81,312,162,881,691,884,730,139,433,352,396,819,523,232,201,791,808,577,40,873,231,272,801,52,155,703,340,546,781,83,869,559,365,49,274,896,510,140,149,551,478,761,846,7,286,58,878,123,423,797,391,345,762,51,420,822,637,574,449,283,475,625,622,288,646,432,327,99,752,91,700,382,318,709,417,18,243,598,303,72,561,339,701,897,344,652,706,639,783,799,815,126,890,829,228,624,634,354,156,587,673,718,247,858,662,75,211,43,876,235,440,9
 8,629,862,398,362,519,410,473,682,879,697,774,222,111,694,425,750,113,579,242,125,33,606,360,187,698,642,664,221,39,772,443,422,600,631,42,198,372,188,654,378,374,412,102,588,205,828,226,437,627,395,465,610,448,359,512,330,824,264,64,343,704,121,194,387,60,576,306,256,138,685,503,229,800,717,416,105,284,308,727,550,464,775,835,461,124,886,458,208,603,552,847,285,369,61,562,602,894,320,84,294,172,641,658,898,628,55,177,97,505,351,361,556,883,34,601,53,754,450,442,636,887,329,370,623,357,537,316,145,368,527,106,617,169,82,355,740,488,524,675,739,659,621,108,615,456,666,599,36,173,435,453,830,94,530,462,806,630,270,6,651,89,665,585,589,321,836,747,529,193,186,14,660,196,871,544,266,56,154,180,678,406,260,590,227,486,582,153,722,899,483,168,291,141,409,455,146,810,254,119,293,68,733,770,612,217,376,161,826,767,28,405,528,261,54,276,689,516,813,778,497,491,296,756,586,346,373,45,389,785,581,795,215,643,522,70,397,684,563,763,743,76,143,142,474,136,12,257,771,252,900,633,26,22,183
 ,570,379,163,776,548,506,741,48,250,817,667,769,350,716,511,696,358,411,837,619,271,861,3,804,553,856,265,554,62,239,724,234,129,77,134,892,855,616,262,59,337,331,501,16,347,213,573,278,888,204,299,885,854,309,324,9,415,784,384,116,687,720,620,73,364,591,430,542,87,419,645,175,605,812,178,889,190,377,790,248,711,295,402,807,165,578,468,268,114,298,555,74,122,151,693,44,870,543,677,5,100,514,794,705,749,210,792,493,496,766,472,246,866,15,385,840,712,809,10,853,895,560,469,891,132,240,471,532,565,118,893,742,777,128,349,332,184,223,273,547,485,690,489,823,407,86,683,390,85,482,436,782,820,421,802,133,164,852,521,857,50,300,728,237,746,202,315,872,686,731,269,394,342,640,424,267,567,479,408,737,203,515,833,336,292,702,492,366,481,375,520,719,181,764,37,459,874,811,112,844,818,2,281,865,147,470,494,875,805,863,120,157,758,104,592,509,738,158,723,708,427,253,632,441,428,499,179,110,707,757,734,447,838,32,29,245,539,477,319,745,20,258,536,144,607,517,572,174,148,466,109,549,793,23
 3,786,834,101,317,787,525,788,209,580,313,341,571,96,644,726,383,137,638,305,725,460,538,212,46,103,729,613,568,224,130,200,401,325,827,434,451,721,816,79,674,850,230,841,71,218,768,759,414,282,593,831,107,773,297,23,13,11,454,490,715,867,842,225,649,609,798,63,30,487,748,457,463,93,335,498,117,500,38,310,280,41,859,302,713,534,167,502,392,753,504,24,655,760,825,322,95,160,508,821,367,66,386,307,779,192,531,426,69,438,736,388,131,584,19,513,363,575,751,868,845,152,191,668,182,452,849,566,259,803,353,699,755,626,431,880
+707,80,218,443,139,821,99,62,173,587,713,518,67,798,724,95,525,648,380,739,123,423,451,262,366,703,369,387,386,109,48,27,132,164,368,823,184,488,813,562,556,537,322,340,312,91,175,236,121,34,344,776,817,791,490,705,110,390,186,315,260,759,637,290,497,431,15,154,770,553,407,321,320,455,131,219,692,192,588,808,530,536,267,688,183,716,357,21,273,211,5,829,72,818,245,163,584,79,282,742,234,46,466,671,706,529,660,144,289,410,809,146,442,460,292,779,461,59,319,664,667,517,546,254,58,435,20,843,8,426,86,480,887,167,427,550,258,753,314,56,295,685,691,878,694,227,355,717,374,376,348,690,676,696,755,269,892,391,141,659,889,300,432,806,378,802,44,807,276,505,744,521,725,895,394,563,470,326,456,477,555,420,589,440,441,704,454,462,601,743,654,255,231,324,899,87,89,190,395,305,623,25,13,658,740,39,622,71,103,138,90,160,620,857,793,51,49,413,18,298,634,544,661,383,405,7,513,47,419,311,882,42,616,108,150,784,678,358,564,481,206,847,33,695,30,107,65,429,181,567,212,641,579,266,178,145,720,85
 8,444,810,593,53,811,202,794,397,60,268,81,746,722,778,665,274,684,309,689,630,272,29,240,673,73,624,118,573,333,182,171,23,126,709,780,606,856,586,422,323,343,261,220,434,900,157,762,836,458,14,523,100,328,4,66,463,119,626,701,77,833,597,877,617,155,774,229,835,425,332,345,591,43,325,787,834,629,28,653,88,769,582,828,801,359,242,632,674,16,308,112,82,511,17,876,522,485,800,894,287,159,134,447,213,750,751,467,6,22,61,152,527,731,257,280,279,249,335,651,404,106,230,253,318,338,191,201,825,476,822,84,687,675,507,193,166,411,790,883,365,94,539,24,830,785,837,797,331,317,10,415,535,756,542,663,221,327,645,277,543,504,194,69,296,574,471,375,381,459,509,859,596,526,259,866,686,840,600,826,288,421,104,83,41,399,102,888,607,133,541,552,812,156,781,711,768,737,710,98,789,533,76,870,188,281,516,551,647,350,222,353,681,733,113,356,875,285,547,754,371,639,373,342,745,168,479,682,85,627,124,666,367,708,814,677,891,293,187,865,766,482,670,337,207,577,424,849,478,599,55,605,727,732,652,400
 ,839,346,715,179,75,761,702,233,844,568,216,63,57,203,469,880,226,26,698,239,615,760,64,625,354,819,557,752,37,566,502,520,347,382,571,437,763,278,93,135,860,412,827,569,35,824,472,871,886,363,576,816,96,608,398,457,783,748,291,122,896,430,662,244,799,862,575,105,396,370,864,111,491,643,414,127,741,200,850,726,120,581,503,128,36,45,598,303,820,307,519,465,172,697,250,165,631,636,284,869,117,885,775,585,70,483,162,137,198,735,448,403,531,364,275,487,657,302,362,114,416,450,861,148,863,672,500,730,453,786,669,592,248,241,484,224,401,409,115,486,492,246,143,235,116,614,223,628,68,408,74,832,204,729,838,540,846,649,619,788,683,385,721,738,38,428,514,349,339,644,635,316,772,805,3,225,11,264,379,1,436,125,594,215,777,565,9,50,538,831,388,868,389,438,304,161,147,893,406,515,496,501,512,728,101,532,217,197,842,377,650,693,177,149,559,352,452,417,402,196,613,92,499,773,142,554,209,699,433,498,853,578,719,180,2,489,283,633,718,52,270,306,854,286,867,604,445,852,301,12,384,474,765,468,
 361,897,572,618,549,848,646,884,185,195,446,151,595,189,330,510,758,874,40,851,252,736,609,329,621,771,473,351,170,803,205,392,19,782,796,712,764,898,313,611,243,232,872,464,31,680,256,528,310,294,890,545,548,558,655,334,153,640,372,879,638,97,841,140,534,590,610,734,169,855,238,297,439,570,210,700,78,129,299,506,804,271,815,612,561,247,602,792,580,493,32,723,176,214,560,136,475,237,749,495,208,251,767,341,603,336,265,881,583,747,393,642,656,508,54,757,679,263,668,714,845,174,494,199,795,158,873,524,130,360,449,418,228
+45,792,285,74,701,167,351,347,558,72,697,467,685,644,440,365,244,31,854,11,719,255,561,496,761,258,153,176,863,240,758,494,203,370,669,679,339,515,524,41,63,151,723,633,294,262,216,545,224,620,312,50,271,688,783,84,306,193,747,833,864,272,222,489,830,739,546,420,3,661,94,521,450,591,542,492,238,350,19,157,862,340,261,491,626,282,844,726,846,256,706,452,378,497,632,304,239,266,358,381,186,399,54,476,92,684,416,615,855,602,323,653,567,105,872,393,170,552,109,154,263,595,62,346,716,42,671,471,457,578,572,34,667,556,134,118,850,510,611,318,251,550,582,472,26,147,330,51,874,756,873,710,86,361,213,442,709,502,241,78,665,771,655,13,884,70,321,791,102,131,670,275,473,657,182,836,617,368,106,331,898,592,130,234,640,487,748,861,24,296,95,871,196,453,752,379,355,807,79,499,762,624,631,328,325,466,539,612,380,588,407,324,168,735,91,765,441,403,740,390,18,316,658,300,110,616,310,766,885,260,547,704,702,742,759,824,96,891,847,315,708,480,382,87,622,619,694,336,845,597,136,82,81,875,233,53
 6,46,445,881,334,292,608,287,575,715,889,750,810,281,25,672,376,781,117,531,341,185,43,630,383,273,680,606,599,305,32,821,437,481,648,705,14,60,322,187,581,478,367,317,121,656,163,795,236,444,459,410,511,628,537,430,566,392,831,283,108,384,733,122,198,373,35,493,144,235,119,744,462,184,725,700,501,57,115,210,722,587,559,776,843,464,29,882,461,274,623,618,857,313,456,39,621,486,897,402,76,248,156,707,727,895,696,64,227,190,569,391,446,651,858,36,686,132,809,523,526,603,890,389,460,577,455,636,276,211,174,576,77,647,195,111,423,784,431,422,673,718,738,693,52,614,411,590,543,30,142,513,528,799,181,443,498,819,642,250,12,729,171,645,518,553,417,803,753,598,288,120,59,625,93,848,506,71,17,159,80,579,503,366,560,308,475,674,228,605,899,580,209,192,140,505,458,205,714,249,113,301,2,662,797,432,217,327,88,796,804,83,342,593,104,4,320,743,488,839,736,345,589,229,703,676,362,421,116,268,788,555,826,152,583,554,49,454,634,638,780,681,8,247,207,412,226,27,356,778,343,900,601,9,23,165,44
 8,436,164,816,404,551,745,65,97,785,596,698,371,767,585,773,400,396,842,691,206,841,21,732,514,866,204,520,33,125,746,286,199,129,123,887,870,557,319,107,401,360,395,68,169,141,646,219,892,194,270,886,867,309,408,44,344,786,269,53,763,682,574,158,277,687,451,530,161,426,677,232,512,800,253,894,166,349,713,259,627,295,495,806,215,659,470,338,47,243,465,128,67,245,760,5,859,607,565,7,201,468,814,695,777,200,772,586,425,802,398,197,878,69,388,808,775,812,1,869,893,610,548,896,101,242,414,500,447,124,888,717,712,212,280,424,278,289,264,643,541,711,570,828,418,139,757,463,180,538,434,811,794,435,789,37,173,856,477,820,89,326,689,293,741,90,353,852,654,801,220,372,387,609,333,208,613,516,479,774,150,563,822,415,352,721,474,246,544,386,405,663,231,768,58,529,876,823,177,834,829,20,183,883,137,335,562,851,827,868,99,138,734,149,666,490,769,127,730,690,509,237,675,409,527,375,221,188,699,764,770,484,751,73,10,357,564,573,406,720,6,354,637,225,600,533,535,75,175,311,178,584,825,146,78
 7,835,189,265,817,532,737,218,485,290,385,629,148,649,779,348,223,604,252,683,482,413,191,22,100,793,525,522,303,126,298,329,279,798,504,428,650,749,85,652,860,284,815,143,202,805,790,307,257,507,849,155,639,377,48,61,28,517,433,635,880,838,103,724,439,832,135,15,438,692,394,369,162,267,594,56,519,66,337,302,114,879,98,755,364,145,568,483,678,363,16,728,754,840,299,160,172,449,837,314,38,291,332,731,230,549,427,133,469,571,297,179,664,40,374,429,641,668,877,818,55,112,508,214,359,853,397,254,782,419,660,813,540,534,865
+803,215,224,831,805,665,706,325,41,679,134,616,489,298,330,212,854,834,89,873,744,289,252,70,408,414,593,818,211,436,536,315,409,619,59,425,228,866,445,666,697,685,37,108,598,346,323,649,611,543,589,855,652,286,4,735,569,507,216,639,175,615,515,65,71,316,457,809,874,230,712,329,80,22,808,61,433,295,746,736,96,201,626,217,664,424,244,296,20,241,332,648,274,328,326,624,852,387,125,342,699,564,573,331,778,399,280,820,294,157,461,551,24,776,100,350,504,758,606,725,667,35,856,133,116,645,418,465,441,66,532,692,594,840,597,773,68,420,732,496,547,245,145,529,812,643,131,877,45,842,95,88,595,338,628,72,472,53,528,825,501,225,836,876,200,870,560,240,677,477,139,313,259,516,563,179,167,119,779,210,381,806,451,814,364,317,14,181,841,491,745,113,719,60,659,398,698,174,487,146,197,673,571,490,891,511,214,794,277,829,434,281,651,302,791,263,206,366,234,160,709,844,401,188,405,341,236,284,268,657,466,300,368,531,407,304,565,50,93,743,680,498,601,630,144,566,625,754,375,141,548,817,570,63,4
 79,629,700,592,400,449,308,380,555,539,442,117,132,123,309,860,122,367,205,618,164,356,858,637,12,586,266,83,731,147,596,682,494,171,73,674,696,787,885,265,896,163,557,156,804,689,795,506,688,430,394,553,99,613,38,170,788,444,242,5,703,807,662,82,890,370,730,695,668,763,549,749,869,190,822,209,656,747,718,815,552,458,276,222,187,28,546,875,34,109,823,219,345,43,722,410,789,272,475,182,452,893,900,724,755,158,168,78,739,760,742,373,535,463,505,207,740,191,467,627,816,799,103,32,178,640,198,389,568,672,307,797,111,766,811,530,646,843,54,447,392,255,448,423,126,796,371,439,256,335,865,701,821,422,140,650,293,148,185,25,334,756,704,671,31,385,485,471,87,3,850,715,782,764,390,721,104,142,897,781,849,768,311,591,734,321,542,603,588,478,497,360,517,337,632,711,282,395,762,327,486,584,663,888,239,118,585,581,347,861,46,324,514,716,857,887,880,250,58,653,129,67,554,397,419,237,602,480,759,544,527,136,105,285,519,196,391,889,533,524,771,21,297,879,681,859,261,303,669,769,416,468,291,6
 31,802,867,550,322,143,790,785,429,40,159,838,775,238,306,203,127,124,173,339,162,786,29,273,502,349,720,189,600,135,726,372,777,660,194,374,379,474,562,137,310,152,793,453,184,192,488,610,752,559,233,587,94,847,898,42,229,634,427,717,406,1,523,708,271,819,642,621,388,365,541,579,723,783,13,251,412,199,354,195,443,693,226,288,305,437,572,15,299,183,658,320,837,757,352,733,727,377,154,872,166,780,318,765,636,540,90,567,353,355,404,464,609,86,767,510,112,635,155,161,85,7,824,257,98,69,218,213,895,605,537,172,393,622,107,169,153,798,784,344,495,748,269,384,79,9,830,17,121,690,525,483,492,357,713,882,481,620,75,886,892,27,438,186,614,638,110,227,115,694,556,138,56,678,655,253,864,74,417,576,319,36,421,8,654,435,11,623,343,18,336,575,526,670,361,260,249,462,633,862,33,48,578,473,19,738,839,386,426,518,710,120,101,92,827,561,51,705,102,151,62,729,6,30,235,686,193,675,617,415,676,545,91,114,10,106,369,583,792,500,456,508,314,49,863,383,484,770,482,26,521,835,312,612,753,258,851,750
 ,180,2,358,899,267,150,84,828,243,871,774,57,363,77,262,402,761,55,450,351,254,455,707,751,503,813,220,270,801,534,604,440,580,97,279,362,247,202,881,644,44,476,275,454,868,884,204,428,403,221,47,772,520,460,599,714,848,76,800,231,128,432,691,359,558,333,641,810,177,149,737,513,687,577,522,826,39,832,684,741,647,301,894,16,607,459,283,683,223,538,833,292,376,248,396,661,378,574,81,431,728,469,165,290,878,23,176,411,52,582,382,853,264,702,493,340,130,246,208,232,883,608,512,413,470,64,509,499,348,845,846,590,278,446,287
+96,531,312,349,480,592,491,369,489,501,553,38,814,842,732,284,70,476,642,468,865,461,165,545,294,506,9,593,896,304,836,562,178,667,750,373,417,195,841,82,26,4,437,289,692,239,231,151,313,763,12,616,162,475,733,615,521,518,359,453,670,98,81,290,577,285,632,683,414,844,42,106,281,495,782,478,487,78,112,714,663,383,626,424,263,244,888,740,810,235,546,180,432,672,206,97,40,278,222,338,441,241,194,793,665,221,260,831,894,784,472,253,465,59,739,445,503,572,29,708,19,532,504,215,657,133,741,798,352,668,248,240,464,808,499,16,682,837,223,209,591,783,650,772,466,108,318,630,872,371,882,719,387,603,690,295,879,540,413,643,870,861,259,276,713,696,331,627,126,395,680,542,625,858,6,893,251,397,66,176,761,205,305,72,171,271,765,600,142,201,20,873,157,353,640,550,463,509,189,188,876,723,455,745,104,617,764,716,137,811,608,452,11,622,107,498,293,48,651,543,217,52,243,367,131,419,426,494,900,658,706,775,258,859,864,547,297,853,621,21,319,816,404,449,515,818,826,44,884,779,143,644,83,849,423,
 212,375,845,619,460,537,286,655,167,339,771,539,508,232,525,633,459,471,330,563,30,36,207,523,408,92,646,791,769,129,301,400,549,314,529,388,326,675,447,153,778,51,462,758,302,341,486,705,379,273,833,317,448,474,252,140,428,229,727,403,23,55,648,128,272,237,337,795,721,511,202,385,652,541,868,817,148,324,711,624,802,277,254,576,699,267,554,863,536,22,351,356,720,392,150,350,389,679,804,31,146,255,450,415,390,899,374,125,35,17,393,316,192,249,898,211,288,60,411,270,200,607,832,227,109,753,67,161,571,216,776,287,219,589,139,61,99,551,703,766,526,579,265,401,479,697,405,742,564,203,488,228,329,871,1,628,279,535,609,485,175,315,2,689,768,737,39,867,662,266,28,558,68,530,599,883,654,770,357,111,594,788,95,43,724,145,635,187,214,822,821,210,172,659,154,147,309,24,881,242,220,446,410,848,631,823,431,584,557,843,398,89,695,292,735,399,325,438,299,567,813,787,130,513,851,213,191,261,15,686,781,533,555,433,786,246,186,100,578,268,691,754,454,5,34,660,105,174,63,502,14,847,777,307,159,
 269,767,185,136,467,790,363,760,93,676,860,704,855,355,570,320,348,197,218,792,425,505,890,120,850,715,666,620,427,380,566,726,88,79,64,391,897,575,748,41,123,236,358,587,47,736,517,366,421,797,156,225,827,611,168,127,65,688,707,606,412,332,840,470,3,559,247,224,306,8,527,490,164,645,824,53,759,430,585,854,342,785,233,177,693,158,308,582,282,524,629,623,132,493,33,420,376,880,347,838,204,25,409,656,492,434,303,839,114,734,580,730,370,712,49,300,874,458,684,245,641,886,402,179,796,199,442,406,477,799,149,895,674,835,13,637,74,10,173,422,169,345,569,166,749,439,196,386,86,50,170,560,534,862,208,805,574,124,725,435,889,57,113,773,138,618,561,378,885,731,354,605,418,80,702,602,429,484,368,321,601,538,456,819,152,117,653,360,700,365,416,762,743,190,510,250,230,830,722,182,678,649,160,698,612,327,755,328,891,597,815,163,440,738,27,334,581,528,481,694,746,144,496,335,638,76,701,310,18,757,590,565,298,887,75,283,62,552,103,69,744,234,181,184,116,372,457,407,604,257,747,121,522,507,6
 14,588,780,54,256,443,343,829,115,718,183,262,346,110,661,377,583,87,669,381,687,520,673,483,291,226,436,756,500,46,361,85,512,573,857,311,362,807,869,101,482,728,56,878,91,155,497,664,671,516,752,677,193,866,37,119,32,134,275,709,828,717,639,610,344,825,544,7,322,556,801,710,598,122,634,118,514,451,71,382,396,58,613,789,548,812,336,198,135,852,774,296,280,809,568,519,141,264,729,586,596,274,681,333,856,73,444,340,77,384,877,636,45,238,102,794,84,394,834,685,875,595,469,846,323,751,806,800,473,647,94,820,364,803,90,892
+739,7,233,654,249,856,380,156,109,733,537,340,329,799,745,86,563,813,116,861,525,483,184,237,107,708,338,674,503,240,311,147,212,474,375,634,235,488,847,602,578,506,90,94,585,137,229,162,310,281,241,879,726,607,333,840,357,555,23,154,68,652,542,121,219,135,187,517,863,629,467,106,174,277,521,171,704,83,662,880,244,493,539,559,134,624,502,123,182,197,25,689,164,766,63,193,597,175,173,639,507,97,519,723,853,257,504,562,477,484,758,71,267,513,87,685,589,305,355,824,568,386,769,151,75,515,202,849,80,399,57,609,798,574,605,575,76,816,247,111,520,694,614,869,827,319,289,874,328,347,374,592,729,701,835,136,889,320,353,841,888,448,387,859,117,894,205,620,409,596,633,583,673,893,323,631,188,295,514,309,264,359,611,485,169,531,365,148,696,635,641,270,378,224,878,262,344,26,460,95,672,296,74,755,724,252,642,403,49,545,298,261,550,710,773,3,40,215,44,345,702,530,423,382,405,19,496,4,535,601,850,204,352,418,419,543,688,222,273,431,141,860,218,768,35,429,396,397,416,586,293,832,554,200,36
 4,119,795,882,150,753,618,17,830,81,582,140,10,52,112,864,598,700,408,478,599,153,683,667,144,207,145,538,443,613,168,681,101,243,79,155,143,808,887,576,857,604,232,334,676,487,255,573,895,315,612,867,303,142,332,18,342,54,42,238,379,630,572,70,838,569,814,722,511,872,461,812,424,421,637,653,366,288,820,890,732,236,440,11,556,336,687,884,263,253,594,469,12,98,362,45,693,5,846,245,271,834,897,552,221,14,492,39,750,679,464,31,110,58,59,616,765,51,276,127,317,322,544,227,53,176,384,128,149,494,231,892,230,819,314,619,628,486,41,420,579,621,779,114,6,747,186,735,736,742,833,591,350,38,495,479,709,348,394,170,453,714,195,498,435,426,316,138,577,280,398,363,691,580,737,775,560,326,900,801,815,786,794,161,368,284,125,297,198,194,881,325,66,489,730,774,37,643,661,809,663,686,349,875,622,24,883,422,451,760,518,377,388,557,401,877,854,166,99,777,67,526,826,132,678,510,165,617,274,428,770,124,508,20,698,475,512,848,500,829,266,92,792,865,413,664,458,167,645,402,656,286,327,376,746,793,
 697,706,203,803,265,781,73,139,764,852,391,776,627,209,15,8,34,259,817,130,2,738,465,668,731,360,337,636,684,725,822,89,433,404,471,516,442,251,491,669,321,50,179,821,445,886,677,1,806,210,844,885,191,260,713,61,632,565,272,800,818,65,528,845,385,682,62,649,728,532,392,192,292,811,225,343,372,522,454,740,269,805,626,84,383,427,13,290,93,789,615,762,449,707,313,21,837,341,248,712,717,285,778,36,784,534,570,283,234,490,29,558,719,159,452,406,468,60,256,757,77,346,33,157,178,871,400,780,553,646,690,463,651,666,571,593,85,324,335,441,146,46,278,430,122,163,411,47,425,228,410,354,437,339,695,223,876,836,291,749,692,595,670,623,250,547,831,214,499,476,201,603,581,600,330,759,790,32,104,56,96,610,64,351,133,439,129,648,716,69,246,659,751,318,699,529,447,185,78,268,783,160,625,763,206,566,804,189,587,43,102,828,548,540,650,27,226,304,608,306,381,158,482,371,407,301,782,370,473,239,509,196,294,862,564,797,108,100,242,105,533,807,72,88,417,703,183,756,810,438,873,432,55,358,705,549,27
 9,275,898,258,444,551,802,658,858,312,48,390,172,300,389,412,457,711,788,118,825,527,796,606,287,638,647,459,505,181,761,466,446,22,665,754,721,785,843,103,480,434,254,851,462,30,743,436,588,91,470,891,367,584,590,734,131,523,675,115,715,791,16,870,28,497,744,567,680,524,823,361,546,213,771,126,718,299,393,369,208,899,82,868,640,307,220,660,842,727,199,211,472,356,331,541,450,180,455,787,644,216,456,748,217,481,308,177,896,657,720,120,671,767,282,9,752,415,414,855,772,866,302,655,113,839,373,741,501,536,152,561,190,395
+811,220,92,579,639,715,342,49,25,505,548,753,61,494,459,51,817,684,371,799,308,207,481,36,567,514,523,492,109,153,104,16,203,202,59,818,42,845,533,616,685,724,270,327,240,132,157,593,278,102,562,776,838,736,223,619,168,259,321,703,354,804,654,192,433,545,68,415,820,212,598,474,204,229,393,29,508,295,700,707,493,331,252,525,566,651,81,17,99,131,127,864,24,604,438,460,841,125,191,624,362,320,425,367,643,667,557,385,78,88,679,486,222,690,306,636,291,426,479,536,800,276,648,177,3,490,41,617,151,119,392,519,878,427,334,780,245,463,731,246,210,376,440,754,716,428,176,778,137,816,106,435,550,472,564,146,743,130,178,633,759,35,825,862,464,791,216,730,476,346,507,284,485,786,526,208,453,124,689,361,718,802,457,758,560,663,141,496,772,725,798,79,506,145,893,48,339,299,350,317,264,261,296,399,889,97,302,410,200,408,55,44,745,784,852,213,54,503,28,66,665,832,749,183,348,147,282,235,152,287,790,10,711,93,45,789,580,247,501,770,605,615,244,584,14,116,171,757,65,238,314,612,569,128,160,515
 ,674,650,637,688,351,285,627,499,823,398,105,333,122,783,512,625,629,323,467,412,865,599,86,234,256,437,310,300,386,538,603,15,83,375,555,748,801,377,896,257,635,108,413,396,687,283,897,139,723,592,267,281,336,165,732,170,120,262,360,809,831,11,888,465,882,576,232,668,197,853,848,64,498,237,217,726,774,775,429,57,622,193,661,436,827,819,169,30,849,587,194,258,391,311,574,126,779,540,594,885,899,400,628,242,186,211,806,857,714,143,228,304,473,185,782,355,352,655,708,761,401,273,117,553,20,480,618,280,166,737,382,844,528,666,744,829,173,73,156,680,851,577,155,563,23,767,522,712,861,380,763,199,80,698,520,448,634,21,158,728,702,720,195,43,58,504,224,227,807,681,491,694,795,518,184,26,869,710,881,546,570,581,739,12,319,179,692,226,781,741,450,456,403,836,315,735,847,421,677,673,292,850,190,110,697,239,107,614,225,734,379,322,797,760,815,47,313,877,347,221,510,534,446,67,657,755,561,524,470,8,389,325,502,60,738,879,777,859,740,46,713,821,704,863,84,233,582,764,842,573,683,182,671
 ,846,656,356,335,868,793,449,74,1,854,632,22,662,218,52,98,121,422,363,890,82,163,527,69,696,439,159,586,381,752,591,623,6,539,469,511,290,138,682,112,871,307,103,33,756,497,733,404,135,750,417,886,898,263,602,837,324,721,180,206,590,706,444,390,883,575,434,471,810,860,773,454,236,275,747,9,483,653,265,298,409,96,640,675,447,374,387,243,254,94,642,395,638,537,500,475,272,796,50,620,301,717,513,828,118,874,792,423,39,647,181,161,358,597,431,509,372,56,286,289,762,452,162,63,430,495,894,241,814,478,219,742,164,589,332,812,406,394,565,556,188,551,53,269,835,115,18,455,461,722,353,664,338,855,75,856,13,803,892,411,788,288,660,833,384,316,544,641,189,113,198,746,312,458,870,40,543,709,87,85,172,136,341,149,133,468,559,27,686,365,248,328,260,611,277,858,407,826,175,77,318,875,294,607,530,672,364,489,517,187,253,140,873,297,369,808,214,4,445,419,167,100,420,326,558,255,751,529,359,609,5,547,274,357,552,588,771,402,111,670,397,337,824,196,532,621,830,95,840,606,293,699,578,19,834,46
 6,658,231,366,900,626,482,209,880,345,895,571,154,373,2,630,76,645,205,613,787,7,691,368,766,521,794,303,600,785,279,451,649,201,72,114,678,516,370,876,887,266,652,37,305,891,867,70,443,134,215,271,554,765,644,541,705,805,250,388,309,405,866,531,340,608,378,669,659,349,442,330,727,487,230,646,601,38,839,344,416,488,631,813,174,595,477,572,610,251,549,693,568,31,729,91,424,418,142,414,123,769,268,62,32,884,144,432,343,89,701,329,872,484,719,383,542,90,441,676,34,768,585,596,150,249,101,535,148,822,843,462,695,129,583,71
+749,339,176,816,861,580,759,377,55,637,68,624,589,218,239,212,854,796,164,843,825,228,240,57,514,309,579,813,317,487,642,414,434,659,56,379,196,883,368,619,667,668,63,103,612,382,325,694,639,626,603,810,575,202,4,688,597,489,295,723,315,556,443,45,100,393,565,848,842,187,708,369,40,5,859,53,336,318,713,677,152,93,643,95,728,331,348,456,87,197,490,595,298,207,407,656,844,424,88,231,714,616,528,270,736,444,180,865,457,149,345,622,7,770,222,229,474,826,594,689,629,8,837,97,208,615,553,362,543,35,602,671,535,874,573,757,159,359,793,554,555,151,61,404,764,653,83,864,127,879,204,27,525,237,564,48,380,24,548,789,395,282,866,846,342,836,600,162,679,423,60,254,126,401,547,216,157,79,773,113,534,838,372,812,416,243,14,281,805,398,711,247,743,28,590,466,750,286,452,136,174,754,661,435,891,576,120,856,301,872,515,285,608,215,726,391,235,370,352,119,663,839,399,108,358,482,117,432,403,670,349,440,385,621,538,305,483,168,110,756,753,394,658,562,224,635,705,772,531,90,546,782,508,177,510,6
 86,641,521,551,337,223,492,453,598,427,258,251,219,350,819,50,252,178,613,66,366,833,572,17,647,227,25,806,84,631,638,593,167,69,760,783,727,870,147,894,99,571,102,815,695,849,480,628,465,299,475,37,685,11,211,817,563,266,23,744,777,634,161,880,275,673,652,716,706,558,684,892,163,824,181,742,798,654,752,491,583,209,271,118,39,472,845,131,89,807,135,485,122,768,496,766,374,356,319,468,888,900,739,829,244,322,105,683,718,745,494,592,545,585,273,681,246,463,709,855,831,30,130,188,682,214,418,614,693,296,735,75,696,867,437,587,851,109,518,392,156,371,522,213,767,493,334,128,220,822,703,850,537,194,620,179,86,184,42,314,707,784,648,13,459,570,516,85,1,878,738,775,747,284,690,148,145,895,725,801,741,201,632,762,415,577,664,644,520,376,530,584,260,596,650,333,293,724,292,383,512,697,875,203,242,507,599,357,852,43,363,488,758,884,885,862,256,77,582,241,38,486,461,330,263,662,397,808,505,455,264,31,447,425,189,335,877,500,419,828,74,186,860,676,841,236,294,618,795,388,470,478,701,761
 ,832,451,261,98,720,857,361,54,268,790,734,320,190,171,104,248,238,477,96,731,107,389,400,506,678,106,665,183,737,269,748,588,312,304,310,417,544,277,429,115,765,449,198,182,365,586,691,504,313,495,205,797,898,154,290,567,511,680,405,6,412,649,355,871,568,604,288,471,479,519,704,830,9,172,291,323,302,276,413,740,133,280,195,351,627,12,221,259,715,375,804,781,232,746,702,332,249,847,297,840,287,717,640,439,192,501,347,265,549,509,660,175,811,396,210,611,72,230,132,15,776,402,233,92,193,367,893,625,431,70,381,552,217,81,94,780,809,386,484,787,191,442,91,2,853,78,116,699,623,473,503,329,779,896,609,566,144,881,886,62,338,185,560,578,44,143,59,633,601,225,26,755,657,124,863,67,307,481,460,34,527,36,645,557,33,672,279,49,234,539,606,719,326,134,166,422,607,882,140,129,591,436,58,710,827,523,364,438,785,173,200,226,763,541,16,669,150,165,47,733,3,29,199,712,153,721,636,316,698,497,123,65,21,51,306,532,729,540,569,536,346,18,821,446,561,794,406,20,426,803,255,529,769,353,890,751,11
 4,19,321,899,303,73,64,771,137,835,818,76,300,101,274,445,778,22,344,245,311,341,722,692,410,868,121,146,802,513,630,328,605,139,360,257,138,142,869,574,125,428,390,464,823,897,340,354,408,155,111,792,409,448,550,687,814,52,834,158,267,411,651,499,476,502,610,774,82,71,791,387,700,581,559,799,41,788,732,786,646,441,889,46,542,373,262,730,170,458,800,343,524,253,430,674,283,617,112,467,666,454,141,384,873,10,80,378,32,517,308,820,289,655,450,324,206,160,250,327,876,533,421,433,469,169,420,526,278,858,887,675,272,498,462
+423,160,354,430,57,829,279,300,364,692,639,88,553,884,837,244,123,685,313,715,606,605,176,506,79,747,142,587,812,299,530,334,219,537,677,521,414,48,887,345,285,183,288,215,664,217,290,3,262,442,71,810,509,602,641,800,385,627,120,42,241,387,344,297,353,122,325,402,700,836,177,90,316,498,461,422,740,107,370,864,393,596,595,626,4,549,804,375,556,304,164,409,331,821,74,67,138,248,298,630,396,85,416,847,815,152,472,551,781,736,752,15,482,172,330,702,646,195,168,817,239,585,625,277,351,324,398,881,158,660,34,431,670,508,621,197,319,883,1,119,611,835,756,882,720,162,432,775,704,8,735,761,689,783,842,310,899,573,368,777,898,748,10,634,283,844,209,673,205,623,766,687,770,895,147,866,232,480,173,332,296,11,603,103,106,453,678,270,357,500,287,666,151,399,790,406,253,167,381,184,867,321,98,834,190,365,808,306,113,489,447,427,260,730,474,131,189,126,289,568,528,95,266,514,336,125,617,117,838,637,857,478,228,644,681,494,638,565,411,77,6,886,202,732,264,600,534,60,714,786,227,771,363,581,4
 13,9,707,894,163,743,717,62,843,14,412,350,211,203,206,760,716,719,405,397,708,111,233,532,415,204,191,703,439,795,80,582,69,484,272,116,31,662,820,663,394,794,63,533,661,322,27,628,823,371,522,889,433,148,501,134,39,137,153,545,261,237,224,348,418,561,564,636,601,856,504,597,25,655,488,854,456,12,695,868,779,452,359,108,622,554,540,787,653,511,145,471,96,361,220,52,541,130,853,404,127,419,520,436,36,144,813,212,492,305,118,128,139,59,23,865,578,129,208,32,43,17,697,559,178,16,658,87,28,473,294,879,307,612,150,477,360,55,271,588,750,657,741,75,161,642,389,688,833,765,555,519,29,100,788,181,789,376,417,479,577,486,2,182,682,645,495,58,826,579,26,73,620,258,718,744,839,607,875,676,448,738,862,20,50,542,92,343,38,193,891,362,22,434,767,552,84,576,273,890,575,580,295,690,830,257,893,400,609,635,792,292,274,557,35,803,671,314,281,586,221,782,869,82,734,772,21,466,72,240,822,467,656,133,710,724,358,499,265,780,5,421,845,712,105,201,665,200,468,53,566,136,440,457,567,469,631,828,26
 8,512,19,860,293,476,407,819,713,827,840,379,226,146,76,311,496,491,124,757,763,420,870,445,441,614,669,598,802,382,308,309,318,516,784,254,725,243,275,174,342,816,245,874,706,132,758,435,535,462,526,317,490,56,335,711,591,818,733,112,517,723,143,759,61,449,560,180,229,403,328,825,574,252,463,593,392,873,390,861,538,24,608,388,115,301,207,680,562,807,185,649,222,154,651,705,49,858,497,99,691,302,675,437,590,569,94,583,256,531,694,340,238,475,778,223,539,529,199,721,242,186,338,487,366,709,652,798,525,791,753,849,159,503,81,156,93,572,91,249,523,33,464,374,218,45,214,149,278,276,46,599,451,592,755,378,527,699,880,346,391,796,303,668,793,225,809,722,18,624,654,104,640,806,754,171,323,121,369,610,157,686,44,320,459,629,785,102,187,799,831,349,613,410,41,548,383,198,729,401,373,701,196,589,855,51,851,246,444,558,571,745,315,170,483,450,513,616,679,179,395,355,386,68,841,247,263,594,619,425,380,897,352,633,54,235,89,97,751,544,114,37,110,604,424,672,728,455,878,141,255,30,674,618
 ,615,236,524,267,493,801,446,797,505,86,234,329,485,284,543,101,683,693,814,327,846,438,650,536,13,805,684,78,510,66,768,515,764,135,647,859,876,341,698,372,291,742,213,518,40,269,811,547,773,337,192,896,188,408,280,384,282,443,848,312,667,776,70,888,109,216,563,696,832,502,824,155,632,65,659,367,339,210,230,166,231,863,326,885,643,250,7,850,871,507,165,454,460,481,169,546,570,333,584,648,749,356,731,251,429,550,259,377,900,762,286,140,426,852,194,175,872,465,737,726,746,892,347,774,470,877,428,739,64,458,47,769,83,727
+595,114,270,360,41,830,86,103,291,601,746,344,250,863,803,118,316,621,436,686,292,475,366,384,265,745,228,395,627,126,226,109,108,267,524,787,275,245,871,454,430,379,367,329,427,87,178,80,96,152,169,774,741,786,600,730,164,451,162,187,320,648,552,322,513,338,85,181,701,711,247,224,352,502,203,326,717,112,466,834,567,576,349,699,48,673,603,145,446,225,28,742,148,850,153,46,373,89,306,725,240,6,408,783,736,433,626,256,543,562,811,51,487,272,391,789,494,38,195,706,515,584,505,268,192,341,132,874,13,536,17,410,869,242,453,380,359,841,119,18,390,795,771,891,666,110,401,700,579,168,572,780,664,765,798,314,899,484,190,663,897,523,193,710,425,804,44,822,157,519,802,594,788,898,254,767,413,406,269,438,545,185,583,220,321,662,582,448,461,679,499,481,97,388,895,179,71,215,365,282,793,81,2,752,529,121,729,84,63,223,196,258,473,856,672,78,73,298,105,419,560,332,570,443,362,15,553,62,654,396,889,214,525,328,387,768,651,512,592,261,59,879,32,698,101,295,218,209,440,687,142,658,491,457,234,
 36,695,887,389,810,641,19,836,69,727,460,123,302,83,714,782,792,638,277,739,204,504,568,376,33,201,734,156,733,30,527,238,315,221,8,31,659,775,635,705,703,251,420,415,216,55,464,900,212,709,877,459,7,565,91,117,4,60,544,88,450,557,222,683,588,824,589,308,805,310,766,197,463,330,759,159,120,753,844,676,173,610,75,779,634,781,778,539,370,434,646,14,416,68,24,456,34,885,577,340,642,825,287,43,146,661,241,645,606,259,10,11,12,56,748,647,227,207,147,76,122,712,533,104,67,439,208,175,243,199,851,445,754,37,625,566,283,273,317,538,796,876,257,113,521,134,819,837,843,681,346,107,3,613,383,801,528,643,363,414,554,106,386,609,371,213,151,740,550,149,177,444,357,853,622,719,418,857,640,715,611,866,116,198,274,21,100,232,72,894,623,45,507,620,722,95,750,555,862,690,657,92,713,696,172,890,219,403,486,707,596,285,304,130,684,660,163,382,833,324,691,828,252,680,574,174,675,40,355,762,278,669,138,670,531,639,682,561,886,98,337,880,697,294,470,462,154,497,200,820,331,633,166,532,608,693,763,
 369,751,165,809,249,262,624,738,465,864,720,296,131,74,135,431,818,400,42,728,498,508,852,158,636,399,808,514,776,184,480,429,441,374,619,526,569,598,239,93,217,861,303,849,605,53,814,530,790,800,501,559,743,27,476,506,549,816,724,248,229,882,264,704,150,716,813,398,64,452,358,872,333,397,668,447,161,845,260,875,677,23,644,458,115,65,57,575,342,838,167,511,356,182,629,495,39,772,546,128,848,235,868,723,587,281,336,300,233,266,731,478,289,534,586,312,558,564,327,581,176,347,488,744,180,839,694,628,655,649,826,797,402,293,136,339,77,455,297,171,540,255,409,253,141,54,496,125,535,70,202,301,755,407,692,688,615,832,823,510,678,791,364,770,761,47,632,630,186,405,665,423,471,806,799,22,305,5,375,426,9,593,20,518,361,769,637,1,29,656,859,381,842,350,189,467,318,94,888,469,422,509,449,517,807,16,737,288,368,757,417,749,563,188,309,591,351,548,551,334,210,590,139,319,827,99,442,392,732,482,489,892,477,653,61,35,335,183,726,617,26,133,129,821,377,840,607,437,873,140,66,194,483,777,578
 ,299,831,522,618,702,735,747,815,49,237,385,325,541,313,144,614,756,881,127,865,263,674,571,143,721,785,246,378,50,817,290,599,25,773,855,835,602,884,428,503,492,160,794,236,124,758,348,650,404,155,896,432,472,424,516,345,205,784,435,867,671,58,878,137,393,520,667,829,244,858,111,394,284,537,311,556,52,82,170,468,812,353,860,616,485,79,760,846,493,411,191,708,280,102,547,286,490,354,689,585,271,474,573,421,612,279,343,893,652,580,323,542,764,412,90,847,685,500,631,718,883,211,604,372,854,230,870,307,206,231,597,276,479
+784,1,260,744,348,850,462,221,100,765,429,393,317,719,688,136,667,845,53,879,532,463,190,212,127,689,438,746,334,323,293,184,287,504,269,574,259,575,786,666,656,587,70,94,601,224,283,267,410,306,341,885,747,519,204,846,408,573,25,187,16,673,566,120,108,134,229,594,881,528,567,160,168,218,578,151,692,156,736,874,121,443,582,487,237,619,347,118,80,241,54,694,207,703,96,319,685,252,194,605,583,216,584,676,862,258,465,597,332,379,741,133,214,627,22,652,603,395,453,830,616,284,819,185,63,598,209,800,154,309,130,684,757,621,646,665,17,759,342,223,546,620,521,833,853,440,282,886,162,421,199,459,751,668,820,140,848,266,409,856,854,330,468,880,47,894,296,499,513,610,526,556,614,857,416,480,169,279,629,320,144,449,628,593,189,489,236,81,771,641,706,131,488,195,841,307,439,9,508,114,549,345,145,735,791,308,554,466,105,596,333,289,612,625,807,8,85,255,43,316,761,638,371,353,446,61,457,14,355,631,797,179,315,364,336,428,711,73,158,522,232,816,304,774,50,402,383,500,300,482,390,851,607,78
 ,413,228,813,859,98,731,590,69,803,165,517,51,4,24,196,878,481,671,301,540,510,226,763,713,103,295,215,419,478,516,285,739,116,238,89,247,240,836,896,533,882,509,298,321,727,565,361,591,864,368,576,834,272,242,251,48,456,109,95,110,470,715,602,46,869,563,808,766,531,873,491,826,494,356,710,536,370,394,832,892,733,233,376,42,432,192,678,893,107,234,674,380,58,33,464,115,762,38,796,99,326,871,898,633,310,13,273,31,782,737,562,83,219,137,112,451,802,62,369,175,437,431,442,79,97,280,314,197,220,545,286,888,191,837,405,643,682,572,12,407,538,530,714,138,10,783,198,696,654,683,865,651,460,101,343,548,659,305,271,117,445,770,270,568,318,386,331,227,417,174,492,472,753,677,675,795,381,278,900,829,843,815,726,254,471,274,245,352,248,291,842,164,132,484,749,789,87,604,718,724,661,717,436,891,523,2,863,479,435,811,362,290,452,609,498,887,877,217,74,764,23,387,790,183,672,397,230,611,400,485,754,86,414,11,704,382,474,875,501,768,366,52,707,884,497,750,403,243,695,506,571,344,148,388,793
 ,844,708,657,205,822,329,745,75,104,812,860,276,699,520,213,5,30,57,263,818,59,20,730,337,740,623,384,200,686,645,776,821,82,433,427,514,560,249,170,392,723,398,92,210,775,527,883,690,21,788,76,861,895,64,153,728,141,702,542,155,769,827,67,561,810,473,663,93,639,701,624,483,125,327,758,142,373,203,543,512,637,313,729,622,186,231,430,28,365,172,828,680,709,555,760,363,15,866,206,358,649,773,401,752,6,738,448,559,246,268,502,3,615,722,66,535,354,324,36,135,809,34,161,39,166,65,890,461,755,476,600,725,261,537,551,658,653,157,385,467,423,180,60,188,511,55,171,515,90,425,325,375,434,496,288,693,124,889,867,147,700,553,647,687,505,277,420,835,294,328,350,244,644,534,681,257,732,778,72,102,123,56,655,119,201,262,426,88,599,721,143,349,617,664,338,636,606,541,68,27,377,691,77,705,801,122,581,767,302,406,7,35,852,589,399,698,29,208,211,679,202,265,178,547,297,458,359,748,469,518,173,372,106,264,779,618,831,222,167,281,176,396,849,152,150,529,662,146,720,840,447,855,539,84,411,756,422
 ,139,340,897,193,367,412,825,586,870,441,44,424,126,235,391,525,339,697,716,149,777,608,824,632,357,557,577,558,544,303,742,503,299,71,630,669,613,839,798,37,495,311,346,868,524,18,712,444,507,32,579,858,389,642,670,799,129,592,585,40,626,806,45,838,26,564,794,493,569,580,785,477,570,250,814,113,781,404,490,475,111,899,49,847,650,292,322,552,805,787,177,181,335,374,450,550,455,91,454,817,635,225,351,804,163,418,378,159,872,634,780,128,734,743,312,19,660,253,275,876,772,823,360,640,41,792,415,648,595,588,182,486,239,256
+317,569,171,19,417,522,34,90,403,169,815,546,316,779,634,162,296,155,808,231,322,260,585,399,687,521,163,38,756,24,387,178,36,92,566,854,181,482,730,180,205,292,646,581,135,63,74,405,3,240,289,297,648,841,744,294,40,139,586,723,776,594,471,450,819,701,172,100,252,639,108,494,436,590,165,377,487,243,157,462,860,466,72,694,426,577,699,385,727,154,369,761,143,759,524,137,357,48,306,659,4,134,107,592,283,715,633,238,693,515,658,451,572,133,805,692,164,176,82,277,518,638,69,286,441,55,290,738,128,537,331,52,883,183,101,250,747,665,486,66,114,677,728,793,224,25,326,218,809,612,782,796,329,573,461,388,876,492,23,191,867,579,555,349,845,339,30,881,16,194,803,362,681,873,214,790,641,324,127,430,893,517,300,221,627,713,688,831,149,604,347,752,39,428,897,116,37,655,106,472,749,219,271,464,549,125,620,210,211,200,126,147,392,878,474,513,208,449,432,308,195,401,764,304,158,291,413,512,810,91,843,371,765,404,459,884,376,842,851,361,506,737,60,346,345,272,298,323,601,622,12,185,275,773,42,
 335,307,714,850,668,438,360,596,424,853,855,509,705,78,248,799,671,838,7,706,319,425,246,526,62,226,772,201,664,112,138,726,265,356,269,440,247,280,499,562,624,491,303,111,1,431,148,900,47,712,702,476,152,673,359,330,220,188,788,15,302,636,490,511,393,768,170,168,391,54,545,608,370,21,703,287,407,410,447,348,354,731,364,864,847,771,301,823,341,452,760,309,777,28,245,51,333,818,890,496,420,708,5,445,547,857,553,400,542,225,239,94,197,457,804,327,576,89,670,338,416,720,849,234,311,406,435,551,29,96,468,611,497,279,484,398,448,628,173,340,832,887,662,478,80,253,745,770,806,372,18,384,217,676,320,682,617,861,485,175,199,558,314,637,274,212,381,767,716,473,264,50,129,852,179,802,373,414,223,574,159,789,423,350,266,86,117,605,22,859,896,390,374,237,541,375,732,495,780,560,434,20,273,623,575,736,13,187,65,769,846,85,73,446,196,216,131,674,826,742,722,554,556,429,552,580,653,186,227,456,529,678,645,382,470,750,415,661,879,479,598,863,241,305,419,318,130,160,332,886,433,898,207,122,2
 81,488,571,475,584,684,583,422,467,394,284,565,824,666,249,523,358,602,483,792,700,409,454,630,190,820,153,880,53,791,88,412,444,469,325,278,56,821,872,505,599,61,229,174,751,99,489,244,383,588,871,640,709,837,870,672,228,230,261,734,568,353,654,276,875,203,477,557,741,825,313,103,635,256,813,544,378,894,150,45,795,123,827,593,288,822,336,481,109,87,118,41,743,35,95,334,589,182,710,352,609,177,132,811,618,885,869,380,437,606,141,619,102,504,848,84,530,669,657,781,167,800,830,427,559,877,528,11,778,685,421,455,833,844,754,368,44,365,386,119,262,610,367,696,543,704,254,6,531,625,81,690,83,667,460,758,587,206,550,856,784,817,312,656,766,344,835,363,43,755,647,689,70,567,533,502,600,561,267,418,161,644,64,202,748,215,535,548,735,293,198,68,443,836,268,889,27,453,797,649,9,899,775,77,104,866,236,539,270,807,698,740,538,79,786,442,519,295,785,14,680,607,532,10,757,75,570,626,2,366,501,839,724,563,858,258,263,222,184,597,379,762,242,120,525,121,840,458,829,140,233,650,71,257,697,76
 ,868,787,209,729,828,675,719,621,614,733,166,498,232,439,816,142,146,616,564,874,192,739,8,299,310,632,613,753,315,67,145,652,59,683,235,718,801,798,395,888,783,507,595,57,651,686,516,503,124,534,763,31,862,527,189,193,204,500,110,691,834,895,251,508,707,660,282,105,578,794,97,717,32,115,582,98,397,343,33,26,58,865,328,642,615,342,663,355,679,603,93,725,408,882,113,17,337,151,814,144,351,285,213,510,520,514,591,136,396,812,411,480,631,259,493,536,402,774,891,629,156,389,746,46,321,711,643,49,892,463,255,721,465,540,695
+420,764,127,359,870,59,509,281,353,28,548,777,504,209,85,289,733,140,815,225,678,26,644,218,846,65,453,314,570,229,615,380,245,310,298,732,132,869,105,267,394,538,628,599,123,287,161,816,363,525,637,110,516,649,495,29,292,24,757,890,847,536,400,397,768,819,478,573,244,196,472,687,350,370,636,258,57,468,322,30,821,126,174,377,836,347,517,565,646,164,695,720,237,247,742,598,737,266,271,355,307,601,100,66,53,807,431,665,592,190,228,820,362,540,824,312,9,739,388,27,625,358,252,270,514,215,542,128,520,222,748,169,760,653,46,561,776,81,862,466,89,137,296,219,114,422,138,199,682,891,659,411,40,72,6,326,330,217,201,97,301,398,884,383,872,118,435,711,391,8,404,12,194,337,457,445,641,121,543,316,895,873,54,702,773,539,407,856,406,424,510,699,523,260,813,251,522,791,93,521,309,673,735,5,842,409,122,736,462,679,293,134,494,643,474,750,408,590,618,103,177,790,775,83,124,651,73,769,667,162,379,496,795,547,486,823,94,809,794,734,864,116,507,31,492,460,591,754,624,165,264,92,236,729,145,789
 ,76,82,889,238,34,713,64,784,796,859,677,788,303,154,448,261,756,158,308,511,707,133,399,498,332,427,640,191,562,86,878,178,371,786,861,149,187,99,771,155,743,96,356,306,866,14,838,148,501,77,263,660,449,546,818,630,426,657,477,576,725,537,684,108,680,74,429,32,130,421,893,109,374,254,655,832,153,61,1,580,612,582,694,722,606,189,726,170,755,584,686,778,544,613,205,627,336,881,645,639,828,288,871,714,738,622,369,650,609,604,531,616,808,503,241,717,279,886,841,852,348,801,386,762,226,652,829,317,157,47,532,375,826,328,390,839,689,231,78,571,704,840,648,143,470,414,257,415,436,197,850,619,418,528,175,459,798,368,42,246,879,545,300,239,413,675,396,493,876,705,203,443,572,48,488,179,284,119,623,75,234,783,765,343,512,476,853,342,319,898,770,192,10,430,610,487,635,224,323,216,441,338,198,710,101,210,69,295,425,835,207,367,875,240,302,200,668,708,817,346,19,749,20,294,855,483,759,349,3,564,335,831,25,182,663,554,693,611,868,563,444,255,642,724,88,272,156,774,810,579,896,549,195,450
 ,193,58,439,541,894,43,417,506,497,50,456,364,227,160,685,560,822,387,751,661,697,37,574,278,324,463,837,211,491,144,21,558,412,291,259,63,696,880,147,752,180,389,185,273,311,41,2,634,184,858,620,827,804,863,551,595,365,51,527,60,79,805,721,701,480,33,792,629,698,578,670,485,172,360,555,381,877,16,433,276,107,333,376,730,607,183,676,552,351,159,318,250,473,91,382,731,280,621,851,102,235,519,524,712,761,812,84,567,781,341,715,471,111,848,334,290,452,718,632,274,865,745,484,605,882,700,262,467,345,62,313,691,499,268,690,405,593,533,666,45,780,432,479,874,654,221,402,849,688,373,669,586,899,617,683,500,248,727,758,469,393,339,600,340,283,569,23,437,530,277,887,129,188,844,242,90,141,589,361,557,583,95,603,515,709,454,461,451,4,664,575,38,392,152,800,125,867,746,674,357,830,719,265,233,888,22,18,806,490,779,766,489,52,423,518,614,232,656,223,438,327,577,344,662,465,814,70,416,428,378,626,596,401,305,249,202,585,559,785,566,384,366,455,811,633,681,320,594,136,67,68,556,482,897,14
 2,706,608,285,833,834,446,329,647,106,747,740,534,167,372,803,139,638,243,163,529,354,206,297,166,115,892,117,395,753,55,587,186,204,434,526,403,282,304,631,763,782,481,502,253,672,900,703,15,71,98,767,513,286,602,173,410,442,447,553,176,857,845,13,793,80,854,464,212,146,325,458,214,475,112,802,168,321,508,535,550,419,883,213,597,39,49,658,799,208,44,275,797,588,825,131,440,87,331,787,104,181,11,150,385,772,352,315,220,269,151,7,692,728,299,17,581,568,230,860,505,256,35,113,135,36,716,56,171,723,843,744,885,120,741,671
+680,618,82,520,851,298,501,165,143,186,545,808,258,148,99,177,832,413,678,544,505,25,647,56,803,184,591,391,200,191,372,180,266,193,58,778,49,888,122,514,619,703,516,550,86,230,166,797,367,318,705,410,716,681,295,236,202,51,660,878,715,709,585,306,661,772,300,554,578,20,638,674,271,243,564,96,181,479,570,250,713,158,141,428,810,510,156,308,369,142,533,817,106,328,700,652,837,208,228,473,347,586,272,33,257,789,527,561,227,11,412,770,238,692,667,433,52,682,532,164,764,244,459,222,263,398,301,209,431,53,701,377,830,577,110,732,602,60,860,446,64,85,255,364,401,526,112,468,361,893,314,319,240,135,145,220,344,87,170,302,345,75,889,689,773,423,383,691,521,94,371,27,216,406,595,117,622,63,694,352,876,877,190,781,748,632,163,766,654,606,720,366,623,168,862,116,511,666,211,494,61,542,655,32,890,249,47,663,424,587,131,50,684,677,726,616,281,649,390,18,451,855,782,62,253,523,90,637,287,149,528,215,785,269,179,805,320,581,695,806,843,188,450,242,288,223,388,807,284,40,336,294,455,448,120
 ,761,360,173,861,429,67,635,219,753,815,729,485,665,241,464,421,400,717,232,296,572,836,396,203,440,343,355,524,78,607,305,850,29,229,699,828,460,480,151,884,42,771,30,335,389,858,57,879,118,633,136,224,582,373,444,834,518,333,452,490,760,819,279,854,254,824,313,277,226,109,688,895,6,449,39,467,846,470,329,66,340,662,500,670,604,733,529,445,35,848,621,567,596,559,599,414,489,471,801,704,833,896,359,853,592,403,502,644,799,734,487,474,594,751,153,560,642,375,868,839,859,280,590,299,765,19,669,813,278,169,268,512,664,775,539,630,873,508,71,3,624,754,802,506,354,234,574,262,522,712,273,857,540,88,687,231,476,740,130,21,546,867,702,124,43,192,690,127,315,883,769,323,645,668,189,171,17,609,427,820,260,265,777,809,95,536,357,844,327,408,885,727,324,77,679,583,629,790,84,517,462,417,646,16,503,218,194,14,453,161,814,341,307,880,463,608,108,558,811,686,107,83,737,114,23,838,651,759,513,70,276,285,711,175,9,719,791,763,724,866,316,486,580,743,840,4,293,411,822,816,673,869,376,456,710
 ,430,28,432,767,892,54,264,207,741,245,119,426,26,73,478,436,745,407,863,384,556,176,217,547,178,303,756,252,615,379,221,286,543,425,439,128,339,852,10,856,274,297,80,441,475,267,92,492,437,718,825,894,597,795,730,588,613,7,326,204,368,728,610,804,639,100,735,742,786,736,643,365,214,472,233,497,812,55,380,139,65,356,551,706,482,289,573,465,256,394,330,363,614,261,495,626,575,275,831,15,534,631,683,496,823,800,196,283,780,182,537,419,317,722,498,304,105,598,457,565,776,438,322,611,792,864,246,648,353,1,563,342,493,101,798,415,617,650,708,34,755,270,351,887,399,74,507,779,744,442,707,549,899,337,787,183,548,870,627,620,115,562,757,206,310,552,248,370,174,97,881,146,259,886,41,201,387,435,198,469,385,152,484,235,697,569,197,568,38,579,555,5,405,199,826,282,882,499,422,395,845,557,504,348,865,123,76,768,162,625,530,746,98,290,723,509,44,576,311,212,89,593,338,658,381,829,150,447,600,93,589,454,386,187,481,525,628,409,788,601,239,657,418,774,714,750,157,721,346,134,247,671,292,89
 8,251,675,392,374,897,784,458,91,827,68,874,749,402,291,104,762,45,725,102,362,612,147,350,331,488,312,891,46,466,821,111,641,358,144,103,416,541,225,121,818,841,605,640,154,332,847,900,477,69,36,13,603,636,349,693,404,634,685,378,519,48,731,849,172,698,159,752,653,461,138,213,393,397,584,81,793,382,137,738,538,571,553,842,483,434,132,185,676,794,31,129,535,758,321,783,59,531,210,167,672,37,491,12,79,72,872,195,334,325,140,205,24,835,696,566,22,656,420,133,796,155,515,237,160,125,8,443,113,126,739,875,659,871,2,747,309
+131,809,226,143,822,74,422,329,498,11,633,630,639,453,278,341,470,16,854,17,717,147,613,396,823,141,256,191,813,231,735,480,215,338,540,698,261,742,335,95,146,292,706,641,218,279,185,702,271,615,468,9,336,658,696,13,307,100,779,881,873,351,257,477,829,799,551,510,19,491,228,616,409,515,606,419,121,399,86,56,863,240,216,428,767,266,771,695,810,222,733,559,339,366,707,444,462,272,324,337,209,526,48,300,23,755,401,652,811,445,239,760,497,267,872,332,91,661,204,66,392,505,98,319,660,80,648,306,519,443,676,51,683,618,81,286,846,322,775,384,171,374,455,327,3,245,250,50,842,862,838,590,24,210,84,397,535,393,214,43,483,651,817,83,891,22,370,762,202,59,556,144,340,488,280,737,646,273,269,312,898,776,73,431,719,512,636,869,114,316,234,847,330,382,764,343,432,827,75,538,598,663,710,157,589,469,364,693,430,643,371,254,275,681,187,790,446,506,732,295,20,550,716,207,101,659,199,795,851,211,439,650,754,687,673,831,69,880,840,521,818,305,463,18,609,584,668,546,806,424,167,47,108,853,188,679
 ,5,252,895,247,156,675,148,701,752,888,748,826,302,8,578,304,782,120,421,417,379,31,562,458,298,580,642,429,427,6,864,349,452,741,816,4,40,213,408,411,623,253,314,162,803,93,808,194,449,265,353,610,572,576,647,631,423,796,365,284,547,682,317,132,473,2,485,46,182,169,861,334,227,561,703,700,35,33,88,697,607,604,744,821,514,10,860,357,499,614,669,849,415,560,62,653,376,897,529,260,507,180,824,749,877,685,118,369,354,624,486,554,751,783,58,723,166,868,718,730,495,875,403,629,459,564,758,287,179,67,577,127,766,197,177,655,773,360,289,627,690,814,699,54,585,375,436,467,109,137,721,608,680,308,315,492,825,555,151,49,837,309,518,420,525,553,665,667,787,481,119,163,588,39,768,387,77,1,311,41,416,656,571,494,404,501,791,262,441,900,694,165,92,189,586,448,356,524,230,103,359,53,493,794,255,195,221,125,672,830,110,344,781,105,44,283,736,573,848,594,164,678,107,563,793,381,612,174,117,740,460,850,71,433,601,186,557,603,800,734,570,26,406,412,299,236,28,569,792,442,899,605,21,122,129,277
 ,440,263,883,232,530,677,183,30,689,478,531,303,763,611,820,388,545,812,724,99,788,72,575,520,865,178,496,25,32,704,321,205,149,96,856,886,398,513,124,413,301,310,130,60,55,662,140,890,325,523,874,876,368,533,115,212,711,135,7,804,720,599,281,142,759,516,587,320,558,626,192,405,746,293,893,97,377,541,200,484,294,638,756,170,688,537,347,52,243,345,249,45,285,778,38,819,765,372,36,331,464,807,705,798,123,728,692,386,797,434,116,878,136,342,709,774,772,42,884,870,591,595,896,313,237,394,418,290,139,855,628,543,390,326,534,373,472,158,727,527,635,769,802,355,223,828,567,241,597,536,887,761,532,715,57,378,843,438,686,138,414,549,282,670,12,385,784,517,866,159,274,640,489,193,128,637,474,548,731,104,621,747,579,367,645,437,112,632,503,244,539,184,780,65,750,858,801,233,833,815,76,160,894,70,161,708,770,832,857,201,90,622,264,664,407,738,134,634,568,565,258,666,450,674,219,291,246,600,712,729,457,574,102,15,475,596,684,504,593,79,402,743,389,617,466,544,64,111,155,333,582,889,113,7
 57,789,203,522,839,500,592,352,328,471,583,620,133,566,805,270,391,476,173,602,447,296,208,14,85,871,358,451,528,87,435,224,242,691,552,383,487,581,276,671,852,350,739,168,348,885,786,153,176,346,841,297,456,479,68,150,126,509,508,454,882,844,27,785,251,859,238,34,318,542,426,248,288,190,714,61,461,196,425,410,217,892,89,726,175,78,619,657,502,181,63,777,725,845,235,259,106,400,836,229,29,154,268,625,465,482,363,145,395,361,152,362,713,94,198,511,644,490,879,745,82,37,323,172,206,834,225,220,753,654,722,867,380,649,835
+808,301,58,621,767,616,429,72,13,455,498,772,133,379,346,63,841,668,422,770,408,127,488,11,672,415,559,521,92,176,204,53,222,238,17,801,23,871,424,608,692,745,279,350,226,155,144,708,335,189,643,733,815,689,170,567,210,212,389,796,440,776,641,177,451,625,147,509,802,104,658,505,173,168,493,12,416,328,693,615,519,246,257,459,705,594,71,79,107,98,240,848,34,503,496,538,851,146,163,561,400,407,399,259,588,715,517,490,96,24,593,597,164,736,375,557,235,563,497,482,799,215,662,152,29,480,120,499,239,46,494,508,867,539,293,783,291,348,809,308,187,271,349,644,677,471,109,755,140,866,111,354,483,364,476,118,613,61,192,601,636,21,863,842,541,756,277,688,502,280,423,198,384,679,556,137,457,60,738,324,778,844,380,788,630,639,77,565,766,681,795,114,581,88,888,70,427,378,320,322,166,377,419,300,893,157,195,554,243,530,84,35,741,731,834,305,86,535,97,19,646,852,753,101,316,248,201,338,161,283,710,51,735,160,82,771,518,282,512,804,749,495,330,510,54,175,270,790,121,126,332,591,555,172,159,6
 40,617,536,740,598,260,382,528,600,817,464,184,391,142,750,437,544,638,326,374,445,869,574,59,311,255,362,409,199,465,507,727,5,76,515,713,704,769,288,897,150,700,48,456,434,791,230,895,136,678,474,214,393,281,218,797,275,158,249,443,825,832,37,889,387,874,547,278,595,193,829,881,15,551,131,323,798,721,702,352,154,606,252,631,417,800,787,196,7,857,564,289,296,477,386,585,219,684,614,642,884,899,435,762,302,211,244,779,846,758,241,306,388,577,138,744,405,363,768,792,822,321,307,134,671,6,527,723,319,153,659,373,820,683,622,725,859,224,80,83,633,823,676,223,570,73,690,414,626,843,396,826,292,47,719,412,404,649,10,91,707,794,739,103,44,117,572,135,181,854,752,487,722,747,469,125,4,853,674,878,533,463,685,784,27,385,261,763,262,670,793,549,392,353,813,370,680,839,309,620,623,365,833,89,188,579,250,62,651,139,751,376,369,847,742,810,50,327,862,411,122,406,603,355,30,757,709,691,523,368,39,314,431,420,16,726,880,764,827,818,66,607,805,746,868,32,229,568,806,828,605,761,273,664,835
 ,592,245,318,855,849,337,74,18,840,580,25,573,112,31,174,182,522,339,887,108,263,436,95,682,329,232,612,397,687,587,548,49,529,433,481,268,151,748,36,873,294,123,26,657,500,653,343,220,666,468,883,898,297,667,816,398,716,106,171,484,648,504,511,870,611,336,553,789,837,773,562,206,236,654,38,460,695,207,367,299,65,534,629,545,347,351,298,356,128,637,432,540,604,472,458,344,774,75,760,200,698,575,785,186,856,775,357,102,701,221,225,428,526,478,532,312,43,333,274,743,543,191,85,447,582,894,272,765,394,129,696,165,514,228,830,462,448,596,669,113,627,68,227,865,132,9,486,584,734,381,673,444,885,169,836,14,782,892,410,729,203,652,824,287,276,492,569,264,81,99,821,295,371,882,8,453,618,183,64,266,143,331,254,90,566,552,28,624,286,360,425,162,520,233,838,402,861,216,124,358,860,304,619,546,759,290,383,656,130,317,208,858,265,285,803,251,1,421,441,110,41,439,372,560,334,780,413,418,609,3,513,267,315,446,576,737,466,209,728,442,256,814,253,634,706,811,56,807,599,237,589,665,69,876,454
 ,635,205,359,900,675,426,115,877,242,896,697,178,345,2,663,67,724,116,542,712,20,583,401,718,461,850,197,537,819,247,516,558,217,40,185,610,403,269,875,879,303,650,52,313,890,891,167,342,94,100,310,645,647,661,524,711,812,234,475,202,470,845,467,449,491,489,686,660,258,341,395,628,550,213,720,602,22,831,438,501,531,714,786,190,485,390,590,730,145,452,694,632,105,732,78,473,361,179,450,87,717,194,42,33,886,93,366,340,55,578,231,872,525,699,284,571,148,325,703,45,754,506,479,141,180,149,430,156,781,864,586,777,57,655,119
+636,168,340,835,632,773,771,462,236,798,131,176,756,647,600,288,595,849,43,870,880,491,22,313,55,525,345,867,681,511,776,512,405,805,398,109,408,546,754,524,500,388,32,18,821,382,383,302,645,740,260,883,347,112,206,843,704,693,64,252,106,290,261,92,12,19,634,856,859,652,537,53,122,149,875,263,541,156,661,853,23,303,812,198,356,283,707,534,276,298,360,239,441,455,67,404,559,444,160,264,787,420,548,676,869,26,147,891,743,544,449,241,145,597,129,327,683,770,428,862,291,179,868,173,338,588,654,686,454,358,287,701,240,889,752,514,116,765,370,410,750,547,318,666,840,516,262,895,397,492,495,270,664,519,807,142,736,279,650,882,732,656,465,825,77,896,565,108,591,609,277,542,403,706,296,678,7,306,602,148,79,431,496,564,38,123,299,25,735,268,485,467,617,182,333,607,741,82,482,41,657,785,475,762,637,680,531,838,192,884,670,478,336,194,566,205,247,87,368,425,677,501,37,344,372,325,373,213,731,836,489,596,16,810,772,34,536,245,10,393,359,729,623,716,289,816,831,427,760,497,487,879,401,324
 ,635,339,746,832,88,434,507,224,688,211,63,100,197,44,341,872,212,357,8,692,278,136,572,583,165,611,184,214,844,470,417,720,130,435,151,618,461,792,897,377,758,505,150,371,890,722,539,679,366,575,181,804,163,589,102,128,490,436,220,127,734,540,233,292,719,374,389,749,845,873,711,570,573,504,854,660,827,414,708,877,744,700,45,137,73,52,221,885,323,365,460,54,284,118,728,237,826,253,506,75,115,778,818,813,522,83,622,49,580,411,473,350,488,297,207,703,669,30,348,254,577,472,251,204,188,322,557,96,158,809,363,887,28,629,769,330,406,479,99,725,727,146,231,62,133,841,603,311,452,310,761,819,520,361,608,332,447,69,5,274,553,689,346,352,301,717,724,152,503,153,549,412,851,614,235,842,576,469,900,814,586,858,533,228,391,642,395,738,157,459,665,114,230,286,830,499,107,202,423,751,331,468,723,871,667,210,802,702,631,881,418,3,415,847,593,898,864,376,21,285,47,424,791,58,579,671,190,222,594,328,739,426,216,161,604,587,76,789,135,317,453,226,387,876,335,560,578,266,624,445,91,143,124,811
 ,806,764,457,658,61,526,429,726,141,456,643,874,651,402,641,305,209,164,111,94,392,269,234,610,774,628,529,783,13,846,232,828,784,433,166,238,314,682,585,15,513,381,416,201,351,494,464,863,712,199,556,98,590,757,203,6,315,246,552,714,169,655,763,39,886,334,343,561,80,195,225,419,793,74,248,439,532,174,33,619,815,574,448,481,273,300,105,267,86,745,375,866,850,438,638,834,185,68,852,581,582,721,718,396,312,196,217,40,399,715,65,822,139,865,502,48,480,171,626,36,101,779,93,463,144,24,113,797,710,342,223,748,446,538,227,527,466,855,120,183,598,450,42,159,117,437,208,329,648,255,103,337,46,782,649,775,242,409,893,699,57,295,672,407,281,367,162,134,817,592,620,355,275,824,308,484,400,558,567,369,155,390,125,800,458,321,385,140,249,215,803,442,674,705,379,259,132,668,562,257,229,515,172,60,690,892,50,518,755,535,615,95,282,627,698,265,413,59,430,29,829,218,353,31,790,20,801,170,639,685,271,432,85,51,90,747,421,768,250,543,84,97,293,795,309,138,599,186,193,258,878,386,781,616,384,51
 7,857,70,187,244,799,1,110,471,510,508,571,630,71,304,354,2,662,551,320,443,316,440,555,808,733,451,476,528,243,474,653,378,477,767,530,272,256,493,601,709,294,119,191,697,380,612,625,307,673,633,554,89,687,737,126,498,521,730,56,860,605,72,121,837,177,796,167,362,823,349,422,848,545,568,786,104,861,219,621,695,753,486,35,899,78,833,509,27,364,640,766,820,4,646,11,613,563,394,794,17,684,694,742,319,713,606,154,189,326,200,839,644,550,9,569,788,66,175,584,14,659,894,691,780,523,777,280,759,663,180,483,888,178,675,81,696
+463,134,374,459,48,844,283,300,358,719,620,93,518,879,839,255,141,710,275,737,560,616,171,506,61,760,165,599,786,312,487,334,243,529,665,507,434,49,887,388,317,207,269,204,672,235,311,16,277,412,78,819,527,587,613,814,396,636,104,15,188,413,372,296,328,107,321,394,725,829,198,94,327,497,442,418,751,125,420,871,343,606,602,621,10,565,778,347,502,319,149,417,339,820,65,74,155,266,304,633,416,83,457,848,825,143,480,516,747,730,759,18,479,192,292,706,661,173,190,826,253,578,638,294,336,356,362,881,156,652,43,471,656,483,634,222,287,882,8,136,617,838,749,883,740,180,452,795,666,4,691,745,715,790,852,320,899,566,391,791,898,728,13,653,228,856,212,643,231,639,756,698,779,895,167,854,229,492,193,350,216,19,626,117,100,469,655,220,401,523,316,614,162,405,785,411,254,144,425,183,860,305,88,840,189,357,804,281,126,468,450,443,286,720,503,113,186,139,256,571,564,106,250,532,365,114,625,99,806,637,858,444,213,608,651,462,660,493,360,85,5,885,197,750,247,577,494,73,679,787,252,789,407,514
 ,438,23,734,894,115,752,729,55,851,25,390,302,176,168,219,775,703,727,373,435,704,129,251,568,398,200,208,692,406,799,91,611,50,488,276,102,21,687,836,680,419,796,69,544,662,344,22,640,811,395,530,890,445,142,496,137,47,132,157,499,267,265,240,333,447,588,575,659,585,864,520,618,12,649,510,847,428,27,724,874,792,423,359,109,598,511,543,805,597,513,158,460,92,325,230,59,567,120,853,335,140,453,531,458,24,130,774,187,533,322,146,124,147,64,26,849,607,118,236,11,46,31,693,489,181,37,644,90,34,475,313,884,303,635,131,501,400,58,241,581,748,642,733,56,151,657,364,696,834,762,586,538,40,97,771,203,797,381,370,465,589,528,1,205,676,629,481,67,813,548,28,77,631,293,707,761,816,604,877,694,478,753,865,36,60,522,105,342,39,209,891,295,32,466,781,580,81,579,297,888,594,605,298,717,821,224,893,426,615,641,780,260,306,550,35,810,689,326,261,583,182,772,872,76,746,763,20,484,72,273,831,430,647,101,732,716,361,536,270,777,9,377,841,736,123,217,669,223,508,66,539,153,340,439,603,504,646,837
 ,274,542,2,863,288,440,449,830,685,828,835,392,194,145,57,323,509,448,110,767,731,464,866,436,378,619,670,624,815,349,324,331,346,545,742,199,722,258,301,177,353,818,280,876,726,122,768,354,555,477,455,282,515,63,366,713,553,824,755,96,476,723,164,765,53,461,559,201,226,387,351,822,526,278,386,610,393,867,410,862,551,41,576,427,112,290,214,695,570,808,202,674,248,138,677,671,45,859,540,119,697,257,663,403,609,524,95,572,225,519,718,299,268,486,754,195,495,561,154,675,237,178,284,517,383,714,648,800,556,758,741,842,172,512,84,170,103,584,86,246,505,38,414,380,242,33,215,166,279,272,17,552,467,549,769,402,474,699,873,385,409,794,318,645,809,234,783,711,7,628,658,111,623,812,766,160,330,121,345,622,150,667,51,337,441,627,798,98,179,803,827,376,590,451,44,485,341,218,702,355,422,709,148,612,861,52,832,206,375,582,593,735,338,161,482,431,535,595,668,175,408,348,379,70,846,264,291,563,600,389,384,896,397,654,71,221,89,108,738,574,127,42,128,601,415,673,744,490,880,159,244,6,684,59
 2,573,263,534,233,500,788,473,801,521,82,227,352,472,259,547,116,683,712,807,329,850,456,681,562,3,802,688,87,537,75,782,525,739,133,650,857,870,369,690,332,309,705,239,541,14,232,817,558,776,308,211,897,191,454,315,433,285,437,845,262,630,793,54,889,80,245,596,701,823,498,833,169,632,62,682,363,368,210,238,185,174,869,314,886,664,249,30,843,875,546,152,424,421,491,184,569,557,307,591,678,757,371,708,271,432,554,289,382,900,770,310,135,470,855,196,163,868,399,700,743,764,892,367,784,404,878,446,721,68,429,29,773,79,686
+820,294,165,717,800,570,554,219,76,508,369,786,180,193,230,188,861,710,300,799,445,183,483,61,650,382,670,626,8,309,226,161,366,332,16,702,124,882,254,688,748,777,233,323,287,286,265,750,467,248,703,727,785,544,73,575,328,275,396,774,353,766,648,200,319,586,243,615,814,50,742,543,201,126,584,74,395,420,751,579,373,232,358,375,745,559,10,137,54,224,290,823,154,376,532,663,868,281,228,477,529,533,490,160,599,682,466,557,38,31,510,660,133,793,244,458,289,667,629,499,804,144,724,227,81,601,195,362,368,52,583,623,802,607,391,824,210,213,822,446,262,149,218,464,705,613,168,770,27,865,13,179,503,278,441,167,374,83,317,645,398,11,867,856,410,743,419,489,647,343,250,209,261,436,651,9,426,123,795,346,649,860,415,834,617,551,33,440,813,646,817,37,699,131,838,197,550,345,424,348,42,455,507,247,896,255,108,635,352,597,207,147,763,542,839,325,216,569,156,91,694,866,689,163,409,329,206,361,23,384,534,107,674,174,102,638,537,122,377,831,769,355,457,527,129,225,305,828,88,72,462,631,606,71,2
 76,701,643,394,641,517,234,450,438,668,726,311,202,334,271,762,270,453,497,449,251,516,877,621,85,443,351,217,479,101,598,588,691,78,152,603,747,729,779,252,897,82,719,110,535,565,818,298,858,259,600,338,214,505,215,267,832,387,260,120,573,841,825,77,892,402,853,604,356,578,299,815,883,68,664,40,383,827,709,679,342,203,536,312,454,241,735,796,58,70,864,461,381,187,614,475,684,279,521,428,672,889,899,552,790,306,29,237,791,851,803,339,434,494,624,7,755,406,470,761,830,840,205,135,235,728,39,574,725,431,266,608,333,810,740,627,734,870,184,170,116,469,692,665,240,653,162,589,246,472,859,506,843,404,3,752,302,370,487,45,182,749,805,773,67,106,204,633,20,97,863,797,591,775,594,524,6,51,847,704,878,582,282,721,821,103,519,371,767,405,452,630,612,425,386,798,430,593,846,119,592,632,488,844,47,176,427,388,150,713,28,654,480,460,862,759,826,172,256,819,344,41,320,622,326,19,758,673,768,605,318,63,223,411,423,36,657,885,738,698,835,69,408,816,784,880,90,350,644,836,711,658,545,349,718
 ,854,580,164,331,850,849,236,127,60,852,590,22,400,43,117,181,242,522,341,876,66,307,413,59,733,125,315,435,485,563,677,531,98,540,476,546,380,17,620,48,869,421,231,132,528,619,595,379,263,602,288,881,898,141,513,781,500,760,159,87,429,656,478,567,812,700,285,561,739,780,811,680,155,297,481,53,504,484,272,473,118,185,336,587,636,178,393,330,459,257,693,539,407,716,556,515,321,807,24,792,104,744,687,697,157,782,681,372,130,696,292,190,523,492,340,642,280,4,273,143,776,448,46,145,439,417,895,403,686,296,121,695,12,337,84,848,571,512,659,754,175,625,142,138,871,79,100,637,611,706,502,628,555,886,166,801,18,806,894,239,609,34,690,794,136,322,335,562,401,2,57,808,399,308,888,26,378,568,258,115,389,105,422,364,21,675,541,49,530,295,456,549,139,327,284,737,520,873,95,99,493,746,194,708,616,655,354,301,722,5,245,114,855,363,134,809,253,65,291,548,62,25,444,491,463,433,789,314,558,669,14,365,171,277,199,634,756,576,303,715,498,113,833,390,666,783,712,96,707,671,293,474,753,169,874,53
 8,451,80,437,900,560,360,32,872,153,893,772,191,416,35,553,173,788,75,482,518,128,447,526,730,496,857,112,418,842,357,640,465,316,1,274,525,222,94,884,829,189,661,30,442,887,890,177,269,208,86,212,741,412,678,596,765,837,238,581,93,347,731,495,471,367,468,732,723,192,158,486,511,683,283,714,685,89,845,566,639,662,585,787,148,397,414,547,771,56,359,757,577,151,564,198,618,392,249,324,196,720,220,140,44,891,111,304,432,109,385,221,879,501,736,229,572,211,146,514,15,778,509,313,264,186,92,310,268,610,875,652,764,64,676,55
+781,66,271,835,609,807,698,332,127,794,189,342,541,585,571,202,749,862,1,885,793,421,108,194,139,573,447,849,398,424,549,335,359,699,232,313,299,704,730,656,655,564,7,36,733,315,330,365,574,544,363,887,600,251,111,851,581,626,42,294,34,517,416,73,13,101,431,808,884,480,641,145,112,119,814,159,588,180,761,861,20,312,731,272,380,423,428,307,100,255,213,510,306,511,122,427,745,352,157,384,746,371,589,599,864,163,260,832,456,368,568,254,120,708,21,429,630,687,497,853,513,156,867,160,162,643,410,713,331,240,267,743,507,839,720,695,14,710,457,353,661,487,320,726,859,551,224,893,175,586,244,248,722,537,800,115,750,191,543,877,753,397,595,875,35,895,466,219,618,596,296,496,414,751,400,446,62,238,715,199,109,557,546,694,141,266,171,22,817,438,693,212,644,142,633,441,674,33,503,70,474,639,366,723,820,508,435,757,168,830,495,350,533,327,774,106,164,190,182,308,768,696,200,301,406,208,344,124,445,769,614,345,166,601,528,183,637,71,31,558,383,742,516,760,148,636,666,569,489,376,479,873,5
 29,128,525,360,796,816,117,556,493,176,739,252,273,23,69,8,285,881,245,458,110,660,300,203,775,686,79,502,196,214,755,375,412,764,169,288,96,509,434,841,897,387,876,399,281,293,852,714,570,624,678,469,341,783,170,471,113,86,590,310,167,38,684,738,464,129,858,432,691,785,752,868,612,773,676,355,842,476,668,519,797,882,729,460,184,97,178,45,442,890,133,235,683,174,188,15,685,220,828,154,631,41,247,866,894,777,524,37,324,18,756,672,617,241,393,268,216,450,780,40,389,290,628,572,246,55,146,379,356,181,249,737,322,879,76,790,707,492,594,662,12,559,591,261,422,150,49,848,385,482,449,425,855,778,616,269,361,505,473,151,87,140,459,786,403,535,206,520,532,233,329,83,659,540,844,732,392,838,340,309,900,845,802,854,547,311,536,413,369,593,264,402,724,118,237,354,787,725,130,357,670,652,491,615,648,889,488,65,803,619,494,874,262,135,453,789,680,898,886,280,5,566,10,289,772,161,584,436,279,404,610,433,727,195,225,89,647,394,256,870,328,531,522,64,454,888,498,770,417,257,711,580,295,278,9
 9,658,834,850,587,576,123,771,490,690,61,228,799,865,377,472,455,218,74,93,107,155,718,88,137,653,504,744,448,627,47,809,378,833,801,215,298,325,415,635,304,85,358,664,418,149,253,620,545,869,706,114,701,25,811,883,50,46,560,239,709,592,75,702,812,57,822,613,465,562,134,407,468,611,741,43,259,553,283,275,58,561,735,485,348,521,420,314,80,323,53,622,291,863,819,514,682,818,286,30,878,303,582,607,795,467,530,51,463,204,443,452,201,705,28,810,608,11,567,209,364,2,39,836,48,205,56,91,44,880,625,548,265,623,621,282,277,408,675,821,172,317,634,381,147,84,72,597,54,210,651,222,287,367,207,697,712,527,499,187,896,857,32,462,477,565,526,316,198,185,826,484,346,250,336,762,347,719,243,606,688,230,90,297,26,759,319,158,396,270,102,349,754,338,583,602,411,274,339,673,692,82,59,500,382,4,763,871,103,534,740,518,372,17,95,806,657,217,638,27,263,52,791,125,211,105,736,126,703,326,640,649,409,226,153,24,136,689,554,831,292,373,227,165,229,856,258,193,669,395,121,470,872,386,798,677,221,598,
 840,173,67,302,891,68,179,321,776,451,823,645,29,351,186,92,506,646,231,552,444,276,642,765,813,538,539,437,333,632,603,405,575,665,305,177,391,475,478,847,579,16,343,419,390,829,717,143,650,515,430,3,728,766,284,604,679,827,60,804,486,19,318,825,144,782,116,523,843,334,370,788,663,605,700,223,860,131,784,629,716,550,63,899,9,815,563,152,426,483,758,846,98,388,132,481,577,439,654,6,555,792,667,234,461,805,104,236,362,138,824,578,779,77,721,734,192,81,512,78,374,892,747,767,440,681,94,748,542,337,671,837,242,501,197,401
+135,565,313,45,257,590,114,242,529,324,751,275,575,860,717,267,23,236,741,252,561,450,470,557,516,589,30,190,879,134,604,392,80,338,695,711,374,137,826,85,52,65,622,530,417,131,159,173,59,477,75,419,482,744,777,463,228,354,526,531,712,421,331,478,743,549,382,240,241,784,9,335,471,631,356,518,567,169,54,594,802,541,314,655,223,510,853,566,780,249,439,552,316,761,395,24,41,139,359,612,98,81,127,722,466,535,563,458,849,681,634,291,619,5,767,653,376,203,20,496,256,667,148,328,586,42,508,793,192,665,206,70,764,389,292,27,719,787,211,68,362,762,746,810,293,13,438,318,869,342,870,813,420,649,605,449,899,608,176,378,894,753,248,207,778,469,94,843,11,353,796,532,705,891,55,885,543,473,4,416,854,197,385,16,460,606,758,736,32,502,100,845,8,509,872,326,104,611,144,424,863,383,274,638,154,340,727,310,182,409,369,345,168,840,263,506,286,285,550,514,162,64,596,453,172,336,523,498,895,344,829,581,602,633,679,805,405,866,783,61,299,809,126,443,475,546,540,46,773,732,34,380,188,833,218,147,36
 8,808,718,636,574,296,666,237,686,825,547,635,145,311,775,643,726,99,702,184,86,227,609,136,194,768,415,754,28,187,559,484,433,266,282,253,408,576,214,734,251,486,347,40,210,346,890,205,603,794,517,180,662,350,67,272,230,791,71,50,373,607,193,432,570,245,457,555,265,398,315,583,122,842,507,119,397,571,536,564,615,341,803,830,621,363,868,524,107,663,317,756,60,158,93,372,789,874,287,121,358,101,271,519,900,544,246,259,21,290,116,128,303,893,244,497,53,488,95,123,723,864,270,96,623,260,321,219,166,614,562,355,247,396,232,97,626,465,598,757,836,492,489,191,479,661,800,748,185,161,103,226,828,87,703,568,766,616,404,117,325,82,713,556,476,177,865,731,171,31,201,18,769,379,883,585,493,255,301,337,832,183,62,527,44,302,377,57,878,888,234,366,474,387,284,624,198,881,495,381,112,222,779,618,806,163,452,170,857,690,69,300,157,375,178,278,628,647,677,814,684,384,542,737,348,520,49,89,617,657,680,595,480,668,599,160,464,818,212,678,861,239,58,79,560,129,130,48,792,233,897,448,118,90,462
 ,700,440,371,456,710,491,629,156,472,742,819,812,410,577,388,501,454,553,750,428,548,804,88,875,400,838,261,688,150,521,600,361,258,196,213,889,760,672,294,77,269,343,715,29,613,429,413,580,858,403,357,856,785,504,120,76,528,759,632,407,545,483,749,36,591,425,579,656,66,124,640,295,776,687,273,876,334,204,867,289,852,512,141,807,332,447,238,174,221,231,728,2,235,224,554,165,834,167,763,113,19,682,651,782,739,442,637,411,422,627,308,525,797,22,537,823,620,770,102,704,884,490,467,850,216,149,673,669,642,352,896,831,847,63,208,220,186,17,441,444,446,692,199,733,436,15,423,431,33,533,175,418,659,569,714,280,217,839,685,892,181,459,822,327,795,485,133,871,729,468,306,597,155,654,658,572,367,500,189,671,264,281,827,72,430,650,652,539,209,105,641,846,309,798,84,132,837,689,25,882,747,39,305,745,349,675,143,886,664,772,330,262,820,202,503,511,720,142,725,716,437,138,648,268,298,694,37,195,660,786,696,551,898,164,229,78,319,386,250,801,115,111,333,6,699,558,701,297,312,706,1,414,455,
 283,815,821,153,390,691,625,824,365,709,461,35,513,215,610,676,401,10,693,573,851,399,740,125,279,320,402,721,698,38,225,26,645,288,816,277,639,848,877,92,771,765,339,774,51,391,412,592,630,351,683,730,3,887,323,146,43,47,494,276,799,781,873,445,427,790,588,83,110,646,844,304,697,7,370,364,200,515,91,74,56,12,752,487,644,724,426,534,109,817,707,73,578,601,811,322,14,393,435,735,406,307,538,360,708,151,582,593,106,499,880,587,152,505,140,670,394,451,855,859,788,254,481,835,179,584,755,738,243,862,108,434,522,674,329,841
+789,382,86,745,852,526,647,203,22,500,300,766,353,187,184,138,864,718,369,798,684,104,438,5,664,291,607,692,150,311,448,209,318,443,1,652,74,889,282,617,700,738,201,285,361,261,206,774,508,423,676,737,727,492,48,568,390,267,422,834,469,699,542,106,345,593,359,740,811,54,724,511,98,50,747,12,302,355,716,578,415,116,421,269,790,466,145,266,102,134,402,785,142,303,531,653,866,281,117,383,574,567,433,149,615,648,364,749,217,16,424,695,51,783,363,362,265,770,573,530,760,63,753,118,115,547,339,331,418,4,624,591,772,771,374,802,287,215,845,470,307,105,143,437,694,606,65,794,114,888,130,132,444,204,429,78,393,6,343,666,410,83,881,843,528,764,474,477,623,284,193,131,188,456,575,85,367,35,786,218,750,870,317,835,597,479,8,512,797,541,782,168,717,43,823,226,641,406,347,283,70,627,616,235,894,365,67,775,309,769,273,108,703,504,803,411,178,509,242,24,631,868,643,66,312,403,97,451,216,461,484,220,628,381,278,620,454,262,389,824,813,336,535,478,158,395,525,830,299,32,439,654,513,182,295,73
 5,587,398,732,431,156,502,387,683,697,446,254,379,232,762,210,356,482,462,171,457,867,540,26,520,244,152,673,53,612,544,744,40,81,728,812,701,800,162,895,44,704,33,655,589,855,276,850,256,510,350,94,613,126,251,848,475,227,137,637,826,796,103,886,288,827,557,514,594,327,773,893,27,721,60,585,840,649,669,314,375,471,313,426,259,665,799,166,10,859,386,440,271,688,496,682,337,473,549,603,883,899,609,847,342,222,221,739,828,788,400,499,522,659,110,707,396,405,814,853,856,119,257,176,746,42,532,741,518,197,626,252,768,832,521,656,873,208,233,146,416,640,679,274,658,280,506,199,404,838,546,862,472,52,706,223,264,497,7,136,710,841,729,11,175,328,600,39,58,879,795,634,755,533,539,68,15,863,680,860,610,250,733,819,170,527,494,779,385,447,754,638,308,392,743,407,507,821,169,493,534,565,846,55,255,428,408,133,759,31,635,414,583,880,806,825,121,239,784,409,18,324,605,243,62,780,564,805,519,296,147,127,516,346,30,576,874,686,646,857,82,366,816,757,869,57,263,572,837,689,580,705,524,708,8
 39,483,139,229,818,877,219,76,120,833,614,107,335,49,45,241,237,577,224,858,123,371,334,247,685,124,476,489,558,485,657,498,177,441,370,455,351,173,678,14,854,352,179,79,465,551,602,329,315,523,419,861,898,268,561,720,505,713,164,59,358,598,517,767,776,644,213,584,672,734,781,763,93,183,432,159,401,570,228,590,113,129,301,488,660,167,260,341,588,249,715,621,332,726,566,413,357,807,161,842,111,711,650,622,225,748,639,245,322,667,430,238,661,399,434,586,172,75,297,144,758,554,195,109,377,553,892,450,599,198,148,608,154,290,71,836,674,481,569,778,88,611,96,84,876,112,41,632,691,645,467,548,675,896,388,752,56,820,890,286,529,87,604,742,92,200,293,536,464,90,9,849,458,196,885,2,298,491,348,47,436,101,460,452,36,690,445,29,442,316,538,633,128,289,174,714,490,882,191,160,495,736,212,681,696,731,258,294,787,80,325,234,831,338,91,765,240,38,270,595,20,3,373,556,412,559,777,272,601,562,25,319,153,181,248,537,723,550,417,698,453,73,815,368,668,793,651,17,642,693,189,468,761,214,891,592
 ,427,89,340,900,571,253,21,851,95,884,810,155,304,23,545,190,792,13,391,480,151,384,582,687,394,878,72,326,844,323,629,380,378,37,306,435,185,100,872,801,277,552,163,376,871,897,292,230,186,46,279,756,425,596,515,725,817,157,722,77,463,730,503,543,360,581,670,719,99,122,625,449,671,344,712,702,19,829,636,709,619,662,822,140,397,320,487,791,61,333,751,560,321,563,194,618,275,372,354,205,663,207,64,135,887,34,192,349,28,420,165,865,486,677,231,501,211,141,555,125,808,459,330,236,202,180,310,305,579,875,804,809,69,630,246
+313,800,182,343,874,13,544,359,412,29,504,730,602,215,92,355,688,112,831,143,749,62,618,300,845,47,418,339,673,298,704,466,296,392,382,672,206,857,116,197,320,465,643,601,210,329,207,810,403,615,592,65,413,578,531,15,370,67,776,889,858,445,322,426,775,812,554,630,155,279,441,660,364,395,692,335,34,469,235,7,832,126,250,337,843,248,622,662,703,208,744,613,330,202,748,591,681,323,299,272,342,632,91,105,40,781,378,720,697,284,139,827,384,484,849,229,46,777,369,42,527,372,239,302,590,179,633,107,570,292,767,144,671,702,78,489,808,109,853,492,156,163,280,141,69,423,173,148,740,891,733,415,12,64,2,360,289,261,263,90,246,499,880,257,877,79,475,663,389,20,391,45,168,262,422,518,619,171,486,287,895,862,33,652,753,472,463,856,334,328,435,766,511,307,715,357,556,821,98,517,381,726,778,32,793,485,164,787,478,724,390,214,424,567,365,791,456,547,691,175,113,745,723,117,120,694,93,804,751,244,304,588,762,646,594,802,50,840,797,693,868,104,546,4,558,545,685,714,718,227,283,87,172,794,218,79
 2,28,70,890,157,48,732,36,786,743,869,713,806,354,102,430,189,729,198,278,488,603,83,452,541,331,420,700,225,568,59,879,269,414,822,865,85,125,99,664,209,708,146,411,316,870,52,771,217,436,75,274,696,451,563,801,680,458,684,510,493,651,605,540,84,534,49,503,16,201,294,892,195,400,347,725,830,71,21,5,679,559,612,648,722,505,110,788,251,689,535,707,809,562,637,178,675,238,884,586,516,734,318,873,736,818,650,245,532,550,661,565,640,817,589,137,710,260,885,841,844,333,835,432,752,338,628,828,379,199,19,512,234,847,228,301,825,712,344,161,513,607,838,683,134,549,321,241,351,311,233,842,669,502,461,138,440,782,446,94,165,878,470,350,367,500,645,464,522,872,665,224,388,491,54,566,275,185,72,490,81,211,769,728,444,523,542,846,375,243,900,774,145,44,305,627,421,525,273,219,122,479,222,293,758,76,267,142,291,476,829,183,439,871,231,205,268,678,582,834,398,27,735,18,405,848,408,764,290,11,659,317,850,10,285,584,447,604,507,867,636,394,170,575,642,167,295,111,739,755,528,896,631,136,356
 ,114,88,431,416,894,56,457,593,397,41,548,310,312,230,721,595,837,377,638,717,727,14,686,188,341,539,839,256,425,123,1,649,362,240,204,103,768,881,236,670,181,438,253,177,259,9,8,677,97,866,483,737,836,860,448,609,277,118,560,30,23,811,780,569,450,31,795,521,580,501,695,506,174,270,655,346,876,51,482,309,169,286,288,741,626,149,690,614,404,140,366,193,459,101,353,765,192,706,851,166,159,494,433,761,676,770,63,674,750,429,754,524,58,855,297,264,538,731,656,186,875,814,530,583,886,553,324,371,308,133,194,759,467,315,596,453,581,477,653,80,763,473,498,861,701,303,409,854,616,374,599,639,899,711,557,585,190,617,773,386,462,242,496,352,265,536,3,480,625,327,887,191,151,813,345,60,73,654,407,600,635,132,668,577,699,402,519,383,43,698,620,96,361,152,742,127,859,803,719,376,789,738,213,271,888,26,24,823,572,807,824,373,82,442,434,647,332,644,249,474,399,551,387,624,526,779,57,449,363,471,587,623,396,314,180,115,576,634,756,543,410,255,481,805,597,573,368,495,129,77,37,529,552,897,17
 6,666,658,254,746,833,417,393,508,128,629,747,555,147,454,785,237,598,306,106,460,437,130,336,89,74,893,154,349,705,86,579,119,282,509,571,325,266,348,514,667,815,428,611,258,520,898,757,22,135,158,798,497,226,537,121,340,358,455,610,232,864,816,17,820,68,863,406,160,150,326,515,124,468,184,783,153,380,419,561,564,401,882,162,641,35,25,606,790,281,39,220,784,687,819,216,443,66,427,796,187,95,61,212,487,682,385,276,203,319,131,38,574,716,200,53,533,621,252,852,608,223,6,108,196,100,772,55,247,657,826,799,883,221,709,760
+694,31,182,605,256,855,329,106,108,705,592,322,365,831,752,59,521,783,205,847,558,455,178,237,139,708,259,643,599,179,364,126,123,449,412,673,198,467,864,536,523,451,118,104,561,84,156,134,245,296,187,870,725,640,410,824,310,524,39,207,131,631,518,107,283,169,174,502,851,671,391,95,157,308,527,163,700,48,606,873,360,478,519,579,122,616,586,154,268,133,32,698,121,788,58,119,547,105,130,634,460,69,469,744,844,282,503,576,562,509,759,67,284,456,186,701,549,286,265,815,534,407,737,109,92,452,208,865,51,426,42,546,826,572,566,520,142,834,234,73,496,727,639,879,805,239,257,863,457,373,483,633,709,713,830,114,897,337,288,822,894,501,383,843,224,884,137,680,323,554,677,567,692,896,251,707,194,272,459,281,421,349,580,427,173,545,432,238,647,624,600,392,293,200,889,228,292,57,388,85,731,302,72,758,716,230,661,400,17,551,274,223,508,753,743,15,19,168,66,332,662,499,445,348,333,11,479,16,637,570,867,218,387,464,468,617,668,347,378,377,149,871,159,745,38,443,424,344,488,614,215,814,505,3
 09,311,96,772,886,252,754,610,9,836,77,622,262,26,90,75,853,632,717,471,418,619,103,651,626,165,151,94,591,447,642,100,635,158,225,68,148,147,777,882,565,850,630,196,319,665,420,253,533,899,255,620,876,287,112,372,8,303,43,14,331,315,589,557,89,819,537,813,690,514,868,413,796,441,422,602,697,389,260,802,885,726,269,465,3,618,438,703,875,396,249,552,495,7,190,305,20,649,4,859,398,241,810,891,504,210,25,608,49,722,654,395,18,80,28,54,695,736,61,201,171,290,301,582,357,27,129,397,99,144,458,160,887,226,801,314,597,595,454,78,402,583,656,820,138,12,711,185,742,763,761,807,541,325,21,560,425,732,359,472,188,416,679,204,442,470,433,324,102,636,354,384,300,660,522,765,748,638,341,900,771,797,764,823,127,318,294,79,278,193,115,890,490,46,444,721,749,22,644,625,848,641,666,291,861,658,52,888,363,430,735,598,439,298,535,385,869,837,113,141,794,111,588,838,125,672,550,167,613,229,358,770,180,531,53,686,493,532,828,492,854,261,143,827,856,351,628,453,97,594,353,706,246,500,380,702,755,6
 84,729,177,785,316,799,74,184,734,845,461,806,674,166,36,2,55,242,818,216,6,728,542,623,779,352,450,609,712,688,812,117,390,350,417,473,553,369,506,648,244,24,135,832,367,883,653,1,803,334,835,880,317,375,714,30,587,556,356,804,798,83,548,860,304,682,71,650,746,486,361,217,243,829,277,289,494,487,411,781,219,833,621,63,463,381,13,266,60,760,590,780,371,678,258,40,809,446,231,741,681,212,800,81,816,596,539,343,222,475,64,543,715,267,370,394,538,87,346,723,155,481,37,152,312,862,342,793,571,652,669,574,693,719,526,559,65,273,271,408,153,41,336,419,197,136,330,62,409,140,415,321,474,401,704,276,866,821,403,756,757,540,659,670,213,603,817,150,584,516,227,568,581,575,366,766,784,29,101,34,145,577,44,440,93,414,175,655,718,45,203,664,789,270,747,476,431,295,128,192,840,233,573,740,306,528,808,162,663,86,206,811,507,601,615,35,211,376,563,374,429,146,434,406,379,285,795,297,423,280,564,247,299,881,510,768,76,91,236,82,593,773,33,88,345,733,183,778,786,386,874,355,47,404,683,612,382
 ,214,892,340,466,607,787,676,857,264,50,327,189,368,362,339,482,710,825,98,841,485,769,569,328,657,667,405,462,110,767,435,517,5,675,792,774,750,858,199,448,497,181,846,489,56,739,393,604,176,399,895,338,529,530,689,124,513,720,220,782,775,23,877,70,437,699,578,730,511,839,275,525,191,738,120,685,248,335,279,307,893,116,872,611,326,172,696,849,687,221,235,544,313,250,512,436,254,428,762,629,164,498,724,209,480,232,161,898,645,691,132,627,776,263,10,791,515,484,842,751,878,240,646,202,852,320,790,477,555,195,585,170,491
+577,576,72,194,697,436,152,47,211,124,741,772,132,529,398,112,683,229,767,381,242,82,663,157,799,387,422,104,443,39,215,71,88,26,263,863,48,811,463,380,468,580,596,589,11,79,66,676,84,129,569,320,761,821,548,209,25,24,643,853,758,737,586,393,779,787,114,189,434,273,408,637,363,444,222,172,361,372,400,339,824,324,12,623,684,606,365,216,535,109,389,854,42,616,655,418,719,55,259,636,68,330,144,292,197,810,639,239,383,163,593,660,432,478,746,629,46,396,309,135,733,482,186,235,261,190,151,537,183,251,545,161,890,237,37,584,671,370,770,192,2,409,547,651,277,231,185,293,579,851,531,632,275,388,276,296,712,256,15,167,704,225,838,581,833,344,117,850,223,102,659,136,508,740,449,455,668,141,475,425,894,805,236,595,752,736,437,828,445,667,628,523,317,278,899,19,162,666,123,507,416,245,433,182,852,59,332,364,290,252,22,23,619,844,687,543,174,605,325,87,350,753,837,139,176,356,226,549,511,17,760,158,836,160,166,884,375,720,816,691,744,520,150,282,233,93,173,670,327,314,121,156,411,597,9,6
 07,343,480,867,610,227,491,453,649,870,812,461,700,100,340,675,600,829,45,557,487,751,337,360,142,266,633,208,397,352,180,832,60,254,465,689,368,342,347,843,322,707,113,75,108,729,40,900,13,738,452,378,299,566,391,681,291,210,654,147,644,813,319,794,348,856,207,69,257,3,695,858,86,128,355,220,724,479,376,143,188,755,424,826,776,820,412,645,119,773,750,410,694,201,429,159,371,718,868,665,743,888,73,715,570,634,534,585,777,565,297,196,394,652,474,488,641,199,827,677,742,554,739,214,615,99,601,756,41,76,338,602,650,539,563,573,788,562,16,50,793,877,792,476,137,120,725,582,732,626,49,726,321,333,583,516,591,845,246,31,404,801,592,399,38,65,590,473,546,798,611,83,439,823,116,498,95,489,305,797,126,598,672,680,54,267,98,803,110,722,898,599,382,70,685,494,745,748,467,594,497,111,493,247,503,532,20,14,168,499,865,181,56,784,244,426,51,646,866,735,438,298,709,249,179,786,717,530,405,218,316,538,686,269,131,802,706,791,862,774,440,763,423,625,754,57,170,281,682,886,618,895,134,262,575
 ,504,268,485,766,861,303,313,234,662,193,232,702,311,106,464,367,711,483,878,521,448,328,315,406,568,81,859,43,768,171,307,264,555,415,401,29,560,879,165,830,125,205,62,664,285,366,118,407,567,822,819,887,727,864,782,414,470,34,552,431,369,730,306,883,481,283,696,809,860,631,308,524,228,716,289,484,885,44,80,527,32,673,638,541,701,334,528,153,92,175,64,624,318,96,457,614,390,435,657,248,379,419,807,533,889,874,302,206,769,36,559,115,450,814,294,458,326,647,658,392,806,635,346,630,857,808,33,783,572,89,564,587,749,469,698,101,522,578,454,91,747,272,553,831,544,90,191,693,762,238,764,198,873,243,842,335,353,825,785,771,496,495,790,551,349,757,274,105,442,386,848,18,459,839,195,451,526,265,284,240,518,27,253,505,490,609,351,714,78,345,219,127,705,224,891,103,796,648,506,130,897,688,280,107,882,138,287,561,492,661,608,734,28,603,669,513,77,728,67,471,331,604,58,759,94,789,428,133,540,200,781,622,519,613,413,421,447,178,778,525,556,502,204,708,472,855,286,841,145,146,486,403,169,
 875,63,834,620,301,892,847,627,420,815,358,869,509,446,250,184,835,5,501,374,514,818,74,612,61,430,341,849,323,674,679,35,417,558,10,359,255,690,588,510,721,893,703,640,270,148,840,881,441,258,7,203,692,329,699,678,310,477,517,460,164,373,804,896,140,617,466,723,536,241,395,574,97,621,295,6,765,155,212,642,187,213,300,871,354,542,384,260,731,656,336,385,288,795,221,872,4,217,279,30,780,1,456,52,85,154,817,362,515,202,230,571,149,775,710,462,177,653,377,512,880,304,271,312,500,21,53,550,402,8,876,800,357,846,122,713,427
+726,294,215,839,845,619,774,421,73,673,44,562,629,297,317,239,833,820,107,864,853,301,154,94,420,357,561,847,399,504,665,459,444,694,106,285,256,861,454,618,648,636,29,64,655,408,354,650,649,654,563,844,541,131,10,721,630,538,233,662,247,505,407,35,49,295,594,866,857,284,700,299,40,9,875,81,386,286,709,717,79,121,681,91,688,313,430,479,105,223,474,535,347,241,335,633,822,446,96,207,742,607,546,356,782,337,140,879,510,229,352,576,11,756,158,230,523,834,595,734,592,12,858,109,240,623,575,428,540,80,568,685,455,886,622,723,117,449,741,543,605,216,78,439,789,644,108,882,151,850,257,34,554,293,610,51,437,50,582,827,453,374,836,849,253,868,614,103,679,476,60,326,157,440,514,314,95,116,762,114,427,803,410,798,328,175,32,174,806,366,687,277,732,38,529,507,761,217,472,104,269,773,640,506,881,612,194,863,281,885,557,342,574,152,705,349,245,311,363,187,669,808,296,150,381,461,161,390,470,706,350,484,274,659,591,192,492,144,54,711,704,464,661,597,244,676,738,730,577,149,555,819,494,178,
 545,647,657,580,447,340,287,442,495,551,322,170,222,146,368,846,46,255,99,638,77,321,810,593,19,652,209,22,831,130,620,656,520,235,72,747,745,746,887,173,892,163,508,148,852,712,825,530,566,500,251,534,45,684,8,179,788,558,263,14,754,750,581,169,870,291,624,672,760,755,604,663,878,248,848,275,767,752,660,791,547,616,132,237,71,15,402,869,138,133,769,87,450,97,779,456,787,359,371,218,393,880,899,765,804,188,375,83,668,680,713,482,601,515,536,362,683,166,457,651,832,802,41,113,182,642,305,345,552,722,332,784,43,686,865,418,567,817,92,569,483,110,303,431,176,801,527,312,164,204,823,733,826,519,278,596,208,55,102,66,389,710,719,615,36,516,611,452,137,2,854,701,809,729,236,725,213,206,900,748,776,783,258,590,714,478,570,690,579,526,422,424,539,262,646,626,280,250,689,392,372,501,715,883,310,219,559,631,434,872,85,249,486,796,867,895,877,290,39,528,160,90,544,370,394,351,602,344,793,481,512,298,37,383,468,279,252,873,417,369,792,84,189,876,637,816,327,307,628,751,276,404,365,724,7
 81,835,443,339,75,696,811,441,53,316,770,780,401,201,268,142,225,210,400,82,677,120,364,445,560,678,162,695,101,778,220,775,625,343,266,292,409,586,333,308,200,707,460,193,228,382,589,731,549,288,498,134,764,896,122,172,518,469,666,488,7,463,664,265,884,509,584,346,387,405,438,675,842,4,181,300,379,271,156,473,766,202,336,227,325,598,3,224,198,728,403,838,813,260,739,735,302,184,862,360,821,391,718,621,396,168,415,234,289,588,419,697,139,843,426,128,608,68,320,89,5,785,323,264,93,124,272,890,653,398,69,475,532,270,63,153,744,840,330,425,772,261,341,100,1,812,76,159,702,578,384,487,246,794,894,639,496,186,889,874,21,306,273,542,531,70,127,30,667,617,309,58,693,699,141,830,119,361,489,451,42,517,27,682,556,56,641,232,62,195,600,603,720,423,143,177,324,627,860,126,125,606,334,23,716,859,413,414,503,759,259,147,214,737,585,20,635,112,231,16,763,13,65,136,740,88,749,573,385,708,458,185,28,6,33,397,522,743,497,583,448,283,24,829,435,490,777,331,25,367,841,282,571,758,378,871,790,6
 7,18,318,898,190,52,118,727,203,805,807,57,315,145,155,499,757,47,358,211,355,380,753,703,432,837,197,123,771,548,613,348,643,205,353,221,183,212,855,511,98,377,462,465,800,893,338,429,477,238,86,786,466,376,550,674,815,31,856,243,180,304,692,436,533,433,587,799,115,111,818,411,698,632,480,828,59,768,736,797,634,329,897,26,599,416,167,691,267,513,814,242,553,135,485,670,319,658,61,525,671,521,171,467,851,17,74,388,48,572,395,795,196,645,524,254,191,226,129,406,888,565,493,471,537,165,491,564,199,824,891,609,373,412,502

Copied: mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_r_3_900.csv (from rev 14992, mlpack/trunk/src/mlpack/tests/data/rann_test_r_3_900.csv)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_r_3_900.csv	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/data/rann_test_r_3_900.csv	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,900 @@
+0.637150933,0.126536213,0.823749724
+0.637940649,0.951567917,0.397777975
+0.344749598,0.517031469,0.48297473
+0.296545224,0.419944602,0.99985146
+0.707956343,0.985929306,0.942420811
+0.24734852,0.001808114,0.489512545
+0.29395388,0.751934338,0.924845167
+0.306350765,0.676837884,0.614397758
+0.387029257,0.668882644,0.316866608
+0.166701475,0.220250465,0.70788096
+0.666366134,0.343214579,0.063804166
+0.970614577,0.514452347,0.643280872
+0.084297811,0.906111319,0.590434434
+0.163302217,0.226212634,0.074753132
+0.20207705,0.197835179,0.217985026
+0.413236066,0.640190511,0.520645448
+0.807941459,0.463910044,0.996796367
+0.208875906,0.182468954,0.876826443
+0.743474185,0.840439019,0.143677671
+0.266758693,0.103719005,0.920995789
+0.030607849,0.973154392,0.814015083
+0.237753714,0.374336732,0.44138091
+0.83212984,0.547216604,0.371699647
+0.302411666,0.58054099,0.303141758
+0.949214871,0.783756542,0.457582838
+0.32776739,0.133095384,0.351183944
+0.673471065,0.432009028,0.761641303
+0.120361022,0.494421101,0.954699616
+0.049975694,0.857405242,0.133753572
+0.314326245,0.599784238,0.698931698
+0.10972582,0.994733888,0.603365409
+0.246939825,0.79385323,0.576049373
+0.420949269,0.55824091,0.684730016
+0.085903635,0.678776288,0.759533545
+0.221902971,0.606683148,0.183625782
+0.934582003,0.263106456,0.195228637
+0.276550653,0.563455012,0.477130256
+0.939865401,0.683543172,0.98694541
+0.090714119,0.155392084,0.183225576
+0.546170002,0.226065658,0.757518873
+0.635725491,0.259656977,0.803254796
+0.768135532,0.329687113,0.784471673
+0.67201594,0.69314804,0.216292884
+0.731388623,0.632648812,0.298465113
+0.030104188,0.531279626,0.68605789
+0.404907965,0.617707054,0.646985633
+0.38264213,0.522044947,0.606066308
+0.850778503,0.771072538,0.780038925
+0.333386945,0.62981651,0.838539888
+0.144526261,0.90723358,0.672092924
+0.803193149,0.545698586,0.740250704
+0.144775421,0.073065649,0.81327723
+0.800150626,0.077947117,0.498989131
+0.805355858,0.282274855,0.111520406
+0.432276345,0.614069782,0.04562788
+0.119740317,0.122788948,0.68461108
+0.188596378,0.666133286,0.753645204
+0.143050522,0.393902986,0.609633117
+0.754401856,0.84172035,0.387786256
+0.97549575,0.97044364,0.621482928
+0.735098473,0.96738673,0.239086021
+0.825090649,0.153687653,0.520111132
+0.720848546,0.211391499,0.513430909
+0.572411742,0.56579983,0.313933048
+0.766584951,0.704264072,0.103088529
+0.933914925,0.70795791,0.378434849
+0.232266382,0.864968616,0.664769493
+0.180748316,0.792633394,0.983236654
+0.320744207,0.073646797,0.915148464
+0.058415284,0.478244018,0.171213592
+0.613274471,0.423949271,0.899198164
+0.83818587,0.622457639,0.496368891
+0.547369341,0.5160996,0.318684775
+0.489079348,0.504840066,0.174865371
+0.133510366,0.873938618,0.95342181
+0.355477984,0.610358907,0.32242224
+0.32167355,0.132961802,0.381440702
+0.660257981,0.59386003,0.570704079
+0.519799486,0.220676336,0.85452965
+0.097125446,0.037837774,0.581579153
+0.801485909,0.741547848,0.06310355
+0.413142247,0.303102946,0.30224609
+0.07746447,0.555846316,0.750106689
+0.593760097,0.256631753,0.179035377
+0.819000445,0.86578977,0.797167379
+0.644052663,0.148335877,0.377067692
+0.02037784,0.835405997,0.192438566
+0.248506314,0.951214215,0.492923258
+0.387445752,0.862693509,0.11983047
+0.411437123,0.512831692,0.516380652
+0.481199694,0.970780992,0.565521666
+0.967908564,0.168755985,0.447517833
+0.280607962,0.670538365,0.548021587
+0.402044213,0.121532495,0.136718448
+0.83696286,0.739549154,0.495218329
+0.652215616,0.664877651,0.838254198
+0.846246408,0.411635906,0.96601722
+0.359827733,0.627436225,0.666295882
+0.522326573,0.496565812,0.404066784
+0.614406114,0.160072022,0.269439305
+0.221722954,0.558736063,0.890699947
+0.561777087,0.782270647,0.792345194
+0.385698506,0.295964873,0.697613223
+0.101162968,0.27600378,0.239798872
+0.075127486,0.14163579,0.728168103
+0.982440842,0.583109151,0.395072917
+0.69628067,0.26642599,0.283866713
+0.073093261,0.914332418,0.925554624
+0.01642578,0.927883834,0.248712685
+0.11636724,0.556067816,0.248282085
+0.487453151,0.058684617,0.294624957
+0.813726551,0.860917181,0.678149491
+0.492581545,0.501803813,0.193032429
+0.642766795,0.422421802,0.950458987
+0.662519175,0.950448071,0.157126432
+0.548815699,0.127905654,0.23337741
+0.159163516,0.345059322,0.586704542
+0.40029112,0.928563882,0.954476476
+0.587201396,0.44357769,0.797926632
+0.026827624,0.206281621,0.680220462
+0.884217164,0.266754666,0.652197582
+0.475019281,0.447732834,0.14299077
+0.193076354,0.317892868,0.976621856
+0.515208981,0.512331237,0.422351595
+0.336671812,0.870606258,0.364554196
+0.438596677,0.333836845,0.801388791
+0.194389409,0.929245672,0.589545825
+0.205377525,0.079938747,0.187363423
+0.426814991,0.823224852,0.707435026
+0.262972959,0.517545732,0.19872636
+0.720354434,0.847649202,0.709246477
+0.355306192,0.303943053,0.835051265
+0.949975427,0.106134411,0.204516092
+0.106374426,0.874129261,0.971439223
+0.14517828,0.371147898,0.695954142
+0.739099753,0.331888701,0.890413781
+0.627551297,0.9001009,0.177324543
+0.047488938,0.224289129,0.220822902
+0.912785118,0.79570392,0.838242455
+0.49717293,0.703176431,0.754883589
+0.090976094,0.502530756,0.657999889
+0.194042479,0.284561692,0.14516165
+0.409960603,0.285564554,0.097001811
+0.310205693,0.003434942,0.173823303
+0.233583043,0.118822434,0.816665508
+0.513843271,0.539640669,0.864405207
+0.40692643,0.436463418,0.369798489
+0.126544008,0.159580886,0.933714485
+0.286441339,0.872974675,0.04454198
+0.964565622,0.910027403,0.897861798
+0.203121728,0.899714292,0.085173744
+0.445639841,0.360999337,0.016645134
+0.307793993,0.117750087,0.562967352
+0.281587526,0.174834541,0.274581395
+0.119660773,0.099740072,0.484016211
+0.511583585,0.54938211,0.339766424
+0.188451695,0.073022292,0.006123739
+0.346586219,0.49567248,0.234826476
+0.225242461,0.587641331,0.725805817
+0.075409614,0.208266437,0.826377328
+0.204076002,0.04779427,0.040457828
+0.050861901,0.763043363,0.256073344
+0.972150662,0.792678045,0.909955027
+0.506115605,0.031837525,0.903340416
+0.804010111,0.955685921,0.175896939
+0.092926989,0.062223289,0.821308211
+0.363715968,0.726101463,0.79168981
+0.787381816,0.338102828,0.005758252
+0.484331698,0.495765424,0.891180155
+0.241982415,0.277129738,0.561477087
+0.484161267,0.286665154,0.03556541
+0.211600046,0.304292614,0.395789513
+0.372524976,0.202611617,0.166595985
+0.265124748,0.017345601,0.037686194
+0.701786714,0.420334817,0.714000487
+0.034048463,0.651290563,0.050634716
+0.802331316,0.558297752,0.291679579
+0.344037056,0.467477672,0.358504649
+0.639463582,0.425507582,0.954817361
+0.602885138,0.374751922,0.374607167
+0.993637385,0.955212301,0.16550343
+0.955669008,0.745723993,0.889786752
+0.365337348,0.19682491,0.506234866
+0.7457291,0.51831627,0.978818087
+0.92625289,0.631584997,0.443128894
+0.786168714,0.264993195,0.263960382
+0.316681591,0.61079768,0.089349247
+0.858371024,0.834969763,0.174819213
+0.525393487,0.243792169,0.955241627
+0.720242053,0.143419208,0.402799979
+0.749292304,0.217311863,0.799688479
+0.246462289,0.958943724,0.142358796
+0.528138907,0.590786754,0.948225902
+0.454799161,0.510565688,0.295103038
+0.953069085,0.021533141,0.116332423
+0.188120341,0.690529852,0.623168048
+0.318359731,0.758493036,0.91843922
+0.726077549,0.902046947,0.327147423
+0.386752461,0.338547997,0.651921958
+0.707225745,0.584329479,0.37703596
+0.060288975,0.494620757,0.075518168
+0.237652566,0.962903992,0.824801251
+0.535945075,0.958493881,0.754701994
+0.064404553,0.235151293,0.39448081
+0.979476468,0.347342952,0.99138709
+0.189166661,0.798328607,0.697048046
+0.180560013,0.342106481,0.174983336
+0.28337819,0.962425666,0.955845318
+0.593924663,0.66654314,0.570147835
+0.114749593,0.903677338,0.957687266
+0.151925114,0.716482401,0.637800283
+0.235669594,0.580788646,0.528893286
+0.778117587,0.250968708,0.684104646
+0.747849981,0.214563448,0.02984775
+0.720813243,0.066656345,0.737883757
+0.626964368,0.953760147,0.459809098
+0.469018562,0.720549931,0.518332767
+0.821461664,0.507041049,0.514946331
+0.384160041,0.953174654,0.443907617
+0.233220889,0.511502601,0.369065624
+0.434955659,0.150497671,0.76574469
+0.8958592,0.481635774,0.942994014
+0.979260732,0.445148596,0.323549157
+0.334878174,0.403760723,0.385124629
+0.460214884,0.33828675,0.592783427
+0.518346254,0.909618383,0.6009723
+0.338370801,0.317375424,0.337490389
+0.636668843,0.96449714,0.481975016
+0.025064304,0.923419227,0.119203699
+0.048318449,0.53489191,0.76133984
+0.491930784,0.016568024,0.112619998
+0.17743988,0.903969674,0.481918653
+0.981634317,0.513179093,0.316557669
+0.02560158,0.930375993,0.563316641
+0.017997936,0.890571459,0.4580491
+0.96277821,0.443025655,0.083145161
+0.419576578,0.112060055,0.531294103
+0.494454706,0.954168063,0.047922651
+0.800000835,0.673332473,0.064026809
+0.870702162,0.510095577,0.863030178
+0.851121904,0.916229763,0.781903614
+0.159726434,0.082081261,0.19548317
+0.362450326,0.788524336,0.826141196
+0.270846003,0.098989879,0.574494436
+0.406889772,0.838173717,0.436699777
+0.035503139,0.853255007,0.642800341
+0.083155666,0.952721164,0.708076056
+0.847697478,0.56519776,0.894660498
+0.037841045,0.984301359,0.365909559
+0.177721428,0.418447797,0.157612683
+0.429370039,0.508723836,0.767724035
+0.071851749,0.216253471,0.819600825
+0.578083664,0.212360494,0.627380646
+0.380746754,0.954034946,0.11483721
+0.211278539,0.560080096,0.685450354
+0.770737322,0.813954563,0.79322567
+0.318759117,0.06983,0.664250133
+0.059856737,0.06677071,0.26622355
+0.968241527,0.953861837,0.311894576
+0.504226431,0.06220937,0.289105117
+0.256406511,0.249902695,0.348997399
+0.674888311,0.860374,0.605942473
+0.246067727,0.048342783,0.343006159
+0.830735494,0.783740344,0.677522751
+0.99887952,0.341758368,0.229922444
+0.731699282,0.940258743,0.10886285
+0.541383735,0.910293019,0.381124662
+0.750868727,0.848911762,0.265718422
+0.425671591,0.626146239,0.622684142
+0.214013066,0.091251581,0.864057899
+0.545601885,0.310480085,0.046543211
+0.517244356,0.115819763,0.248517895
+0.872633121,0.50117097,0.12009094
+0.255496857,0.472006579,0.796438566
+0.468962035,0.26918685,0.131735945
+0.742353904,0.528441793,0.565922864
+0.85366711,0.2676075,0.914062206
+0.447698287,0.149534939,0.670156644
+0.445589481,0.6431063,0.225580433
+0.357872915,0.788565726,0.814611643
+0.580287142,0.506307991,0.527031912
+0.500500265,0.365277722,0.04677688
+0.141881394,0.926001483,0.86894952
+0.221717771,0.366035312,0.125658418
+0.600339909,0.684670388,0.826168927
+0.307898392,0.20966968,0.752966481
+0.959700077,0.899536378,0.491452813
+0.230433688,0.613941888,0.415683508
+0.495527265,0.634504412,0.370199526
+0.506575734,0.986633413,0.84941237
+0.761764339,0.963921599,0.828872018
+0.348601654,0.087553061,0.791174897
+0.104944192,0.102179531,0.905877926
+0.375324247,0.246387607,0.301420991
+0.875454272,0.118686164,0.988824311
+0.17698346,0.393647261,0.159870783
+0.917659703,0.583236755,0.630992101
+0.285048123,0.469986869,0.37272766
+0.011480822,0.597073945,0.904116141
+0.313259229,0.510005423,0.894823085
+0.795838324,0.911141124,0.928152818
+0.164974957,0.359128099,0.60236716
+0.983429159,0.003861397,0.083218217
+0.242529745,0.562773547,0.664077813
+0.765913188,0.194009625,0.286229668
+0.070781352,0.102661854,0.249285398
+0.511452125,0.418997177,0.284014634
+0.439472205,0.891870259,0.82363463
+0.580892549,0.466753672,0.140496383
+0.615517449,0.738921356,0.461546367
+0.824697707,0.698589656,0.941554339
+0.46610398,0.902958283,0.688012984
+0.523365471,0.691567649,0.547171487
+0.545929937,0.714552317,0.041938604
+0.32756288,0.701840615,0.927731162
+0.761874356,0.276228477,0.886668834
+0.979442228,0.298771691,0.591610911
+0.374731022,0.860510449,0.321638525
+0.8074911,0.097011746,0.930723417
+0.453431338,0.206882669,0.431005917
+0.910029309,0.03223923,0.493150704
+0.2897017,0.170401689,0.739971322
+0.024666309,0.777054677,0.769170439
+0.05624039,0.089983601,0.64642539
+0.149696037,0.539762835,0.702098143
+0.676100319,0.000479419,0.639516981
+0.967411256,0.893394783,0.958913773
+0.158669993,0.527294695,0.347808355
+0.181672491,0.532695548,0.988953142
+0.053598946,0.497693858,0.118111495
+0.132496571,0.985450674,0.753931807
+0.87586561,0.732063591,0.884137731
+0.419609591,0.012639269,0.645369169
+0.102047486,0.008854525,0.658344391
+0.123913855,0.210708056,0.499395878
+0.159685659,0.968477268,0.586268979
+0.834269522,0.369645239,0.245380904
+0.637297781,0.768550638,0.48870442
+0.778386961,0.376787501,0.03205647
+0.67713794,0.632054697,0.000672655
+0.860752189,0.140567399,0.326727043
+0.220600271,0.039797462,0.871431738
+0.373493897,0.910009286,0.043303147
+0.269453424,0.571833998,0.346704152
+0.919787568,0.373470212,0.873193468
+0.776952353,0.362003265,0.172733797
+0.575862615,0.900415576,0.599884308
+0.616882997,0.8845633,0.13177173
+0.366855251,0.729104299,0.950578149
+0.668847681,0.753527405,0.660832331
+0.264243456,0.308498641,0.912106098
+0.542527865,0.880831766,0.535728949
+0.460634645,0.013712653,0.152280892
+0.828209711,0.921304334,0.049084108
+0.874065663,0.473229025,0.545232499
+0.731220357,0.126627169,0.996060848
+0.943461868,0.033256065,0.992038738
+0.211193798,0.522810965,0.907780013
+0.767158364,0.967162642,0.888059793
+0.689583275,0.841550923,0.377520241
+0.147705388,0.959063909,0.031580823
+0.654707489,0.752912445,0.305046055
+0.628378168,0.075829853,0.719349441
+0.886468112,0.185491156,0.719710557
+0.749470564,0.448017109,0.897349202
+0.492693185,0.884164268,0.633427171
+0.44686733,0.7934547,0.773846432
+0.630683325,0.776592453,0.708944434
+0.814848973,0.845977344,0.643222219
+0.016975156,0.729138989,0.058020996
+0.511298247,0.07057554,0.733405098
+0.784480806,0.738595698,0.373688534
+0.530814843,0.44312087,0.691107945
+0.944091316,0.957332961,0.639542386
+0.771047017,0.811962024,0.977774991
+0.87020688,0.755962661,0.925248114
+0.458700988,0.334773333,0.095844508
+0.533831151,0.912609619,0.027149015
+0.524625598,0.652693277,0.497418106
+0.805674264,0.723021478,0.80073208
+0.113696528,0.650247192,0.344709776
+0.826900827,0.593783006,0.550936366
+0.940655423,0.740273144,0.630218018
+0.141520315,0.632429144,0.838610834
+0.39673597,0.503240828,0.590691376
+0.037602886,0.040815285,0.620639119
+0.716116291,0.506754028,0.253596249
+0.619782298,7.76626E-05,0.676065593
+0.496033457,0.98742451,0.984019601
+0.649314148,0.147470427,0.489967654
+0.691622038,0.161245902,0.647851723
+0.936526892,0.590442875,0.939555093
+0.604802621,0.838823011,0.251219058
+0.071190531,0.67647138,0.597666328
+0.019410183,0.495778133,0.44031324
+0.726411874,0.262687025,0.086312948
+0.830480537,0.135077568,0.079159787
+0.950841893,0.769723105,0.47873095
+0.611417896,0.84114966,0.395349789
+0.181347141,0.287776713,0.883076078
+0.200712222,0.873964629,0.571505353
+0.65202277,0.084117342,0.250545655
+0.342561024,0.202306216,0.079726003
+0.584301932,0.122693153,0.129858724
+0.591176502,0.051275102,0.876431468
+0.165946295,0.474087103,0.856717365
+0.839385948,0.763414504,0.961778868
+0.528260865,0.865453126,0.680673095
+0.076050301,0.71693581,0.15210816
+0.780443967,0.33197709,0.73242445
+0.363327494,0.164977224,0.185099911
+0.687912867,0.396104619,0.249748592
+0.88391393,0.554502064,0.089705278
+0.33788714,0.686247878,0.252660937
+0.19163616,0.441496434,0.513458703
+0.478908993,0.15156254,0.818829745
+0.918896553,0.899169945,0.780767514
+0.782967436,0.327693122,0.755050753
+0.32558364,0.492239506,0.12339517
+0.047070459,0.693552034,0.508452959
+0.109465204,0.821862145,0.632136838
+0.826253828,0.610682399,0.632137891
+0.162364171,0.5709024,0.027035072
+0.479768494,0.607203769,0.077566143
+0.897031412,0.795684932,0.974415558
+0.801002173,0.551618649,0.876984199
+0.123312093,0.411438516,0.901446561
+0.594677287,0.32833558,0.914104796
+0.741635419,0.14325589,0.115905361
+0.08993896,0.243272135,0.742401503
+0.116491314,0.690400792,0.020805328
+0.180855336,0.599454312,0.340688071
+0.087037755,0.006886539,0.952560809
+0.300603611,0.113658264,0.797478049
+0.832235841,0.05963984,0.771465426
+0.095194013,0.247650851,0.801344581
+0.300632189,0.150924198,0.086360387
+0.874625368,0.700861247,0.713919826
+0.863383564,0.57922769,0.870911826
+0.11913471,0.767551415,0.50918181
+0.556749667,0.691513618,0.782003681
+0.197331319,0.827247513,0.779623914
+0.987023902,0.734883462,0.623629089
+0.420615082,0.614082171,0.741891207
+0.312249031,0.014913149,0.070878868
+0.974642188,0.983123549,0.086275706
+0.783360774,0.814835668,0.67625897
+0.540478752,0.254940938,0.449867885
+0.048763621,0.290768213,0.625363258
+0.697965851,0.033892112,0.612844092
+0.724879255,0.708375839,0.525641059
+0.747562377,0.173208535,0.263779612
+0.867179342,0.213616814,0.754428508
+0.02226162,0.326141353,0.081963664
+0.627227744,0.116451144,0.409565408
+0.543129433,0.092850944,0.54072763
+0.281594806,0.709633472,0.876793176
+0.35647452,0.063874296,0.965050871
+0.045168661,0.497624359,0.186815072
+0.524949861,0.944601324,0.332059785
+0.126474627,0.02739514,0.246752374
+0.208604998,0.568408651,0.772918262
+0.125784169,0.514833609,0.514478954
+0.154512957,0.373291441,0.993402025
+0.233618131,0.572616698,0.016411005
+0.999890963,0.570275565,0.216853317
+0.486828361,0.379924401,0.696213866
+0.075314427,0.667395497,0.863855433
+0.86294927,0.812782874,0.997533964
+0.031445186,0.249022328,0.973324576
+0.326573891,0.118171329,0.965763005
+0.332020059,0.604459411,0.538268842
+0.706622108,0.694323961,0.209014536
+0.932949763,0.08165582,0.356510191
+0.75591714,0.880443277,0.240181713
+0.227219665,0.515538046,0.063202431
+0.069200681,0.150851636,0.361221939
+0.902427408,0.646942656,0.504832272
+0.262382978,0.180972368,0.403132445
+0.032506623,0.656194,0.257345113
+0.959652463,0.776117592,0.653289283
+0.778669537,0.171816058,0.383820737
+0.64856927,0.78342696,0.966231461
+0.638608998,0.323023815,0.667259556
+0.120265759,0.176019011,0.416173717
+0.275065523,0.921190579,0.324061946
+0.490137925,0.337844445,0.135339916
+0.724097632,0.992269402,0.410123181
+0.296958503,0.142356399,0.479483213
+0.092381103,0.57773093,0.290898447
+0.89183933,0.312149005,0.295126666
+0.669251799,0.071453982,0.955861716
+0.938378225,0.324238979,0.455589077
+0.762236627,0.048617283,0.120655973
+0.886194063,0.842136906,0.886167779
+0.420448588,0.826040453,0.209811195
+0.496120113,0.140244984,0.010275807
+0.291770734,0.089337397,0.940136172
+0.823744617,0.442752205,0.79506829
+0.86635257,0.308919721,0.929313191
+0.124187371,0.515507145,0.3952627
+0.515643261,0.514493405,0.592216269
+0.435577703,0.202265522,0.749380396
+0.851215206,0.581140662,0.909262689
+0.97276388,0.305964393,0.119556192
+0.833642983,0.44267292,0.574065373
+0.908658096,0.985442117,0.032891222
+0.120536868,0.898167052,0.754847347
+0.328480689,0.206500348,0.883388839
+0.584233318,0.127164736,0.934356548
+0.520904286,0.085542266,0.469645136
+0.118804512,0.276694477,0.255706174
+0.669152609,0.480169645,0.350044668
+0.784599588,0.030844507,0.672270616
+0.97462202,0.984822685,0.801402402
+0.09061512,0.20599842,0.288943446
+0.500630874,0.668012143,0.326107661
+0.243946646,0.885842685,0.356343047
+0.704519934,0.112411764,0.840776533
+0.064722176,0.148130565,0.724221405
+0.069998846,0.826917642,0.285248236
+0.463142105,0.129132053,0.071693121
+0.065672617,0.491471158,0.143248345
+0.345719852,0.550477283,0.417188691
+0.523811405,0.923188335,0.366706095
+0.57113315,0.798590349,0.465646081
+0.828359309,0.886833757,0.470994632
+0.649200809,0.422037446,0.338970547
+0.991959241,0.065292471,0.545926733
+0.402707667,0.892315167,0.157737898
+0.583371677,0.915247643,0.510882162
+0.286752954,0.119216908,0.422178531
+0.000574842,0.932477989,0.322762631
+0.521100182,0.182516345,0.799539149
+0.217552185,0.32460329,0.001286413
+0.129263953,0.832799191,0.746800354
+0.859133069,0.682500693,0.035727655
+0.081296267,0.499283963,0.851895509
+0.709384988,0.14985208,0.186521894
+0.247922963,0.253358356,0.872326832
+0.203028631,0.068652472,0.553487984
+0.292370767,0.925595124,0.401383438
+0.721522222,0.300176493,0.452098604
+0.622021123,0.308001842,0.51395483
+0.601298816,0.268135963,0.584441602
+0.207949629,0.407128704,0.699430418
+0.152216375,0.92660356,0.07049208
+0.997031345,0.789488864,0.194662825
+0.14170589,0.513011324,0.250918681
+0.979853004,0.246273698,0.732371057
+0.441466086,0.428787477,0.680856737
+0.513859379,0.668402062,0.50429415
+0.32103853,0.59436219,0.481843963
+0.466004374,0.019901121,0.225087815
+0.546731744,0.359957666,0.776590304
+0.088133727,0.021028123,0.579299556
+0.172044151,0.237278834,0.567876411
+0.576325796,0.86256513,0.487980769
+0.459957415,0.004052068,0.41344615
+0.72021758,0.906208873,0.049850195
+0.835505139,0.006504875,0.716129577
+0.974913096,0.06350265,0.945758998
+0.538076764,0.931252476,0.05429443
+0.921879308,0.750002283,0.120075272
+0.825790117,0.095295707,0.471769578
+0.667512779,0.726667248,0.68041055
+0.604774928,0.209313615,0.803678279
+0.058678158,0.457882119,0.491090679
+0.46503574,0.647148555,0.063745514
+0.268569925,0.07151649,0.354414339
+0.309997568,0.048651773,0.652050824
+0.852057231,0.800064591,0.378993288
+0.101844132,0.975250128,0.919521375
+0.879950774,0.012524944,0.243977924
+0.71298613,0.410784591,0.766666426
+0.253953963,0.18863912,0.353408633
+0.859540187,0.786140568,0.50468592
+0.885165537,0.182373738,0.365436093
+0.919226953,0.132590959,0.305319302
+0.794222067,0.325843691,0.81503301
+0.360472386,0.828503699,0.992751302
+0.568328182,0.596642015,0.166689456
+0.495797608,0.390533497,0.466894225
+0.497383703,0.057721092,0.136501948
+0.18770586,0.924785691,0.325442341
+0.693138587,0.351786889,0.499636742
+0.898980429,0.759285754,0.006488642
+0.203362481,0.362873482,0.576750046
+0.178651329,0.720602676,0.881219809
+0.176525065,0.325805008,0.029694687
+0.280908733,0.527522643,0.545345238
+0.370750152,0.138599939,0.044930538
+0.675097184,0.14761356,0.378589866
+0.735023127,0.793326142,0.751658301
+0.589712544,0.569527756,0.006401988
+0.528971516,0.297342992,0.454367414
+0.691477287,0.799565463,0.424110191
+0.261622015,0.848996059,0.848455301
+0.401014342,0.684428894,0.631646442
+0.16646465,0.252704215,0.907185556
+0.100875707,0.566947803,0.906685851
+0.434813596,0.104021401,0.167032575
+0.525475323,0.508926771,0.950312938
+0.159164103,0.298161029,0.813651341
+0.688364345,0.371765734,0.533450516
+0.712069354,0.849924822,0.351626269
+0.322500041,0.141195673,0.954104724
+0.146595062,0.93264431,0.190821916
+0.71991816,0.904994255,0.945180752
+0.025505056,0.369278227,0.225567491
+0.450884297,0.163076541,0.835655337
+0.666130325,0.52707414,0.82767262
+0.747584223,0.050899988,0.253442115
+0.525074918,0.930938393,0.27765909
+0.940041036,0.129750051,0.169526547
+0.976328221,0.406056506,0.156213454
+0.413206486,0.217043404,0.425652131
+0.108491931,0.963192763,0.498477601
+0.958709036,0.585116585,0.507265441
+0.048428848,0.713725414,0.728970388
+0.587791364,0.896305822,0.279922122
+0.086686919,0.740059232,0.914875869
+0.422027713,0.086096483,0.419750985
+0.767716034,0.871663257,0.103971292
+0.549835043,0.371430165,0.801009346
+0.557408598,0.341725364,0.279171927
+0.071240148,0.765613908,0.173767574
+0.713230298,0.779720404,0.253165546
+0.572322236,0.663937254,0.045664107
+0.428432377,0.161070991,0.891029544
+0.818292324,0.971164957,0.271696059
+0.269446053,0.962766931,0.051526478
+0.515277086,0.74833971,0.351491465
+0.796419252,0.556278732,0.361314209
+0.801556269,0.987424165,0.117197305
+0.782772261,0.05866778,0.982749779
+0.21806961,0.609256862,0.798461899
+0.699205142,0.038761394,0.271238908
+0.534754129,0.27476979,0.163606178
+0.003518131,0.437675965,0.388250875
+0.619198012,0.090710318,0.566559914
+0.178576562,0.885793567,0.022734794
+0.578539981,0.281190469,0.008260142
+0.177713211,0.393560621,0.052236228
+0.846158221,0.357695748,0.875170299
+0.127568308,0.638314871,0.946658268
+0.767138325,0.621405933,0.564104167
+0.798451074,0.40443786,0.599831193
+0.616223487,0.665752297,0.971012789
+0.267441096,0.388352985,0.430687937
+0.923867358,0.654582643,0.464037122
+0.492137227,0.706258913,0.378247168
+0.536642887,0.555595419,0.104998227
+0.992969717,0.688862613,0.896407883
+0.454975157,0.851727744,0.144297419
+0.317976254,0.620102227,0.416793119
+0.440632343,0.535615753,0.913356284
+0.791010869,0.962116708,0.627040144
+0.926826073,0.382456611,0.465806072
+0.568904993,0.514101455,0.724489494
+0.895517901,0.391005356,0.347893715
+0.289875186,0.830981849,0.92116788
+0.95185048,0.996829271,0.970163256
+0.079055453,0.999386589,0.528208258
+0.926932102,0.147799896,0.417138668
+0.244651465,0.832349744,0.221104338
+0.179560876,0.149581841,0.97827318
+0.869778794,0.116050413,0.930858226
+0.681347988,0.700100934,0.003010153
+0.688804753,0.087819887,0.217246073
+0.054919581,0.536206628,0.011960678
+0.640496257,0.193125181,0.654595034
+0.879605152,0.152112809,0.50946439
+0.336877078,0.352944356,0.032651908
+0.578287892,0.410740871,0.424981809
+0.655610763,0.370342392,0.021605292
+0.184746216,0.078627828,0.615262076
+0.335250916,0.744164606,0.7834867
+0.086006226,0.796624922,0.100735176
+0.278674471,0.483655368,0.117132599
+0.994681992,0.915583798,0.682419845
+0.077364925,0.488968443,0.762836001
+0.460939585,0.226843633,0.262301782
+0.998409563,0.464398025,0.918229672
+0.221191504,0.605272697,0.236818579
+0.305532514,0.107986913,0.285771959
+0.429457882,0.021852143,0.417044654
+0.4398254,0.904405397,0.587007492
+0.472361927,0.615492219,0.311474339
+0.4847793,0.830454499,0.692963217
+0.525054945,0.760690911,0.176296268
+0.117729529,0.425190139,0.763022992
+0.435815483,0.901034288,0.68353143
+0.310722347,0.711502874,0.050054312
+0.692557474,0.756865138,0.823601442
+0.748561397,0.302607431,0.404056776
+0.370478834,0.749199053,0.220199408
+0.686929375,0.172808164,0.22046762
+0.037511035,0.299597568,0.543432459
+0.513900441,0.892613907,0.740051648
+0.389543522,0.806516669,0.891439062
+0.053758187,0.367104684,0.356060944
+0.450039969,0.18662041,0.022226949
+0.481122219,0.376490604,0.455652341
+0.97009151,0.252002631,0.121449418
+0.322174741,0.359645571,0.785282495
+0.904310053,0.730301338,0.994210513
+0.450101531,0.92830086,0.086584177
+0.456948101,0.90305291,0.216589856
+0.430158828,0.574385535,0.812451667
+0.958800913,0.229029132,0.004822368
+0.641856333,0.757170989,0.097059421
+0.442276634,0.278413528,0.877655305
+0.036927777,0.425286999,0.92305997
+0.996003678,0.902465847,0.265142606
+0.306340939,0.260744837,0.528606261
+0.098272048,0.162476078,0.354882218
+0.658054373,0.890822429,0.9000076
+0.087284546,0.695167739,0.026293663
+0.667310433,0.902843368,0.248946207
+0.451887926,0.995052067,0.181712955
+0.721298527,0.006611482,0.727102995
+0.180137144,0.38951174,0.678305837
+0.420761331,0.419860176,0.010656383
+0.788488075,0.180473318,0.708019695
+0.662265015,0.757397169,0.348937464
+0.22732873,0.663301685,0.39923678
+0.716892599,0.552981067,0.089832495
+0.177215605,0.465175647,0.887666589
+0.4010009,0.597937203,0.09497585
+0.259096154,0.591668012,0.145793124
+0.7855796,0.541345166,0.383678057
+0.201753532,0.613603748,0.879697044
+0.825321851,0.452349759,0.192581377
+0.171266337,0.782789247,0.848185787
+0.989170718,0.575391852,0.643933271
+0.224216552,0.128615538,0.261286445
+0.355440689,0.629457955,0.902600249
+0.72784327,0.282293864,0.605943451
+0.210467186,0.748327916,0.269725684
+0.703080367,0.411052005,0.029450281
+0.611720264,0.653108765,0.115754888
+0.625714261,0.426502244,0.253625516
+0.080879639,0.231561531,0.000776511
+0.580765049,0.214103901,0.655333535
+0.411287343,0.079075761,0.794277642
+0.710073858,0.646863988,0.71074505
+0.335569397,0.900645276,0.683474835
+0.967747154,0.579773932,0.534024604
+0.766717973,0.582199309,0.533102234
+0.383468743,0.426721157,0.027251934
+0.490400205,0.117276739,0.92366954
+0.526437331,0.70107653,0.671085752
+0.889392656,0.764668251,0.594183178
+0.638642815,0.578480214,0.97861599
+0.87668719,0.16462794,0.216101311
+0.42672965,0.578827138,0.263549989
+0.811170473,0.093966938,0.225951223
+0.099089206,0.263591386,0.882393744
+0.38399777,0.327948679,0.494541301
+0.183583616,0.008025085,0.345896483
+0.584960878,0.5469813,0.968535684
+0.361345034,0.854037953,0.527327995
+0.984905322,0.997741532,0.876521812
+0.074758264,0.39928899,0.847634791
+0.78330323,0.392062416,0.024783838
+0.467728166,0.712167022,0.024533141
+0.587280899,0.398576247,0.573112113
+0.964829971,0.025982741,0.969019811
+0.9497508,0.659436309,0.204878206
+0.657359903,0.347373583,0.193308068
+0.186434557,0.521059421,0.070439079
+0.870109867,0.062761012,0.710077454
+0.217962469,0.288311322,0.190708548
+0.955539243,0.022311215,0.71590241
+0.625665814,0.76136552,0.988044588
+0.597252746,0.710748192,0.314068902
+0.516054372,0.327282916,0.54307302
+0.271367679,0.738701611,0.304169987
+0.933804469,0.580994455,0.210076964
+0.127919156,0.599299518,0.585857959
+0.676065679,0.558987708,0.958866142
+0.316141871,0.460898294,0.141769324
+0.471335921,0.089770919,0.358606362
+0.623875078,0.120949677,0.031070096
+0.279561054,0.756633154,0.523821594
+0.367638452,0.041473293,0.205100917
+0.194748444,0.554149226,0.891998106
+0.41189445,0.060780804,0.739908884
+0.463521747,0.175865472,0.535693142
+0.945971006,0.966028962,0.856940254
+0.183047078,0.337562524,0.181769865
+0.594627884,0.198176957,0.150059332
+0.843270928,0.530723522,0.928016742
+0.223830394,0.396224789,0.671524797
+0.660767374,0.651553136,0.816830801
+0.435601302,0.067504838,0.286367496
+0.118647364,0.597413606,0.736034901
+0.130876628,0.718657894,0.132667782
+0.512036173,0.807939768,0.573980493
+0.651567779,0.146952948,0.239972065
+0.288725439,0.224872447,0.043641949
+0.13707238,0.381109232,0.022199238
+0.754226814,0.167426623,0.961971718
+0.951586322,0.053557001,0.223348551
+0.618926676,0.885546611,0.123622882
+0.790423531,0.278666859,0.501354777
+0.038612914,0.868235102,0.288826116
+0.488859959,0.478054033,0.700027159
+0.862804894,0.011591559,0.750381881
+0.994070885,0.954113216,0.968886216
+0.452966461,0.985185262,0.402556559
+0.163204173,0.188199516,0.352205827
+0.15850908,0.505182571,0.583169832
+0.135779826,0.409087768,0.238200196
+0.643385144,0.86154063,0.14538336
+0.50233965,0.544662955,0.992305772
+0.208435385,0.031950832,0.061424365
+0.866478253,0.391456921,0.511463088
+0.4937369,0.216683838,0.68183869
+0.635277683,0.264963125,0.828569956
+0.57036797,0.199089208,0.947261901
+0.622849636,0.554898686,0.300444481
+0.148150252,0.793195105,0.95852649
+0.118643776,0.375521816,0.127817104
+0.758672306,0.928120507,0.147843091
+0.988902496,0.305378105,0.027460368
+0.101391422,0.187140233,0.666743757
+0.742622491,0.913697728,0.538923383
+0.093250323,0.083342814,0.253041857
+0.769590781,0.9991462,0.438612548
+0.729371479,0.304770086,0.732577389
+0.309854988,0.231328158,0.907015378
+0.357043464,0.291981607,0.210471606
+0.310867898,0.310831132,0.021305479
+0.099716251,0.743995352,0.892636908
+0.41508308,0.015438634,0.257251295
+0.53442204,0.552940574,0.911759333
+0.066875817,0.519643391,0.683239895
+0.960228558,0.637860456,0.564663828
+0.166667197,0.282113595,0.909573438
+0.400063729,0.629753113,0.314970443
+0.708945745,0.167807931,0.868195558
+0.371947838,0.749772529,0.913374887
+0.364252703,0.719347038,0.968988396
+0.565947998,0.47317603,0.848594323
+0.963005103,0.86347636,0.213376655
+0.010974265,0.115488107,0.918644935
+0.579274525,0.748172658,0.195517101
+0.054742886,0.089561473,0.35514667
+0.352904397,0.177453817,0.485671073
+0.86540568,0.455589491,0.325840682
+0.826269285,0.742045207,0.836774969
+0.075485913,0.446267336,0.134777488
+0.123130773,0.10695964,0.319080831
+0.353341713,0.250920125,0.94582804
+0.934151416,0.641155987,0.332526901
+0.183094596,0.975798892,0.512697523
+0.931523642,0.525759501,0.067066893
+0.171012136,0.581683693,0.603794825
+0.489763176,0.561915728,0.886623062
+0.427818728,0.227974683,0.462025302
+0.059325421,0.726266371,0.692412984
+0.770271664,0.743519141,0.117959307
+0.107862896,0.552555172,0.592259145
+0.445007388,0.046308389,0.69499137
+0.056486616,0.370154602,0.498507879
+0.347798483,0.541312622,0.44955603
+0.01637411,0.777726654,0.346640124
+0.918778501,0.247274577,0.931656904
+0.468325578,0.552066653,0.233304727
+0.558842714,0.30110019,0.237582706
+0.520406065,0.396600845,0.627623904
+0.42717615,0.55961213,0.312743984
+0.043819454,0.060632818,0.168267929
+0.151405047,0.276450913,0.385322692
+0.864539894,0.203199707,0.865006307
+0.866179018,0.649792248,0.369625823
+0.566181508,0.155001949,0.751738414
+0.022193506,0.262524266,0.378478591
+0.835870282,0.436869514,0.439857307
+0.54507765,0.825712044,0.425012638
+0.180124959,0.284189803,0.059324375
+0.91303517,0.659662103,0.021990781
+0.068890512,0.857174742,0.245915138
+0.146299591,0.2282098,0.992357695
+0.279495766,0.087424865,0.532747766
+0.095737503,0.107245868,0.190786801
+0.276947216,0.537071712,0.654100689
+0.010738646,0.40673838,0.479608479
+0.420307684,0.947352567,0.178277524
+0.108124774,0.127227634,0.278086371
+0.18958629,0.587262704,0.69187928
+0.814773727,0.220263054,0.007250506
+0.948149379,0.572617808,0.939774741
+0.150492895,0.970045889,0.979230909
+0.997567108,0.897085006,0.573132383
+0.039773611,0.517659257,0.317936584
+0.915778891,0.598912752,0.541405962
+0.081857212,0.994515385,0.261260636

Added: mlpack/branches/mlpack-1.x/src/mlpack/tests/fastmks_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/fastmks_test.cpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/fastmks_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,124 @@
+/**
+ * @file fastmks_test.cpp
+ * @author Ryan Curtin
+ *
+ * Ensure that fast max-kernel search is correct.
+ */
+#include <mlpack/core.hpp>
+#include <mlpack/methods/fastmks/fastmks.hpp>
+#include <mlpack/core/kernels/linear_kernel.hpp>
+#include <mlpack/core/kernels/polynomial_kernel.hpp>
+
+#include <boost/test/unit_test.hpp>
+#include "old_boost_test_definitions.hpp"
+
+using namespace mlpack;
+using namespace mlpack::tree;
+using namespace mlpack::fastmks;
+using namespace mlpack::kernel;
+
+BOOST_AUTO_TEST_SUITE(FastMKSTest);
+
+/**
+ * Compare single-tree and naive.
+ */
+BOOST_AUTO_TEST_CASE(SingleTreeVsNaive)
+{
+  // First create a random dataset.
+  arma::mat data;
+  data.randn(5, 1000);
+  LinearKernel lk;
+
+  // Now run FastMKS naively.
+  FastMKS<LinearKernel> naive(data, lk, false, true);
+
+  arma::Mat<size_t> naiveIndices;
+  arma::mat naiveProducts;
+  naive.Search(10, naiveIndices, naiveProducts);
+
+  // Now run it in single-tree mode.
+  FastMKS<LinearKernel> single(data, lk, true);
+
+  arma::Mat<size_t> singleIndices;
+  arma::mat singleProducts;
+  single.Search(10, singleIndices, singleProducts);
+
+  // Compare the results.
+  for (size_t q = 0; q < singleIndices.n_cols; ++q)
+  {
+    for (size_t r = 0; r < singleIndices.n_rows; ++r)
+    {
+      BOOST_REQUIRE_EQUAL(singleIndices(r, q), naiveIndices(r, q));
+      BOOST_REQUIRE_CLOSE(singleProducts(r, q), naiveProducts(r, q), 1e-5);
+    }
+  }
+}
+
+/**
+ * Compare dual-tree and naive.
+ */
+BOOST_AUTO_TEST_CASE(DualTreeVsNaive)
+{
+  // First create a random dataset.
+  arma::mat data;
+  data.randn(10, 5000);
+  LinearKernel lk;
+
+  // Now run FastMKS naively.
+  FastMKS<LinearKernel> naive(data, lk, false, true);
+
+  arma::Mat<size_t> naiveIndices;
+  arma::mat naiveProducts;
+  naive.Search(10, naiveIndices, naiveProducts);
+
+  // Now run it in dual-tree mode.
+  FastMKS<LinearKernel> tree(data, lk);
+
+  arma::Mat<size_t> treeIndices;
+  arma::mat treeProducts;
+  tree.Search(10, treeIndices, treeProducts);
+
+  for (size_t q = 0; q < treeIndices.n_cols; ++q)
+  {
+    for (size_t r = 0; r < treeIndices.n_rows; ++r)
+    {
+      BOOST_REQUIRE_EQUAL(treeIndices(r, q), naiveIndices(r, q));
+      BOOST_REQUIRE_CLOSE(treeProducts(r, q), naiveProducts(r, q), 1e-5);
+    }
+  }
+}
+
+/**
+ * Compare dual-tree and single-tree on a larger dataset.
+ */
+BOOST_AUTO_TEST_CASE(DualTreeVsSingleTree)
+{
+  // First create a random dataset.
+  arma::mat data;
+  data.randu(20, 15000);
+  PolynomialKernel pk(5.0, 2.5);
+
+  FastMKS<PolynomialKernel> single(data, pk, true);
+
+  arma::Mat<size_t> singleIndices;
+  arma::mat singleProducts;
+  single.Search(10, singleIndices, singleProducts);
+
+  // Now run it in dual-tree mode.
+  FastMKS<PolynomialKernel> tree(data, pk);
+
+  arma::Mat<size_t> treeIndices;
+  arma::mat treeProducts;
+  tree.Search(10, treeIndices, treeProducts);
+
+  for (size_t q = 0; q < treeIndices.n_cols; ++q)
+  {
+    for (size_t r = 0; r < treeIndices.n_rows; ++r)
+    {
+      BOOST_REQUIRE_EQUAL(treeIndices(r, q), singleIndices(r, q));
+      BOOST_REQUIRE_CLOSE(treeProducts(r, q), singleProducts(r, q), 1e-5);
+    }
+  }
+}
+
+BOOST_AUTO_TEST_SUITE_END();

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/gmm_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/gmm_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/gmm_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -205,7 +205,7 @@
     covar.randu(2);
 
     arma::mat data;
-    data.randn(2 /* dimension */, 100 * pow(10, (iterations / 3.0)));
+    data.randn(2 /* dimension */, 150 * pow(10, (iterations / 3.0)));
 
     // Now apply mean and covariance.
     data.row(0) *= covar(0);
@@ -592,4 +592,46 @@
   BOOST_REQUIRE_EQUAL(classes[12], 2);
 }
 
+BOOST_AUTO_TEST_CASE(GMMLoadSaveTest)
+{
+  // Create a GMM, save it, and load it.
+  GMM<> gmm(10, 4);
+  gmm.Weights().randu();
+
+  for (size_t i = 0; i < gmm.Gaussians(); ++i)
+  {
+    gmm.Means()[i].randu();
+    gmm.Covariances()[i].randu();
+  }
+
+  gmm.Save("test-gmm-save.xml");
+
+  GMM<> gmm2;
+  gmm2.Load("test-gmm-save.xml");
+
+  // Remove clutter.
+  remove("test-gmm-save.xml");
+
+  BOOST_REQUIRE_EQUAL(gmm.Gaussians(), gmm2.Gaussians());
+  BOOST_REQUIRE_EQUAL(gmm.Dimensionality(), gmm2.Dimensionality());
+
+  for (size_t i = 0; i < gmm.Dimensionality(); ++i)
+    BOOST_REQUIRE_CLOSE(gmm.Weights()[i], gmm2.Weights()[i], 1e-3);
+
+  for (size_t i = 0; i < gmm.Gaussians(); ++i)
+  {
+    for (size_t j = 0; j < gmm.Dimensionality(); ++j)
+      BOOST_REQUIRE_CLOSE(gmm.Means()[i][j], gmm2.Means()[i][j], 1e-3);
+
+    for (size_t j = 0; j < gmm.Dimensionality(); ++j)
+    {
+      for (size_t k = 0; k < gmm.Dimensionality(); ++k)
+      {
+        BOOST_REQUIRE_CLOSE(gmm.Covariances()[i](j, k),
+            gmm2.Covariances()[i](j, k), 1e-3);
+      }
+    }
+  }
+}
+
 BOOST_AUTO_TEST_SUITE_END();


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/tests/gmm_test.cpp
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/tests/gmm_test.cpp:13981-14239

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/hmm_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/hmm_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/hmm_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -730,19 +730,19 @@
   {
     // Check that the mean is the same.
     BOOST_REQUIRE_SMALL(hmm.Emission()[em].Mean()(0) -
-        hmm2.Emission()[em].Mean()(0), 0.07);
+        hmm2.Emission()[em].Mean()(0), 0.09);
     BOOST_REQUIRE_SMALL(hmm.Emission()[em].Mean()(1) -
-        hmm2.Emission()[em].Mean()(1), 0.07);
+        hmm2.Emission()[em].Mean()(1), 0.09);
 
     // Check that the covariances are the same.
     BOOST_REQUIRE_SMALL(hmm.Emission()[em].Covariance()(0, 0) -
-        hmm2.Emission()[em].Covariance()(0, 0), 0.1);
+        hmm2.Emission()[em].Covariance()(0, 0), 0.2);
     BOOST_REQUIRE_SMALL(hmm.Emission()[em].Covariance()(0, 1) -
-        hmm2.Emission()[em].Covariance()(0, 1), 0.1);
+        hmm2.Emission()[em].Covariance()(0, 1), 0.2);
     BOOST_REQUIRE_SMALL(hmm.Emission()[em].Covariance()(1, 0) -
-        hmm2.Emission()[em].Covariance()(1, 0), 0.1);
+        hmm2.Emission()[em].Covariance()(1, 0), 0.2);
     BOOST_REQUIRE_SMALL(hmm.Emission()[em].Covariance()(1, 1) -
-        hmm2.Emission()[em].Covariance()(1, 1), 0.1);
+        hmm2.Emission()[em].Covariance()(1, 1), 0.2);
   }
 }
 

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/kernel_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/kernel_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/kernel_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -92,8 +92,8 @@
   arma::vec a = "3.0 5.0 6.0 7.0";
   arma::vec b = "1.0 2.0 1.0 0.0";
 
-  BOOST_REQUIRE_CLOSE(LMetric<3>::Evaluate(a, b), 503.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(LMetric<3>::Evaluate(b, a), 503.0, 1e-5);
+  BOOST_REQUIRE_CLOSE((LMetric<3, false>::Evaluate(a, b)), 503.0, 1e-5);
+  BOOST_REQUIRE_CLOSE((LMetric<3, false>::Evaluate(b, a)), 503.0, 1e-5);
 
   BOOST_REQUIRE_CLOSE((LMetric<3, true>::Evaluate(a, b)), 7.95284762, 1e-5);
   BOOST_REQUIRE_CLOSE((LMetric<3, true>::Evaluate(b, a)), 7.95284762, 1e-5);

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/kmeans_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/kmeans_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/kmeans_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -21,6 +21,7 @@
 
 #include <mlpack/methods/kmeans/kmeans.hpp>
 #include <mlpack/methods/kmeans/allow_empty_clusters.hpp>
+#include <mlpack/methods/kmeans/refined_start.hpp>
 
 #include <boost/test/unit_test.hpp>
 #include "old_boost_test_definitions.hpp"
@@ -221,6 +222,243 @@
     BOOST_REQUIRE_LT(assignments[i], 18);
 }
 
+/**
+ * Make sure that random initialization fails for a corner case dataset.
+ */
+BOOST_AUTO_TEST_CASE(RandomInitialAssignmentFailureTest)
+{
+  // This is a very synthetic dataset.  It is one Gaussian with a huge number of
+  // points combined with one faraway Gaussian with very few points.  Normally,
+  // k-means should not get the correct result -- which is one cluster at each
+  // Gaussian.  This is because the random partitioning scheme has very low
+  // (virtually zero) likelihood of separating the two Gaussians properly, and
+  // then the algorithm will never converge to that result.
+  //
+  // So we will set the initial assignments appropriately.  Remember, once the
+  // initial assignments are done, k-means is deterministic.
+  arma::mat dataset(2, 10002);
+  dataset.randn();
+  // Now move the second Gaussian far away.
+  for (size_t i = 0; i < 2; ++i)
+    dataset.col(10000 + i) += arma::vec("50 50");
+
+  // Ensure that k-means fails when run with random initialization.  This isn't
+  // strictly a necessary test, but it does help let us know that this is a good
+  // test.
+  size_t successes = 0;
+  for (size_t run = 0; run < 15; ++run)
+  {
+    arma::mat centroids;
+    arma::Col<size_t> assignments;
+    KMeans<> kmeans;
+    kmeans.Cluster(dataset, 2, assignments, centroids);
+
+    // Inspect centroids.  See if one is close to the second Gaussian.
+    if ((centroids(0, 0) >= 30.0 && centroids(1, 0) >= 30.0) ||
+        (centroids(0, 1) >= 30.0 && centroids(1, 1) >= 30.0))
+      ++successes;
+  }
+
+  // Only one success allowed.  The probability of two successes should be
+  // infinitesimal.
+  BOOST_REQUIRE_LT(successes, 2);
+}
+
+/**
+ * Make sure that specifying initial assignments is successful for a corner case
+ * dataset which doesn't usually converge otherwise.
+ */
+BOOST_AUTO_TEST_CASE(InitialAssignmentTest)
+{
+  // For a better description of this dataset, see
+  // RandomInitialAssignmentFailureTest.
+  arma::mat dataset(2, 10002);
+  dataset.randn();
+  // Now move the second Gaussian far away.
+  for (size_t i = 0; i < 2; ++i)
+    dataset.col(10000 + i) += arma::vec("50 50");
+
+  // Now, if we specify initial assignments, the algorithm should converge (with
+  // zero iterations, actually, because this is the solution).
+  arma::Col<size_t> assignments(10002);
+  assignments.fill(0);
+  assignments[10000] = 1;
+  assignments[10001] = 1;
+
+  KMeans<> kmeans;
+  kmeans.Cluster(dataset, 2, assignments, true);
+
+  // Check results.
+  for (size_t i = 0; i < 10000; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 0);
+  for (size_t i = 10000; i < 10002; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 1);
+
+  // Now, slightly harder.  Give it one incorrect assignment in each cluster.
+  // The wrong assignment should be quickly fixed.
+  assignments[9999] = 1;
+  assignments[10000] = 0;
+
+  kmeans.Cluster(dataset, 2, assignments, true);
+
+  // Check results.
+  for (size_t i = 0; i < 10000; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 0);
+  for (size_t i = 10000; i < 10002; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 1);
+}
+
+/**
+ * Make sure specifying initial centroids is successful for a corner case which
+ * doesn't usually converge otherwise.
+ */
+BOOST_AUTO_TEST_CASE(InitialCentroidTest)
+{
+  // For a better description of this dataset, see
+  // RandomInitialAssignmentFailureTest.
+  arma::mat dataset(2, 10002);
+  dataset.randn();
+  // Now move the second Gaussian far away.
+  for (size_t i = 0; i < 2; ++i)
+    dataset.col(10000 + i) += arma::vec("50 50");
+
+  arma::Col<size_t> assignments;
+  arma::mat centroids(2, 2);
+
+  centroids.col(0) = arma::vec("0 0");
+  centroids.col(1) = arma::vec("50 50");
+
+  // This should converge correctly.
+  KMeans<> k;
+  k.Cluster(dataset, 2, assignments, centroids, false, true);
+
+  // Check results.
+  for (size_t i = 0; i < 10000; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 0);
+  for (size_t i = 10000; i < 10002; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 1);
+
+  // Now add a little noise to the initial centroids.
+  centroids.col(0) = arma::vec("3 4");
+  centroids.col(1) = arma::vec("25 10");
+
+  k.Cluster(dataset, 2, assignments, centroids, false, true);
+
+  // Check results.
+  for (size_t i = 0; i < 10000; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 0);
+  for (size_t i = 10000; i < 10002; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 1);
+}
+
+/**
+ * Ensure that initial assignments override initial centroids.
+ */
+BOOST_AUTO_TEST_CASE(InitialAssignmentOverrideTest)
+{
+  // For a better description of this dataset, see
+  // RandomInitialAssignmentFailureTest.
+  arma::mat dataset(2, 10002);
+  dataset.randn();
+  // Now move the second Gaussian far away.
+  for (size_t i = 0; i < 2; ++i)
+    dataset.col(10000 + i) += arma::vec("50 50");
+
+  arma::Col<size_t> assignments(10002);
+  assignments.fill(0);
+  assignments[10000] = 1;
+  assignments[10001] = 1;
+
+  // Note that this initial centroid guess is the opposite of the assignments
+  // guess!
+  arma::mat centroids(2, 2);
+  centroids.col(0) = arma::vec("50 50");
+  centroids.col(1) = arma::vec("0 0");
+
+  KMeans<> k;
+  k.Cluster(dataset, 2, assignments, centroids, true, true);
+
+  // Because the initial assignments guess should take priority, we should get
+  // those same results back.
+  for (size_t i = 0; i < 10000; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 0);
+  for (size_t i = 10000; i < 10002; ++i)
+    BOOST_REQUIRE_EQUAL(assignments[i], 1);
+
+  // Make sure the centroids are about right too.
+  BOOST_REQUIRE_LT(centroids(0, 0), 10.0);
+  BOOST_REQUIRE_LT(centroids(1, 0), 10.0);
+  BOOST_REQUIRE_GT(centroids(0, 1), 40.0);
+  BOOST_REQUIRE_GT(centroids(1, 1), 40.0);
+}
+
+/**
+ * Test that the refined starting policy returns decent initial cluster
+ * estimates.
+ */
+BOOST_AUTO_TEST_CASE(RefinedStartTest)
+{
+  // Our dataset will be five Gaussians of largely varying numbers of points and
+  // we expect that the refined starting policy should return good guesses at
+  // what these Gaussians are.
+  math::RandomSeed(std::time(NULL));
+  arma::mat data(3, 3000);
+  data.randn();
+
+  // First Gaussian: 10000 points, centered at (0, 0, 0).
+  // Second Gaussian: 2000 points, centered at (5, 0, -2).
+  // Third Gaussian: 5000 points, centered at (-2, -2, -2).
+  // Fourth Gaussian: 1000 points, centered at (-6, 8, 8).
+  // Fifth Gaussian: 12000 points, centered at (1, 6, 1).
+  arma::mat centroids(" 0  5 -2 -6  1;"
+                      " 0  0 -2  8  6;"
+                      " 0 -2 -2  8  1");
+
+  for (size_t i = 1000; i < 1200; ++i)
+    data.col(i) += centroids.col(1);
+  for (size_t i = 1200; i < 1700; ++i)
+    data.col(i) += centroids.col(2);
+  for (size_t i = 1700; i < 1800; ++i)
+    data.col(i) += centroids.col(3);
+  for (size_t i = 1800; i < 3000; ++i)
+    data.col(i) += centroids.col(4);
+
+  // Now run the RefinedStart algorithm and make sure it doesn't deviate too
+  // much from the actual solution.
+  RefinedStart rs;
+  arma::Col<size_t> assignments;
+  arma::mat resultingCentroids;
+  rs.Cluster(data, 5, assignments);
+
+  // Calculate resulting centroids.
+  resultingCentroids.zeros(3, 5);
+  arma::Col<size_t> counts(5);
+  counts.zeros();
+  for (size_t i = 0; i < 3000; ++i)
+  {
+    resultingCentroids.col(assignments[i]) += data.col(i);
+    ++counts[assignments[i]];
+  }
+
+  // Normalize centroids.
+  for (size_t i = 0; i < 5; ++i)
+    if (counts[i] != 0)
+      resultingCentroids /= counts[i];
+
+  // Calculate sum of distances from centroid means.
+  double distortion = 0;
+  for (size_t i = 0; i < 3000; ++i)
+    distortion += metric::EuclideanDistance::Evaluate(data.col(i),
+        resultingCentroids.col(assignments[i]));
+
+  // Using the refined start, the distance for this dataset is usually around
+  // 13500.  Regular k-means is between 10000 and 30000 (I think the 10000
+  // figure is a corner case which actually does not give good clusters), and
+  // random initial starts give distortion around 22000.  So we'll require that
+  // our distortion is less than 14000.
+  BOOST_REQUIRE_LT(distortion, 14000.0);
+}
+
 #ifdef ARMA_HAS_SPMAT
 // Can't do this test on Armadillo 3.4; var(SpBase) is not implemented.
 #if !((ARMA_VERSION_MAJOR == 3) && (ARMA_VERSION_MINOR == 4))
@@ -267,6 +505,7 @@
   BOOST_REQUIRE_EQUAL(assignments[10], clusterTwo);
   BOOST_REQUIRE_EQUAL(assignments[11], clusterTwo);
 }
+
 #endif // Exclude Armadillo 3.4.
 #endif // ARMA_HAS_SPMAT
 


Property changes on: mlpack/branches/mlpack-1.x/src/mlpack/tests/kmeans_test.cpp
___________________________________________________________________
Deleted: svn:mergeinfo
   - /mlpack/trunk/src/mlpack/tests/kmeans_test.cpp:13981-14239

Copied: mlpack/branches/mlpack-1.x/src/mlpack/tests/lsh_test.cpp (from rev 14992, mlpack/trunk/src/mlpack/tests/lsh_test.cpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/lsh_test.cpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/lsh_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,115 @@
+/**
+ * @file lsh_test.cpp
+ *
+ * Unit tests for the 'LSHSearch' class.
+ */
+#include <mlpack/core.hpp>
+#include <mlpack/core/metrics/lmetric.hpp>
+
+// So that we can test private members.  This is hackish (for now).
+#define private public
+#include <mlpack/methods/lsh/lsh_search.hpp>
+#undef private
+
+#include <boost/test/unit_test.hpp>
+#include "old_boost_test_definitions.hpp"
+
+using namespace std;
+using namespace mlpack;
+using namespace mlpack::neighbor;
+
+BOOST_AUTO_TEST_SUITE(LSHTest);
+
+BOOST_AUTO_TEST_CASE(LSHSearchTest)
+{
+  // Force to specific random seed for these results.
+  math::RandomSeed(0);
+
+  // Precomputed hash width value.
+  const double hashWidth = 4.24777;
+
+  arma::mat rdata(2, 10);
+  rdata << 3 << 2 << 4 << 3 << 5 << 6 << 0 << 8 << 3 << 1 << arma::endr <<
+           0 << 3 << 4 << 7 << 8 << 4 << 1 << 0 << 4 << 3 << arma::endr;
+
+  arma::mat qdata(2, 3);
+  qdata << 3 << 2 << 0 << arma::endr << 5 << 3 << 4 << arma::endr;
+
+  // INPUT TO LSH:
+  // Number of points: 10
+  // Number of dimensions: 2
+  // Number of projections per table: 'numProj' = 3
+  // Number of hash tables: 'numTables' = 2
+  // hashWidth (computed): 'hashWidth' = 4.24777
+  // Second hash size: 'secondHashSize' = 11
+  // Size of the bucket: 'bucketSize' = 3
+
+  // Things obtained by random sampling listed in the sequences
+  // as they will be obtained in the 'LSHSearch::BuildHash()' private function
+  // in 'LSHSearch' class.
+  //
+  // 1. The weights of the second hash obtained as:
+  //    secondHashWeights = arma::floor(arma::randu(3) * 11.0);
+  //    COR.SOL.: secondHashWeights = [9, 4, 8];
+  //
+  // 2. The offsets for all the 3 projections in each of the 2 tables:
+  //    offsets.randu(3, 2)
+  //    COR.SOL.: [0.7984 0.3352; 0.9116 0.7682; 0.1976 0.2778]
+  //    offsets *= hashWidth
+  //    COR.SOL.: [3.3916 1.4240; 3.8725 3.2633; 0.8392 1.1799]
+  //
+  // 3. The  (2 x 3) projection matrices for the 2 tables:
+  //    projMat.randn(2, 3)
+  //    COR.SOL.: Proj. Mat 1: [2.7020 0.0187 0.4355; 1.3692 0.6933 0.0416]
+  //    COR.SOL.: Proj. Mat 2: [-0.3961 -0.2666 1.1001; 0.3895 -1.5118 -1.3964]
+  LSHSearch<> lsh_test(rdata, qdata, 3, 2, hashWidth, 11, 3);
+//   LSHSearch<> lsh_test(rdata, qdata, 3, 2, 0.0, 11, 3);
+
+  // Given this, the 'LSHSearch::bucketRowInHashTable' should be:
+  // COR.SOL.: [2 11 4 7 6 3 11 0 5 1 8]
+  //
+  // The 'LSHSearch::bucketContentSize' should be:
+  // COR.SOL.: [2 0 1 1 3 1 0 3 3 3 1]
+  //
+  // The final hash table 'LSHSearch::secondHashTable' should be
+  // of size (3 x 9) with the following content:
+  // COR.SOL.:
+  // [0 2 4; 1 7 8; 3 9 10; 5 10 10; 6 10 10; 0 5 6; 1 2 8; 3 10 10; 4 10 10]
+
+  arma::Mat<size_t> neighbors;
+  arma::mat distances;
+
+  lsh_test.Search(2, neighbors, distances);
+
+  // The private function 'LSHSearch::ReturnIndicesFromTable(0, refInds)'
+  // should hash the query 0 into the following buckets:
+  // COR.SOL.: Table 1 Bucket 7, Table 2 Bucket 0, refInds = [0 2 3 4 9]
+  //
+  // The private function 'LSHSearch::ReturnIndicesFromTable(1, refInds)'
+  // should hash the query 1 into the following buckets:
+  // COR.SOL.: Table 1 Bucket 9, Table 2 Bucket 4, refInds = [1 2 7 8]
+  //
+  // The private function 'LSHSearch::ReturnIndicesFromTable(2, refInds)'
+  // should hash the query 2 into the following buckets:
+  // COR.SOL.: Table 1 Bucket 0, Table 2 Bucket 7, refInds = [0 2 3 4 9]
+
+  // After search
+  // COR.SOL.: 'neighbors' = [2 1 9; 3 8 2]
+  // COR.SOL.: 'distances' = [2 0 2; 4 2 16]
+
+  arma::Mat<size_t> true_neighbors(2, 3);
+  true_neighbors << 2 << 1 << 9 << arma::endr << 3 << 8 << 2 << arma::endr;
+  arma::mat true_distances(2, 3);
+  true_distances << 2 << 0 << 2 << arma::endr << 4 << 2 << 16 << arma::endr;
+
+  for (size_t i = 0; i < 3; i++)
+  {
+    for (size_t j = 0; j < 2; j++)
+    {
+//      BOOST_REQUIRE_EQUAL(neighbors(j, i), true_neighbors(j, i));
+//      BOOST_REQUIRE_CLOSE(distances(j, i), true_distances(j, i), 1e-5);
+    }
+  }
+}
+
+BOOST_AUTO_TEST_SUITE_END();

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/nmf_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/nmf_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/nmf_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -101,8 +101,9 @@
 }
 
 /**
- * Check the if the product of the calculated factorization is close to the
- * input matrix. Random Initialization Alternating Least Squares Update
+ * Check that the product of the calculated factorization is close to the
+ * input matrix.  This uses the random initialization and alternating least
+ * squares update rule.
  */
 BOOST_AUTO_TEST_CASE(NMFALSTest)
 {
@@ -120,7 +121,7 @@
 
   for (size_t row = 0; row < 5; row++)
     for (size_t col = 0; col < 5; col++)
-      BOOST_REQUIRE_CLOSE(v(row, col), wh(row, col), 10.0);
+      BOOST_REQUIRE_CLOSE(v(row, col), wh(row, col), 13.0);
 }
 
 BOOST_AUTO_TEST_SUITE_END();

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/sort_policy_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/sort_policy_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/sort_policy_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -109,7 +109,9 @@
 {
   // Well, there's no easy way to make HRectBounds the way we want, so we have
   // to make them and then expand the region to include new points.
-  tree::BinarySpaceTree<HRectBound<2>, arma::mat> nodeOne;
+  arma::mat dataset("1");
+  tree::BinarySpaceTree<HRectBound<2>, tree::EmptyStatistic, arma::mat>
+      nodeOne(dataset);
   arma::vec utility(1);
   utility[0] = 0;
 
@@ -118,7 +120,8 @@
   utility[0] = 1;
   nodeOne.Bound() |= utility;
 
-  tree::BinarySpaceTree<HRectBound<2>, arma::mat> nodeTwo;
+  tree::BinarySpaceTree<HRectBound<2>, tree::EmptyStatistic, arma::mat>
+      nodeTwo(dataset);
   nodeTwo.Bound() = HRectBound<2>(1);
 
   utility[0] = 5;
@@ -126,9 +129,9 @@
   utility[0] = 6;
   nodeTwo.Bound() |= utility;
 
-  // This should use the L2 squared distance.
+  // This should use the L2 distance.
   BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
-      &nodeTwo), 16.0, 1e-5);
+      &nodeTwo), 4.0, 1e-5);
 
   // And another just to be sure, from the other side.
   nodeTwo.Bound().Clear();
@@ -137,7 +140,7 @@
   utility[0] = -1;
   nodeTwo.Bound() |= utility;
 
-  // Again, the distance is the L2 squared distance.
+  // Again, the distance is the L2 distance.
   BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
       &nodeTwo), 1.0, 1e-5);
 
@@ -148,8 +151,8 @@
   utility[0] = 0.5;
   nodeTwo.Bound() |= utility;
 
-  BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
-      &nodeTwo), 0.0, 1e-5);
+  BOOST_REQUIRE_SMALL(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
+      &nodeTwo), 1e-5);
 }
 
 /**
@@ -163,7 +166,8 @@
   arma::vec utility(1);
   utility[0] = 0;
 
-  tree::BinarySpaceTree<HRectBound<2>, arma::mat> node;
+  arma::mat dataset("1");
+  tree::BinarySpaceTree<HRectBound<2> > node(dataset);
   node.Bound() = HRectBound<2>(1);
   node.Bound() |= utility;
   utility[0] = 1;
@@ -172,21 +176,21 @@
   arma::vec point(1);
   point[0] = -0.5;
 
-  // The distance is the L2 squared distance.
+  // The distance is the L2 distance.
   BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestPointToNodeDistance(point,
-      &node), 0.25, 1e-5);
+      &node), 0.5, 1e-5);
 
   // Now from the other side of the bound.
   point[0] = 1.5;
 
   BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestPointToNodeDistance(point,
-      &node), 0.25, 1e-5);
+      &node), 0.5, 1e-5);
 
   // And now when the point is inside the bound.
   point[0] = 0.5;
 
-  BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestPointToNodeDistance(point,
-      &node), 0.0, 1e-5);
+  BOOST_REQUIRE_SMALL(NearestNeighborSort::BestPointToNodeDistance(point,
+      &node), 1e-5);
 }
 
 // Tests for FurthestNeighborSort
@@ -266,22 +270,23 @@
   arma::vec utility(1);
   utility[0] = 0;
 
-  tree::BinarySpaceTree<HRectBound<2>, arma::mat> nodeOne;
+  arma::mat dataset("1");
+  tree::BinarySpaceTree<HRectBound<2> > nodeOne(dataset);
   nodeOne.Bound() = HRectBound<2>(1);
   nodeOne.Bound() |= utility;
   utility[0] = 1;
   nodeOne.Bound() |= utility;
 
-  tree::BinarySpaceTree<HRectBound<2>, arma::mat> nodeTwo;
+  tree::BinarySpaceTree<HRectBound<2> > nodeTwo(dataset);
   nodeTwo.Bound() = HRectBound<2>(1);
   utility[0] = 5;
   nodeTwo.Bound() |= utility;
   utility[0] = 6;
   nodeTwo.Bound() |= utility;
 
-  // This should use the L2 squared distance.
+  // This should use the L2 distance.
   BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne,
-      &nodeTwo), 36.0, 1e-5);
+      &nodeTwo), 6.0, 1e-5);
 
   // And another just to be sure, from the other side.
   nodeTwo.Bound().Clear();
@@ -290,9 +295,9 @@
   utility[0] = -1;
   nodeTwo.Bound() |= utility;
 
-  // Again, the distance is the L2 squared distance.
+  // Again, the distance is the L2 distance.
   BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne,
-      &nodeTwo), 9.0, 1e-5);
+      &nodeTwo), 3.0, 1e-5);
 
   // Now, when the bounds overlap.
   nodeTwo.Bound().Clear();
@@ -302,7 +307,7 @@
   nodeTwo.Bound() |= utility;
 
   BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne,
-      &nodeTwo), (1.5 * 1.5), 1e-5);
+      &nodeTwo), 1.5, 1e-5);
 }
 
 /**
@@ -316,7 +321,8 @@
   arma::vec utility(1);
   utility[0] = 0;
 
-  tree::BinarySpaceTree<HRectBound<2>, arma::mat> node;
+  arma::mat dataset("1");
+  tree::BinarySpaceTree<HRectBound<2> > node(dataset);
   node.Bound() = HRectBound<2>(1);
   node.Bound() |= utility;
   utility[0] = 1;
@@ -325,21 +331,21 @@
   arma::vec point(1);
   point[0] = -0.5;
 
-  // The distance is the L2 squared distance.
+  // The distance is the L2 distance.
   BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestPointToNodeDistance(point,
-      &node), (1.5 * 1.5), 1e-5);
+      &node), 1.5, 1e-5);
 
   // Now from the other side of the bound.
   point[0] = 1.5;
 
   BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestPointToNodeDistance(point,
-      &node), (1.5 * 1.5), 1e-5);
+      &node), 1.5, 1e-5);
 
   // And now when the point is inside the bound.
   point[0] = 0.5;
 
   BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestPointToNodeDistance(point,
-      &node), 0.25, 1e-5);
+      &node), 0.5, 1e-5);
 }
 
 BOOST_AUTO_TEST_SUITE_END();

Modified: mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_test.cpp
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_test.cpp	2013-05-01 23:51:49 UTC (rev 14992)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -164,8 +164,8 @@
 
   arma::vec point = "-2.0 0.0 10.0 3.0 3.0";
 
-  // This will be the Euclidean squared distance.
-  BOOST_REQUIRE_CLOSE(b.MinDistance(point), 95.0, 1e-5);
+  // This will be the Euclidean distance.
+  BOOST_REQUIRE_CLOSE(b.MinDistance(point), sqrt(95.0), 1e-5);
 
   point = "2.0 5.0 2.0 -5.0 1.0";
 
@@ -204,8 +204,8 @@
   c[3] = Range(2.0, 5.0);
   c[4] = Range(3.0, 4.0);
 
-  BOOST_REQUIRE_CLOSE(b.MinDistance(c), 22.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MinDistance(b), 22.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MinDistance(c), sqrt(22.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MinDistance(b), sqrt(22.0), 1e-5);
 
   // The other bound is on the edge of the bound.
   c[0] = Range(-2.0, 0.0);
@@ -267,16 +267,16 @@
 
   arma::vec point = "-2.0 0.0 10.0 3.0 3.0";
 
-  // This will be the Euclidean squared distance.
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 253.0, 1e-5);
+  // This will be the Euclidean distance.
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(point), sqrt(253.0), 1e-5);
 
   point = "2.0 5.0 2.0 -5.0 1.0";
 
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 46.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(point), sqrt(46.0), 1e-5);
 
   point = "1.0 2.0 0.0 -2.0 1.5";
 
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(point), 23.25, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(point), sqrt(23.25), 1e-5);
 }
 
 /**
@@ -307,8 +307,8 @@
   c[3] = Range(2.0, 5.0);
   c[4] = Range(3.0, 4.0);
 
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 210.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 210.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), sqrt(210.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), sqrt(210.0), 1e-5);
 
   // The other bound is on the edge of the bound.
   c[0] = Range(-2.0, 0.0);
@@ -317,8 +317,8 @@
   c[3] = Range(-10.0, -5.0);
   c[4] = Range(2.0, 3.0);
 
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 134.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 134.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), sqrt(134.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), sqrt(134.0), 1e-5);
 
   // The other bound partially overlaps the bound.
   c[0] = Range(-2.0, 1.0);
@@ -327,12 +327,12 @@
   c[3] = Range(-8.0, -4.0);
   c[4] = Range(0.0, 4.0);
 
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 102.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 102.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), sqrt(102.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), sqrt(102.0), 1e-5);
 
   // The other bound fully overlaps the bound.
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(b), 46.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MaxDistance(c), 61.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(b), sqrt(46.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MaxDistance(c), sqrt(61.0), 1e-5);
 
   // The other bound is entirely inside the bound / the other bound entirely
   // envelops the bound.
@@ -342,13 +342,13 @@
   c[3] = Range(-7.0, 0.0);
   c[4] = Range(0.0, 5.0);
 
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), 100.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), 100.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(c), sqrt(100.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MaxDistance(b), sqrt(100.0), 1e-5);
 
   // Identical bounds.  This will be the sum of the squared widths in each
   // dimension.
-  BOOST_REQUIRE_CLOSE(b.MaxDistance(b), 46.0, 1e-5);
-  BOOST_REQUIRE_CLOSE(c.MaxDistance(c), 162.0, 1e-5);
+  BOOST_REQUIRE_CLOSE(b.MaxDistance(b), sqrt(46.0), 1e-5);
+  BOOST_REQUIRE_CLOSE(c.MaxDistance(c), sqrt(162.0), 1e-5);
 
   // One last additional case.  If the bound encloses only one point, the
   // maximum distance between it and itself is 0.
@@ -954,6 +954,34 @@
 }
 
 /**
+ * Ensure that HRectBound::Diameter() works properly.
+ */
+BOOST_AUTO_TEST_CASE(HRectBoundDiameter)
+{
+  HRectBound<3> b(4);
+  b[0] = math::Range(0.0, 1.0);
+  b[1] = math::Range(-1.0, 0.0);
+  b[2] = math::Range(2.0, 3.0);
+  b[3] = math::Range(7.0, 7.0);
+
+  BOOST_REQUIRE_CLOSE(b.Diameter(), std::pow(3.0, 1.0 / 3.0), 1e-5);
+
+  HRectBound<2, false> c(4);
+  c[0] = math::Range(0.0, 1.0);
+  c[1] = math::Range(-1.0, 0.0);
+  c[2] = math::Range(2.0, 3.0);
+  c[3] = math::Range(0.0, 0.0);
+
+  BOOST_REQUIRE_CLOSE(c.Diameter(), 3.0, 1e-5);
+
+  HRectBound<5> d(2);
+  d[0] = math::Range(2.2, 2.2);
+  d[1] = math::Range(1.0, 1.0);
+
+  BOOST_REQUIRE_SMALL(d.Diameter(), 1e-5);
+}
+
+/**
  * Ensure that a bound, by default, is empty and has no dimensionality, and the
  * box size vector is empty.
  */
@@ -1505,6 +1533,53 @@
   BOOST_REQUIRE(rootNode.Right()->Right()->Count() == 1);
 }
 
+BOOST_AUTO_TEST_CASE(CheckParents)
+{
+  arma::mat dataset = "2.0 5.0 9.0 4.0 8.0 7.0;"
+                      "3.0 4.0 6.0 7.0 1.0 2.0 ";
+
+  // Leaf size of 1.
+  BinarySpaceTree<HRectBound<2> > rootNode(dataset, 1);
+
+  BOOST_REQUIRE_EQUAL(rootNode.Parent(),
+      (BinarySpaceTree<HRectBound<2> >*) NULL);
+  BOOST_REQUIRE_EQUAL(&rootNode, rootNode.Left()->Parent());
+  BOOST_REQUIRE_EQUAL(&rootNode, rootNode.Right()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Left(), rootNode.Left()->Left()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Left(), rootNode.Left()->Right()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Left()->Left(),
+      rootNode.Left()->Left()->Left()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Left()->Left(),
+      rootNode.Left()->Left()->Right()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Right(), rootNode.Right()->Left()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Right(), rootNode.Right()->Right()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Right()->Left(),
+      rootNode.Right()->Left()->Left()->Parent());
+  BOOST_REQUIRE_EQUAL(rootNode.Right()->Left(),
+      rootNode.Right()->Left()->Right()->Parent());
+}
+
+BOOST_AUTO_TEST_CASE(CheckDataset)
+{
+  arma::mat dataset = "2.0 5.0 9.0 4.0 8.0 7.0;"
+                      "3.0 4.0 6.0 7.0 1.0 2.0 ";
+
+  // Leaf size of 1.
+  BinarySpaceTree<HRectBound<2> > rootNode(dataset, 1);
+
+  BOOST_REQUIRE_EQUAL(&rootNode.Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Left()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Right()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Left()->Left()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Left()->Right()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Right()->Left()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Right()->Right()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Left()->Left()->Left()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Left()->Left()->Right()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Right()->Left()->Left()->Dataset(), &dataset);
+  BOOST_REQUIRE_EQUAL(&rootNode.Right()->Left()->Right()->Dataset(), &dataset);
+}
+
 // Ensure FurthestDescendantDistance() works.
 BOOST_AUTO_TEST_CASE(FurthestDescendantDistanceTest)
 {
@@ -1517,7 +1592,7 @@
 
   // Both points are contained in the one node.
   BinarySpaceTree<HRectBound<2> > twoPoint(dataset);
-  BOOST_REQUIRE_CLOSE(twoPoint.FurthestDescendantDistance(), 2, 1e-5);
+  BOOST_REQUIRE_CLOSE(twoPoint.FurthestDescendantDistance(), sqrt(2.0), 1e-5);
 }
 
 // Forward declaration of methods we need for the next test.
@@ -1687,6 +1762,11 @@
 }
 
 #ifdef ARMA_HAS_SPMAT
+// Only run sparse tree tests if we are using Armadillo 3.6.  Armadillo 3.4 has
+// some bugs that cause the kd-tree splitting procedure to fail terribly.  Soon,
+// that version will be obsolete, though.
+#if !((ARMA_VERSION_MAJOR == 3) && (ARMA_VERSION_MINOR == 4))
+
 /**
  * Exhaustive sparse kd-tree test based on #125.
  *
@@ -1775,6 +1855,8 @@
   // Check the tree depth.
   BOOST_REQUIRE_EQUAL(root.TreeDepth(), 7);
 }
+
+#endif // Using Armadillo 3.4.
 #endif // ARMA_HAS_SPMAT
 
 template<typename TreeType>
@@ -1985,12 +2067,13 @@
   arma::mat dataset;
   dataset.zeros(10, 10);
 
-  CoverTree<> node(dataset, 1.3, 3, 2, 1.5, 2.75);
+  CoverTree<> node(dataset, 1.3, 3, 2, NULL, 1.5, 2.75);
 
   BOOST_REQUIRE_EQUAL(&node.Dataset(), &dataset);
   BOOST_REQUIRE_EQUAL(node.Base(), 1.3);
   BOOST_REQUIRE_EQUAL(node.Point(), 3);
   BOOST_REQUIRE_EQUAL(node.Scale(), 2);
+  BOOST_REQUIRE_EQUAL(node.Parent(), (CoverTree<>*) NULL);
   BOOST_REQUIRE_EQUAL(node.ParentDistance(), 1.5);
   BOOST_REQUIRE_EQUAL(node.FurthestDescendantDistance(), 2.75);
 }
@@ -2025,4 +2108,102 @@
   CheckSeparation<CoverTree<LMetric<1, true> >, LMetric<1, true> >(tree, tree);
 }
 
+/**
+ * Make sure copy constructor works for the cover tree.
+ */
+BOOST_AUTO_TEST_CASE(CoverTreeCopyConstructor)
+{
+  arma::mat dataset;
+  dataset.randu(10, 10); // dataset is irrelevant.
+  CoverTree<> c(dataset, 1.3, 0, 5, NULL, 1.45, 5.2); // Random parameters.
+  c.Children().push_back(new CoverTree<>(dataset, 1.3, 1, 4, &c, 1.3, 2.45));
+  c.Children().push_back(new CoverTree<>(dataset, 1.5, 2, 3, &c, 1.2, 5.67));
+
+  CoverTree<> d = c;
+
+  // Check that everything is the same.
+  BOOST_REQUIRE_EQUAL(c.Dataset().memptr(), d.Dataset().memptr());
+  BOOST_REQUIRE_CLOSE(c.Base(), d.Base(), 1e-50);
+  BOOST_REQUIRE_EQUAL(c.Point(), d.Point());
+  BOOST_REQUIRE_EQUAL(c.Scale(), d.Scale());
+  BOOST_REQUIRE_EQUAL(c.Parent(), d.Parent());
+  BOOST_REQUIRE_EQUAL(c.ParentDistance(), d.ParentDistance());
+  BOOST_REQUIRE_EQUAL(c.FurthestDescendantDistance(),
+                      d.FurthestDescendantDistance());
+  BOOST_REQUIRE_EQUAL(c.NumChildren(), d.NumChildren());
+  BOOST_REQUIRE_NE(&c.Child(0), &d.Child(0));
+  BOOST_REQUIRE_NE(&c.Child(1), &d.Child(1));
+
+  BOOST_REQUIRE_EQUAL(c.Child(0).Parent(), &c);
+  BOOST_REQUIRE_EQUAL(c.Child(1).Parent(), &c);
+  BOOST_REQUIRE_EQUAL(d.Child(0).Parent(), &d);
+  BOOST_REQUIRE_EQUAL(d.Child(1).Parent(), &d);
+
+  // Check that the children are okay.
+  BOOST_REQUIRE_EQUAL(c.Child(0).Dataset().memptr(),
+                      d.Child(0).Dataset().memptr());
+  BOOST_REQUIRE_CLOSE(c.Child(0).Base(), d.Child(0).Base(), 1e-50);
+  BOOST_REQUIRE_EQUAL(c.Child(0).Point(), d.Child(0).Point());
+  BOOST_REQUIRE_EQUAL(c.Child(0).Scale(), d.Child(0).Scale());
+  BOOST_REQUIRE_EQUAL(c.Child(0).ParentDistance(), d.Child(0).ParentDistance());
+  BOOST_REQUIRE_EQUAL(c.Child(0).FurthestDescendantDistance(),
+                      d.Child(0).FurthestDescendantDistance());
+  BOOST_REQUIRE_EQUAL(c.Child(0).NumChildren(), d.Child(0).NumChildren());
+
+  BOOST_REQUIRE_EQUAL(c.Child(1).Dataset().memptr(),
+                      d.Child(1).Dataset().memptr());
+  BOOST_REQUIRE_CLOSE(c.Child(1).Base(), d.Child(1).Base(), 1e-50);
+  BOOST_REQUIRE_EQUAL(c.Child(1).Point(), d.Child(1).Point());
+  BOOST_REQUIRE_EQUAL(c.Child(1).Scale(), d.Child(1).Scale());
+  BOOST_REQUIRE_EQUAL(c.Child(1).ParentDistance(), d.Child(1).ParentDistance());
+  BOOST_REQUIRE_EQUAL(c.Child(1).FurthestDescendantDistance(),
+                      d.Child(1).FurthestDescendantDistance());
+  BOOST_REQUIRE_EQUAL(c.Child(1).NumChildren(), d.Child(1).NumChildren());
+}
+
+/**
+ * Make sure copy constructor works right for the binary space tree.
+ */
+BOOST_AUTO_TEST_CASE(BinarySpaceTreeCopyConstructor)
+{
+  arma::mat data("1");
+  BinarySpaceTree<HRectBound<2> > b(data);
+  b.Begin() = 10;
+  b.Count() = 50;
+  b.Left() = new BinarySpaceTree<HRectBound<2> >(data);
+  b.Left()->Begin() = 10;
+  b.Left()->Count() = 30;
+  b.Right() = new BinarySpaceTree<HRectBound<2> >(data);
+  b.Right()->Begin() = 40;
+  b.Right()->Count() = 20;
+
+  // Copy the tree.
+  BinarySpaceTree<HRectBound<2> > c(b);
+
+  // Ensure everything copied correctly.
+  BOOST_REQUIRE_EQUAL(b.Begin(), c.Begin());
+  BOOST_REQUIRE_EQUAL(b.Count(), c.Count());
+  BOOST_REQUIRE_NE(b.Left(), c.Left());
+  BOOST_REQUIRE_NE(b.Right(), c.Right());
+
+  // Check the children.
+  BOOST_REQUIRE_EQUAL(b.Left()->Begin(), c.Left()->Begin());
+  BOOST_REQUIRE_EQUAL(b.Left()->Count(), c.Left()->Count());
+  BOOST_REQUIRE_EQUAL(b.Left()->Left(),
+      (BinarySpaceTree<HRectBound<2> >*) NULL);
+  BOOST_REQUIRE_EQUAL(b.Left()->Left(), c.Left()->Left());
+  BOOST_REQUIRE_EQUAL(b.Left()->Right(),
+      (BinarySpaceTree<HRectBound<2> >*) NULL);
+  BOOST_REQUIRE_EQUAL(b.Left()->Right(), c.Left()->Right());
+
+  BOOST_REQUIRE_EQUAL(b.Right()->Begin(), c.Right()->Begin());
+  BOOST_REQUIRE_EQUAL(b.Right()->Count(), c.Right()->Count());
+  BOOST_REQUIRE_EQUAL(b.Right()->Left(),
+      (BinarySpaceTree<HRectBound<2> >*) NULL);
+  BOOST_REQUIRE_EQUAL(b.Right()->Left(), c.Right()->Left());
+  BOOST_REQUIRE_EQUAL(b.Right()->Right(),
+      (BinarySpaceTree<HRectBound<2> >*) NULL);
+  BOOST_REQUIRE_EQUAL(b.Right()->Right(), c.Right()->Right());
+}
+
 BOOST_AUTO_TEST_SUITE_END();

Copied: mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_traits_test.cpp (from rev 14992, mlpack/trunk/src/mlpack/tests/tree_traits_test.cpp)
===================================================================
--- mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_traits_test.cpp	                        (rev 0)
+++ mlpack/branches/mlpack-1.x/src/mlpack/tests/tree_traits_test.cpp	2013-05-02 02:38:08 UTC (rev 14993)
@@ -0,0 +1,64 @@
+/**
+ * @file tree_traits_test.cpp
+ * @author Ryan Curtin
+ *
+ * Tests for the TreeTraits class.  These could all be known at compile-time,
+ * but realistically the function is to be sure that nobody changes tree traits
+ * without breaking something.  Thus, people must be certain when they make a
+ * change like that (because they have to change the test too).  That's the
+ * hope, at least...
+ */
+#include <mlpack/core.hpp>
+#include <mlpack/core/tree/tree_traits.hpp>
+#include <mlpack/core/tree/binary_space_tree.hpp>
+#include <mlpack/core/tree/cover_tree.hpp>
+
+#include <boost/test/unit_test.hpp>
+#include "old_boost_test_definitions.hpp"
+
+using namespace mlpack;
+using namespace mlpack::tree;
+using namespace mlpack::metric;
+
+BOOST_AUTO_TEST_SUITE(TreeTraitsTest);
+
+// Be careful!  When writing new tests, always get the boolean value and store
+// it in a temporary, because the Boost unit test macros do weird things and
+// will cause bizarre problems.
+
+// Test the defaults.
+BOOST_AUTO_TEST_CASE(DefaultsTraitsTest)
+{
+  // An irrelevant non-tree type class is used here so that the default
+  // implementation of TreeTraits is chosen.
+  bool b = TreeTraits<int>::HasParentDistance;
+  BOOST_REQUIRE_EQUAL(b, false);
+  b = TreeTraits<int>::HasOverlappingChildren;
+  BOOST_REQUIRE_EQUAL(b, true);
+}
+
+// Test the binary space tree traits.
+BOOST_AUTO_TEST_CASE(BinarySpaceTreeTraitsTest)
+{
+  // ParentDistance() is not available.
+  bool b = TreeTraits<BinarySpaceTree<LMetric<2, false> > >::HasParentDistance;
+  BOOST_REQUIRE_EQUAL(b, false);
+
+  // Children are non-overlapping.
+  b = TreeTraits<BinarySpaceTree<LMetric<2, false> > >::HasOverlappingChildren;
+  BOOST_REQUIRE_EQUAL(b, false);
+}
+
+// Test the cover tree traits.
+BOOST_AUTO_TEST_CASE(CoverTreeTraitsTest)
+{
+  // ParentDistance() is available.
+  bool b = TreeTraits<CoverTree<> >::HasParentDistance;
+  BOOST_REQUIRE_EQUAL(b, true);
+
+  // Children may be overlapping.
+  b = TreeTraits<CoverTree<> >::HasOverlappingChildren;
+  BOOST_REQUIRE_EQUAL(b, true);
+}
+
+BOOST_AUTO_TEST_SUITE_END();




More information about the mlpack-svn mailing list