Merge remote-tracking branch 'origin/master' into lr-doc-workaround
This commit is contained in:
+3
-3
@@ -11,7 +11,7 @@ jobs:
|
||||
- job: Linux
|
||||
timeoutInMinutes: 360
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
vmImage: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
Plain:
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=ON -DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
|
||||
Julia:
|
||||
julia.version: '1.3.0'
|
||||
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_GO_BINDINGS=OFF -DJULIA_EXECUTABLE=/opt/julia-1.3.0/bin/julia -DBUILD_R_BINDINGS=OFF'
|
||||
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_GO_BINDINGS=OFF -DJULIA_EXECUTABLE=/opt/julia-1.6.3/bin/julia -DBUILD_R_BINDINGS=OFF'
|
||||
Go:
|
||||
binding: 'go'
|
||||
go.version: '1.11.0'
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=ON -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
|
||||
Julia:
|
||||
python.version: '2.7'
|
||||
julia.version: '1.3.0'
|
||||
julia.version: '1.6.3'
|
||||
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
|
||||
Go:
|
||||
binding: 'go'
|
||||
|
||||
+14
-11
@@ -11,6 +11,15 @@ steps:
|
||||
|
||||
# Install build dependencies.
|
||||
- script: |
|
||||
# Workaround to avoid a build failure, because we run out of memory.
|
||||
free -h
|
||||
df -h
|
||||
sudo dd if=/dev/zero of=/usr/swapfile.img bs=1024 count=12M
|
||||
sudo mkswap /usr/swapfile.img
|
||||
sudo swapon /usr/swapfile.img
|
||||
free -h
|
||||
df -h
|
||||
|
||||
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
|
||||
|
||||
sudo add-apt-repository ppa:mhier/libboost-latest
|
||||
@@ -30,12 +39,12 @@ steps:
|
||||
fi
|
||||
|
||||
if [ "a$(julia.version)" != "a" ]; then
|
||||
wget https://julialang-s3.julialang.org/bin/linux/x64/1.3/julia-1.3.0-linux-x86_64.tar.gz
|
||||
sudo tar -C /opt/ -xvpf julia-1.3.0-linux-x86_64.tar.gz
|
||||
wget https://julialang-s3.julialang.org/bin/linux/x64/1.6/julia-1.6.3-linux-x86_64.tar.gz
|
||||
sudo tar -C /opt/ -xvpf julia-1.6.3-linux-x86_64.tar.gz
|
||||
fi
|
||||
|
||||
# Install armadillo.
|
||||
curl -L https://sourceforge.net/projects/arma/files/armadillo-9.800.6.tar.xz | tar -xvJ && \
|
||||
curl -k -L https://sourceforge.net/projects/arma/files/armadillo-9.800.6.tar.xz | tar -xvJ && \
|
||||
cd armadillo* && \
|
||||
cmake . && \
|
||||
make && \
|
||||
@@ -45,7 +54,7 @@ steps:
|
||||
# Install ensmallen.
|
||||
wget https://ensmallen.org/files/ensmallen-latest.tar.gz
|
||||
tar -xvzpf ensmallen-latest.tar.gz # Unpack into ensmallen-*/.
|
||||
cd ensmallen-* && \
|
||||
cd ensmallen-*/ && \
|
||||
sudo cp -vr include/* /usr/include/ && \
|
||||
cd ..
|
||||
|
||||
@@ -77,13 +86,7 @@ steps:
|
||||
displayName: 'CMake'
|
||||
|
||||
# Build mlpack
|
||||
- script: cd build && make && make mlpack_test
|
||||
condition: eq(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF')
|
||||
displayName: 'Build'
|
||||
|
||||
# Build mlpack
|
||||
- script: cd build && make -j2 && make -j2 mlpack_test
|
||||
condition: ne(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF')
|
||||
- script: cd build && make -j2 && make mlpack_test -j2
|
||||
displayName: 'Build'
|
||||
|
||||
# Run tests via ctest.
|
||||
|
||||
@@ -9,9 +9,7 @@ steps:
|
||||
# Fetch build dependencies
|
||||
- powershell: |
|
||||
nuget install OpenBLAS -o $(Agent.ToolsDirectory)
|
||||
nuget install boost -o $(Agent.ToolsDirectory) -Version 1.60.0
|
||||
nuget install boost_random-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
|
||||
nuget install boost_math_c99-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
|
||||
nuget install boost -o $(Agent.ToolsDirectory) -Version 1.66.0
|
||||
nuget install unofficial-flayan-cereal -o $(Agent.ToolsDirectory)
|
||||
nuget install ensmallen -o $(Agent.ToolsDirectory) -Version 2.17.0
|
||||
## Delete all ensmallen dependencies including armadillo headers, we do not need them here
|
||||
@@ -19,8 +17,7 @@ steps:
|
||||
Remove-Item $(Agent.ToolsDirectory)\ensmallen.2.17.0\installed\x64-linux\include\armadillo_bits -Force -Recurse
|
||||
Remove-Item $(Agent.ToolsDirectory)\ensmallen.2.17.0\installed\x64-linux\include\armadillo -Force
|
||||
mkdir -p $(Agent.ToolsDirectory)/boost_libs
|
||||
cp $(Agent.ToolsDirectory)/boost_math_c99-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
|
||||
cp $(Agent.ToolsDirectory)/boost_random-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
|
||||
|
||||
displayName: 'Fetch build dependencies'
|
||||
|
||||
# Configure armadillo
|
||||
@@ -62,7 +59,7 @@ steps:
|
||||
-DLAPACK_LIBRARIES:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
|
||||
-DARMADILLO_INCLUDE_DIR="..\armadillo-9.800.6\tmp\include" `
|
||||
-DARMADILLO_LIBRARY="..\armadillo-9.800.6\Release\armadillo.lib" `
|
||||
-DBOOST_INCLUDEDIR=$(Agent.ToolsDirectory)\boost.1.60.0.0\lib\native\include `
|
||||
-DBOOST_INCLUDEDIR=$(Agent.ToolsDirectory)\boost.1.66.0.0\lib\native\include `
|
||||
-DBOOST_LIBRARYDIR=$(Agent.ToolsDirectory)\boost_libs `
|
||||
-DCEREAL_INCLUDE_DIR=$(Agent.ToolsDirectory)\unofficial-flayan-cereal.1.2.2\build\native\include `
|
||||
-DENSMALLEN_INCLUDE_DIR=$(Agent.ToolsDirectory)\ensmallen.2.17.0\installed\x64-linux\include `
|
||||
@@ -84,15 +81,13 @@ steps:
|
||||
|
||||
# Configure mlpack
|
||||
- powershell: |
|
||||
cp $(Agent.ToolsDirectory)\boost_libs\*.* build\Release\
|
||||
cp $(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\*.* build\Release\
|
||||
cp $(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.* build\Release\
|
||||
displayName: 'Configure mlpack'
|
||||
|
||||
# Run tests via ctest.
|
||||
- bash: |
|
||||
cd build
|
||||
cmake --build . --target mlpack_test -C Release
|
||||
cmake --build . --target mlpack_test
|
||||
CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test -C Release . -j1
|
||||
displayName: 'Run tests via ctest'
|
||||
|
||||
|
||||
@@ -51,9 +51,7 @@ jobs:
|
||||
- name: Install Build Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev libcereal-dev
|
||||
curl -L https://sourceforge.net/projects/arma/files/armadillo-9.800.6.tar.xz | tar -xvJ && cd armadillo*
|
||||
cmake . && make && sudo make install && cd ..
|
||||
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev libcereal-dev libensmallen-dev libhdf5-dev libarmadillo-dev libcurl4-openssl-dev
|
||||
|
||||
- name: Install R-bindings dependencies
|
||||
run: |
|
||||
@@ -64,7 +62,7 @@ jobs:
|
||||
- name: CMake
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_CLI_EXECUTABLES=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON ..
|
||||
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_CLI_EXECUTABLES=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON -DDOWNLOAD_DEPENDENCIES=ON ..
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -127,6 +125,12 @@ jobs:
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('depends.Rds') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-
|
||||
|
||||
- name: Install check dependencies
|
||||
if: runner.os != 'Windows' && runner.os != 'macOS'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-unauthenticated libcurl4-openssl-dev
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
install.packages('remotes')
|
||||
|
||||
+12
-6
@@ -44,6 +44,11 @@ else()
|
||||
"Compile shared libraries (if OFF, static libraries and binaries are compiled)." ON)
|
||||
endif()
|
||||
|
||||
# Enable auto-download if we are cross compiling.
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
set(DOWNLOAD_DEPENDENCIES ON)
|
||||
endif()
|
||||
|
||||
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES.
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
if(WIN32)
|
||||
@@ -156,7 +161,8 @@ set(COMPILER_SUPPORT_LIBRARIES "")
|
||||
|
||||
# If we are using MSVC, we need /bigobj.
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /Zm400")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /Zm200 /Zc:__cplusplus")
|
||||
endif ()
|
||||
|
||||
# If we are using MINGW, we need sections and big-obj, otherwise we create too
|
||||
@@ -282,7 +288,7 @@ if (CMAKE_CROSSCOMPILING)
|
||||
search_openblas(0.3.13)
|
||||
endif()
|
||||
|
||||
if (DOWNLOAD_DEPENDENCIES)
|
||||
if (NOT DOWNLOAD_DEPENDENCIES)
|
||||
find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED)
|
||||
else()
|
||||
find_package(Armadillo "${ARMADILLO_VERSION}")
|
||||
@@ -304,7 +310,7 @@ set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS})
|
||||
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${ARMADILLO_LIBRARIES})
|
||||
|
||||
# Find stb_image.h and stb_image_write.h.
|
||||
if (DOWNLOAD_DEPENDENCIES)
|
||||
if (NOT DOWNLOAD_DEPENDENCIES)
|
||||
find_package(StbImage)
|
||||
else()
|
||||
find_package(StbImage)
|
||||
@@ -322,7 +328,7 @@ if (STB_IMAGE_FOUND)
|
||||
endif()
|
||||
|
||||
# Find ensmallen.
|
||||
if (DOWNLOAD_DEPENDENCIES)
|
||||
if (NOT DOWNLOAD_DEPENDENCIES)
|
||||
find_package(Ensmallen "${ENSMALLEN_VERSION}" REQUIRED)
|
||||
else()
|
||||
find_package(Ensmallen "${ENSMALLEN_VERSION}")
|
||||
@@ -335,7 +341,7 @@ endif()
|
||||
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${ENSMALLEN_INCLUDE_DIR}")
|
||||
|
||||
# Find cereal.
|
||||
if (DOWNLOAD_DEPENDENCIES)
|
||||
if (NOT DOWNLOAD_DEPENDENCIES)
|
||||
find_package(cereal "${CEREAL_VERSION}" REQUIRED)
|
||||
else()
|
||||
find_package(cereal "${CEREAL_VERSION}")
|
||||
@@ -376,7 +382,7 @@ set(Boost_ADDITIONAL_VERSIONS
|
||||
# TODO for the brave: transition all mlpack's CMake to 'target-based modern
|
||||
# CMake'. Good luck! You'll need it.
|
||||
set(Boost_NO_BOOST_CMAKE 1)
|
||||
if (DOWNLOAD_DEPENDENCIES)
|
||||
if (NOT DOWNLOAD_DEPENDENCIES)
|
||||
find_package(Boost "${BOOST_VERSION}" REQUIRED)
|
||||
else()
|
||||
find_package(Boost "${BOOST_VERSION}")
|
||||
|
||||
@@ -145,6 +145,7 @@ Copyright:
|
||||
Copyright 2021, Mark Fischinger <markfischinger@gmail.com>
|
||||
Copyright 2021, Muhammad Fawwaz Mayda <maydafawwaz@gmail.com>
|
||||
Copyright 2021, Roshan Nrusing Swain <swainroshan001@gmail.com>
|
||||
Copyright 2021, Suvarsha Chennareddy <suvarshachennareddy@gmail.com>
|
||||
|
||||
License: BSD-3-clause
|
||||
All rights reserved.
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
|
||||
* Fix double-free of model pointers in R bindings (#3034).
|
||||
|
||||
* Fix Julia, Python, R, and Go handling of categorical data for
|
||||
`decision_tree()` and `hoeffding_tree()` (#2971).
|
||||
|
||||
### mlpack 3.4.2
|
||||
###### 2020-10-26
|
||||
* Added Mean Absolute Percentage Error.
|
||||
|
||||
@@ -12,6 +12,11 @@ licensed under the Boost Software License, version 1.0. This code is found in
|
||||
src/mlpack/core/boost_backport/ and more details on the licensing are available
|
||||
there.
|
||||
|
||||
mlpack contain some usage of the source code of MNMLSTC Core library, which is
|
||||
a backport of C++17 features to C++11. MNMLSTC is licensed under the Apache 2.0
|
||||
License. This code can be found in src/mlpack/core/std_backport/ and more
|
||||
details about licensing can be found there.
|
||||
|
||||
mlpack may contain some usage of the source code of stb, which is licensed
|
||||
under the MIT License and the Public Domain (www.unlicense.org). This code
|
||||
is used in src/mlpack/core/data/load_image.hpp.
|
||||
|
||||
@@ -73,7 +73,7 @@ class ROption
|
||||
data.cppType = cppName;
|
||||
|
||||
// Every parameter we'll get from R will have the correct type.
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
|
||||
// Set the function pointers that we'll need. All of these function
|
||||
// pointers will be used by both the program that generates the R, and
|
||||
|
||||
@@ -36,7 +36,7 @@ std::string DefaultParamImpl(
|
||||
if (std::is_same<T, bool>::value)
|
||||
oss << "FALSE";
|
||||
else
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ std::string DefaultParamImpl(
|
||||
{
|
||||
// Print each element in an array delimited by square brackets.
|
||||
std::ostringstream oss;
|
||||
const T& vector = boost::any_cast<T>(data.value);
|
||||
const T& vector = ANY_CAST<T>(data.value);
|
||||
oss << "c(";
|
||||
if (std::is_same<T, std::vector<std::string>>::value)
|
||||
{
|
||||
@@ -92,7 +92,7 @@ std::string DefaultParamImpl(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<std::is_same<T, std::string>::value>::type*)
|
||||
{
|
||||
const std::string& s = *boost::any_cast<std::string>(&data.value);
|
||||
const std::string& s = *ANY_CAST<std::string>(&data.value);
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void GetParam(util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((T**) output) = const_cast<T*>(boost::any_cast<T>(&d.value));
|
||||
*((T**) output) = const_cast<T*>(ANY_CAST<T>(&d.value));
|
||||
}
|
||||
|
||||
} // namespace r
|
||||
|
||||
@@ -32,7 +32,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ std::string GetPrintableParam(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
@@ -61,7 +61,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& matrix = boost::any_cast<T>(data.value);
|
||||
const T& matrix = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix";
|
||||
@@ -78,7 +78,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
|
||||
oss << data.cppType << " model at " << ANY_CAST<T*>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& tuple = boost::any_cast<T>(data.value);
|
||||
const T& tuple = ANY_CAST<T>(data.value);
|
||||
const arma::mat& matrix = std::get<1>(tuple);
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -35,7 +35,6 @@ bool inline inplace_transpose(arma::Mat<eT>& X)
|
||||
SEXP CreateParams(const std::string& bindingName)
|
||||
{
|
||||
util::Params* p = new util::Params(IO::Parameters(bindingName));
|
||||
std::cout << "create params " << p << "\n";
|
||||
return std::move(Rcpp::XPtr<util::Params>(p));
|
||||
}
|
||||
|
||||
@@ -44,7 +43,6 @@ SEXP CreateParams(const std::string& bindingName)
|
||||
SEXP CreateTimers()
|
||||
{
|
||||
util::Timers* t = new util::Timers();
|
||||
std::cout << "create timers " << t << "\n";
|
||||
return std::move(Rcpp::XPtr<util::Timers>(t));
|
||||
}
|
||||
|
||||
@@ -91,8 +89,8 @@ void SetParamBool(SEXP params, const std::string& paramName, bool paramValue)
|
||||
// Call params.Get<std::vector<std::string>>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamVecString(SEXP params,
|
||||
const std::string& paramName,
|
||||
const std::vector<std::string>& str)
|
||||
const std::string& paramName,
|
||||
const std::vector<std::string>& str)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
p.Get<std::vector<std::string>>(paramName) = std::move(str);
|
||||
@@ -102,8 +100,8 @@ void SetParamVecString(SEXP params,
|
||||
// Call params.Get<std::vector<int>>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamVecInt(SEXP params,
|
||||
const std::string& paramName,
|
||||
const std::vector<int>& ints)
|
||||
const std::string& paramName,
|
||||
const std::vector<int>& ints)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
p.Get<std::vector<int>>(paramName) = std::move(ints);
|
||||
@@ -113,8 +111,8 @@ void SetParamVecInt(SEXP params,
|
||||
// Call params.Get<arma::mat>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamMat(SEXP params,
|
||||
const std::string& paramName,
|
||||
const arma::mat& paramValue)
|
||||
const std::string& paramName,
|
||||
const arma::mat& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
p.Get<arma::mat>(paramName) = paramValue.t();
|
||||
@@ -124,8 +122,8 @@ void SetParamMat(SEXP params,
|
||||
// Call params.Get<arma::Mat<size_t>>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamUMat(SEXP params,
|
||||
const std::string& paramName,
|
||||
const arma::Mat<size_t>& paramValue)
|
||||
const std::string& paramName,
|
||||
const arma::Mat<size_t>& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
p.Get<arma::Mat<size_t>>(paramName) = paramValue.t();
|
||||
@@ -135,8 +133,8 @@ void SetParamUMat(SEXP params,
|
||||
// Call params.Get<arma::rowvec>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamRow(SEXP params,
|
||||
const std::string& paramName,
|
||||
const arma::rowvec& paramValue)
|
||||
const std::string& paramName,
|
||||
const arma::rowvec& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
p.Get<arma::rowvec>(paramName) = std::move(paramValue);
|
||||
@@ -146,10 +144,19 @@ void SetParamRow(SEXP params,
|
||||
// Call params.Get<arma::Row<size_t>>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamURow(SEXP params,
|
||||
const std::string& paramName,
|
||||
const arma::Row<size_t>& paramValue)
|
||||
const std::string& paramName,
|
||||
const arma::Row<size_t>& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
|
||||
// Check for zeros in the input---if we received these, the user is mistaken,
|
||||
// because in R labels should start from 1.
|
||||
if (arma::any(paramValue == 0))
|
||||
{
|
||||
Log::Fatal << "When passing labels from R to mlpack, labels should be in "
|
||||
<< "the range from 1 to the number of classes!" << std::endl;
|
||||
}
|
||||
|
||||
p.Get<arma::Row<size_t>>(paramName) = paramValue - 1;
|
||||
p.SetPassed(paramName);
|
||||
}
|
||||
@@ -157,8 +164,8 @@ void SetParamURow(SEXP params,
|
||||
// Call params.Get<arma::vec>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamCol(SEXP params,
|
||||
const std::string& paramName,
|
||||
const arma::vec& paramValue)
|
||||
const std::string& paramName,
|
||||
const arma::vec& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
p.Get<arma::vec>(paramName) = std::move(paramValue);
|
||||
@@ -168,10 +175,19 @@ void SetParamCol(SEXP params,
|
||||
// Call params.Get<arma::Col<size_t>>() to set the value of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamUCol(SEXP params,
|
||||
const std::string& paramName,
|
||||
const arma::Col<size_t>& paramValue)
|
||||
const std::string& paramName,
|
||||
const arma::Col<size_t>& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
|
||||
// Check for zeros in the input---if we received these, the user is mistaken,
|
||||
// because in R labels should start from 1.
|
||||
if (arma::any(paramValue == 0))
|
||||
{
|
||||
Log::Fatal << "When passing labels from R to mlpack, labels should be in "
|
||||
<< "the range from 1 to the number of classes!" << std::endl;
|
||||
}
|
||||
|
||||
p.Get<arma::Col<size_t>>(paramName) = paramValue - 1;
|
||||
p.SetPassed(paramName);
|
||||
}
|
||||
@@ -180,21 +196,47 @@ void SetParamUCol(SEXP params,
|
||||
// of a parameter.
|
||||
// [[Rcpp::export]]
|
||||
void SetParamMatWithInfo(SEXP params,
|
||||
const std::string& paramName,
|
||||
const LogicalVector& dimensions,
|
||||
const arma::mat& paramValue)
|
||||
const std::string& paramName,
|
||||
const LogicalVector& dimensions,
|
||||
const arma::mat& paramValue)
|
||||
{
|
||||
util::Params& p = *Rcpp::as<Rcpp::XPtr<util::Params>>(params);
|
||||
data::DatasetInfo d(paramValue.n_cols);
|
||||
bool hasCategoricals = false;
|
||||
for (size_t i = 0; i < d.Dimensionality(); ++i)
|
||||
{
|
||||
d.Type(i) = (dimensions[i]) ? data::Datatype::categorical :
|
||||
data::Datatype::numeric;
|
||||
if (dimensions[i])
|
||||
hasCategoricals = true;
|
||||
}
|
||||
|
||||
arma::mat m = paramValue.t();
|
||||
|
||||
// Do we need to find how many categories we have?
|
||||
if (hasCategoricals)
|
||||
{
|
||||
arma::vec maxs = arma::max(paramValue, 1) + 1;
|
||||
|
||||
for (size_t i = 0; i < d.Dimensionality(); ++i)
|
||||
{
|
||||
if (dimensions[i])
|
||||
{
|
||||
// Map the right number of objects.
|
||||
for (size_t j = 0; j < (size_t) maxs[i]; ++j)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << j;
|
||||
d.MapString<double>(oss.str(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::get<0>(p.Get<std::tuple<data::DatasetInfo, arma::mat>>(
|
||||
paramName)) = std::move(d);
|
||||
std::get<1>(p.Get<std::tuple<data::DatasetInfo, arma::mat>>(
|
||||
paramName)) = paramValue.t();
|
||||
paramName)) = std::move(m);
|
||||
p.SetPassed(paramName);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ test_that("TestCol", {
|
||||
|
||||
# Test an unsigned column vector input parameter.
|
||||
test_that("TestUCol", {
|
||||
x <- matrix(as.integer(rexp(100, rate = .1)), nrow = 1)
|
||||
x <- matrix(as.integer(rexp(100, rate = .1)), nrow = 1) + 1
|
||||
|
||||
output <- test_r_binding(4.0, 12, "hello",
|
||||
ucol_in=x)
|
||||
@@ -148,7 +148,7 @@ test_that("TestRow", {
|
||||
|
||||
# Test an unsigned row vector input parameter.
|
||||
test_that("TestURow", {
|
||||
x <- matrix(as.integer(rexp(100, rate = .1)), ncol = 1)
|
||||
x <- matrix(as.integer(rexp(100, rate = .1)), ncol = 1) + 1
|
||||
|
||||
output <- test_r_binding(4.0, 12, "hello",
|
||||
urow_in=x)
|
||||
@@ -269,6 +269,15 @@ test_that("TestNotMatrix", {
|
||||
matrix_and_info_in=1e6))
|
||||
})
|
||||
|
||||
# If we pass labels that start from 0, we should get an error.
|
||||
test_that("TestZeroLabels", {
|
||||
x <- vector(mode="integer", 10)
|
||||
expect_error(test_r_binding(4.0, 12, "hello", urow_in=x))
|
||||
|
||||
y <- matrix(0, 10, 1)
|
||||
expect_error(test_r_binding(4.0, 12, "hello", ucol_in=y))
|
||||
})
|
||||
|
||||
# First create a GaussianKernel object, then send it back and make sure we get
|
||||
# the right double value.
|
||||
test_that("TestModel", {
|
||||
|
||||
@@ -55,19 +55,19 @@ void PrintDoc(util::ParamData& d,
|
||||
oss << ". Default value \"";
|
||||
if (d.cppType == "std::string")
|
||||
{
|
||||
oss << boost::any_cast<std::string>(d.value);
|
||||
oss << ANY_CAST<std::string>(d.value);
|
||||
}
|
||||
else if (d.cppType == "double")
|
||||
{
|
||||
oss << boost::any_cast<double>(d.value);
|
||||
oss << ANY_CAST<double>(d.value);
|
||||
}
|
||||
else if (d.cppType == "int")
|
||||
{
|
||||
oss << boost::any_cast<int>(d.value);
|
||||
oss << ANY_CAST<int>(d.value);
|
||||
}
|
||||
else if (d.cppType == "bool")
|
||||
{
|
||||
oss << (boost::any_cast<bool>(d.value) ? "TRUE" : "FALSE");
|
||||
oss << (ANY_CAST<bool>(d.value) ? "TRUE" : "FALSE");
|
||||
}
|
||||
oss << "\"";
|
||||
}
|
||||
|
||||
@@ -182,7 +182,22 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
for (size_t i = 0; i < m.n_rows; ++i)
|
||||
{
|
||||
if (di.Type(i) == data::Datatype::numeric)
|
||||
{
|
||||
m.row(i) *= 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure input data is valid.
|
||||
for (size_t c = 0; c < m.n_cols; ++c)
|
||||
{
|
||||
if (ceil(m(i, c)) != m(i, c))
|
||||
throw std::invalid_argument("non-integer value in categorical!");
|
||||
else if (m(i, c) < 0)
|
||||
throw std::invalid_argument("negative value in categorical!");
|
||||
else if (size_t(m(i, c)) >= di.NumMappings(i))
|
||||
throw std::invalid_argument("value outside number of categories!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
|
||||
@@ -47,8 +47,8 @@ void AddToCLI11(const std::string& cliName,
|
||||
[¶m](const std::string& value)
|
||||
{
|
||||
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(¶m.value);
|
||||
std::get<0>(std::get<1>(tuple)) = boost::any_cast<std::string>(value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(¶m.value);
|
||||
std::get<0>(std::get<1>(tuple)) = ANY_CAST<std::string>(value);
|
||||
param.wasPassed = true;
|
||||
},
|
||||
param.desc.c_str());
|
||||
@@ -79,8 +79,8 @@ void AddToCLI11(const std::string& cliName,
|
||||
[¶m](const std::string& value)
|
||||
{
|
||||
using TupleType = std::tuple<T*, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(¶m.value);
|
||||
std::get<1>(tuple) = boost::any_cast<std::string>(value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(¶m.value);
|
||||
std::get<1>(tuple) = ANY_CAST<std::string>(value);
|
||||
param.wasPassed = true;
|
||||
},
|
||||
param.desc.c_str());
|
||||
@@ -109,8 +109,8 @@ void AddToCLI11(const std::string& cliName,
|
||||
[¶m](const std::string& value)
|
||||
{
|
||||
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(¶m.value);
|
||||
std::get<0>(std::get<1>(tuple)) = boost::any_cast<std::string>(value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(¶m.value);
|
||||
std::get<0>(std::get<1>(tuple)) = ANY_CAST<std::string>(value);
|
||||
param.wasPassed = true;
|
||||
},
|
||||
param.desc.c_str());
|
||||
|
||||
@@ -95,12 +95,12 @@ class CLIOption
|
||||
typename ParameterType<typename
|
||||
std::remove_pointer<N>::type>::type>::value)
|
||||
{
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
typename ParameterType<typename std::remove_pointer<N>::type>::type tmp;
|
||||
data.value = boost::any(std::tuple<N, decltype(tmp)>(defaultValue, tmp));
|
||||
data.value = ANY(std::tuple<N, decltype(tmp)>(defaultValue, tmp));
|
||||
}
|
||||
|
||||
const std::string tname = data.tname;
|
||||
|
||||
@@ -34,7 +34,7 @@ std::string DefaultParamImpl(
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (!std::is_same<T, bool>::value)
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
@@ -49,7 +49,7 @@ std::string DefaultParamImpl(
|
||||
{
|
||||
// Print each element in an array delimited by square brackets.
|
||||
std::ostringstream oss;
|
||||
const T& vector = boost::any_cast<T>(data.value);
|
||||
const T& vector = ANY_CAST<T>(data.value);
|
||||
oss << "[";
|
||||
if (std::is_same<T, std::vector<std::string>>::value)
|
||||
{
|
||||
@@ -91,7 +91,7 @@ std::string DefaultParamImpl(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<std::is_same<T, std::string>::value>::type*)
|
||||
{
|
||||
const std::string& s = *boost::any_cast<std::string>(&data.value);
|
||||
const std::string& s = *ANY_CAST<std::string>(&data.value);
|
||||
return "'" + s + "'";
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void DeleteAllocatedMemoryImpl(
|
||||
{
|
||||
// Delete the allocated memory (hopefully we actually own it).
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
delete std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
delete std::get<0>(*ANY_CAST<TupleType>(&d.value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -45,7 +45,7 @@ void* GetAllocatedMemory(
|
||||
// Here we have a model, which is a tuple, and we need the address of the
|
||||
// memory.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
return std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
return std::get<0>(*ANY_CAST<TupleType>(&d.value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -34,7 +34,7 @@ T& GetParam(
|
||||
std::tuple<mlpack::data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// No mapping is needed, so just cast it directly.
|
||||
return *boost::any_cast<T>(&d.value);
|
||||
return *ANY_CAST<T>(&d.value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ T& GetParam(
|
||||
// times, but I am not bothered by that---it shouldn't be something that
|
||||
// happens.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(&d.value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(&d.value);
|
||||
const std::string& value = std::get<0>(std::get<1>(tuple));
|
||||
T& matrix = std::get<0>(tuple);
|
||||
size_t& n_rows = std::get<1>(std::get<1>(tuple));
|
||||
@@ -86,7 +86,7 @@ T& GetParam(
|
||||
// If this is an input parameter, we need to load both the matrix and the
|
||||
// dataset info.
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
TupleType* tuple = boost::any_cast<TupleType>(&d.value);
|
||||
TupleType* tuple = ANY_CAST<TupleType>(&d.value);
|
||||
const std::string& value = std::get<0>(std::get<1>(*tuple));
|
||||
T& t = std::get<0>(*tuple);
|
||||
size_t& n_rows = std::get<1>(std::get<1>(*tuple));
|
||||
@@ -116,7 +116,7 @@ T*& GetParam(
|
||||
// If the model is an input model, we have to load it from file. 'value'
|
||||
// contains the filename.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
TupleType* tuple = boost::any_cast<TupleType>(&d.value);
|
||||
TupleType* tuple = ANY_CAST<TupleType>(&d.value);
|
||||
const std::string& value = std::get<1>(*tuple);
|
||||
if (d.input && !d.loaded)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* /* junk */)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type*
|
||||
/* junk */)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
@@ -80,7 +80,7 @@ std::string GetPrintableParam(
|
||||
{
|
||||
// Extract the string from the tuple that's being held.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
const TupleType* tuple = boost::any_cast<TupleType>(&data.value);
|
||||
const TupleType* tuple = ANY_CAST<TupleType>(&data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "'" << std::get<0>(std::get<1>(*tuple)) << "'";
|
||||
@@ -108,7 +108,7 @@ std::string GetPrintableParam(
|
||||
{
|
||||
// Extract the string from the tuple that's being held.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
const TupleType* tuple = boost::any_cast<TupleType>(&data.value);
|
||||
const TupleType* tuple = ANY_CAST<TupleType>(&data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << std::get<1>(*tuple);
|
||||
|
||||
@@ -33,7 +33,7 @@ T& GetRawParam(
|
||||
std::tuple<mlpack::data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// No mapping is needed, so just cast it directly.
|
||||
return *boost::any_cast<T>(&d.value);
|
||||
return *ANY_CAST<T>(&d.value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ T& GetRawParam(
|
||||
{
|
||||
// Don't load the matrix.
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
T& value = std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
T& value = std::get<0>(*ANY_CAST<TupleType>(&d.value));
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ T*& GetRawParam(
|
||||
{
|
||||
// Don't load the model.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
T*& value = std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
T*& value = std::get<0>(*ANY_CAST<TupleType>(&d.value));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,10 +58,10 @@ void InPlaceCopyInternal(
|
||||
{
|
||||
// Make the output filename the same as the input filename.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(&d.value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(&d.value);
|
||||
std::string& value = std::get<0>(std::get<1>(tuple));
|
||||
|
||||
const TupleType& inputTuple = *boost::any_cast<TupleType>(&input.value);
|
||||
const TupleType& inputTuple = *ANY_CAST<TupleType>(&input.value);
|
||||
value = std::get<0>(std::get<1>(inputTuple));
|
||||
}
|
||||
|
||||
@@ -81,10 +81,10 @@ void InPlaceCopyInternal(
|
||||
{
|
||||
// Make the output filename the same as the input filename.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(&d.value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(&d.value);
|
||||
std::string& value = std::get<1>(tuple);
|
||||
|
||||
const TupleType& inputTuple = *boost::any_cast<TupleType>(&input.value);
|
||||
const TupleType& inputTuple = *ANY_CAST<TupleType>(&input.value);
|
||||
value = std::get<1>(inputTuple);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ void OutputParamImpl(
|
||||
const typename std::enable_if<!std::is_same<T,
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* /* junk */)
|
||||
{
|
||||
std::cout << data.name << ": " << *boost::any_cast<T>(&data.value)
|
||||
std::cout << data.name << ": " << *ANY_CAST<T>(&data.value)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void OutputParamImpl(
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* /* junk */)
|
||||
{
|
||||
std::cout << data.name << ": ";
|
||||
const T& t = *boost::any_cast<T>(&data.value);
|
||||
const T& t = *ANY_CAST<T>(&data.value);
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
std::cout << t[i] << " ";
|
||||
std::cout << std::endl;
|
||||
@@ -54,9 +54,9 @@ void OutputParamImpl(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* /* junk */)
|
||||
{
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
const T& output = std::get<0>(*boost::any_cast<TupleType>(&data.value));
|
||||
const T& output = std::get<0>(*ANY_CAST<TupleType>(&data.value));
|
||||
const std::string& filename =
|
||||
std::get<0>(std::get<1>(*boost::any_cast<TupleType>(&data.value)));
|
||||
std::get<0>(std::get<1>(*ANY_CAST<TupleType>(&data.value)));
|
||||
|
||||
if (output.n_elem > 0 && filename != "")
|
||||
{
|
||||
@@ -78,10 +78,10 @@ void OutputParamImpl(
|
||||
// const. In this case we can assume it though, since we will be saving and
|
||||
// not loading.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
T*& output = const_cast<T*&>(std::get<0>(*boost::any_cast<TupleType>(
|
||||
T*& output = const_cast<T*&>(std::get<0>(*ANY_CAST<TupleType>(
|
||||
&data.value)));
|
||||
const std::string& filename =
|
||||
std::get<1>(*boost::any_cast<TupleType>(&data.value));
|
||||
std::get<1>(*ANY_CAST<TupleType>(&data.value));
|
||||
|
||||
if (filename != "")
|
||||
data::Save(filename, "model", *output);
|
||||
@@ -96,9 +96,9 @@ void OutputParamImpl(
|
||||
{
|
||||
// Output the matrix with the mappings.
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
const T& tuple = std::get<0>(*boost::any_cast<TupleType>(&data.value));
|
||||
const T& tuple = std::get<0>(*ANY_CAST<TupleType>(&data.value));
|
||||
const std::string& filename =
|
||||
std::get<0>(std::get<1>(*boost::any_cast<TupleType>(&data.value)));
|
||||
std::get<0>(std::get<1>(*ANY_CAST<TupleType>(&data.value)));
|
||||
const arma::mat& matrix = std::get<1>(tuple);
|
||||
|
||||
// The mapping isn't taken into account. We should write a data::Save()
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace cli {
|
||||
template<typename T>
|
||||
void SetParam(
|
||||
util::ParamData& d,
|
||||
const boost::any& value,
|
||||
const ANY& value,
|
||||
const typename std::enable_if<!arma::is_arma_type<T>::value>::type* = 0,
|
||||
const typename std::enable_if<!data::HasSerialize<T>::value>::type* = 0,
|
||||
const typename std::enable_if<!std::is_same<T,
|
||||
@@ -43,7 +43,7 @@ void SetParam(
|
||||
template<typename T>
|
||||
void SetParam(
|
||||
util::ParamData& d,
|
||||
const boost::any& /* value */,
|
||||
const ANY& /* value */,
|
||||
const typename std::enable_if<std::is_same<T, bool>::value>::type* = 0)
|
||||
{
|
||||
// Force set to the value of whether or not this was passed.
|
||||
@@ -57,15 +57,15 @@ void SetParam(
|
||||
template<typename T>
|
||||
void SetParam(
|
||||
util::ParamData& d,
|
||||
const boost::any& value,
|
||||
const ANY& value,
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value ||
|
||||
std::is_same<T,
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// We're setting the string filename.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(&d.value);
|
||||
std::get<0>(std::get<1>(tuple)) = boost::any_cast<std::string>(value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(&d.value);
|
||||
std::get<0>(std::get<1>(tuple)) = ANY_CAST<std::string>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,14 +75,14 @@ void SetParam(
|
||||
template<typename T>
|
||||
void SetParam(
|
||||
util::ParamData& d,
|
||||
const boost::any& value,
|
||||
const ANY& value,
|
||||
const typename std::enable_if<!arma::is_arma_type<T>::value>::type* = 0,
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
// We're setting the string filename.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(&d.value);
|
||||
std::get<1>(tuple) = boost::any_cast<std::string>(value);
|
||||
TupleType& tuple = *ANY_CAST<TupleType>(&d.value);
|
||||
std::get<1>(tuple) = ANY_CAST<std::string>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +97,7 @@ template<typename T>
|
||||
void SetParam(util::ParamData& d, const void* input, void* /* output */)
|
||||
{
|
||||
SetParam<typename std::remove_pointer<T>::type>(
|
||||
const_cast<util::ParamData&>(d), *((boost::any*) input));
|
||||
const_cast<util::ParamData&>(d), *((ANY*) input));
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
+26
-26
@@ -1,11 +1,11 @@
|
||||
// CLI11: Version 2.1.1
|
||||
// CLI11: Version 2.1.2
|
||||
// Originally designed by Henry Schreiner
|
||||
// https://github.com/CLIUtils/CLI11
|
||||
//
|
||||
// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
|
||||
// from: v2.1.1
|
||||
// from: v2.1.2
|
||||
//
|
||||
// CLI11 2.1.1 Copyright (c) 2017-2021 University of Cincinnati, developed by Henry
|
||||
// CLI11 2.1.2 Copyright (c) 2017-2021 University of Cincinnati, developed by Henry
|
||||
// Schreiner under NSF AWARD 1414736. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms of CLI11, with or without
|
||||
@@ -34,34 +34,34 @@
|
||||
#pragma once
|
||||
|
||||
// Standard combined includes:
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <iomanip>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <tuple>
|
||||
#include <cmath>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <exception>
|
||||
|
||||
|
||||
#define CLI11_VERSION_MAJOR 2
|
||||
#define CLI11_VERSION_MINOR 1
|
||||
#define CLI11_VERSION_PATCH 1
|
||||
#define CLI11_VERSION "2.1.1"
|
||||
#define CLI11_VERSION_PATCH 2
|
||||
#define CLI11_VERSION "2.1.2"
|
||||
|
||||
|
||||
|
||||
@@ -891,7 +891,7 @@ constexpr enabler dummy = {};
|
||||
/// A copy of enable_if_t from C++14, compatible with C++11.
|
||||
///
|
||||
/// We could check to see if C++14 is being used, but it does not hurt to redefine this
|
||||
/// (even Google does this: https://github.com/google/skia/blob/master/include/private/SkTLogic.h)
|
||||
/// (even Google does this: https://github.com/google/skia/blob/main/include/private/SkTLogic.h)
|
||||
/// It is not in the std namespace anyway, so no harm done.
|
||||
template <bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
@@ -6956,10 +6956,10 @@ class App {
|
||||
/// Get a pointer to the version option. (const)
|
||||
const Option *get_version_ptr() const { return version_ptr_; }
|
||||
|
||||
/// Get the parent of this subcommand (or nullptr if master app)
|
||||
/// Get the parent of this subcommand (or nullptr if main app)
|
||||
App *get_parent() { return parent_; }
|
||||
|
||||
/// Get the parent of this subcommand (or nullptr if master app) (const version)
|
||||
/// Get the parent of this subcommand (or nullptr if main app) (const version)
|
||||
const App *get_parent() const { return parent_; }
|
||||
|
||||
/// Get the name of the current app
|
||||
@@ -7673,7 +7673,7 @@ class App {
|
||||
}
|
||||
|
||||
/// Parse "one" argument (some may eat more than one), delegate to parent if fails, add to missing if missing
|
||||
/// from master return false if the parse has failed and needs to return to parent
|
||||
/// from main return false if the parse has failed and needs to return to parent
|
||||
bool _parse_single(std::vector<std::string> &args, bool &positional_only) {
|
||||
bool retval = true;
|
||||
detail::Classifier classifier = positional_only ? detail::Classifier::NONE : _recognize(args.back());
|
||||
@@ -7948,7 +7948,7 @@ class App {
|
||||
}
|
||||
}
|
||||
}
|
||||
// If a subcommand, try the master command
|
||||
// If a subcommand, try the main command
|
||||
if(parent_ != nullptr && fallthrough_)
|
||||
return _get_fallthrough_parent()->_parse_arg(args, current_type);
|
||||
// don't capture missing if this is a nameless subcommand
|
||||
|
||||
@@ -36,7 +36,7 @@ std::string DefaultParamImpl(
|
||||
if (std::is_same<T, bool>::value)
|
||||
oss << "false";
|
||||
else
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ std::string DefaultParamImpl(
|
||||
{
|
||||
// Print each element in an array delimited by square brackets.
|
||||
std::ostringstream oss;
|
||||
const T& vector = boost::any_cast<T>(data.value);
|
||||
const T& vector = ANY_CAST<T>(data.value);
|
||||
if (std::is_same<T, std::vector<std::string>>::value)
|
||||
{
|
||||
oss << "[]string{";
|
||||
@@ -93,7 +93,7 @@ std::string DefaultParamImpl(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<std::is_same<T, std::string>::value>::type*)
|
||||
{
|
||||
const std::string& s = *boost::any_cast<std::string>(&data.value);
|
||||
const std::string& s = *ANY_CAST<std::string>(&data.value);
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void GetParam(util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((T**) output) = const_cast<T*>(boost::any_cast<T>(&d.value));
|
||||
*((T**) output) = const_cast<T*>(ANY_CAST<T>(&d.value));
|
||||
}
|
||||
|
||||
} // namespace go
|
||||
|
||||
@@ -32,7 +32,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ std::string GetPrintableParam(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
@@ -61,7 +61,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& matrix = boost::any_cast<T>(data.value);
|
||||
const T& matrix = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix";
|
||||
@@ -78,7 +78,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
|
||||
oss << data.cppType << " model at " << ANY_CAST<T*>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& tuple = boost::any_cast<T>(data.value);
|
||||
const T& tuple = ANY_CAST<T>(data.value);
|
||||
const arma::mat& matrix = std::get<1>(tuple);
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -78,7 +78,7 @@ class GoOption
|
||||
data.loaded = false;
|
||||
data.cppType = cppName;
|
||||
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
|
||||
// Set the function pointers that we'll need. All of these function
|
||||
// pointers will be used by both the program that generates the .cpp,
|
||||
|
||||
@@ -328,16 +328,40 @@ void mlpackToArmaMatWithInfo(void* params,
|
||||
{
|
||||
util::Params& p = *((util::Params*) params);
|
||||
data::DatasetInfo d(rows);
|
||||
bool hasCategoricals = false;
|
||||
for (size_t i = 0; i < d.Dimensionality(); ++i)
|
||||
{
|
||||
d.Type(i) = (dimensions[i]) ? data::Datatype::categorical :
|
||||
data::Datatype::numeric;
|
||||
if (dimensions[i])
|
||||
hasCategoricals = true;
|
||||
}
|
||||
|
||||
arma::mat m(memptr, rows, cols, false, true);
|
||||
std::get<0>(p.Get<std::tuple<data::DatasetInfo, arma::mat>>( identifier)) =
|
||||
|
||||
// Do we need to find how many categories we have?
|
||||
if (hasCategoricals)
|
||||
{
|
||||
arma::vec maxs = arma::max(m, 1) + 1;
|
||||
|
||||
for (size_t i = 0; i < d.Dimensionality(); ++i)
|
||||
{
|
||||
if (dimensions[i])
|
||||
{
|
||||
// Map the right number of objects.
|
||||
for (size_t j = 0; j < (size_t) maxs[i]; ++j)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << j;
|
||||
d.MapString<double>(oss.str(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::get<0>(p.Get<std::tuple<data::DatasetInfo, arma::mat>>(identifier)) =
|
||||
std::move(d);
|
||||
std::get<1>(p.Get<std::tuple<data::DatasetInfo, arma::mat>>( identifier)) =
|
||||
std::get<1>(p.Get<std::tuple<data::DatasetInfo, arma::mat>>(identifier)) =
|
||||
std::move(m);
|
||||
p.SetPassed(identifier);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ void mlpackSetParamVectorStr(void* params,
|
||||
*/
|
||||
void mlpackSetParamPtr(void* params,
|
||||
const char* identifier,
|
||||
const double* ptr)
|
||||
double* ptr)
|
||||
{
|
||||
util::Params& p = *((util::Params*) params);
|
||||
util::SetParamPtr(p, identifier, ptr);
|
||||
|
||||
@@ -71,7 +71,7 @@ void mlpackSetParamString(void* params,
|
||||
/**
|
||||
* Set the parameter to the given value, given that the type is a pointer.
|
||||
*/
|
||||
void mlpackSetParamPtr(void* params, const char* identifier, const double* ptr);
|
||||
void mlpackSetParamPtr(void* params, const char* identifier, double* ptr);
|
||||
|
||||
/**
|
||||
* Set the int vector parameter to the given value.
|
||||
|
||||
@@ -53,16 +53,16 @@ void PrintDoc(util::ParamData& d,
|
||||
{
|
||||
if (d.cppType == "std::string")
|
||||
{
|
||||
oss << " Default value '" << boost::any_cast<std::string>(d.value)
|
||||
oss << " Default value '" << ANY_CAST<std::string>(d.value)
|
||||
<< "'.";
|
||||
}
|
||||
else if (d.cppType == "double")
|
||||
{
|
||||
oss << " Default value " << boost::any_cast<double>(d.value) << ".";
|
||||
oss << " Default value " << ANY_CAST<double>(d.value) << ".";
|
||||
}
|
||||
else if (d.cppType == "int")
|
||||
{
|
||||
oss << " Default value " << boost::any_cast<int>(d.value) << ".";
|
||||
oss << " Default value " << ANY_CAST<int>(d.value) << ".";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,22 +67,22 @@ void PrintInputProcessing(
|
||||
// Print out default value.
|
||||
if (d.cppType == "std::string")
|
||||
{
|
||||
std::string value = boost::any_cast<std::string>(d.value);
|
||||
std::string value = ANY_CAST<std::string>(d.value);
|
||||
std::cout << "\"" << value << "\"";
|
||||
}
|
||||
else if (d.cppType == "double")
|
||||
{
|
||||
double value = boost::any_cast<double>(d.value);
|
||||
double value = ANY_CAST<double>(d.value);
|
||||
std::cout << value;
|
||||
}
|
||||
else if (d.cppType == "int")
|
||||
{
|
||||
int value = boost::any_cast<int>(d.value);
|
||||
int value = ANY_CAST<int>(d.value);
|
||||
std::cout << value;
|
||||
}
|
||||
else if (d.cppType == "bool")
|
||||
{
|
||||
bool value = boost::any_cast<bool>(d.value);
|
||||
bool value = ANY_CAST<bool>(d.value);
|
||||
if (value == 0)
|
||||
std::cout << "false";
|
||||
else
|
||||
|
||||
@@ -54,23 +54,23 @@ void PrintMethodInit(
|
||||
{
|
||||
if (d.cppType == "std::string")
|
||||
{
|
||||
std::string value = boost::any_cast<std::string>(d.value);
|
||||
std::string value = ANY_CAST<std::string>(d.value);
|
||||
std::cout << prefix << goParamName << ": \""
|
||||
<< value << "\"," << std::endl;
|
||||
}
|
||||
else if (d.cppType == "double")
|
||||
{
|
||||
double value = boost::any_cast<double>(d.value);
|
||||
double value = ANY_CAST<double>(d.value);
|
||||
std::cout << prefix << goParamName << ": " << value << "," << std::endl;
|
||||
}
|
||||
else if (d.cppType == "int")
|
||||
{
|
||||
int value = boost::any_cast<int>(d.value);
|
||||
int value = ANY_CAST<int>(d.value);
|
||||
std::cout << prefix << goParamName << ": " << value << "," << std::endl;
|
||||
}
|
||||
else if (d.cppType == "bool")
|
||||
{
|
||||
bool value = boost::any_cast<bool>(d.value);
|
||||
bool value = ANY_CAST<bool>(d.value);
|
||||
if (value == 0)
|
||||
std::cout << prefix << goParamName << ": false," << std::endl;
|
||||
else
|
||||
|
||||
@@ -574,6 +574,58 @@ func TestGonumMatrixWithInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGonumMatrixWithInfoCategorical(t *testing.T) {
|
||||
t.Log("Test that the matrix with info option works when we pass categorical ",
|
||||
"data.")
|
||||
|
||||
x := mlpack.DataAndInfo()
|
||||
x.Categoricals = []bool{
|
||||
false, false, true, true, false,
|
||||
}
|
||||
|
||||
x.Data = mat.NewDense(6, 5, []float64{
|
||||
0.1, 0.2, 3, 2, 0.3,
|
||||
0.5, -0.3, 1, 1, 0.5,
|
||||
-3, 0.1, 0, 0, 0.6,
|
||||
0.7, 0.0, 2, 4, 0.4,
|
||||
0.8, 0.1, 2, 3, 0.1,
|
||||
0.3, 0.0, 1, 1, 0.6,
|
||||
})
|
||||
|
||||
param := mlpack.TestGoBindingOptions()
|
||||
param.MatrixAndInfoIn = x
|
||||
d := 4.0
|
||||
i := 12
|
||||
s := "hello"
|
||||
_, _, _, MatrixAndInfoOut, _, _, _, _, _, _, _, _, _, _ :=
|
||||
mlpack.TestGoBinding(d, i, s, param)
|
||||
|
||||
rows, cols := MatrixAndInfoOut.Dims()
|
||||
|
||||
if rows != 6 || cols != 5 {
|
||||
t.Errorf("Error. Wrong shape. %v, %v", rows, cols)
|
||||
}
|
||||
for i := 0; i < rows; i++ {
|
||||
for j := 0; j < cols; j++ {
|
||||
if j == 0 || j == 1 || j == 4 {
|
||||
if x.Data.At(i, j) * 2 != MatrixAndInfoOut.At(i, j) {
|
||||
val := MatrixAndInfoOut.At(i, j)
|
||||
expected := x.Data.At(i, j)*2
|
||||
t.Errorf("Error. Value at [%v,%v] : %v. Expected value : %v",
|
||||
i, j, val, expected)
|
||||
}
|
||||
} else {
|
||||
if x.Data.At(i, j) != MatrixAndInfoOut.At(i, j) {
|
||||
val := MatrixAndInfoOut.At(i, j)
|
||||
expected := x.Data.At(i, j)
|
||||
t.Errorf("Error. Value at [%v,%v] : %v. Expected value: %v",
|
||||
i, j, val, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestModel(t *testing.T) {
|
||||
t.Log("First create a GaussianKernel object, then send it back and",
|
||||
"make sure we get the right double value.")
|
||||
|
||||
@@ -182,7 +182,22 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
for (size_t i = 0; i < m.n_rows; ++i)
|
||||
{
|
||||
if (di.Type(i) == data::Datatype::numeric)
|
||||
{
|
||||
m.row(i) *= 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure input data is valid.
|
||||
for (size_t c = 0; c < m.n_cols; ++c)
|
||||
{
|
||||
if (ceil(m(i, c)) != m(i, c))
|
||||
throw std::invalid_argument("non-integer value in categorical!");
|
||||
else if (m(i, c) < 0)
|
||||
throw std::invalid_argument("negative value in categorical!");
|
||||
else if (size_t(m(i, c)) >= di.NumMappings(i))
|
||||
throw std::invalid_argument("value outside number of categories!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
|
||||
@@ -36,7 +36,7 @@ std::string DefaultParamImpl(
|
||||
if (std::is_same<T, bool>::value)
|
||||
oss << "false";
|
||||
else
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ std::string DefaultParamImpl(
|
||||
{
|
||||
// Print each element in an array delimited by square brackets.
|
||||
std::ostringstream oss;
|
||||
const T& vector = boost::any_cast<T>(data.value);
|
||||
const T& vector = ANY_CAST<T>(data.value);
|
||||
oss << "[";
|
||||
if (std::is_same<T, std::vector<std::string>>::value)
|
||||
{
|
||||
@@ -92,7 +92,7 @@ std::string DefaultParamImpl(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<std::is_same<T, std::string>::value>::type*)
|
||||
{
|
||||
const std::string& s = *boost::any_cast<std::string>(&data.value);
|
||||
const std::string& s = *ANY_CAST<std::string>(&data.value);
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void GetParam(util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((T**) output) = const_cast<T*>(boost::any_cast<T>(&d.value));
|
||||
*((T**) output) = const_cast<T*>(ANY_CAST<T>(&d.value));
|
||||
}
|
||||
|
||||
} // namespace julia
|
||||
|
||||
@@ -32,7 +32,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ std::string GetPrintableParam(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
@@ -61,7 +61,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& matrix = boost::any_cast<T>(data.value);
|
||||
const T& matrix = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix";
|
||||
@@ -78,7 +78,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
|
||||
oss << data.cppType << " model at " << ANY_CAST<T*>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& tuple = boost::any_cast<T>(data.value);
|
||||
const T& tuple = ANY_CAST<T>(data.value);
|
||||
const arma::mat& matrix = std::get<1>(tuple);
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -64,7 +64,7 @@ class JuliaOption
|
||||
data.cppType = cppName;
|
||||
|
||||
// Every parameter we'll get from Julia will have the correct type.
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
|
||||
// Set the function pointers that we'll need. All of these function
|
||||
// pointers will be used by both the program that generates the pyx, and
|
||||
|
||||
@@ -251,13 +251,42 @@ void SetParamMatWithInfo(void* params,
|
||||
{
|
||||
util::Params* p = (util::Params*) params;
|
||||
data::DatasetInfo d(pointsAreRows ? cols : rows);
|
||||
bool hasCategoricals = false;
|
||||
for (size_t i = 0; i < d.Dimensionality(); ++i)
|
||||
{
|
||||
d.Type(i) = (dimensions[i]) ? data::Datatype::categorical :
|
||||
data::Datatype::numeric;
|
||||
if (dimensions[i])
|
||||
hasCategoricals = true;
|
||||
}
|
||||
|
||||
arma::mat m(memptr, arma::uword(rows), arma::uword(cols), false, true);
|
||||
|
||||
// Do we need to find how many categories we have?
|
||||
if (hasCategoricals)
|
||||
{
|
||||
// Compute the maximum in each dimension.
|
||||
arma::vec maxs;
|
||||
if (pointsAreRows)
|
||||
maxs = arma::max(m, 0).t();
|
||||
else
|
||||
maxs = arma::max(m, 1);
|
||||
|
||||
for (size_t i = 0; i < d.Dimensionality(); ++i)
|
||||
{
|
||||
if (dimensions[i])
|
||||
{
|
||||
// Map the right number of objects.
|
||||
for (size_t j = 1; j <= (size_t) maxs[i]; ++j)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << j;
|
||||
d.MapString<double>(oss.str(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::get<0>(p->Get<std::tuple<data::DatasetInfo, arma::mat>>(
|
||||
paramName)) = std::move(d);
|
||||
std::get<1>(p->Get<std::tuple<data::DatasetInfo, arma::mat>>(
|
||||
|
||||
@@ -39,19 +39,19 @@ void PrintDoc(util::ParamData& d, const void* /* input */, void* output)
|
||||
oss << " Default value `";
|
||||
if (d.cppType == "std::string")
|
||||
{
|
||||
oss << boost::any_cast<std::string>(d.value);
|
||||
oss << ANY_CAST<std::string>(d.value);
|
||||
}
|
||||
else if (d.cppType == "double")
|
||||
{
|
||||
oss << boost::any_cast<double>(d.value);
|
||||
oss << ANY_CAST<double>(d.value);
|
||||
}
|
||||
else if (d.cppType == "int")
|
||||
{
|
||||
oss << boost::any_cast<int>(d.value);
|
||||
oss << ANY_CAST<int>(d.value);
|
||||
}
|
||||
else if (d.cppType == "bool")
|
||||
{
|
||||
oss << (boost::any_cast<bool>(d.value) ? "true" : "false");
|
||||
oss << (ANY_CAST<bool>(d.value) ? "true" : "false");
|
||||
}
|
||||
oss << "`." << std::endl;
|
||||
}
|
||||
|
||||
@@ -142,9 +142,10 @@ std::string PrintTypeDoc(
|
||||
"indicating which dimensions are categorical (represented by `true`) and "
|
||||
"which are numeric (represented by `false`). The number of elements in "
|
||||
"the boolean array should be the same as the dimensionality of the data "
|
||||
"matrix. It is expected that each row of the matrix corresponds to a "
|
||||
"single data point, unless `points_are_rows` is set to `false` when "
|
||||
"calling mlpack bindings.";
|
||||
"matrix. Categorical dimensions should take integer values between 1 "
|
||||
"and the number of categories. It is expected that each row of the "
|
||||
"matrix corresponds to a single data point, unless `points_are_rows` is "
|
||||
"set to `false` when calling mlpack bindings.";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -287,6 +287,64 @@ end
|
||||
end
|
||||
end
|
||||
|
||||
# Test that we can pass a matrix with categorical features.
|
||||
@testset "TestMatrixAndInfoCategorical" begin
|
||||
x = collect(hcat(rand(100),
|
||||
rand(1:2, 100),
|
||||
rand(100),
|
||||
rand(1:4, 100),
|
||||
rand(1:6, 100),
|
||||
rand(100))')
|
||||
dims = [false, true, false, true, true, false]
|
||||
z = x
|
||||
|
||||
_, _, _, matrix_and_info_out, _, _, _, _, _, _, _, _, _, _ =
|
||||
test_julia_binding(4.0, 12, "hello",
|
||||
matrix_and_info_in=(dims, z),
|
||||
points_are_rows=false)
|
||||
|
||||
@test size(matrix_and_info_out, 1) == 6
|
||||
@test size(matrix_and_info_out, 2) == 100
|
||||
|
||||
for i in 1:100
|
||||
for j in [1, 3, 6]
|
||||
@test matrix_and_info_out[j, i] == 2.0 * z[j, i]
|
||||
end
|
||||
for j in [2, 4, 5]
|
||||
@test matrix_and_info_out[j, i] == z[j, i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Test that we can pass a matrix with categorical features.
|
||||
@testset "TestMatrixAndInfoCategoricalRowMajor" begin
|
||||
x = hcat(rand(100),
|
||||
rand(1:2, 100),
|
||||
rand(100),
|
||||
rand(1:4, 100),
|
||||
rand(1:6, 100),
|
||||
rand(100))
|
||||
dims = [false, true, false, true, true, false]
|
||||
z = x
|
||||
|
||||
_, _, _, matrix_and_info_out, _, _, _, _, _, _, _, _, _, _ =
|
||||
test_julia_binding(4.0, 12, "hello",
|
||||
matrix_and_info_in=(dims, z),
|
||||
points_are_rows=true)
|
||||
|
||||
@test size(matrix_and_info_out, 1) == 100
|
||||
@test size(matrix_and_info_out, 2) == 6
|
||||
|
||||
for i in 1:100
|
||||
for j in [1, 3, 6]
|
||||
@test matrix_and_info_out[i, j] == 2.0 * z[i, j]
|
||||
end
|
||||
for j in [2, 4, 5]
|
||||
@test matrix_and_info_out[i, j] == z[i, j]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Test that we can pass a vector of ints and get back that same vector but with
|
||||
# the last element removed.
|
||||
@testset "TestIntVector" begin
|
||||
|
||||
@@ -184,7 +184,22 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
for (size_t i = 0; i < m.n_rows; ++i)
|
||||
{
|
||||
if (di.Type(i) == data::Datatype::numeric)
|
||||
{
|
||||
m.row(i) *= 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure input data is valid.
|
||||
for (size_t c = 0; c < m.n_cols; ++c)
|
||||
{
|
||||
if (ceil(m(i, c)) != m(i, c))
|
||||
throw std::invalid_argument("non-integer value in categorical!");
|
||||
else if (m(i, c) <= 0)
|
||||
throw std::invalid_argument("negative/zero value in categorical!");
|
||||
else if (size_t(m(i, c)) > di.NumMappings(i))
|
||||
throw std::invalid_argument("value outside number of categories!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
|
||||
@@ -28,7 +28,7 @@ void GetParam(util::ParamData& d,
|
||||
void* output)
|
||||
{
|
||||
util::ParamData& dmod = const_cast<util::ParamData&>(d);
|
||||
*((T**) output) = boost::any_cast<T>(&dmod.value);
|
||||
*((T**) output) = ANY_CAST<T>(&dmod.value);
|
||||
}
|
||||
|
||||
} // namespace markdown
|
||||
|
||||
@@ -32,7 +32,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ std::string GetPrintableParam(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
@@ -61,7 +61,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& matrix = boost::any_cast<T>(data.value);
|
||||
const T& matrix = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix";
|
||||
@@ -78,7 +78,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
|
||||
oss << data.cppType << " model at " << ANY_CAST<T*>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& tuple = boost::any_cast<T>(data.value);
|
||||
const T& tuple = ANY_CAST<T>(data.value);
|
||||
const arma::mat& matrix = std::get<1>(tuple);
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -63,7 +63,7 @@ class MDOption
|
||||
data.cppType = cppName;
|
||||
|
||||
// Every parameter we'll get from Markdown will have the correct type.
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
|
||||
// Set the function pointers that we'll need. Most of these simply delegate
|
||||
// to the current binding type's implementation. Any new language will need
|
||||
|
||||
@@ -245,7 +245,7 @@ inline std::string PrintTypeDocs()
|
||||
data.required = false;
|
||||
data.input = true;
|
||||
data.loaded = false;
|
||||
data.value = boost::any(int(0));
|
||||
data.value = ANY(int(0));
|
||||
|
||||
std::string type = GetPrintableType<int>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -253,7 +253,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(double).name());
|
||||
data.cppType = "double";
|
||||
data.value = boost::any(double(0.0));
|
||||
data.value = ANY(double(0.0));
|
||||
|
||||
type = GetPrintableType<double>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -262,7 +262,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(bool).name());
|
||||
data.cppType = "double";
|
||||
data.value = boost::any(bool(0.0));
|
||||
data.value = ANY(bool(0.0));
|
||||
|
||||
type = GetPrintableType<bool>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -270,7 +270,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(std::string).name());
|
||||
data.cppType = "std::string";
|
||||
data.value = boost::any(std::string(""));
|
||||
data.value = ANY(std::string(""));
|
||||
|
||||
type = GetPrintableType<std::string>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -279,7 +279,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(std::vector<int>).name());
|
||||
data.cppType = "std::vector<int>";
|
||||
data.value = boost::any(std::vector<int>());
|
||||
data.value = ANY(std::vector<int>());
|
||||
|
||||
type = GetPrintableType<std::vector<int>>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -288,7 +288,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(std::vector<std::string>).name());
|
||||
data.cppType = "std::vector<std::string>";
|
||||
data.value = boost::any(std::vector<std::string>());
|
||||
data.value = ANY(std::vector<std::string>());
|
||||
|
||||
type = GetPrintableType<std::vector<std::string>>(data);
|
||||
oss << " - `" << type << "`{: " << "#doc_" << BindingInfo::Language() << "_"
|
||||
@@ -297,7 +297,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(arma::mat).name());
|
||||
data.cppType = "arma::mat";
|
||||
data.value = boost::any(arma::mat());
|
||||
data.value = ANY(arma::mat());
|
||||
|
||||
type = GetPrintableType<arma::mat>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -306,7 +306,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(arma::Mat<size_t>).name());
|
||||
data.cppType = "arma::Mat<size_t>";
|
||||
data.value = boost::any(arma::Mat<size_t>());
|
||||
data.value = ANY(arma::Mat<size_t>());
|
||||
|
||||
type = GetPrintableType<arma::Mat<size_t>>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -315,7 +315,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(arma::rowvec).name());
|
||||
data.cppType = "arma::rowvec";
|
||||
data.value = boost::any(arma::rowvec());
|
||||
data.value = ANY(arma::rowvec());
|
||||
const std::string& rowType = GetPrintableType<arma::rowvec>(data);
|
||||
|
||||
oss << " - `" << rowType << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -324,7 +324,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(arma::Row<size_t>).name());
|
||||
data.cppType = "arma::Row<size_t>";
|
||||
data.value = boost::any(arma::Row<size_t>());
|
||||
data.value = ANY(arma::Row<size_t>());
|
||||
const std::string& urowType = GetPrintableType<arma::Row<size_t>>(data);
|
||||
|
||||
oss << " - `" << urowType << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -334,7 +334,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(arma::vec).name());
|
||||
data.cppType = "arma::vec";
|
||||
data.value = boost::any(arma::vec());
|
||||
data.value = ANY(arma::vec());
|
||||
const std::string& colType = GetPrintableType<arma::vec>(data);
|
||||
|
||||
// For some languages there is no distinction between column and row vectors.
|
||||
@@ -348,7 +348,7 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(arma::Col<size_t>).name());
|
||||
data.cppType = "arma::Col<size_t>";
|
||||
data.value = boost::any(arma::Col<size_t>());
|
||||
data.value = ANY(arma::Col<size_t>());
|
||||
const std::string& ucolType = GetPrintableType<arma::Col<size_t>>(data);
|
||||
|
||||
// For some languages there is no distinction between column and row vectors.
|
||||
@@ -363,7 +363,7 @@ inline std::string PrintTypeDocs()
|
||||
data.tname =
|
||||
std::string(typeid(std::tuple<data::DatasetInfo, arma::mat>).name());
|
||||
data.cppType = "std::tuple<data::DatasetInfo, arma::mat>";
|
||||
data.value = boost::any(std::tuple<data::DatasetInfo, arma::mat>());
|
||||
data.value = ANY(std::tuple<data::DatasetInfo, arma::mat>());
|
||||
|
||||
type = GetPrintableType<std::tuple<data::DatasetInfo, arma::mat>>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language() << "_"
|
||||
@@ -373,14 +373,14 @@ inline std::string PrintTypeDocs()
|
||||
|
||||
data.tname = std::string(typeid(priv::mlpackModel).name());
|
||||
data.cppType = "mlpackModel";
|
||||
data.value = boost::any(new priv::mlpackModel());
|
||||
data.value = ANY(new priv::mlpackModel());
|
||||
|
||||
type = GetPrintableType<priv::mlpackModel*>(data);
|
||||
oss << " - `" << type << "`{: #doc_" << BindingInfo::Language()
|
||||
<< "_model }: " << PrintTypeDoc<priv::mlpackModel*>(data) << std::endl;
|
||||
|
||||
// Clean up memory.
|
||||
delete boost::any_cast<priv::mlpackModel*>(data.value);
|
||||
delete ANY_CAST<priv::mlpackModel*>(data.value);
|
||||
|
||||
oss << std::endl << "</div>" << std::endl;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ std::string DefaultParamImpl(
|
||||
if (std::is_same<T, bool>::value)
|
||||
oss << "False";
|
||||
else
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ std::string DefaultParamImpl(
|
||||
{
|
||||
// Print each element in an array delimited by square brackets.
|
||||
std::ostringstream oss;
|
||||
const T& vector = boost::any_cast<T>(data.value);
|
||||
const T& vector = ANY_CAST<T>(data.value);
|
||||
oss << "[";
|
||||
if (std::is_same<T, std::vector<std::string>>::value)
|
||||
{
|
||||
@@ -92,7 +92,7 @@ std::string DefaultParamImpl(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<std::is_same<T, std::string>::value>::type*)
|
||||
{
|
||||
const std::string& s = *boost::any_cast<std::string>(&data.value);
|
||||
const std::string& s = *ANY_CAST<std::string>(&data.value);
|
||||
return "'" + s + "'";
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void GetParam(util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((T**) output) = const_cast<T*>(boost::any_cast<T>(&d.value));
|
||||
*((T**) output) = const_cast<T*>(ANY_CAST<T>(&d.value));
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -32,7 +32,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ std::string GetPrintableParam(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
@@ -61,7 +61,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& matrix = boost::any_cast<T>(data.value);
|
||||
const T& matrix = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix";
|
||||
@@ -78,7 +78,7 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
|
||||
oss << data.cppType << " model at " << ANY_CAST<T*>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// Get the matrix.
|
||||
const T& tuple = boost::any_cast<T>(data.value);
|
||||
const T& tuple = ANY_CAST<T>(data.value);
|
||||
const arma::mat& matrix = std::get<1>(tuple);
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -87,7 +87,7 @@ inline void SetParamWithInfo(util::Params& params,
|
||||
if (hasCategoricals)
|
||||
{
|
||||
arma::vec maxs = arma::max(
|
||||
std::get<1>(params.Get<TupleType>(identifier)), 1);
|
||||
std::get<1>(params.Get<TupleType>(identifier)), 1) + 1;
|
||||
|
||||
for (size_t i = 0; i < dimensions; ++i)
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ class PyOption
|
||||
data.cppType = cppName;
|
||||
|
||||
// Every parameter we'll get from Python will have the correct type.
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
|
||||
// Set the function pointers that we'll need. All of these function
|
||||
// pointers will be used by both the program that generates the pyx, and
|
||||
|
||||
@@ -223,7 +223,22 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
for (size_t i = 0; i < m.n_rows; ++i)
|
||||
{
|
||||
if (di.Type(i) == data::Datatype::numeric)
|
||||
{
|
||||
m.row(i) *= 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure input data is valid.
|
||||
for (size_t c = 0; c < m.n_cols; ++c)
|
||||
{
|
||||
if (ceil(m(i, c)) != m(i, c))
|
||||
throw std::invalid_argument("non-integer value in categorical!");
|
||||
else if (m(i, c) < 0)
|
||||
throw std::invalid_argument("negative value in categorical!");
|
||||
else if (size_t(m(i, c)) >= di.NumMappings(i))
|
||||
throw std::invalid_argument("value outside number of categories!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
|
||||
@@ -42,7 +42,7 @@ void DeleteAllocatedMemoryImpl(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
// Delete the allocated memory (hopefully we actually own it).
|
||||
delete *boost::any_cast<T*>(&d.value);
|
||||
delete *ANY_CAST<T*>(&d.value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -43,7 +43,7 @@ void* GetAllocatedMemory(
|
||||
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
|
||||
{
|
||||
// Here we have a model; return its memory location.
|
||||
return *boost::any_cast<T*>(&d.value);
|
||||
return *ANY_CAST<T*>(&d.value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -26,7 +26,7 @@ template<typename T>
|
||||
T& GetParam(util::ParamData& d)
|
||||
{
|
||||
// No mapping is needed, so just cast it directly.
|
||||
return *boost::any_cast<T>(&d.value);
|
||||
return *ANY_CAST<T>(&d.value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* /* junk */)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << boost::any_cast<T>(data.value);
|
||||
oss << ANY_CAST<T>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ std::string GetPrintableParam(
|
||||
util::ParamData& data,
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* /* junk */)
|
||||
{
|
||||
const T& t = boost::any_cast<T>(data.value);
|
||||
const T& t = ANY_CAST<T>(data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
|
||||
@@ -83,7 +83,7 @@ class TestOption
|
||||
data.input = input;
|
||||
data.loaded = false;
|
||||
data.cppType = cppName;
|
||||
data.value = boost::any(defaultValue);
|
||||
data.value = ANY(defaultValue);
|
||||
|
||||
const std::string tname = data.tname;
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ set(SOURCES
|
||||
detail/unchecked_bernoulli.hpp
|
||||
math_fwd.hpp
|
||||
policy.hpp
|
||||
string_view.hpp
|
||||
string_view_fwd.hpp
|
||||
boost_backport_string_view.hpp
|
||||
)
|
||||
|
||||
# add directory name to sources
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* @file core/boost_backport/boost_backport_string_view.hpp
|
||||
* @author Jeffin Sam
|
||||
*
|
||||
* Centralized control of what boost files to include. We have backported the
|
||||
* following boost functionality here:
|
||||
*
|
||||
* * string_view support (added in boost 1.61.0)
|
||||
* * hash function support (added in boost 1.69.0)
|
||||
*
|
||||
* If the detected boost version is greater or equal to 1.61.0, we include the
|
||||
* normal serialization functions (not the backported ones). For all older
|
||||
* versions we include the backported headers.
|
||||
*/
|
||||
#ifndef MLPACK_CORE_BOOST_BACKPORT_STRING_VIEW_HPP
|
||||
#define MLPACK_CORE_BOOST_BACKPORT_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#if BOOST_VERSION < 106100
|
||||
// Backported unordered_map.
|
||||
#include "mlpack/core/boost_backport/string_view.hpp"
|
||||
#else
|
||||
// Boost's version.
|
||||
#include <boost/utility/string_view.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_VERSION < 106900
|
||||
namespace boost
|
||||
{
|
||||
template<>
|
||||
struct hash<boost::string_view>
|
||||
{
|
||||
std::size_t operator()(boost::string_view str) const
|
||||
{
|
||||
return boost::hash_range(str.begin(), str.end());
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MLPACK_CORE_BOOST_BACKPORT_STRING_VIEW_HPP
|
||||
@@ -1,698 +0,0 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2015.
|
||||
Copyright (c) Beman Dawes 2015
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_HPP
|
||||
#define BOOST_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#if BOOST_VERSION < 106100
|
||||
// Backported unordered_map.
|
||||
#include "mlpack/core/boost_backport/string_view_fwd.hpp"
|
||||
#else
|
||||
// Boost's version.
|
||||
#include <boost/utility/string_view_fwd.hpp>
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iosfwd>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
|
||||
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
|
||||
#define BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// A helper functor because sometimes we don't have lambdas
|
||||
template <typename charT, typename traits>
|
||||
class string_view_traits_eq {
|
||||
public:
|
||||
string_view_traits_eq ( charT ch ) : ch_(ch) {}
|
||||
bool operator()( charT val ) const { return traits::eq (ch_, val); }
|
||||
charT ch_;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp
|
||||
class basic_string_view {
|
||||
public:
|
||||
// types
|
||||
typedef traits traits_type;
|
||||
typedef charT value_type;
|
||||
typedef charT* pointer;
|
||||
typedef const charT* const_pointer;
|
||||
typedef charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef const_pointer const_iterator; // impl-defined
|
||||
typedef const_iterator iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
|
||||
|
||||
// construct/copy
|
||||
BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
// by defaulting these functions, basic_string_ref becomes
|
||||
// trivially copy/move constructible.
|
||||
BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
#endif
|
||||
|
||||
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
|
||||
= default;
|
||||
#else
|
||||
{
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
|
||||
// // Constructing a string_view from a temporary string is a bad idea
|
||||
// template<typename Allocator>
|
||||
// basic_string_view( std::basic_string<charT, traits, Allocator>&&)
|
||||
// = delete;
|
||||
// #endif
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str)
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
// iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
||||
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; }
|
||||
|
||||
BOOST_CONSTEXPR const_reference at(size_t pos) const {
|
||||
return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
|
||||
BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; }
|
||||
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; }
|
||||
|
||||
// modifiers
|
||||
void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
ptr_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT {
|
||||
std::swap(ptr_, s.ptr_);
|
||||
std::swap(len_, s.len_);
|
||||
}
|
||||
|
||||
// basic_string_view string operations
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
template<typename Allocator>
|
||||
explicit operator std::basic_string<charT, traits, Allocator>() const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
|
||||
template<typename Allocator = std::allocator<charT> >
|
||||
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a = Allocator()) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#else
|
||||
std::basic_string<charT, traits> to_string() const {
|
||||
return std::basic_string<charT, traits>(begin(), end());
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type copy(charT* s, size_type n, size_type pos=0) const {
|
||||
if (pos > size())
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
|
||||
size_type rlen = (std::min)(n, len_ - pos);
|
||||
traits_type::copy(s, data() + pos, rlen);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
|
||||
return basic_string_view(data() + pos, (std::min)(size() - pos, n));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
|
||||
const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_));
|
||||
return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x)
|
||||
const BOOST_NOEXCEPT {
|
||||
return substr(pos1, n1).compare(x);
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
basic_string_view x, size_type pos2, size_type n2) const {
|
||||
return substr(pos1, n1).compare(x.substr(pos2, n2));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(const charT* x) const {
|
||||
return compare(basic_string_view(x));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x));
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
const charT* x, size_type n2) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x, n2));
|
||||
}
|
||||
|
||||
// Searches
|
||||
BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension
|
||||
return !empty() && traits::eq(c, front());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
|
||||
return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension
|
||||
return !empty() && traits::eq(c, back());
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
|
||||
return len_ >= x.len_ &&
|
||||
traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0;
|
||||
}
|
||||
|
||||
// find
|
||||
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos > size())
|
||||
return npos;
|
||||
if (s.empty())
|
||||
return pos;
|
||||
const_iterator iter = std::search(this->cbegin() + pos, this->cend(),
|
||||
s.cbegin (), s.cend (), traits::eq);
|
||||
return iter == this->cend () ? npos : std::distance(this->cbegin (), iter);
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(s), pos); }
|
||||
|
||||
// rfind
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (len_ < s.len_)
|
||||
return npos;
|
||||
if (pos > len_ - s.len_)
|
||||
pos = len_ - s.len_;
|
||||
if (s.len_ == 0u) // an empty string is always found
|
||||
return pos;
|
||||
for (const charT* cur = ptr_ + pos; ; --cur) {
|
||||
if (traits::compare(cur, s.ptr_, s.len_) == 0)
|
||||
return cur - ptr_;
|
||||
if (cur == ptr_)
|
||||
return npos;
|
||||
};
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_ || s.len_ == 0)
|
||||
return npos;
|
||||
const_iterator iter = std::find_first_of
|
||||
(this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (s.len_ == 0u)
|
||||
return npos;
|
||||
if (pos >= len_)
|
||||
pos = 0;
|
||||
else
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
return npos;
|
||||
if (s.len_ == 0)
|
||||
return pos;
|
||||
const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
pos = len_ - 1;
|
||||
if (s.len_ == 0u)
|
||||
return pos;
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(s), pos); }
|
||||
|
||||
private:
|
||||
template <typename r_iter>
|
||||
size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT {
|
||||
// Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw.
|
||||
return len_ - 1 - std::distance ( first, last );
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT {
|
||||
for (; first != last ; ++first)
|
||||
if ( 0 == traits::find(s.ptr_, s.len_, *first))
|
||||
return first;
|
||||
return last;
|
||||
}
|
||||
|
||||
const charT *ptr_;
|
||||
std::size_t len_;
|
||||
};
|
||||
|
||||
|
||||
// Comparison operators
|
||||
// Equality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if (x.size () != y.size ()) return false;
|
||||
return x.compare(y) == 0;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if ( x.size () != y.size ()) return true;
|
||||
return x.compare(y) != 0;
|
||||
}
|
||||
|
||||
// Less than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) < 0;
|
||||
}
|
||||
|
||||
// Greater than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) > 0;
|
||||
}
|
||||
|
||||
// Less than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) <= 0;
|
||||
}
|
||||
|
||||
// Greater than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) >= 0;
|
||||
}
|
||||
|
||||
// "sufficient additional overloads of comparison functions"
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class charT, class traits>
|
||||
inline void sv_insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
|
||||
enum { chunk_size = 8 };
|
||||
charT fill_chars[chunk_size];
|
||||
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
|
||||
for (; n >= chunk_size && os.good(); n -= chunk_size)
|
||||
os.write(fill_chars, static_cast< std::size_t >(chunk_size));
|
||||
if (n > 0 && os.good())
|
||||
os.write(fill_chars, n);
|
||||
}
|
||||
|
||||
template<class charT, class traits>
|
||||
void sv_insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_view<charT,traits>& str) {
|
||||
const std::size_t size = str.size();
|
||||
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
|
||||
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
|
||||
if (!align_left) {
|
||||
detail::sv_insert_fill_chars(os, alignment_size);
|
||||
if (os.good())
|
||||
os.write(str.data(), size);
|
||||
}
|
||||
else {
|
||||
os.write(str.data(), size);
|
||||
if (os.good())
|
||||
detail::sv_insert_fill_chars(os, alignment_size);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Inserter
|
||||
template<class charT, class traits>
|
||||
inline std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os,
|
||||
const basic_string_view<charT,traits>& str) {
|
||||
if (os.good()) {
|
||||
const std::size_t size = str.size();
|
||||
const std::size_t w = static_cast< std::size_t >(os.width());
|
||||
if (w <= size)
|
||||
os.write(str.data(), size);
|
||||
else
|
||||
detail::sv_insert_aligned(os, str);
|
||||
os.width(0);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// numeric conversions
|
||||
//
|
||||
// These are short-term implementations.
|
||||
// In a production environment, I would rather avoid the copying.
|
||||
//
|
||||
inline int stoi (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (string_view str, size_t* idx=0) {
|
||||
return std::stof ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (string_view str, size_t* idx=0) {
|
||||
return std::stod ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (string_view str, size_t* idx=0) {
|
||||
return std::stold ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (wstring_view str, size_t* idx=0) {
|
||||
return std::stof ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (wstring_view str, size_t* idx=0) {
|
||||
return std::stod ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (wstring_view str, size_t* idx=0) {
|
||||
return std::stold ( std::wstring(str), idx );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace std {
|
||||
// Hashing
|
||||
template<> struct hash<boost::string_view>;
|
||||
template<> struct hash<boost::u16string_view>;
|
||||
template<> struct hash<boost::u32string_view>;
|
||||
template<> struct hash<boost::wstring_view>;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2012-2012.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
|
||||
Based on the StringRef implementation in LLVM (http://llvm.org) and
|
||||
N3422 by Jeffrey Yasskin
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_FWD_HPP
|
||||
#define BOOST_STRING_VIEW_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
|
||||
typedef basic_string_view<char, std::char_traits<char> > string_view;
|
||||
typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,7 +14,6 @@
|
||||
#define MLPACK_CORE_DATA_STRING_ENCODING_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <mlpack/core/boost_backport/boost_backport_string_view.hpp>
|
||||
#include <mlpack/core/data/string_encoding_dictionary.hpp>
|
||||
#include <mlpack/core/data/string_encoding_policies/policy_traits.hpp>
|
||||
#include <vector>
|
||||
@@ -75,7 +74,7 @@ class StringEncoding
|
||||
* @param tokenizer The tokenizer object.
|
||||
*
|
||||
* The tokenization algorithm has to be an object with two public methods:
|
||||
* 1. operator() which accepts a reference to boost::string_view, extracts
|
||||
* 1. operator() which accepts a reference to STRING_VIEW, extracts
|
||||
* the next token from the given view, removes the prefix containing
|
||||
* the extracted token and returns the token;
|
||||
* 2. IsTokenEmpty() that accepts a token and returns true if the given
|
||||
@@ -109,7 +108,7 @@ class StringEncoding
|
||||
* @param tokenizer The tokenizer object.
|
||||
*
|
||||
* The tokenization algorithm has to be an object with two public methods:
|
||||
* 1. operator() which accepts a reference to boost::string_view, extracts
|
||||
* 1. operator() which accepts a reference to STRING_VIEW, extracts
|
||||
* the next token from the given view, removes the prefix containing
|
||||
* the extracted token and returns the token;
|
||||
* 2. IsTokenEmpty() that accepts a token and returns true if the given
|
||||
@@ -159,7 +158,7 @@ class StringEncoding
|
||||
* @param policy The policy object.
|
||||
*
|
||||
* The tokenization algorithm has to be an object with two public methods:
|
||||
* 1. operator() which accepts a reference to boost::string_view, extracts
|
||||
* 1. operator() which accepts a reference to STRING_VIEW, extracts
|
||||
* the next token from the given view, removes the prefix containing
|
||||
* the extracted token and returns the token;
|
||||
* 2. IsTokenEmpty() that accepts a token and returns true if the given
|
||||
@@ -188,7 +187,7 @@ class StringEncoding
|
||||
* @param policy The policy object.
|
||||
*
|
||||
* The tokenization algorithm has to be an object with two public methods:
|
||||
* 1. operator() which accepts a reference to boost::string_view, extracts
|
||||
* 1. operator() which accepts a reference to STRING_VIEW, extracts
|
||||
* the next token from the given view, removes the prefix containing
|
||||
* the extracted token and returns the token;
|
||||
* 2. IsTokenEmpty() that accepts a token and returns true if the given
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
#define MLPACK_CORE_DATA_STRING_ENCODING_DICTIONARY_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <mlpack/core/boost_backport/boost_backport_string_view.hpp>
|
||||
#include <unordered_map>
|
||||
#include <deque>
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
@@ -105,20 +106,20 @@ class StringEncodingDictionary
|
||||
};
|
||||
|
||||
/*
|
||||
* Specialization of the StringEncodingDictionary class for boost::string_view.
|
||||
* Specialization of the StringEncodingDictionary class for STRING_VIEW.
|
||||
*/
|
||||
template<>
|
||||
class StringEncodingDictionary<boost::string_view>
|
||||
class StringEncodingDictionary<STRING_VIEW>
|
||||
{
|
||||
public:
|
||||
//! A convenient alias for the internal type of the map.
|
||||
using MapType = std::unordered_map<
|
||||
boost::string_view,
|
||||
STRING_VIEW,
|
||||
size_t,
|
||||
boost::hash<boost::string_view>>;
|
||||
std::hash<STRING_VIEW>>;
|
||||
|
||||
//! The type of the token that the dictionary stores.
|
||||
using TokenType = boost::string_view;
|
||||
using TokenType = STRING_VIEW;
|
||||
|
||||
//! Construct the default class.
|
||||
StringEncodingDictionary() = default;
|
||||
@@ -155,7 +156,7 @@ class StringEncodingDictionary<boost::string_view>
|
||||
*
|
||||
* @param token The given token.
|
||||
*/
|
||||
bool HasToken(const boost::string_view token) const
|
||||
bool HasToken(const STRING_VIEW token) const
|
||||
{
|
||||
return mapping.find(token) != mapping.end();
|
||||
}
|
||||
@@ -167,7 +168,7 @@ class StringEncodingDictionary<boost::string_view>
|
||||
*
|
||||
* @param token The given token.
|
||||
*/
|
||||
size_t AddToken(const boost::string_view token)
|
||||
size_t AddToken(const STRING_VIEW token)
|
||||
{
|
||||
tokens.emplace_back(token);
|
||||
|
||||
@@ -184,7 +185,7 @@ class StringEncodingDictionary<boost::string_view>
|
||||
*
|
||||
* @param token The given token.
|
||||
*/
|
||||
size_t Value(const boost::string_view token) const
|
||||
size_t Value(const STRING_VIEW token) const
|
||||
{
|
||||
return mapping.at(token);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ void StringEncoding<EncodingPolicyType, DictionaryType>::CreateMap(
|
||||
const std::string& input,
|
||||
const TokenizerType& tokenizer)
|
||||
{
|
||||
boost::string_view strView(input);
|
||||
STRING_VIEW strView(input);
|
||||
auto token = tokenizer(strView);
|
||||
|
||||
static_assert(
|
||||
@@ -112,7 +112,7 @@ EncodeHelper(const std::vector<std::string>& input,
|
||||
// The first pass adds the extracted tokens to the dictionary.
|
||||
for (size_t i = 0; i < input.size(); ++i)
|
||||
{
|
||||
boost::string_view strView(input[i]);
|
||||
STRING_VIEW strView(input[i]);
|
||||
auto token = tokenizer(strView);
|
||||
|
||||
static_assert(
|
||||
@@ -143,7 +143,7 @@ EncodeHelper(const std::vector<std::string>& input,
|
||||
// The second pass writes the encoded values to the output.
|
||||
for (size_t i = 0; i < input.size(); ++i)
|
||||
{
|
||||
boost::string_view strView(input[i]);
|
||||
STRING_VIEW strView(input[i]);
|
||||
auto token = tokenizer(strView);
|
||||
size_t numTokens = 0;
|
||||
|
||||
@@ -172,7 +172,7 @@ EncodeHelper(const std::vector<std::string>& input,
|
||||
// at once.
|
||||
for (size_t i = 0; i < input.size(); ++i)
|
||||
{
|
||||
boost::string_view strView(input[i]);
|
||||
STRING_VIEW strView(input[i]);
|
||||
auto token = tokenizer(strView);
|
||||
|
||||
static_assert(
|
||||
|
||||
@@ -36,7 +36,7 @@ class CharExtract
|
||||
*
|
||||
* @param str String view to retrieve the next token from.
|
||||
*/
|
||||
int operator()(boost::string_view& str) const
|
||||
int operator()(STRING_VIEW& str) const
|
||||
{
|
||||
if (str.empty())
|
||||
return EOF;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#define MLPACK_CORE_DATA_TOKENIZERS_SPLIT_BY_ANY_OF_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <mlpack/core/boost_backport/boost_backport_string_view.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace mlpack {
|
||||
@@ -27,7 +27,7 @@ class SplitByAnyOf
|
||||
{
|
||||
public:
|
||||
//! The type of the token which the tokenizer extracts.
|
||||
using TokenType = boost::string_view;
|
||||
using TokenType = STRING_VIEW;
|
||||
|
||||
//! A convenient alias for the mask type.
|
||||
using MaskType = std::array<bool, 1 << CHAR_BIT>;
|
||||
@@ -37,7 +37,7 @@ class SplitByAnyOf
|
||||
*
|
||||
* @param delimiters The given delimiters.
|
||||
*/
|
||||
SplitByAnyOf(const boost::string_view delimiters)
|
||||
SplitByAnyOf(const STRING_VIEW delimiters)
|
||||
{
|
||||
mask.fill(false);
|
||||
|
||||
@@ -51,9 +51,13 @@ class SplitByAnyOf
|
||||
*
|
||||
* @param str String view to retrieve the token from.
|
||||
*/
|
||||
boost::string_view operator()(boost::string_view& str) const
|
||||
STRING_VIEW operator()(STRING_VIEW& str) const
|
||||
{
|
||||
boost::string_view retval;
|
||||
STRING_VIEW retval;
|
||||
// std::basic_string_view does not have empty function.
|
||||
// Therefore, we are assiging an empty string when reaching the last
|
||||
// delimiter.
|
||||
STRING_VIEW empty_string{""};
|
||||
|
||||
while (retval.empty())
|
||||
{
|
||||
@@ -61,7 +65,7 @@ class SplitByAnyOf
|
||||
if (pos == str.npos)
|
||||
{
|
||||
retval = str;
|
||||
str.clear();
|
||||
str.swap(empty_string);
|
||||
return retval;
|
||||
}
|
||||
retval = str.substr(0, pos);
|
||||
@@ -75,7 +79,7 @@ class SplitByAnyOf
|
||||
*
|
||||
* @param token The given token.
|
||||
*/
|
||||
static bool IsTokenEmpty(const boost::string_view token)
|
||||
static bool IsTokenEmpty(const STRING_VIEW token)
|
||||
{
|
||||
return token.empty();
|
||||
}
|
||||
@@ -89,11 +93,11 @@ class SplitByAnyOf
|
||||
/**
|
||||
* The function finds the first character in the given string view equal to
|
||||
* any of the delimiters and returns the position of the character or
|
||||
* boost::string_view::npos if no such character is found.
|
||||
* STRING_VIEW::npos if no such character is found.
|
||||
*
|
||||
* @param str String where to find the character.
|
||||
*/
|
||||
size_t FindFirstDelimiter(const boost::string_view str) const
|
||||
size_t FindFirstDelimiter(const STRING_VIEW str) const
|
||||
{
|
||||
for (size_t pos = 0; pos < str.size(); pos++)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Copyright © 2013 - 2015 MNMLSTC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this software except in compliance with the License. You may
|
||||
obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
The files in this directory are taken from MNMLSTC Core 1.1.0 in order to
|
||||
backport features from C++ 17 standard library:
|
||||
|
||||
* C++17 STL algorithms such as std::any and std::basic_string_view.
|
||||
* Dependencies files that are used to implement these features.
|
||||
|
||||
These files are licensed under the Apache 2.0 License, available in LICENSE.txt
|
||||
in this directory.
|
||||
|
||||
If you want a copy of mlpack without a dependence on the Apache License or
|
||||
without the backported version then you will need to
|
||||
|
||||
* Remove this entire directory.
|
||||
* Remove the line "std_backport" from src/mlpack/core/CMakeLists.txt.
|
||||
* Use the C++17 standard by modifying the mlpack/CMakeLists.txt.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,337 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_ANY_HPP
|
||||
#define CORE_ANY_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "type_traits.hpp"
|
||||
#include "algorithm.hpp"
|
||||
#include "typeinfo.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#ifndef CORE_NO_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
#endif /* CORE_NO_EXCEPTIONS */
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace impl {
|
||||
|
||||
using data_type = add_pointer_t<void>;
|
||||
|
||||
template <class T>
|
||||
struct is_small final : meta::all_t<
|
||||
sizeof(decay_t<T>) <= sizeof(data_type),
|
||||
alignof(decay_t<T>) <= alignof(data_type),
|
||||
::std::is_nothrow_copy_constructible<decay_t<T>>::value
|
||||
> { };
|
||||
template <> struct is_small<void> final : ::std::true_type { };
|
||||
|
||||
template <class T=void, bool=is_small<T>::value> struct dispatch;
|
||||
template <> struct dispatch<void, true> {
|
||||
dispatch () noexcept = default;
|
||||
virtual ~dispatch () noexcept = default;
|
||||
|
||||
virtual void clone (data_type const&, data_type&) const { }
|
||||
virtual void move (data_type&, data_type&) const noexcept { }
|
||||
virtual void destroy (data_type&) const noexcept { }
|
||||
virtual type_info const& type () const noexcept { return type_of<void>(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct dispatch<T, true> final : dispatch<> {
|
||||
using value_type = T;
|
||||
using const_pointer = add_pointer_t<add_const_t<value_type>>;
|
||||
using pointer = add_pointer_t<value_type>;
|
||||
using allocator_type = ::std::allocator<value_type>;
|
||||
using allocator_traits = ::std::allocator_traits<allocator_type>;
|
||||
|
||||
virtual void clone (data_type const& src, data_type& dst) const final {
|
||||
allocator_type alloc { };
|
||||
auto val = reinterpret_cast<add_const_t<const_pointer>>(&src);
|
||||
auto ptr = reinterpret_cast<pointer>(&dst);
|
||||
allocator_traits::construct(alloc, ptr, *val);
|
||||
}
|
||||
|
||||
virtual void move (data_type& src, data_type& dst) const noexcept final {
|
||||
allocator_type alloc { };
|
||||
auto val = reinterpret_cast<pointer>(&src);
|
||||
auto ptr = reinterpret_cast<pointer>(&dst);
|
||||
allocator_traits::construct(alloc, ptr, ::core::move(*val));
|
||||
}
|
||||
|
||||
virtual void destroy (data_type& src) const noexcept final {
|
||||
allocator_type alloc { };
|
||||
auto ptr = reinterpret_cast<pointer>(&src);
|
||||
allocator_traits::destroy(alloc, ptr);
|
||||
}
|
||||
|
||||
virtual type_info const& type () const noexcept final {
|
||||
return type_of<value_type>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct dispatch<T, false> final : dispatch<> {
|
||||
using value_type = T;
|
||||
using pointer = add_pointer_t<value_type>;
|
||||
using allocator_type = ::std::allocator<value_type>;
|
||||
using allocator_traits = ::std::allocator_traits<allocator_type>;
|
||||
|
||||
virtual void clone (data_type const& src, data_type& dst) const final {
|
||||
allocator_type alloc { };
|
||||
auto const& value = *static_cast<add_const_t<pointer>>(src);
|
||||
auto ptr = allocator_traits::allocate(alloc, 1);
|
||||
auto scope = make_scope_guard([&alloc, ptr] {
|
||||
allocator_traits::deallocate(alloc, ptr, 1);
|
||||
});
|
||||
allocator_traits::construct(alloc, ptr, value);
|
||||
scope.dismiss();
|
||||
dst = ptr;
|
||||
}
|
||||
|
||||
virtual void move (data_type& src, data_type& dst) const noexcept final {
|
||||
allocator_type alloc { };
|
||||
auto& value = *static_cast<pointer>(src);
|
||||
auto ptr = allocator_traits::allocate(alloc, 1);
|
||||
auto scope = make_scope_guard([&alloc, ptr] {
|
||||
allocator_traits::deallocate(alloc, ptr, 1);
|
||||
});
|
||||
allocator_traits::construct(alloc, ptr, ::core::move(value));
|
||||
scope.dismiss();
|
||||
dst = ptr;
|
||||
}
|
||||
|
||||
virtual void destroy (data_type& src) const noexcept final {
|
||||
allocator_type alloc { };
|
||||
auto ptr = static_cast<pointer>(src);
|
||||
allocator_traits::destroy(alloc, ptr);
|
||||
allocator_traits::deallocate(alloc, ptr, 1);
|
||||
}
|
||||
|
||||
virtual type_info const& type () const noexcept final {
|
||||
return type_of<value_type>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> dispatch<> const* lookup () noexcept {
|
||||
static dispatch<T> instance;
|
||||
return ::std::addressof(instance);
|
||||
}
|
||||
|
||||
template <> inline dispatch<> const* lookup<void> () noexcept {
|
||||
static dispatch<> instance;
|
||||
return ::std::addressof(instance);
|
||||
}
|
||||
|
||||
} /* namespace impl */
|
||||
|
||||
#ifndef CORE_NO_EXCEPTIONS
|
||||
class bad_any_cast final : public ::std::bad_cast {
|
||||
public:
|
||||
virtual char const* what () const noexcept override {
|
||||
return "bad any cast";
|
||||
}
|
||||
};
|
||||
|
||||
[[noreturn]] inline void throw_bad_any_cast () { throw bad_any_cast { }; }
|
||||
#else /* CORE_NO_EXCEPTIONS */
|
||||
[[noreturn]] inline void throw_bad_any_cast () { ::std::abort(); }
|
||||
#endif /* CORE_NO_EXCEPTIONS */
|
||||
|
||||
struct any final {
|
||||
|
||||
template <class T> friend T const* any_cast (any const*) noexcept;
|
||||
template <class T> friend T* any_cast (any*) noexcept;
|
||||
|
||||
any (any const& that) :
|
||||
table { that.table },
|
||||
data { nullptr }
|
||||
{ this->table->clone(that.data, this->data); }
|
||||
|
||||
any (any&& that) noexcept :
|
||||
table { that.table },
|
||||
data { nullptr }
|
||||
{ this->table->move(that.data, this->data); }
|
||||
|
||||
any () noexcept :
|
||||
table { impl::lookup<void>() },
|
||||
data { nullptr }
|
||||
{ }
|
||||
|
||||
template <
|
||||
class T,
|
||||
class=enable_if_t<not ::std::is_same<any, decay_t<T>>::value>
|
||||
> any (T&& value) :
|
||||
any { ::std::forward<T>(value), impl::is_small<T> { } }
|
||||
{ }
|
||||
|
||||
~any () noexcept { this->clear(); }
|
||||
|
||||
any& operator = (any const& that) {
|
||||
any { that }.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
any& operator = (any&& that) noexcept {
|
||||
any { ::std::move(that) }.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <
|
||||
class T,
|
||||
class=enable_if_t<not ::std::is_same<any, decay_t<T>>::value>
|
||||
> any& operator = (T&& value) {
|
||||
any {
|
||||
::std::forward<T>(value),
|
||||
impl::is_small<T> { }
|
||||
}.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap (any& that) noexcept {
|
||||
using ::std::swap;
|
||||
swap(this->table, that.table);
|
||||
swap(this->data, that.data);
|
||||
}
|
||||
|
||||
void clear () noexcept {
|
||||
this->table->destroy(this->data);
|
||||
this->table = impl::lookup<void>();
|
||||
}
|
||||
|
||||
type_info const& type () const noexcept { return this->table->type(); }
|
||||
|
||||
bool empty () const noexcept { return this->table == impl::lookup<void>(); }
|
||||
|
||||
private:
|
||||
impl::dispatch<> const* table;
|
||||
impl::data_type data;
|
||||
|
||||
template <class T>
|
||||
any (T&& value, ::std::true_type&&) :
|
||||
table { impl::lookup<decay_t<T>>() },
|
||||
data { nullptr }
|
||||
{
|
||||
using value_type = decay_t<T>;
|
||||
using allocator_type = ::std::allocator<value_type>;
|
||||
using allocator_traits = ::std::allocator_traits<allocator_type>;
|
||||
allocator_type alloc { };
|
||||
auto pointer = reinterpret_cast<value_type*>(::std::addressof(this->data));
|
||||
allocator_traits::construct(alloc, pointer, ::core::forward<T>(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
any (T&& value, ::std::false_type&&) :
|
||||
table { impl::lookup<decay_t<T>>() },
|
||||
data { nullptr }
|
||||
{
|
||||
using value_type = decay_t<T>;
|
||||
using allocator_type = ::std::allocator<value_type>;
|
||||
using allocator_traits = ::std::allocator_traits<allocator_type>;
|
||||
allocator_type alloc { };
|
||||
auto pointer = allocator_traits::allocate(alloc, 1);
|
||||
allocator_traits::construct(alloc, pointer, ::core::forward<T>(value));
|
||||
this->data = pointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T const* cast (::std::true_type&&) const {
|
||||
return reinterpret_cast<T const*>(::std::addressof(this->data));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* cast (::std::true_type&&) {
|
||||
return reinterpret_cast<T*>(::std::addressof(this->data));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T const* cast (::std::false_type&&) const {
|
||||
return static_cast<T const*>(this->data);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* cast (::std::false_type&&) {
|
||||
return static_cast<T*>(this->data);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T const* any_cast (any const* operand) noexcept {
|
||||
return operand and operand->type() == type_of<T>()
|
||||
? operand->cast<T>(impl::is_small<T> { })
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* any_cast (any* operand) noexcept {
|
||||
return operand and operand->type() == type_of<T>()
|
||||
? operand->cast<T>(impl::is_small<T> { })
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template <
|
||||
class T,
|
||||
class=meta::when<
|
||||
meta::any<
|
||||
::std::is_reference<T>::value,
|
||||
::std::is_copy_constructible<T>::value
|
||||
>()
|
||||
>
|
||||
> T any_cast (any const& operand) {
|
||||
using type = remove_reference_t<T>;
|
||||
auto pointer = any_cast<add_const_t<type>>(::std::addressof(operand));
|
||||
if (not pointer) { throw_bad_any_cast(); }
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
template <
|
||||
class T,
|
||||
class=meta::when<
|
||||
meta::any<
|
||||
::std::is_reference<T>::value,
|
||||
::std::is_copy_constructible<T>::value
|
||||
>()
|
||||
>
|
||||
> T any_cast (any&& operand) {
|
||||
using type = remove_reference_t<T>;
|
||||
auto pointer = any_cast<type>(::std::addressof(operand));
|
||||
if (not pointer) { throw_bad_any_cast(); }
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
template <
|
||||
class T,
|
||||
class=meta::when<
|
||||
meta::any<
|
||||
::std::is_reference<T>::value,
|
||||
::std::is_copy_constructible<T>::value
|
||||
>()
|
||||
>
|
||||
> T any_cast (any& operand) {
|
||||
using type = remove_reference_t<T>;
|
||||
auto pointer = any_cast<type>(::std::addressof(operand));
|
||||
if (not pointer) { throw_bad_any_cast(); }
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
inline void swap (any& lhs, any& rhs) noexcept { lhs.swap(rhs); }
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_ANY_HPP */
|
||||
@@ -0,0 +1,435 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_FUNCTIONAL_HPP
|
||||
#define CORE_FUNCTIONAL_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
|
||||
#include "type_traits.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
|
||||
template <class T> using is_reference_wrapper = meta::is_specialization_of<
|
||||
remove_cv_t<T>,
|
||||
::std::reference_wrapper
|
||||
>;
|
||||
|
||||
template <class F> struct function_traits;
|
||||
|
||||
template <class R, class... Args>
|
||||
struct function_traits<R(*)(Args...)> : function_traits<R(Args...)> { };
|
||||
|
||||
template <class C, class R>
|
||||
struct function_traits<R(C::*)> : function_traits<R(C&)> { };
|
||||
|
||||
template <class C, class R, class... Args>
|
||||
struct function_traits<R(C::*)(Args...)> : function_traits<R(C&, Args...)> { };
|
||||
|
||||
template <class C, class R, class... Args>
|
||||
struct function_traits<R(C::*)(Args...) const volatile> :
|
||||
function_traits<R(C volatile const&, Args...)>
|
||||
{ };
|
||||
|
||||
template <class C, class R, class... Args>
|
||||
struct function_traits<R(C::*)(Args...) volatile> :
|
||||
function_traits<R(C volatile&, Args...)>
|
||||
{ };
|
||||
|
||||
template <class C, class R, class... Args>
|
||||
struct function_traits<R(C::*)(Args...) const> :
|
||||
function_traits<R(C const&, Args...)>
|
||||
{ };
|
||||
|
||||
template <class R, class... Args>
|
||||
struct function_traits<R(Args...)> {
|
||||
using typelist = meta::list<Args...>;
|
||||
using return_type = R;
|
||||
|
||||
using pointer = add_pointer_t<return_type(Args...)>;
|
||||
static constexpr auto arity = typelist::size();
|
||||
|
||||
template <::std::size_t N> using argument = meta::get<typelist, N>;
|
||||
};
|
||||
|
||||
template <class F> struct function_traits {
|
||||
using functor_type = function_traits<decltype(&decay_t<F>::operator())>;
|
||||
using return_type = typename functor_type::return_type;
|
||||
using pointer = typename functor_type::pointer;
|
||||
static constexpr auto arity = functor_type::arity - 1;
|
||||
template <::std::size_t N>
|
||||
using argument = typename functor_type::template argument<N>;
|
||||
};
|
||||
|
||||
/* N3727 */
|
||||
template <class Functor, class... Args>
|
||||
auto invoke (Functor&& f, Args&&... args) -> enable_if_t<
|
||||
::std::is_member_pointer<decay_t<Functor>>::value,
|
||||
result_of_t<Functor&&(Args&&...)>
|
||||
> { return ::std::mem_fn(f)(core::forward<Args>(args)...); }
|
||||
|
||||
template <class Functor, class... Args>
|
||||
auto invoke (Functor&& f, Args&&... args) -> enable_if_t<
|
||||
not ::std::is_member_pointer<decay_t<Functor>>::value,
|
||||
result_of_t<Functor&&(Args&&...)>
|
||||
> { return core::forward<Functor>(f)(core::forward<Args>(args)...); }
|
||||
|
||||
template <class F, class T, ::std::size_t... I>
|
||||
auto apply (F&& f, T&& t, index_sequence<I...>) -> decltype(
|
||||
invoke(core::forward<F>(f), ::std::get<I>(core::forward<T>(t))...)
|
||||
) { return invoke(core::forward<F>(f), ::std::get<I>(core::forward<T>(t))...); }
|
||||
|
||||
template <
|
||||
class Functor,
|
||||
class T,
|
||||
class I = make_index_sequence<::std::tuple_size<decay_t<T>>::value>
|
||||
> auto apply (Functor&& f, T&& t) -> decltype(
|
||||
apply(core::forward<Functor>(f), core::forward<T>(t), I { })
|
||||
) { return apply(core::forward<Functor>(f), core::forward<T>(t), I { }); }
|
||||
|
||||
template <class F>
|
||||
struct apply_functor {
|
||||
template <class G>
|
||||
explicit apply_functor (G&& g) : f(core::forward<G>(g)) { }
|
||||
|
||||
template <class Applicable>
|
||||
auto operator () (Applicable&& args) -> decltype(
|
||||
core::apply(core::forward<F>(this->f), core::forward<Applicable>(args))
|
||||
) { return apply(core::forward<F>(f), core::forward<Applicable>(args)); }
|
||||
private:
|
||||
F f;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
auto make_apply (F&& f) -> apply_functor<F> {
|
||||
return apply_functor<F> { core::forward<F>(f) };
|
||||
}
|
||||
|
||||
template <class F>
|
||||
struct not_fn_functor {
|
||||
template <class G>
|
||||
explicit not_fn_functor (G&& g) : f(core::forward<G>(g)) { }
|
||||
|
||||
template <class... Args>
|
||||
auto operator () (Args&&... args) const -> decltype(
|
||||
not (invoke)(::std::declval<F>(), core::forward<Args>(args)...)
|
||||
) { return not (invoke)(f, core::forward<Args>(args)...); }
|
||||
|
||||
template <class... Args>
|
||||
auto operator () (Args&&... args) -> decltype(
|
||||
not (invoke)(::std::declval<F>(), core::forward<Args>(args)...)
|
||||
) { return not (invoke)(f, core::forward<Args>(args)...); }
|
||||
|
||||
private:
|
||||
F f;
|
||||
};
|
||||
|
||||
/* Were this C++14, we could just use a lambda with a capture. Oh Well! */
|
||||
template <class F>
|
||||
not_fn_functor<decay_t<F>> not_fn (F&& f) {
|
||||
return not_fn_functor<decay_t<F>> { core::forward<F>(f) };
|
||||
}
|
||||
|
||||
/* converter function object */
|
||||
template <class T>
|
||||
struct converter {
|
||||
template <class... Args>
|
||||
constexpr T operator () (Args&&... args) const {
|
||||
return T(core::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/* function objects -- arithmetic */
|
||||
template <class T=void>
|
||||
struct plus {
|
||||
constexpr T operator () (T const& l, T const& r) const { return l + r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct minus {
|
||||
constexpr T operator () (T const& l, T const& r) const { return l - r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct multiplies {
|
||||
constexpr T operator () (T const& l, T const& r) const { return l * r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct divides {
|
||||
constexpr T operator () (T const& l, T const& r) const { return l / r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct modulus {
|
||||
constexpr T operator () (T const& l, T const& r) const { return l % r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct negate {
|
||||
constexpr T operator () (T const& arg) const { return -arg; }
|
||||
};
|
||||
|
||||
/* function objects -- comparisons */
|
||||
template <class T=void>
|
||||
struct equal_to {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l == r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct not_equal_to {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l != r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct greater_equal {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l >= r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct less_equal {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l <= r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct greater {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l > r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct less {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l < r; }
|
||||
};
|
||||
|
||||
/* function objects -- logical */
|
||||
template <class T=void>
|
||||
struct logical_and {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l and r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct logical_or {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l or r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct logical_not {
|
||||
constexpr bool operator () (T const& arg) const { return not arg; }
|
||||
};
|
||||
|
||||
/* function objects -- bitwise */
|
||||
|
||||
template <class T=void>
|
||||
struct bit_and {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l & r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct bit_or {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l | r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct bit_xor {
|
||||
constexpr bool operator () (T const& l, T const& r) const { return l ^ r; }
|
||||
};
|
||||
|
||||
template <class T=void>
|
||||
struct bit_not {
|
||||
constexpr bool operator () (T const& arg) const { return ~arg; }
|
||||
};
|
||||
|
||||
/* function objects -- arithmetic specializations */
|
||||
template <> struct plus<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) + core::forward<U>(u)
|
||||
) { return core::forward<T>(t) + core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct minus<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) - core::forward<U>(u)
|
||||
) { return core::forward<T>(t) - core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct multiplies<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) * core::forward<U>(u)
|
||||
) { return core::forward<T>(t) * core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct divides<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) / core::forward<U>(u)
|
||||
) { return core::forward<T>(t) / core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct modulus<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) % core::forward<U>(u)
|
||||
) { return core::forward<T>(t) % core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct negate<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T>
|
||||
constexpr auto operator () (T&& t) const -> decltype(core::forward<T>(t)) {
|
||||
return core::forward<T>(t);
|
||||
}
|
||||
};
|
||||
|
||||
/* function objects -- comparison specialization */
|
||||
template <> struct equal_to<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) == core::forward<U>(u)
|
||||
) { return core::forward<T>(t) == core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct not_equal_to<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) != core::forward<U>(u)
|
||||
) { return core::forward<T>(t) != core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct greater_equal<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) >= core::forward<U>(u)
|
||||
) { return core::forward<T>(t) >= core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct less_equal<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) <= core::forward<U>(u)
|
||||
) { return core::forward<T>(t) <= core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct greater<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) > core::forward<U>(u)
|
||||
) { return core::forward<T>(t) > core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct less<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) < core::forward<U>(u)
|
||||
) { return core::forward<T>(t) < core::forward<U>(u); }
|
||||
};
|
||||
|
||||
/* function objects -- logical specializations */
|
||||
template <> struct logical_and<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) and core::forward<U>(u)
|
||||
) { return core::forward<T>(t) and core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct logical_or<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) or core::forward<U>(u)
|
||||
) { return core::forward<T>(t) or core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct logical_not<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T>
|
||||
constexpr auto operator () (T&& t) const -> decltype(
|
||||
not core::forward<T>(t)
|
||||
) { return not core::forward<T>(t); }
|
||||
};
|
||||
|
||||
/* function objects -- bitwise specializations */
|
||||
template <> struct bit_and<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) & core::forward<U>(u)
|
||||
) { return core::forward<T>(t) & core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct bit_or<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) | core::forward<U>(u)
|
||||
) { return core::forward<T>(t) | core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct bit_xor<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr auto operator () (T&& t, U&& u) const -> decltype(
|
||||
core::forward<T>(t) ^ core::forward<U>(u)
|
||||
) { return core::forward<T>(t) ^ core::forward<U>(u); }
|
||||
};
|
||||
|
||||
template <> struct bit_not<void> {
|
||||
using is_transparent = void;
|
||||
|
||||
template <class T>
|
||||
constexpr auto operator () (T&& t) const -> decltype(~core::forward<T>(t)) {
|
||||
return ~core::forward<T>(t);
|
||||
}
|
||||
};
|
||||
|
||||
/* N3980 Implementation */
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_FUNCTIONAL_HPP */
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_INTERNAL_HPP
|
||||
#define CORE_INTERNAL_HPP
|
||||
|
||||
/* This is a header containing common implementation specific code, to
|
||||
* reduce the complexity of the other headers, especially those that are
|
||||
* closely intertwined, such as <core/functional.hpp> and <core/type_traits.hpp>
|
||||
*
|
||||
* Additionally, some of this code is duplicated elsewhere (such as class_of,
|
||||
* and meta::identity), but aliases are placed to lessen any impact that this
|
||||
* might have.
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <ciso646>
|
||||
|
||||
#include "meta.hpp"
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace impl {
|
||||
|
||||
template <class T, class Void, template <class...> class, class...>
|
||||
struct make_detect : meta::identity<T> { using value_t = ::std::false_type; };
|
||||
template <class T, template <class...> class U, class... Args>
|
||||
struct make_detect<T, meta::deduce<U<Args...>>, U, Args...> :
|
||||
meta::identity<U<Args...>>
|
||||
{ using value_t = ::std::true_type; };
|
||||
|
||||
/* extremely useful custom type traits */
|
||||
template <class T> struct class_of : meta::identity<T> { };
|
||||
template <class Signature, class T>
|
||||
struct class_of<Signature T::*> : meta::identity<T> { };
|
||||
|
||||
/* aliases */
|
||||
template <class T> using class_of_t = typename class_of<T>::type;
|
||||
template <class T> using decay_t = typename ::std::decay<T>::type;
|
||||
template <class T>
|
||||
using remove_reference_t = typename ::std::remove_reference<T>::type;
|
||||
template <bool B, class T = void>
|
||||
using enable_if_t = typename ::std::enable_if<B, T>::type;
|
||||
|
||||
/* is_nothrow_swappable plumbing */
|
||||
using ::std::declval;
|
||||
using ::std::swap;
|
||||
|
||||
// MSVC 2015 workaround
|
||||
template <class T, class U>
|
||||
struct is_swappable_with {
|
||||
template <class X, class Y>
|
||||
static auto test (void*) noexcept(true) -> decltype(
|
||||
swap(declval<X&>(), declval<Y&>())
|
||||
);
|
||||
|
||||
template <class, class>
|
||||
static void test (...) noexcept(false);
|
||||
|
||||
static constexpr bool value = noexcept(test<T, U>(nullptr));
|
||||
};
|
||||
|
||||
// MSVC 2015 workaround
|
||||
template <class T, class U>
|
||||
struct is_noexcept_swappable_with {
|
||||
template <
|
||||
class X,
|
||||
class Y,
|
||||
bool B=noexcept(swap(declval<X&>(), declval<Y&>()))
|
||||
> static void test (enable_if_t<B>*) noexcept(true);
|
||||
|
||||
template <class, class>
|
||||
static void test (...) noexcept(false);
|
||||
|
||||
static constexpr bool value = noexcept(test<T, U>(nullptr));
|
||||
};
|
||||
|
||||
template <class, class, class=void>
|
||||
struct is_swappable : ::std::false_type { };
|
||||
|
||||
template <class T, class U>
|
||||
struct is_swappable<
|
||||
T,
|
||||
U,
|
||||
meta::deduce<
|
||||
is_swappable_with<T, U>,
|
||||
is_swappable_with<U, T>
|
||||
>
|
||||
> : ::std::true_type { };
|
||||
|
||||
template <class T, class U=T>
|
||||
struct is_nothrow_swappable : meta::all_t<
|
||||
is_swappable<T, U>::value,
|
||||
is_noexcept_swappable_with<T, U>::value,
|
||||
is_noexcept_swappable_with<U, T>::value
|
||||
> { };
|
||||
|
||||
/*
|
||||
* If I can't amuse myself when working with C++ templates, then life isn't
|
||||
* worth living. Bury me with my chevrons.
|
||||
*/
|
||||
template <class T>
|
||||
constexpr T&& pass (remove_reference_t<T>& t) noexcept {
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr T&& pass (remove_reference_t<T>&& t) noexcept {
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
/* INVOKE pseudo-expression plumbing, *much* more simplified than previous
|
||||
* versions of Core
|
||||
*/
|
||||
struct undefined { constexpr undefined (...) noexcept { } };
|
||||
|
||||
/* We get some weird warnings under clang, so we actually give these functions
|
||||
* a body to get rid of it.
|
||||
*/
|
||||
template <class... Args>
|
||||
constexpr undefined INVOKE (undefined, Args&&...) noexcept {
|
||||
return undefined { };
|
||||
}
|
||||
|
||||
template <class Functor, class... Args>
|
||||
constexpr auto INVOKE (Functor&& f, Args&&... args) -> enable_if_t<
|
||||
not ::std::is_member_pointer<decay_t<Functor>>::value,
|
||||
decltype(pass<Functor>(f)(pass<Args>(args)...))
|
||||
> { return pass<Functor>(f)(pass<Args>(args)...); }
|
||||
|
||||
template <class Functor, class... Args>
|
||||
auto INVOKE (Functor&& f, Args&&... args) -> enable_if_t<
|
||||
::std::is_member_pointer<decay_t<Functor>>::value,
|
||||
decltype(::std::mem_fn(pass<Functor>(f))(pass<Args>(args)...))
|
||||
> { return ::std::mem_fn(pass<Functor>(f))(pass<Args>(args)...); }
|
||||
|
||||
template <bool, class...> struct invoke_of { };
|
||||
template <class... Args> struct invoke_of<true, Args...> :
|
||||
meta::identity<decltype(INVOKE(declval<Args>()...))>
|
||||
{ };
|
||||
|
||||
}}} /* namespace core::v2::impl */
|
||||
|
||||
#endif /* CORE_INTERNAL_HPP */
|
||||
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_ITERATOR_HPP
|
||||
#define CORE_ITERATOR_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
|
||||
#include "type_traits.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
|
||||
/* capacity */
|
||||
template <class Container>
|
||||
constexpr auto size (Container const& container) noexcept -> decltype(
|
||||
container.size()
|
||||
) { return container.size(); }
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr ::std::size_t size (T const (&)[N]) noexcept { return N; }
|
||||
|
||||
template <class Container>
|
||||
constexpr bool empty (Container const& container) noexcept {
|
||||
return container.empty();
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
constexpr bool empty (T const (&)[N]) noexcept { return false; }
|
||||
|
||||
/* element access */
|
||||
template <class Container>
|
||||
constexpr auto front (Container const& container) -> decltype(
|
||||
container.front()
|
||||
) { return container.front(); }
|
||||
|
||||
template <class Container>
|
||||
constexpr auto front (Container& container) -> decltype(container.front()) {
|
||||
return container.front();
|
||||
}
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr T const& front (T const (&array)[N]) noexcept { return array[0]; }
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr T& front (T (&array)[N]) noexcept { return array[0]; }
|
||||
|
||||
template <class Container>
|
||||
constexpr auto back (Container const& container) -> decltype(
|
||||
container.back()
|
||||
) { return container.back(); }
|
||||
|
||||
template <class Container>
|
||||
constexpr auto back (Container& container) -> decltype(container.back()) {
|
||||
return container.back();
|
||||
}
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr T const& back (T const (&array)[N]) noexcept { return array[N - 1]; }
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr T& back (T (&array)[N]) noexcept { return array[N - 1]; }
|
||||
|
||||
/* data access */
|
||||
template <class Container>
|
||||
constexpr auto data (Container const& container) noexcept -> decltype(
|
||||
container.data()
|
||||
) { return container.data(); }
|
||||
|
||||
template <class Container>
|
||||
constexpr auto data (Container& container) noexcept -> decltype(
|
||||
container.data()
|
||||
) { return container.data(); }
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr T const* data (T const (&array)[N]) noexcept { return array; }
|
||||
|
||||
template <class T, ::std::size_t N>
|
||||
constexpr T* data (T (&array)[N]) noexcept { return array; }
|
||||
|
||||
/* iteration */
|
||||
template <class Container>
|
||||
auto cbegin (Container const& container) -> decltype(::std::begin(container)) {
|
||||
return ::std::begin(container);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto cend (Container const& container) -> decltype(::std::end(container)) {
|
||||
return ::std::end(container);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto rbegin (Container const& container) -> decltype(container.rbegin()) {
|
||||
return container.rbegin();
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto rbegin (Container& container) -> decltype(container.rbegin()) {
|
||||
return container.rbegin();
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto crbegin (Container const& container) -> decltype(rbegin(container)) {
|
||||
return rbegin(container);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto rend (Container const& container) -> decltype(container.rend()) {
|
||||
return container.rend();
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto rend (Container& container) -> decltype(container.rend()) {
|
||||
return container.rend();
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto crend (Container const& container) -> decltype(rend(container)) {
|
||||
return rend(container);
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
::std::reverse_iterator<Iterator> make_reverse_iterator (Iterator iter) {
|
||||
return ::std::reverse_iterator<Iterator>(iter);
|
||||
}
|
||||
|
||||
template <
|
||||
class DelimT,
|
||||
class CharT=char,
|
||||
class Traits=::std::char_traits<CharT>
|
||||
> struct ostream_joiner final : ::std::iterator<
|
||||
::std::output_iterator_tag,
|
||||
void,
|
||||
void,
|
||||
void,
|
||||
void
|
||||
> {
|
||||
using delimiter_type = DelimT;
|
||||
using ostream_type = ::std::basic_ostream<CharT, Traits>;
|
||||
using traits_type = Traits;
|
||||
using char_type = CharT;
|
||||
|
||||
ostream_joiner (ostream_type& stream, delimiter_type const& delimiter) :
|
||||
stream(stream),
|
||||
delimiter { delimiter }
|
||||
{ }
|
||||
|
||||
ostream_joiner (ostream_type& stream, delimiter_type&& delimiter) :
|
||||
stream(stream),
|
||||
delimiter { ::core::move(delimiter) },
|
||||
first { true }
|
||||
{ }
|
||||
|
||||
template <class T>
|
||||
ostream_joiner& operator = (T const& item) {
|
||||
if (not first and delimiter) { this->stream << delimiter; }
|
||||
this->stream << item;
|
||||
this->first = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream_joiner& operator ++ (int) noexcept { return *this; }
|
||||
ostream_joiner& operator ++ () noexcept { return *this; }
|
||||
ostream_joiner& operator * () noexcept { return *this; }
|
||||
|
||||
private:
|
||||
ostream_type& stream;
|
||||
delimiter_type delimiter;
|
||||
bool first;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct number_iterator {
|
||||
using iterator_category = ::std::bidirectional_iterator_tag;
|
||||
using difference_type = T;
|
||||
using value_type = T;
|
||||
using reference = add_lvalue_reference_t<T>;
|
||||
using pointer = add_pointer_t<T>;
|
||||
|
||||
static_assert(::std::is_integral<value_type>::value, "");
|
||||
|
||||
explicit number_iterator (value_type value, value_type step=1) noexcept :
|
||||
value { value },
|
||||
step { step }
|
||||
{ }
|
||||
|
||||
number_iterator (number_iterator const&) noexcept = default;
|
||||
number_iterator () noexcept = default;
|
||||
~number_iterator () noexcept = default;
|
||||
|
||||
number_iterator& operator = (number_iterator const&) noexcept = default;
|
||||
|
||||
void swap (number_iterator& that) noexcept {
|
||||
::std::swap(this->value, that.value);
|
||||
::std::swap(this->step, that.step);
|
||||
}
|
||||
|
||||
reference operator * () noexcept { return this->value; }
|
||||
|
||||
number_iterator& operator ++ () noexcept {
|
||||
this->value += this->step;
|
||||
return *this;
|
||||
}
|
||||
|
||||
number_iterator& operator -- () noexcept {
|
||||
this->value -= this->step;
|
||||
return *this;
|
||||
}
|
||||
|
||||
number_iterator operator ++ (int) const noexcept {
|
||||
return number_iterator { this->value + this->step };
|
||||
}
|
||||
|
||||
number_iterator operator -- (int) const noexcept {
|
||||
return number_iterator { this->value - this->step };
|
||||
}
|
||||
|
||||
bool operator == (number_iterator const& that) const noexcept {
|
||||
return this->value == that.value and this->step == that.step;
|
||||
}
|
||||
|
||||
bool operator != (number_iterator const& that) const noexcept {
|
||||
return this->value != that.value and this->step == that.step;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type value { };
|
||||
value_type step { static_cast<value_type>(1) };
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void swap (number_iterator<T>& lhs, number_iterator<T>& rhs) noexcept {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class DelimT>
|
||||
ostream_joiner<decay_t<DelimT>, CharT, Traits> make_ostream_joiner (
|
||||
::std::basic_ostream<CharT, Traits>& stream,
|
||||
DelimT&& delimiter
|
||||
) {
|
||||
return ostream_joiner<decay_t<DelimT>, CharT, Traits> {
|
||||
stream,
|
||||
::core::forward<DelimT>(delimiter)
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
number_iterator<T> make_number_iterator (T value, T step) noexcept {
|
||||
return number_iterator<T> { value, step };
|
||||
}
|
||||
|
||||
template <class T>
|
||||
number_iterator<T> make_number_iterator (T value) noexcept {
|
||||
return number_iterator<T> { value };
|
||||
}
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_ITERATOR_HPP */
|
||||
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_META_HPP
|
||||
#define CORE_META_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace meta {
|
||||
namespace impl {
|
||||
|
||||
using false_t = ::std::false_type;
|
||||
using true_t = ::std::true_type;
|
||||
|
||||
template <class T, T V> using integral = ::std::integral_constant<T, V>;
|
||||
template <bool B> using boolean = integral<bool, B>;
|
||||
|
||||
template <class T> struct identity { using type = T; };
|
||||
|
||||
template <class...> struct deducer : identity<void> { };
|
||||
template <class... Ts> using deduce = typename deducer<Ts...>::type;
|
||||
|
||||
template <class T, class V, template <class...> class Detector, class... Args>
|
||||
struct detect : identity<T> { using value = false_t; };
|
||||
|
||||
template <class T, template <class...> class Detector, class... Args>
|
||||
struct detect<T, deduce<Detector<Args...>>, Detector, Args...> :
|
||||
identity<Detector<Args...>>
|
||||
{ using value = true_t; };
|
||||
|
||||
template <class... Ts>
|
||||
struct list {
|
||||
static constexpr ::std::size_t size () noexcept { return sizeof...(Ts); }
|
||||
static constexpr bool empty () noexcept { return size() == 0u; }
|
||||
};
|
||||
|
||||
template <class, template <class...> class> struct convert;
|
||||
template <class, class> struct rebind;
|
||||
template <class> struct into;
|
||||
|
||||
template <class, template <class...> class, class...> struct filter;
|
||||
template <class, template <class...> class, class...> struct map;
|
||||
template <class...> struct join;
|
||||
|
||||
template <template <class...> class, class...> struct apply;
|
||||
|
||||
template <class, ::std::size_t> struct get;
|
||||
template <class, class> struct index_of;
|
||||
template <class> struct head;
|
||||
template <class> struct tail;
|
||||
|
||||
template <class, template <class...> class, class...> struct count_if;
|
||||
template <class, template <class...> class, class...> struct find_if;
|
||||
template <class, class> struct count;
|
||||
template <class, class> struct find;
|
||||
|
||||
template <class, ::std::size_t> struct rotate;
|
||||
template <class> struct reverse;
|
||||
|
||||
template <class, class> struct equal;
|
||||
|
||||
template <class, template <class...> class, class...> struct none_of;
|
||||
template <class, template <class...> class, class...> struct all_of;
|
||||
template <class, template <class...> class, class...> struct any_of;
|
||||
|
||||
template <bool...> struct none;
|
||||
template <bool...> struct all;
|
||||
template <bool...> struct any;
|
||||
|
||||
template <class... Ts, template <class...> class To>
|
||||
struct convert<list<Ts...>, To> : identity<To<Ts...>> { };
|
||||
|
||||
template <template <class...> class To, class... Ts, class... Us>
|
||||
struct rebind<list<Ts...>, To<Us...>> : identity<To<Ts...>> { };
|
||||
|
||||
template <template <class...> class T, class... Ts>
|
||||
struct into<T<Ts...>> : identity<list<Ts...>> { };
|
||||
|
||||
template <template <class...> class F, class... Ts, class... Args>
|
||||
struct filter<list<Ts...>, F, Args...> :
|
||||
join<
|
||||
typename ::std::conditional<
|
||||
F<Ts, Args...>::value,
|
||||
list<Ts>,
|
||||
list<>
|
||||
>::type...
|
||||
>
|
||||
{ };
|
||||
|
||||
template <template <class...> class F, class... Ts, class... Args>
|
||||
struct map<list<Ts...>, F, Args...> : identity<list<F<Ts, Args...>...>> { };
|
||||
|
||||
template <class... Ts> struct join<list<Ts...>> : identity<list<Ts...>> { };
|
||||
template <class... Ts, class... Us, class... Vs>
|
||||
struct join<list<Ts...>, list<Us...>, Vs...> :
|
||||
join<list<Ts..., Us...>, Vs...>
|
||||
{ };
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct index_of<list<Ts...>, T> : integral<
|
||||
::std::size_t,
|
||||
list<Ts...>::size() - find<list<Ts...>, T>::type::size()
|
||||
> { };
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct get<list<T, Ts...>, 0> : identity<T> { };
|
||||
template <class T, class... Ts, size_t N>
|
||||
struct get<list<T, Ts...>, N> :
|
||||
get<list<Ts...>, N - 1>
|
||||
{ static_assert(N < (sizeof...(Ts) + 1),""); };
|
||||
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct head<list<T, Ts...>> : identity<T> { };
|
||||
template <class T, class... Ts>
|
||||
struct tail<list<T, Ts...>> : identity<list<Ts...>> { };
|
||||
|
||||
template <class... Ts, template <class...> class F, class... Args>
|
||||
struct count_if<list<Ts...>, F, Args...> : integral<
|
||||
::std::size_t,
|
||||
filter<list<Ts...>, F, Args...>::type::size()
|
||||
> { };
|
||||
|
||||
template <template <class...> class F, class... Args>
|
||||
struct find_if<list<>, F, Args...> : identity<list<>> { };
|
||||
|
||||
template <template <class...> class F, class T, class... Ts, class... Args>
|
||||
struct find_if<list<T, Ts...>, F, Args...> : ::std::conditional<
|
||||
F<Args..., T>::value,
|
||||
list<T, Ts...>,
|
||||
typename find_if<list<Ts...>, F, Args...>::type
|
||||
> { };
|
||||
|
||||
template <class T, class U> struct count : count_if<T, ::std::is_same, U> { };
|
||||
template <class T, class U> struct find : find_if<T, ::std::is_same, U> { };
|
||||
|
||||
template <template <class...> class F, class... Ts, class... Args>
|
||||
struct none_of<list<Ts...>, F, Args...> : none<F<Ts, Args...>::value...> { };
|
||||
|
||||
template <template <class...> class F, class... Ts, class... Args>
|
||||
struct all_of<list<Ts...>, F, Args...> : all<F<Ts, Args...>::value...> { };
|
||||
|
||||
template <template <class...> class F, class... Ts, class... Args>
|
||||
struct any_of<list<Ts...>, F, Args...> : any<F<Ts, Args...>::value...> { };
|
||||
|
||||
template <bool B, bool... Bs> struct none<B, Bs...> :
|
||||
boolean<not B and none<Bs...>::value>
|
||||
{ };
|
||||
template <> struct none<> : true_t { };
|
||||
|
||||
template <bool B, bool... Bs> struct all<B, Bs...> :
|
||||
boolean<B and all<Bs...>::value>
|
||||
{ };
|
||||
template <> struct all<> : true_t { };
|
||||
|
||||
template <bool B, bool... Bs> struct any<B, Bs...> :
|
||||
boolean<B or any<Bs...>::value>
|
||||
{ };
|
||||
template <> struct any<> : false_t { };
|
||||
|
||||
template <class T, template <class...> class U>
|
||||
struct is_specialization_of : false_t { };
|
||||
template <template <class...> class T, class... Ts>
|
||||
struct is_specialization_of<T<Ts...>, T> : true_t { };
|
||||
|
||||
}}}} /* namespace core::v2::meta::impl */
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace meta {
|
||||
|
||||
template <bool B, class T = void>
|
||||
using unless = typename ::std::enable_if<not B, T>::type;
|
||||
|
||||
template <bool B, class T = void>
|
||||
using when = typename ::std::enable_if<B, T>::type;
|
||||
|
||||
template <bool B> using inhibit = unless<B, ::std::size_t>;
|
||||
template <bool B> using require = when<B, ::std::size_t>;
|
||||
|
||||
template <bool B, class T, class F>
|
||||
using either = typename ::std::conditional<B, T, F>::type;
|
||||
|
||||
using impl::integral;
|
||||
using impl::boolean;
|
||||
|
||||
using impl::false_t;
|
||||
using impl::true_t;
|
||||
|
||||
using impl::identity;
|
||||
using impl::list;
|
||||
|
||||
using impl::is_specialization_of;
|
||||
|
||||
template <class... Ts> using deduce = typename impl::deduce<Ts...>;
|
||||
|
||||
template <class T, template <class...> class U>
|
||||
using convert = typename impl::convert<T, U>::type;
|
||||
|
||||
template <class T, class U> using rebind = typename impl::rebind<T, U>::type;
|
||||
template <class T> using into = typename impl::into<T>::type;
|
||||
|
||||
template <class... Ts> using join = typename impl::join<Ts...>::type;
|
||||
|
||||
template <class T, size_t N> using get = typename impl::get<T, N>::type;
|
||||
template <class T> using head = typename impl::head<T>::type;
|
||||
template <class T> using tail = typename impl::tail<T>::type;
|
||||
|
||||
template <class T, class U>
|
||||
using index_of_t = impl::index_of<T, U>;
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
using count_if_t = impl::count_if<T, F, Args...>;
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
using find_if = typename impl::find_if<T, F>::type;
|
||||
|
||||
template <class T, class U> using count_t = impl::count<T, U>;
|
||||
|
||||
template <class T, class U>
|
||||
using find = typename impl::find<T, U>::type;
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
using none_of_t = impl::none_of<T, F, Args...>;
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
using all_of_t = impl::all_of<T, F, Args...>;
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
using any_of_t = impl::any_of<T, F, Args...>;
|
||||
|
||||
template <bool... Bs> using none_t = impl::none<Bs...>;
|
||||
template <bool... Bs> using all_t = impl::all<Bs...>;
|
||||
template <bool... Bs> using any_t = impl::any<Bs...>;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr ::std::size_t index_of () noexcept {
|
||||
return index_of_t<T, U>::value;
|
||||
}
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
constexpr ::std::size_t count_if () noexcept {
|
||||
return count_if_t<T, F, Args...>::value;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
constexpr ::std::size_t count () noexcept { return count_t<T, U>::value; }
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
constexpr bool none_of () noexcept { return none_of_t<T, F, Args...>::value; }
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
constexpr bool all_of () noexcept { return all_of_t<T, F, Args...>::value; }
|
||||
|
||||
template <class T, template <class...> class F, class... Args>
|
||||
constexpr bool any_of () noexcept { return any_of_t<T, F, Args...>::value; }
|
||||
|
||||
template <bool... Bs>
|
||||
constexpr bool none () noexcept { return none_t<Bs...>::value; }
|
||||
|
||||
template <bool... Bs>
|
||||
constexpr bool all () noexcept { return all_t<Bs...>::value; }
|
||||
|
||||
template <bool... Bs>
|
||||
constexpr bool any () noexcept { return any_t<Bs...>::value; }
|
||||
|
||||
}}} /* namespace core::v2::meta */
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace meta {
|
||||
|
||||
template <class T, T... I> struct integer_sequence : identity<T> {
|
||||
static_assert(
|
||||
::std::is_integral<T>::value,
|
||||
"integer_sequence must use an integral type"
|
||||
);
|
||||
|
||||
template <T N> using append = integer_sequence<T, I..., N>;
|
||||
static constexpr ::std::size_t size() noexcept { return sizeof...(I); }
|
||||
using next = append<sizeof...(I)>;
|
||||
};
|
||||
|
||||
template <class T, T Index, ::std::size_t N>
|
||||
struct iota : identity<
|
||||
typename iota<T, Index - 1, N - 1u>::type::next
|
||||
> { static_assert(Index >= 0, "Index cannot be negative"); };
|
||||
|
||||
template <class T, T Index>
|
||||
struct iota<T, Index, 0u> : identity<integer_sequence<T>> { };
|
||||
|
||||
template <::std::size_t... I>
|
||||
using index_sequence = integer_sequence<::std::size_t, I...>;
|
||||
|
||||
template <class T, T N>
|
||||
using make_integer_sequence = typename iota<T, N, N>::type;
|
||||
|
||||
template <::std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<::std::size_t, N>;
|
||||
|
||||
template <class... Ts>
|
||||
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
|
||||
|
||||
template <class> struct index_sequence_from;
|
||||
|
||||
}}} /* namespace core::meta::v2 */
|
||||
|
||||
#endif /* CORE_META_HPP */
|
||||
@@ -0,0 +1,355 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_RANGE_HPP
|
||||
#define CORE_RANGE_HPP
|
||||
|
||||
#include <istream>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "type_traits.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace impl {
|
||||
|
||||
using ::std::begin;
|
||||
using ::std::end;
|
||||
|
||||
template <class T> using adl_begin_t = decltype(begin(::std::declval<T>()));
|
||||
template <class T> using adl_end_t = decltype(end(::std::declval<T>()));
|
||||
|
||||
template <class T>
|
||||
adl_begin_t<T> adl_begin (T&& t) {
|
||||
using ::std::begin;
|
||||
return begin(::core::forward<T>(t));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
adl_end_t<T> adl_end (T&& t) {
|
||||
using ::std::end;
|
||||
return end(::core::forward<T>(t));
|
||||
}
|
||||
|
||||
} /* namespace impl */
|
||||
|
||||
template <class R>
|
||||
struct is_range : meta::all_t<
|
||||
is_detected<impl::adl_begin_t, R>::value,
|
||||
is_detected<impl::adl_end_t, R>::value
|
||||
> { };
|
||||
|
||||
template <class Iterator>
|
||||
struct range {
|
||||
using traits = ::std::iterator_traits<Iterator>;
|
||||
|
||||
using iterator_category = typename traits::iterator_category;
|
||||
|
||||
using difference_type = typename traits::difference_type;
|
||||
using value_type = typename traits::value_type;
|
||||
|
||||
using reference = typename traits::reference;
|
||||
using pointer = typename traits::pointer;
|
||||
|
||||
using iterator = Iterator;
|
||||
|
||||
static constexpr bool is_input = ::std::is_convertible<
|
||||
iterator_category,
|
||||
::std::input_iterator_tag
|
||||
>::value;
|
||||
|
||||
static constexpr bool is_output = ::std::is_convertible<
|
||||
iterator_category,
|
||||
::std::output_iterator_tag
|
||||
>::value;
|
||||
|
||||
static constexpr bool is_forward = ::std::is_convertible<
|
||||
iterator_category,
|
||||
::std::forward_iterator_tag
|
||||
>::value;
|
||||
|
||||
static constexpr bool is_bidirectional = ::std::is_convertible<
|
||||
iterator_category,
|
||||
::std::bidirectional_iterator_tag
|
||||
>::value;
|
||||
|
||||
static constexpr bool is_random_access = ::std::is_convertible<
|
||||
iterator_category,
|
||||
::std::random_access_iterator_tag
|
||||
>::value;
|
||||
|
||||
template <
|
||||
class Range,
|
||||
class=meta::when<
|
||||
meta::all<
|
||||
meta::none<
|
||||
::std::is_pointer<iterator>::value,
|
||||
::std::is_same<decay_t<Range>, range>::value
|
||||
>(),
|
||||
is_range<Range>::value,
|
||||
is_detected_convertible<iterator, impl::adl_begin_t, Range>::value
|
||||
>()
|
||||
>
|
||||
> explicit range (Range&& r) noexcept :
|
||||
begin_ { impl::adl_begin(::core::forward<Range>(r)) },
|
||||
end_ { impl::adl_end(::core::forward<Range>(r)) }
|
||||
{ }
|
||||
|
||||
range (::std::pair<iterator, iterator> pair) noexcept :
|
||||
range { ::std::get<0>(pair), ::std::get<1>(pair) }
|
||||
{ }
|
||||
|
||||
range (iterator begin_, iterator end_) noexcept :
|
||||
begin_ { begin_ },
|
||||
end_ { end_ }
|
||||
{ }
|
||||
|
||||
range (range const& that) :
|
||||
range { that.begin_, that.end_ }
|
||||
{ }
|
||||
|
||||
range (range&& that) noexcept :
|
||||
range { ::core::move(that.begin_), ::core::move(that.end_) }
|
||||
{ that.begin_ = that.end_; }
|
||||
|
||||
range () = default;
|
||||
~range () = default;
|
||||
|
||||
range& operator = (range const& that) {
|
||||
return *this = range { that };
|
||||
}
|
||||
|
||||
range& operator = (range&& that) {
|
||||
range { ::std::move(that) }.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator [](difference_type idx) const {
|
||||
static_assert(is_random_access, "can only subscript into random-access");
|
||||
return idx < 0 ? this->end()[idx] : this->begin()[idx];
|
||||
}
|
||||
|
||||
iterator begin () const { return this->begin_; }
|
||||
iterator end () const { return this->end_; }
|
||||
|
||||
reference front () const { return *this->begin(); }
|
||||
reference back () const {
|
||||
static_assert(is_bidirectional, "can only get back of bidirectional");
|
||||
return *::std::prev(this->end());
|
||||
}
|
||||
|
||||
bool empty () const { return this->begin() == this->end(); }
|
||||
|
||||
difference_type size () const {
|
||||
static_assert(is_forward, "can only get size of forward-range");
|
||||
return ::std::distance(this->begin(), this->end());
|
||||
}
|
||||
|
||||
/* Creates an open-ended range of [start, stop) */
|
||||
range slice (difference_type start, difference_type stop) const {
|
||||
static_assert(is_forward, "can only slice forward-range");
|
||||
/* Behavior is:
|
||||
* if start is negative, the begin marker is this->end() - start
|
||||
* if stop is negative, the end marker is this->end() - stop
|
||||
* if start is positive, the begin marker is this->begin() + start
|
||||
* if stop is positive, the end marker is this->begin() + stop
|
||||
*
|
||||
* if start and stop are positive, and stop is less than or equal to start,
|
||||
* an empty range is returned.
|
||||
*
|
||||
* if start and stop are negative and stop is less than or equal to start,
|
||||
* an empty range is returned.
|
||||
*
|
||||
* if start is positive and stop is negative and abs(stop) + start is
|
||||
* greater than or equal to this->size(), an empty range is returned.
|
||||
*
|
||||
* if start is negative and stop is positive and this->size() + start is
|
||||
* greater or equal to stop, an empty range is returned.
|
||||
*
|
||||
* The first two conditions can be computed cheaply, while the third and
|
||||
* fourth are a bit more expensive, but WILL be required no matter what
|
||||
* iterator type we are. However we don't compute the size until after
|
||||
* we've checked the first two conditions
|
||||
*
|
||||
* An example with python style slicing for each would be:
|
||||
* [4:3] -> empty range
|
||||
* [-4:-4] -> empty range
|
||||
* [7:-4] -> empty range for string of size 11 or more
|
||||
* [-4:15] -> empty range for a string of size 19 or less.
|
||||
*/
|
||||
bool const start_positive = start > 0;
|
||||
bool const stop_positive = stop > 0;
|
||||
bool const stop_less = stop < start;
|
||||
bool const first_return_empty = start_positive == stop_positive and stop_less;
|
||||
if (first_return_empty) { return range { }; }
|
||||
|
||||
/* now safe to compute size */
|
||||
auto const size = this->size();
|
||||
auto const third_empty = ::std::abs(stop) + start;
|
||||
|
||||
bool const second_return_empty =
|
||||
(start_positive and not stop_positive and third_empty >= size) or
|
||||
(not start_positive and stop_positive and size + start >= stop);
|
||||
if (second_return_empty) { return range { }; }
|
||||
|
||||
/* While the code below technically works for all iterators it is
|
||||
* ineffecient in some cases for bidirectional ranges, where either of
|
||||
* start or stop are negative.
|
||||
* TODO: Specialize for bidirectional operators
|
||||
*/
|
||||
if (not start_positive) { start += size; }
|
||||
if (not stop_positive) { stop += size; }
|
||||
|
||||
auto begin = this->begin();
|
||||
::std::advance(begin, start);
|
||||
|
||||
auto end = begin;
|
||||
::std::advance(end, stop - start);
|
||||
|
||||
return range { begin, end };
|
||||
}
|
||||
|
||||
/* Creates an open-ended range of [start, end()) */
|
||||
range slice (difference_type start) const {
|
||||
static_assert(is_forward, "can only slice forward-range");
|
||||
return range { split(start).second };
|
||||
}
|
||||
|
||||
::std::pair<range, range> split (difference_type idx) const {
|
||||
static_assert(is_forward,"can only split a forward-range");
|
||||
if (idx >= 0) {
|
||||
range second { *this };
|
||||
second.pop_front_upto(idx);
|
||||
return ::std::make_pair(range { this->begin(), second.begin() }, second);
|
||||
}
|
||||
|
||||
range first { *this };
|
||||
first.pop_back_upto(-idx);
|
||||
return ::std::make_pair(first, range { first.end(), this->end() });
|
||||
}
|
||||
|
||||
/* mutates range */
|
||||
void pop_front (difference_type n) { ::std::advance(this->begin_, n); }
|
||||
void pop_front () { ++this->begin_; }
|
||||
|
||||
void pop_back (difference_type n) {
|
||||
static_assert(is_bidirectional, "can only pop-back bidirectional-range");
|
||||
::std::advance(this->end_, -n);
|
||||
}
|
||||
|
||||
void pop_back () {
|
||||
static_assert(is_bidirectional, "can only pop-back bidirectional-range");
|
||||
--this->end_;
|
||||
}
|
||||
|
||||
/* Negative argument causes no change */
|
||||
void pop_front_upto (difference_type n) {
|
||||
::std::advance(
|
||||
this->begin_,
|
||||
::std::min(::std::max<difference_type>(0, n), this->size())
|
||||
);
|
||||
}
|
||||
|
||||
/* Negative argument causes no change */
|
||||
void pop_back_upto (difference_type n) {
|
||||
static_assert(is_bidirectional, "can only pop-back-upto bidirectional");
|
||||
::std::advance(
|
||||
this->end_,
|
||||
-::std::min(::std::max<difference_type>(0, n), this->size())
|
||||
);
|
||||
}
|
||||
|
||||
void swap (range& that) noexcept(is_nothrow_swappable<iterator>::value) {
|
||||
using ::std::swap;
|
||||
swap(this->begin_, that.begin_);
|
||||
swap(this->end_, that.end_);
|
||||
}
|
||||
|
||||
private:
|
||||
iterator begin_;
|
||||
iterator end_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
auto make_range (T* ptr, ::std::size_t n) -> range<T*> {
|
||||
return range<T*> { ptr, ptr + n };
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
auto make_range (Iterator begin, Iterator end) -> range<Iterator> {
|
||||
return range<Iterator> { begin, end };
|
||||
}
|
||||
|
||||
template <class Range>
|
||||
auto make_range (Range&& value) -> range<decltype(begin(value))> {
|
||||
using ::std::begin;
|
||||
using ::std::end;
|
||||
return make_range(begin(value), end(value));
|
||||
}
|
||||
|
||||
/* Used like: core::make_range<char>(::std::cin) */
|
||||
template <
|
||||
class T,
|
||||
class CharT,
|
||||
class Traits=::std::char_traits<CharT>
|
||||
> auto make_range (::std::basic_istream<CharT, Traits>& stream) -> range<
|
||||
::std::istream_iterator<T, CharT, Traits>
|
||||
> {
|
||||
using iterator = ::std::istream_iterator<T, CharT, Traits>;
|
||||
return make_range(iterator { stream }, iterator { });
|
||||
}
|
||||
|
||||
template <class CharT, class Traits=::std::char_traits<CharT>>
|
||||
auto make_range (::std::basic_streambuf<CharT, Traits>* buffer) -> range<
|
||||
::std::istreambuf_iterator<CharT, Traits>
|
||||
> {
|
||||
using iterator = ::std::istreambuf_iterator<CharT, Traits>;
|
||||
return make_range(iterator { buffer }, iterator { });
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
range<::std::move_iterator<Iter>> make_move_range (Iter start, Iter stop) {
|
||||
return make_range(
|
||||
::std::make_move_iterator(start),
|
||||
::std::make_move_iterator(stop));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
range<::std::move_iterator<T*>> make_move_range (T* ptr, ::std::size_t n) {
|
||||
return make_move_range(ptr, ptr + n);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
range<number_iterator<T>> make_number_range(T start, T stop, T step) noexcept {
|
||||
auto begin = make_number_iterator(start, step);
|
||||
auto end = make_number_iterator(stop, step);
|
||||
return make_range(begin, end);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
range<number_iterator<T>> make_number_range (T start, T stop) noexcept {
|
||||
return make_range(make_number_iterator(start), make_number_iterator(stop));
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
void swap (range<Iterator>& lhs, range<Iterator>& rhs) noexcept(
|
||||
noexcept(lhs.swap(rhs))
|
||||
) { lhs.swap(rhs); }
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_RANGE_HPP */
|
||||
@@ -0,0 +1,760 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_STRING_VIEW_HPP
|
||||
#define CORE_STRING_VIEW_HPP
|
||||
|
||||
#include <initializer_list>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ciso646>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:5030)
|
||||
#pragma warning(disable:4702)
|
||||
#endif /* defined(_MSC_VER) */
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace impl {
|
||||
|
||||
/* implementations of MurmurHash2 *Endian Neutral* (but not alignment!) */
|
||||
template <::std::size_t=sizeof(::std::size_t)> struct murmur;
|
||||
template <> struct murmur<4> {
|
||||
constexpr murmur () = default;
|
||||
|
||||
::std::uint32_t operator () (void const* p, ::std::size_t len) const noexcept {
|
||||
static constexpr ::std::uint32_t magic = UINT32_C(0x5BD1E995);
|
||||
static constexpr auto shift = 24;
|
||||
|
||||
auto hash = static_cast<::std::uint32_t>(len);
|
||||
auto data = static_cast<::std::uint8_t const*>(p);
|
||||
|
||||
while (len >= sizeof(::std::uint32_t)) {
|
||||
::std::uint32_t mix = data[0];
|
||||
mix |= ::std::uint32_t(data[1]) << 8;
|
||||
mix |= ::std::uint32_t(data[2]) << 16;
|
||||
mix |= ::std::uint32_t(data[3]) << 24;
|
||||
|
||||
mix *= magic;
|
||||
mix ^= mix >> shift;
|
||||
mix *= magic;
|
||||
|
||||
hash *= magic;
|
||||
hash ^= mix;
|
||||
|
||||
data += sizeof(::std::uint32_t);
|
||||
len -= sizeof(::std::uint32_t);
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 3: hash ^= ::std::uint32_t(data[2]) << 16; [[clang::fallthrough]];
|
||||
case 2: hash ^= ::std::uint32_t(data[1]) << 8; [[clang::fallthrough]];
|
||||
case 1: hash ^= ::std::uint32_t(data[0]);
|
||||
hash *= magic;
|
||||
}
|
||||
|
||||
hash ^= hash >> 13;
|
||||
hash *= magic;
|
||||
hash ^= hash >> 15;
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct murmur<8> {
|
||||
constexpr murmur () = default;
|
||||
|
||||
::std::uint64_t operator () (void const* p, ::std::size_t len) const noexcept {
|
||||
static constexpr ::std::uint64_t magic = UINT64_C(0xC6A4A7935BD1E995);
|
||||
static constexpr auto shift = 47;
|
||||
|
||||
::std::uint64_t hash = len * magic;
|
||||
|
||||
auto data = static_cast<::std::uint8_t const*>(p);
|
||||
|
||||
while (len >= sizeof(::std::uint64_t)) {
|
||||
::std::uint64_t mix = data[0];
|
||||
mix |= ::std::uint64_t(data[1]) << 8;
|
||||
mix |= ::std::uint64_t(data[2]) << 16;
|
||||
mix |= ::std::uint64_t(data[3]) << 24;
|
||||
mix |= ::std::uint64_t(data[4]) << 32;
|
||||
mix |= ::std::uint64_t(data[5]) << 40;
|
||||
mix |= ::std::uint64_t(data[6]) << 48;
|
||||
mix |= ::std::uint64_t(data[7]) << 54;
|
||||
|
||||
mix *= magic;
|
||||
mix ^= mix >> shift;
|
||||
mix *= magic;
|
||||
|
||||
hash ^= mix;
|
||||
hash *= magic;
|
||||
|
||||
data += sizeof(::std::uint64_t);
|
||||
len -= sizeof(::std::uint64_t);
|
||||
}
|
||||
|
||||
switch (len & 7) {
|
||||
case 7: hash ^= ::std::uint64_t(data[6]) << 48; [[clang::fallthrough]];
|
||||
case 6: hash ^= ::std::uint64_t(data[5]) << 40; [[clang::fallthrough]];
|
||||
case 5: hash ^= ::std::uint64_t(data[4]) << 32; [[clang::fallthrough]];
|
||||
case 4: hash ^= ::std::uint64_t(data[3]) << 24; [[clang::fallthrough]];
|
||||
case 3: hash ^= ::std::uint64_t(data[2]) << 16; [[clang::fallthrough]];
|
||||
case 2: hash ^= ::std::uint64_t(data[1]) << 8; [[clang::fallthrough]];
|
||||
case 1: hash ^= ::std::uint64_t(data[0]);
|
||||
hash *= magic;
|
||||
}
|
||||
|
||||
hash ^= hash >> shift;
|
||||
hash *= magic;
|
||||
hash ^= hash >> shift;
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
}}} /* namespace core::v2::impl */
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
|
||||
#ifndef CORE_NO_EXCEPTIONS
|
||||
[[noreturn]] inline void throw_out_of_range (char const* msg) {
|
||||
throw ::std::out_of_range { msg };
|
||||
}
|
||||
#else /* CORE_NO_EXCEPTIONS */
|
||||
[[noreturn]] inline void throw_out_of_range (char const*) { ::std::abort(); }
|
||||
#endif /* CORE_NO_EXCEPTIONS */
|
||||
|
||||
template <class CharT, class Traits=::std::char_traits<CharT>>
|
||||
struct basic_string_view {
|
||||
using difference_type = ::std::ptrdiff_t;
|
||||
using value_type = CharT;
|
||||
using size_type = ::std::size_t;
|
||||
|
||||
using reference = value_type const&;
|
||||
using pointer = value_type const*;
|
||||
|
||||
using const_reference = reference;
|
||||
using const_pointer = pointer;
|
||||
|
||||
using const_iterator = pointer;
|
||||
using iterator = const_iterator;
|
||||
|
||||
using const_reverse_iterator = ::std::reverse_iterator<const_iterator>;
|
||||
using reverse_iterator = const_reverse_iterator;
|
||||
|
||||
using traits = Traits;
|
||||
|
||||
static constexpr size_type npos = ::std::numeric_limits<size_type>::max();
|
||||
|
||||
template <class Allocator>
|
||||
basic_string_view (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& that
|
||||
) : str { that.data() }, len { that.size() } { }
|
||||
|
||||
constexpr basic_string_view (pointer str, size_type len) noexcept :
|
||||
str { str },
|
||||
len { len }
|
||||
{ }
|
||||
|
||||
basic_string_view (pointer str) noexcept :
|
||||
basic_string_view { str, traits::length(str) }
|
||||
{ }
|
||||
|
||||
constexpr basic_string_view (basic_string_view const&) noexcept = default;
|
||||
constexpr basic_string_view () noexcept = default;
|
||||
basic_string_view& operator = (basic_string_view const&) noexcept = default;
|
||||
|
||||
template <class Allocator>
|
||||
explicit operator ::std::basic_string<CharT, Traits, Allocator> () const {
|
||||
return ::std::basic_string<CharT, Traits, Allocator> {
|
||||
this->data(),
|
||||
this->size()
|
||||
};
|
||||
}
|
||||
|
||||
template <class Allocator=std::allocator<CharT>>
|
||||
::std::basic_string<CharT, Traits, Allocator> to_string (
|
||||
Allocator const& allocator = Allocator()
|
||||
) const {
|
||||
return ::std::basic_string<CharT, Traits, Allocator> {
|
||||
this->data(),
|
||||
this->size(),
|
||||
allocator
|
||||
};
|
||||
}
|
||||
|
||||
constexpr const_iterator begin () const noexcept { return this->data(); }
|
||||
constexpr const_iterator end () const noexcept {
|
||||
return this->data() + this->size();
|
||||
}
|
||||
|
||||
constexpr const_iterator cbegin () const noexcept { return this->begin(); }
|
||||
constexpr const_iterator cend () const noexcept { return this->end(); }
|
||||
|
||||
const_reverse_iterator rbegin () const noexcept {
|
||||
return const_reverse_iterator { this->end()};
|
||||
}
|
||||
|
||||
const_reverse_iterator rend () const noexcept {
|
||||
return const_reverse_iterator { this->begin() };
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin () const noexcept { return this->rbegin(); }
|
||||
const_reverse_iterator crend () const noexcept { return this->rend(); }
|
||||
|
||||
constexpr size_type max_size () const noexcept {
|
||||
return ::std::numeric_limits<size_type>::max();
|
||||
}
|
||||
constexpr size_type length () const noexcept { return this->size(); }
|
||||
constexpr size_type size () const noexcept { return this->len; }
|
||||
|
||||
constexpr bool empty () const noexcept { return this->size() == 0; }
|
||||
|
||||
constexpr reference operator [] (size_type idx) const {
|
||||
return this->str[idx];
|
||||
}
|
||||
|
||||
constexpr reference front () const { return this->str[0]; }
|
||||
constexpr reference back () const { return this->str[this->size() - 1]; }
|
||||
constexpr pointer data () const { return this->str; }
|
||||
|
||||
void remove_prefix (size_type n) {
|
||||
if (n > this->size()) { n = this->size(); }
|
||||
this->str += n;
|
||||
this->len -= n;
|
||||
}
|
||||
|
||||
void remove_suffix (size_type n) {
|
||||
if (n > this->size()) { n = this->size(); }
|
||||
this->len -= n;
|
||||
}
|
||||
|
||||
void clear () noexcept {
|
||||
this->str = nullptr;
|
||||
this->len = 0;
|
||||
}
|
||||
|
||||
size_type copy (CharT* s, size_type n, size_type pos = 0) const {
|
||||
if (pos > this->size()) {
|
||||
throw_out_of_range("position greater than size");
|
||||
}
|
||||
auto const rlen = std::min(n, this->size() - pos);
|
||||
::std::copy_n(this->begin() + pos, rlen, s);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
constexpr basic_string_view substr (
|
||||
size_type pos=0,
|
||||
size_type n=npos
|
||||
) const noexcept {
|
||||
return pos > this->size()
|
||||
? (throw_out_of_range("start position out of range"), *this)
|
||||
: basic_string_view {
|
||||
this->data() + pos,
|
||||
n == npos or pos + n > this->size()
|
||||
? (this->size() - pos)
|
||||
: n
|
||||
};
|
||||
}
|
||||
|
||||
bool starts_with (value_type value) const noexcept {
|
||||
return not this->empty() and traits::eq(value, this->front());
|
||||
}
|
||||
|
||||
bool ends_with (value_type value) const noexcept {
|
||||
return not this->empty() and traits::eq(value, this->back());
|
||||
}
|
||||
|
||||
bool starts_with (basic_string_view that) const noexcept {
|
||||
return this->size() >= that.size() and
|
||||
traits::compare(this->data(), that.data(), that.size()) == 0;
|
||||
}
|
||||
|
||||
bool ends_with (basic_string_view that) const noexcept {
|
||||
return this->size() >= that.size() and
|
||||
traits::compare(
|
||||
this->data() + this->size() - that.size(),
|
||||
that.data(),
|
||||
that.size()
|
||||
) == 0;
|
||||
}
|
||||
|
||||
/* compare */
|
||||
difference_type compare (basic_string_view s) const noexcept {
|
||||
auto cmp = traits::compare(
|
||||
this->data(),
|
||||
s.data(),
|
||||
::std::min(this->size(), s.size())
|
||||
);
|
||||
|
||||
if (cmp != 0) { return cmp; }
|
||||
if (this->size() == s.size()) { return 0; }
|
||||
if (this->size() < s.size()) { return -1; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
difference_type compare (
|
||||
size_type pos,
|
||||
size_type n,
|
||||
basic_string_view s
|
||||
) const noexcept { return this->substr(pos, n).compare(s); }
|
||||
|
||||
difference_type compare (
|
||||
size_type pos1,
|
||||
size_type n1,
|
||||
basic_string_view s,
|
||||
size_type pos2,
|
||||
size_type n2
|
||||
) const noexcept {
|
||||
return this->substr(pos1, n1).compare(s.substr(pos2, n2));
|
||||
}
|
||||
|
||||
difference_type compare (pointer s) const noexcept {
|
||||
return this->compare(basic_string_view { s });
|
||||
}
|
||||
|
||||
difference_type compare (
|
||||
size_type pos,
|
||||
size_type n,
|
||||
pointer s
|
||||
) const noexcept {
|
||||
return this->substr(pos, n).compare(basic_string_view { s });
|
||||
}
|
||||
|
||||
difference_type compare (
|
||||
size_type pos,
|
||||
size_type n1,
|
||||
pointer s,
|
||||
size_type n2
|
||||
) const noexcept {
|
||||
return this->substr(pos, n1).compare(basic_string_view { s, n2 });
|
||||
}
|
||||
|
||||
reference at (size_type idx) const {
|
||||
static constexpr auto error = "requested index out of range";
|
||||
if (idx >= this->size()) { throw_out_of_range(error); }
|
||||
return this->str[idx];
|
||||
}
|
||||
|
||||
/* find-first-not-of */
|
||||
size_type find_first_not_of (
|
||||
basic_string_view str,
|
||||
size_type pos = 0) const noexcept {
|
||||
if (pos > this->size()) { return npos; }
|
||||
auto begin = this->begin() + pos;
|
||||
auto end = this->end();
|
||||
auto const predicate = [str] (value_type v) { return str.find(v) == npos; };
|
||||
auto iter = std::find_if(begin, end, predicate);
|
||||
if (iter == end) { return npos; }
|
||||
return static_cast<size_type>(::std::distance(this->begin(), iter));
|
||||
}
|
||||
|
||||
size_type find_first_not_of (
|
||||
pointer s,
|
||||
size_type pos,
|
||||
size_type n) const noexcept {
|
||||
return this->find_first_not_of(basic_string_view { s, n }, pos);
|
||||
}
|
||||
|
||||
size_type find_first_not_of (pointer s, size_type pos = 0) const noexcept {
|
||||
return this->find_first_not_of(basic_string_view { s }, pos);
|
||||
}
|
||||
|
||||
size_type find_first_not_of (value_type c, size_type pos = 0) const noexcept {
|
||||
return this->find_first_not_of(
|
||||
basic_string_view { ::std::addressof(c), 1 },
|
||||
pos);
|
||||
}
|
||||
|
||||
/* find-first-of */
|
||||
size_type find_first_of (
|
||||
basic_string_view str,
|
||||
size_type pos = 0) const noexcept {
|
||||
if (pos > this->size()) { return npos; }
|
||||
auto iter = ::std::find_first_of(
|
||||
this->begin() + pos, this->end(),
|
||||
str.begin(), str.end(),
|
||||
traits::eq);
|
||||
if (iter == this->end()) { return npos; }
|
||||
return static_cast<size_type>(::std::distance(this->begin(), iter));
|
||||
}
|
||||
|
||||
size_type find_first_of (pointer s, size_type p, size_type n) const noexcept {
|
||||
return this->find_first_of(basic_string_view { s, n }, p);
|
||||
}
|
||||
|
||||
size_type find_first_of (pointer s, size_type pos = 0) const noexcept {
|
||||
return this->find_first_of(basic_string_view { s }, pos);
|
||||
}
|
||||
|
||||
size_type find_first_of (value_type c, size_type pos = 0) const noexcept {
|
||||
return this->find_first_of(
|
||||
basic_string_view { ::std::addressof(c), 1 },
|
||||
pos);
|
||||
}
|
||||
|
||||
/* find */
|
||||
size_type find (basic_string_view str, size_type pos = 0) const noexcept {
|
||||
if (pos >= this->size()) { return npos; }
|
||||
auto iter = ::std::search(
|
||||
this->begin() + pos, this->end(),
|
||||
str.begin(), str.end(),
|
||||
traits::eq);
|
||||
if (iter == this->end()) { return npos; }
|
||||
return static_cast<size_type>(::std::distance(this->begin(), iter));
|
||||
}
|
||||
|
||||
size_type find (pointer s, size_type p, size_type n) const noexcept {
|
||||
return this->find(basic_string_view { s, n }, p);
|
||||
}
|
||||
|
||||
size_type find (pointer s, size_type pos = 0) const noexcept {
|
||||
return this->find(basic_string_view { s }, pos);
|
||||
}
|
||||
|
||||
size_type find (value_type c, size_type pos = 0) const noexcept {
|
||||
return this->find(basic_string_view { ::std::addressof(c), 1 }, pos);
|
||||
}
|
||||
|
||||
size_type find_last_not_of (
|
||||
basic_string_view str,
|
||||
size_type pos = npos) const noexcept {
|
||||
auto const offset = this->size() - ::std::min(this->size(), pos);
|
||||
auto begin = this->rbegin() + static_cast<difference_type>(offset);
|
||||
auto end = this->rend();
|
||||
auto const predicate = [str] (value_type v) { return str.find(v) == npos; };
|
||||
auto iter = ::std::find_if(begin, end, predicate);
|
||||
if (iter == end) { return npos; }
|
||||
auto const distance = static_cast<size_type>(
|
||||
::std::distance(this->rbegin(), iter));
|
||||
return this->size() - distance - 1;
|
||||
}
|
||||
|
||||
size_type find_last_not_of (
|
||||
pointer s,
|
||||
size_type p,
|
||||
size_type n) const noexcept {
|
||||
return this->find_last_not_of(basic_string_view { s, n }, p);
|
||||
}
|
||||
|
||||
size_type find_last_not_of (pointer s, size_type p = npos) const noexcept {
|
||||
return this->find_last_not_of(basic_string_view { s }, p);
|
||||
}
|
||||
|
||||
size_type find_last_not_of (
|
||||
value_type c,
|
||||
size_type pos = npos) const noexcept {
|
||||
return this->find_last_not_of(
|
||||
basic_string_view { ::std::addressof(c), 1 },
|
||||
pos);
|
||||
}
|
||||
|
||||
size_type find_last_of (
|
||||
basic_string_view str,
|
||||
size_type pos = npos) const noexcept {
|
||||
auto const offset = this->size() - ::std::min(this->size(), pos);
|
||||
auto begin = this->rbegin() + static_cast<difference_type>(offset);
|
||||
auto end = this->rend();
|
||||
|
||||
auto iter = ::std::find_first_of(
|
||||
begin, end,
|
||||
str.rbegin(), str.rend(),
|
||||
traits::eq);
|
||||
if (iter == end) { return npos; }
|
||||
auto const distance = static_cast<size_type>(
|
||||
::std::distance(this->rbegin(), iter));
|
||||
return this->size() - distance - 1;
|
||||
}
|
||||
|
||||
size_type find_last_of (pointer s, size_type p, size_type n) const noexcept {
|
||||
return this->find_last_of(basic_string_view { s, n }, p);
|
||||
}
|
||||
|
||||
size_type find_last_of (pointer s, size_type p=npos) const noexcept {
|
||||
return this->find_last_of(basic_string_view { s }, p);
|
||||
}
|
||||
|
||||
size_type find_last_of (value_type c, size_type p=npos) const noexcept {
|
||||
return this->find_last_of(basic_string_view { ::std::addressof(c), 1 }, p);
|
||||
}
|
||||
|
||||
size_type rfind (basic_string_view str, size_type pos=npos) const noexcept {
|
||||
auto const offset = this->size() - ::std::min(this->size(), pos);
|
||||
auto begin = this->rbegin() + offset;
|
||||
auto end = this->rend();
|
||||
auto iter = ::std::search(
|
||||
begin, end,
|
||||
str.rbegin(), str.rend(),
|
||||
traits::eq);
|
||||
if (iter == end) { return npos; }
|
||||
auto const distance = static_cast<size_type>(
|
||||
::std::distance(this->rbegin(), iter));
|
||||
return this->size() - distance - 1;
|
||||
}
|
||||
|
||||
size_type rfind (pointer s, size_type p, size_type n) const noexcept {
|
||||
return this->rfind(basic_string_view { s, n }, p);
|
||||
}
|
||||
|
||||
size_type rfind (pointer s, size_type p=npos) const noexcept {
|
||||
return this->rfind(basic_string_view { s }, p);
|
||||
}
|
||||
|
||||
size_type rfind (value_type c, size_type p=npos) const noexcept {
|
||||
return this->rfind(basic_string_view { ::std::addressof(c), 1 }, p);
|
||||
}
|
||||
|
||||
void swap (basic_string_view& that) noexcept {
|
||||
using ::std::swap;
|
||||
swap(this->str, that.str);
|
||||
swap(this->len, that.len);
|
||||
}
|
||||
|
||||
private:
|
||||
pointer str { nullptr };
|
||||
size_type len { 0 };
|
||||
};
|
||||
|
||||
using u32string_view = basic_string_view<char32_t>;
|
||||
using u16string_view = basic_string_view<char16_t>;
|
||||
using wstring_view = basic_string_view<wchar_t>;
|
||||
using string_view = basic_string_view<char>;
|
||||
|
||||
/* string_view comparison string_view */
|
||||
template <class CharT, typename Traits>
|
||||
bool operator == (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return lhs.size() == rhs.size() and lhs.compare(rhs) == 0; }
|
||||
|
||||
template <class CharT, typename Traits>
|
||||
bool operator != (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return lhs.size() != rhs.size() or lhs.compare(rhs) != 0; }
|
||||
|
||||
template <class CharT, typename Traits>
|
||||
bool operator >= (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return lhs.compare(rhs) >= 0; }
|
||||
|
||||
template <class CharT, typename Traits>
|
||||
bool operator <= (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return lhs.compare(rhs) <= 0; }
|
||||
|
||||
template <class CharT, typename Traits>
|
||||
bool operator > (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return lhs.compare(rhs) > 0; }
|
||||
|
||||
template <class CharT, typename Traits>
|
||||
bool operator < (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return lhs.compare(rhs) < 0; }
|
||||
|
||||
/* string_view comparison string */
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator == (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
::std::basic_string<CharT, Traits, Allocator> const& rhs
|
||||
) noexcept { return lhs == basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator != (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
::std::basic_string<CharT, Traits, Allocator> const& rhs
|
||||
) noexcept { return lhs != basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator >= (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
::std::basic_string<CharT, Traits, Allocator> const& rhs
|
||||
) noexcept { return lhs >= basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator <= (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
::std::basic_string<CharT, Traits, Allocator> const& rhs
|
||||
) noexcept { return lhs <= basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator > (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
::std::basic_string<CharT, Traits, Allocator> const& rhs
|
||||
) noexcept { return lhs > basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator < (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
::std::basic_string<CharT, Traits, Allocator> const& rhs
|
||||
) noexcept { return lhs < basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
/* string comparison string_view */
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator == (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } == rhs; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator != (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } != rhs; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator >= (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } >= rhs; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator <= (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } <= rhs; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator > (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } > rhs; }
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator < (
|
||||
::std::basic_string<CharT, Traits, Allocator> const& lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } < rhs; }
|
||||
|
||||
/* string_view comparison CharT* */
|
||||
template <class CharT, class Traits>
|
||||
bool operator == (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
CharT const* rhs
|
||||
) noexcept { return lhs == basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator != (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
CharT const* rhs
|
||||
) noexcept { return lhs != basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator >= (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
CharT const* rhs
|
||||
) noexcept { return lhs >= basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator <= (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
CharT const* rhs
|
||||
) noexcept { return lhs <= basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator > (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
CharT const* rhs
|
||||
) noexcept { return lhs > basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator < (
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
CharT const* rhs
|
||||
) noexcept { return lhs < basic_string_view<CharT, Traits> { rhs }; }
|
||||
|
||||
/* CharT* comparison string_view */
|
||||
template <class CharT, class Traits>
|
||||
bool operator == (
|
||||
CharT const* lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } == rhs; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator != (
|
||||
CharT const* lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } != rhs; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator >= (
|
||||
CharT const* lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } >= rhs; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator <= (
|
||||
CharT const* lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } <= rhs; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator > (
|
||||
CharT const* lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } > rhs; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator < (
|
||||
CharT const* lhs,
|
||||
basic_string_view<CharT, Traits> rhs
|
||||
) noexcept { return basic_string_view<CharT, Traits> { lhs } < rhs; }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
::std::basic_ostream<CharT, Traits>& operator << (
|
||||
::std::basic_ostream<CharT, Traits>& os,
|
||||
basic_string_view<CharT, Traits> const& str
|
||||
) { return os << str.to_string(); }
|
||||
|
||||
template <class CharT, class Traits>
|
||||
void swap (
|
||||
basic_string_view<CharT, Traits>& lhs,
|
||||
basic_string_view<CharT, Traits>& rhs
|
||||
) noexcept { return lhs.swap(rhs); }
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
struct hash<core::v2::basic_string_view<CharT, Traits>> {
|
||||
using argument_type = core::v2::basic_string_view<CharT, Traits>;
|
||||
using result_type = size_t;
|
||||
|
||||
result_type operator ()(argument_type const& ref) const noexcept {
|
||||
static constexpr core::impl::murmur<sizeof(size_t)> hasher { };
|
||||
return hasher(ref.data(), ref.size());
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif /* defined(_MSC_VER) */
|
||||
#endif /* CORE_STRING_VIEW_HPP */
|
||||
@@ -0,0 +1,266 @@
|
||||
#ifndef CORE_TYPE_TRAITS_HPP
|
||||
#define CORE_TYPE_TRAITS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
|
||||
#include "internal.hpp"
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
namespace impl {
|
||||
|
||||
/* union used for variant<Ts...> and implementing aligned_union, which is
|
||||
* not provided by gcc 4.8.x, but is provided by clang. (aligned_union_t is
|
||||
* the only alias missing from <type_traits>)
|
||||
*/
|
||||
template <class... Ts> union discriminate;
|
||||
template <> union discriminate<> { };
|
||||
template <class T, class... Ts>
|
||||
union discriminate<T, Ts...> {
|
||||
T value;
|
||||
discriminate<Ts...> rest;
|
||||
};
|
||||
|
||||
} /* namespace impl */
|
||||
|
||||
/* custom type traits and types */
|
||||
template <class T> using identity_t = typename meta::identity<T>::type;
|
||||
template <class T> using identity = meta::identity<T>;
|
||||
|
||||
/* extracts the class of a member function ponter */
|
||||
template <class T> using class_of_t = impl::class_of_t<T>;
|
||||
template <class T> using class_of = impl::class_of<T>;
|
||||
|
||||
template <::std::size_t I, class T>
|
||||
using tuple_element_t = typename ::std::tuple_element<I, T>::type;
|
||||
template <class T> using tuple_size_t = typename ::std::tuple_size<T>::type;
|
||||
|
||||
/* Implementation of N4389 */
|
||||
template <bool B> using bool_constant = ::std::integral_constant<bool, B>;
|
||||
|
||||
template <class...> struct conjunction;
|
||||
template <class...> struct disjunction;
|
||||
template <class...> struct negation;
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct conjunction<T, Ts...> :
|
||||
bool_constant<T::value and conjunction<Ts...>::value>
|
||||
{ };
|
||||
template <> struct conjunction<> : ::std::true_type { };
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct disjunction<T, Ts...> :
|
||||
bool_constant<T::value or disjunction<Ts...>::value>
|
||||
{ };
|
||||
template <> struct disjunction<> : ::std::false_type { };
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct negation<T, Ts...> :
|
||||
bool_constant<not T::value and negation<Ts...>::value>
|
||||
{ };
|
||||
template <> struct negation<> : ::std::false_type { };
|
||||
|
||||
/* C++ Library Fundamentals V2 TS detection idiom */
|
||||
template <class... Ts> using void_t = meta::deduce<Ts...>;
|
||||
|
||||
struct nonesuch {
|
||||
nonesuch (nonesuch const&) = delete;
|
||||
nonesuch () = delete;
|
||||
~nonesuch () = delete;
|
||||
void operator = (nonesuch const&) = delete;
|
||||
};
|
||||
|
||||
template <class T, template <class...> class U, class... Args>
|
||||
using detected_or = impl::make_detect<T, void, U, Args...>;
|
||||
|
||||
template <template <class...> class T, class... Args>
|
||||
using detected_t = typename detected_or<nonesuch, T, Args...>::type;
|
||||
|
||||
template <class T, template <class...> class U, class... Args>
|
||||
using detected_or_t = typename detected_or<T, U, Args...>::type;
|
||||
|
||||
template <class To, template <class...> class T, class... Args>
|
||||
using is_detected_convertible = ::std::is_convertible<
|
||||
detected_t<T, Args...>,
|
||||
To
|
||||
>;
|
||||
|
||||
template <class T, template <class...> class U, class... Args>
|
||||
using is_detected_same = ::std::is_same<T, detected_t<U, Args...>>;
|
||||
|
||||
template <class T, template<class...> class U, class... Args>
|
||||
using is_detected_convertible = ::std::is_convertible<
|
||||
detected_t<U, Args...>,
|
||||
T
|
||||
>;
|
||||
|
||||
template <template <class...> class T, class... Args>
|
||||
using is_detected = typename detected_or<nonesuch, T, Args...>::value_t;
|
||||
|
||||
/* forward declaration */
|
||||
template <::std::size_t, class...> struct aligned_union;
|
||||
template <class...> struct invokable;
|
||||
template <class...> struct invoke_of;
|
||||
template <class T> struct result_of; /* SFINAE result_of */
|
||||
|
||||
/* C++14 style aliases for standard traits */
|
||||
template <class T>
|
||||
using remove_volatile_t = typename ::std::remove_volatile<T>::type;
|
||||
|
||||
template <class T>
|
||||
using remove_const_t = typename ::std::remove_const<T>::type;
|
||||
template <class T> using remove_cv_t = typename ::std::remove_cv<T>::type;
|
||||
|
||||
template <class T>
|
||||
using add_volatile_t = typename ::std::add_volatile<T>::type;
|
||||
template <class T> using add_const_t = typename ::std::add_const<T>::type;
|
||||
template <class T> using add_cv_t = typename ::std::add_cv<T>::type;
|
||||
|
||||
template <class T>
|
||||
using add_lvalue_reference_t = typename ::std::add_lvalue_reference<T>::type;
|
||||
|
||||
template <class T>
|
||||
using add_rvalue_reference_t = typename ::std::add_rvalue_reference<T>::type;
|
||||
|
||||
template <class T>
|
||||
using remove_reference_t = typename ::std::remove_reference<T>::type;
|
||||
|
||||
template <class T>
|
||||
using remove_pointer_t = typename ::std::remove_pointer<T>::type;
|
||||
|
||||
template <class T> using add_pointer_t = typename ::std::add_pointer<T>::type;
|
||||
|
||||
template <class T>
|
||||
using make_unsigned_t = typename ::std::make_unsigned<T>::type;
|
||||
template <class T> using make_signed_t = typename ::std::make_signed<T>::type;
|
||||
|
||||
template <class T>
|
||||
using remove_extent_t = typename ::std::remove_extent<T>::type;
|
||||
|
||||
template <class T>
|
||||
using remove_all_extents_t = typename ::std::remove_all_extents<T>::type;
|
||||
|
||||
template <
|
||||
::std::size_t Len,
|
||||
::std::size_t Align = alignof(typename ::std::aligned_storage<Len>::type)
|
||||
> using aligned_storage_t = typename ::std::aligned_storage<Len, Align>::type;
|
||||
|
||||
template <::std::size_t Len, class... Types>
|
||||
using aligned_union_t = typename aligned_union<Len, Types...>::type;
|
||||
|
||||
template <class T> using decay_t = impl::decay_t<T>;
|
||||
|
||||
template <bool B, class T = void>
|
||||
using enable_if_t = typename ::std::enable_if<B, T>::type;
|
||||
|
||||
template <bool B, class T, class F>
|
||||
using conditional_t = typename ::std::conditional<B, T, F>::type;
|
||||
|
||||
template <class T>
|
||||
using underlying_type_t = typename ::std::underlying_type<T>::type;
|
||||
|
||||
template <::std::size_t Len, class... Types>
|
||||
struct aligned_union {
|
||||
using union_type = impl::discriminate<Types...>;
|
||||
static constexpr ::std::size_t size () noexcept {
|
||||
return Len > sizeof(union_type) ? Len : sizeof(union_type);
|
||||
}
|
||||
|
||||
static constexpr ::std::size_t alignment_value = alignof(
|
||||
impl::discriminate<Types...>
|
||||
);
|
||||
|
||||
using type = aligned_storage_t<
|
||||
(Len > sizeof(union_type) ? Len : sizeof(union_type)),
|
||||
alignment_value
|
||||
>;
|
||||
};
|
||||
|
||||
/* custom type trait specializations */
|
||||
template <class... Args> using invoke_of_t = typename invoke_of<Args...>::type;
|
||||
|
||||
template <class... Args>
|
||||
struct invokable : meta::none_t<
|
||||
std::is_same<
|
||||
decltype(impl::INVOKE(::std::declval<Args>()...)),
|
||||
impl::undefined
|
||||
>::value
|
||||
> { };
|
||||
|
||||
template <class... Args> struct invoke_of :
|
||||
impl::invoke_of<invokable<Args...>::value, Args...>
|
||||
{ };
|
||||
|
||||
template <class F, class... Args>
|
||||
struct result_of<F(Args...)> : invoke_of<F, Args...> { };
|
||||
|
||||
template <class T> using result_of_t = typename result_of<T>::type;
|
||||
|
||||
template <class... Ts> struct common_type;
|
||||
|
||||
template <class T> struct common_type<T> : identity<decay_t<T>> { };
|
||||
template <class T, class U>
|
||||
struct common_type<T, U> : identity<
|
||||
decay_t<decltype(true ? ::std::declval<T>() : ::std::declval<U>())>
|
||||
> { };
|
||||
|
||||
template <class T, class U, class... Ts>
|
||||
struct common_type<T, U, Ts...> : identity<
|
||||
typename common_type<
|
||||
typename common_type<T, U>::type,
|
||||
Ts...
|
||||
>::type
|
||||
> { };
|
||||
|
||||
template <class... T> using common_type_t = typename common_type<T...>::type;
|
||||
|
||||
/* is_null_pointer */
|
||||
template <class T> struct is_null_pointer : ::std::false_type { };
|
||||
|
||||
template <>
|
||||
struct is_null_pointer<add_cv_t<::std::nullptr_t>> : ::std::true_type { };
|
||||
template <>
|
||||
struct is_null_pointer<::std::nullptr_t volatile> : ::std::true_type { };
|
||||
template <>
|
||||
struct is_null_pointer<::std::nullptr_t const> : ::std::true_type { };
|
||||
template <>
|
||||
struct is_null_pointer<::std::nullptr_t> : ::std::true_type { };
|
||||
|
||||
/* is_nothrow_swappable - N4426 (implemented before paper was proposed) */
|
||||
template <class T, class U=T>
|
||||
using is_nothrow_swappable = impl::is_nothrow_swappable<T, U>;
|
||||
|
||||
/* propagates const or volatile without using the name propagate :) */
|
||||
template <class T, class U>
|
||||
struct transmit_volatile : ::std::conditional<
|
||||
::std::is_volatile<T>::value,
|
||||
add_volatile_t<U>,
|
||||
U
|
||||
> { };
|
||||
|
||||
template <class T, class U>
|
||||
struct transmit_const : ::std::conditional<
|
||||
::std::is_const<T>::value,
|
||||
add_const_t<U>,
|
||||
U
|
||||
> { };
|
||||
|
||||
template <class T, class U>
|
||||
struct transmit_cv : transmit_volatile<
|
||||
T, typename transmit_const<T, U>::type
|
||||
> { };
|
||||
|
||||
template <class T, class U>
|
||||
using transmit_volatile_t = typename transmit_volatile<T, U>::type;
|
||||
|
||||
template <class T, class U>
|
||||
using transmit_const_t = typename transmit_const<T, U>::type;
|
||||
|
||||
template <class T, class U>
|
||||
using transmit_cv_t = typename transmit_cv<T, U>::type;
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_TYPE_TRAITS_HPP */
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_TYPEINFO_HPP
|
||||
#define CORE_TYPEINFO_HPP
|
||||
|
||||
#include "type_traits.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#ifndef CORE_NO_RTTI
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#endif /* CORE_NO_RTTI */
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
|
||||
#ifndef CORE_NO_RTTI
|
||||
using type_info = ::std::type_info;
|
||||
|
||||
template <class T>
|
||||
type_info const& type_of () noexcept { return typeid(T); }
|
||||
#else /* CORE_NO_RTTI */
|
||||
struct type_info final {
|
||||
|
||||
type_info (type_info const&) = delete;
|
||||
type_info () = delete;
|
||||
virtual ~type_info () = default;
|
||||
|
||||
type_info& operator = (type_info const&) = delete;
|
||||
|
||||
/* If we had C++14 template variables, this would actually be easier */
|
||||
template <class T>
|
||||
friend type_info const& type_of () noexcept {
|
||||
return type_info::cref<remove_reference_t<remove_cv_t<T>>>();
|
||||
}
|
||||
|
||||
bool operator == (type_info const& that) const noexcept {
|
||||
return this->id == that.id;
|
||||
}
|
||||
|
||||
bool operator != (type_info const& that) const noexcept {
|
||||
return this->id != that.id;
|
||||
}
|
||||
|
||||
bool before (type_info const& that) const noexcept {
|
||||
return this->id < that.id;
|
||||
}
|
||||
|
||||
::std::size_t hash_code () const noexcept { return this->id; }
|
||||
|
||||
private:
|
||||
type_info (::std::uintptr_t id) noexcept : id { id } { }
|
||||
|
||||
template <class T>
|
||||
static type_info const& cref () noexcept {
|
||||
static ::std::uintptr_t const value { };
|
||||
static type_info const instance { as_int(::std::addressof(value)) };
|
||||
return instance;
|
||||
}
|
||||
|
||||
::std::uintptr_t const id;
|
||||
};
|
||||
|
||||
#endif /* CORE_NO_RTTI */
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_TYPEINFO_HPP */
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Copyright © 2013 - 2015 MNMLSTC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this software except in compliance with the License. You may
|
||||
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
#ifndef CORE_UTILITY_HPP
|
||||
#define CORE_UTILITY_HPP
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "type_traits.hpp"
|
||||
|
||||
namespace core {
|
||||
inline namespace v2 {
|
||||
|
||||
template <class T>
|
||||
constexpr T&& forward (remove_reference_t<T>& t) noexcept {
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr T&& forward (remove_reference_t<T>&& t) noexcept {
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr auto move (T&& t) noexcept -> decltype(
|
||||
static_cast<remove_reference_t<T>&&>(t)
|
||||
) { return static_cast<remove_reference_t<T>&&>(t); }
|
||||
|
||||
|
||||
template <class T, T... I>
|
||||
using integer_sequence = meta::integer_sequence<T, I...>;
|
||||
|
||||
template <::std::size_t... I>
|
||||
using index_sequence = integer_sequence<::std::size_t, I...>;
|
||||
|
||||
template <class T, T N>
|
||||
using make_integer_sequence = typename meta::iota<T, N, N>::type;
|
||||
|
||||
template <::std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<::std::size_t, N>;
|
||||
|
||||
template <class... Ts>
|
||||
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
|
||||
|
||||
template <::std::size_t N, class T, class... Ts>
|
||||
constexpr auto value_at (T&& value, Ts&&...) -> enable_if_t<
|
||||
N == 0 and N < (sizeof...(Ts) + 1),
|
||||
decltype(::core::forward<T>(value))
|
||||
> { return ::core::forward<T>(value); }
|
||||
|
||||
template <::std::size_t N, class T, class... Ts>
|
||||
constexpr auto value_at (T&&, Ts&&... values) -> enable_if_t<
|
||||
N != 0 and N < (sizeof...(Ts) + 1),
|
||||
meta::get<meta::list<T, Ts...>, N>
|
||||
> { return value_at<N - 1, Ts...>(::core::forward<Ts>(values)...); }
|
||||
|
||||
template <class Callable>
|
||||
struct scope_guard final {
|
||||
|
||||
static_assert(
|
||||
::std::is_nothrow_move_constructible<Callable>::value,
|
||||
"Given type must be nothrow move constructible"
|
||||
);
|
||||
|
||||
explicit scope_guard (Callable callable) noexcept :
|
||||
callable { ::core::move(callable) },
|
||||
dismissed { false }
|
||||
{ }
|
||||
|
||||
scope_guard (scope_guard const&) = delete;
|
||||
scope_guard (scope_guard&&) = default;
|
||||
scope_guard () = delete;
|
||||
~scope_guard () noexcept { if (not this->dismissed) { callable(); } }
|
||||
|
||||
scope_guard& operator = (scope_guard const&) = delete;
|
||||
scope_guard& operator = (scope_guard&&) = default;
|
||||
|
||||
void dismiss () noexcept { this->dismissed = true; }
|
||||
|
||||
private:
|
||||
Callable callable;
|
||||
bool dismissed;
|
||||
};
|
||||
|
||||
template <class Callable>
|
||||
auto make_scope_guard(Callable&& callable) -> scope_guard<decay_t<Callable>> {
|
||||
return scope_guard<decay_t<Callable>> {
|
||||
::core::forward<Callable>(callable)
|
||||
};
|
||||
}
|
||||
|
||||
template <class T, class U=T>
|
||||
T exchange (T& obj, U&& value) noexcept(
|
||||
meta::all<
|
||||
::std::is_nothrow_move_constructible<T>,
|
||||
::std::is_nothrow_assignable<add_lvalue_reference_t<T>, U>
|
||||
>()
|
||||
) {
|
||||
T old = ::core::move(obj);
|
||||
obj = ::core::forward<U>(value);
|
||||
return old;
|
||||
}
|
||||
|
||||
inline ::std::uintptr_t as_int (void const* ptr) noexcept {
|
||||
return reinterpret_cast<::std::uintptr_t>(ptr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void const* as_void (T const* ptr) { return static_cast<void const*>(ptr); }
|
||||
|
||||
template <class T>
|
||||
void* as_void (T* ptr) { return static_cast<void*>(ptr); }
|
||||
|
||||
template <class T>
|
||||
void const* as_void (T const& ref) { return as_void(::std::addressof(ref)); }
|
||||
|
||||
template <class T>
|
||||
void* as_void (T& ref) { return as_void(::std::addressof(ref)); }
|
||||
|
||||
template <class E>
|
||||
constexpr auto as_under(E e) noexcept -> meta::when<
|
||||
std::is_enum<E>::value,
|
||||
underlying_type_t<E>
|
||||
> { return static_cast<underlying_type_t<E>>(e); }
|
||||
|
||||
template <class T>
|
||||
struct capture final {
|
||||
static_assert(::std::is_move_constructible<T>::value, "T must be movable");
|
||||
using value_type = T;
|
||||
using reference = add_lvalue_reference_t<value_type>;
|
||||
using pointer = add_pointer_t<value_type>;
|
||||
|
||||
capture (T&& data) : data { core::move(data) } { }
|
||||
|
||||
capture (capture&&) = default;
|
||||
capture (capture& that) : data { core::move(that.data) } { }
|
||||
capture () = delete;
|
||||
|
||||
capture& operator = (capture const&) = delete;
|
||||
capture& operator = (capture&&) = delete;
|
||||
|
||||
operator reference () const noexcept { return this->get(); }
|
||||
reference operator * () const noexcept { return this->get(); }
|
||||
pointer operator -> () const noexcept {
|
||||
return ::std::addressof(this->get());
|
||||
}
|
||||
|
||||
reference get () const noexcept { return this->data; }
|
||||
|
||||
private:
|
||||
value_type data;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
auto make_capture (remove_reference_t<T>& ref) -> capture<T> {
|
||||
return capture<T> { core::move(ref) };
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto make_capture (remove_reference_t<T>&& ref) -> capture<T> {
|
||||
return capture<T> { core::move(ref) };
|
||||
}
|
||||
|
||||
struct erased_type { };
|
||||
|
||||
}} /* namespace core::v2 */
|
||||
|
||||
#endif /* CORE_UTILITY_HPP */
|
||||
@@ -18,8 +18,6 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
#include "timers.hpp"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#define MLPACK_CORE_UTIL_PARAM_DATA_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <boost/any.hpp>
|
||||
|
||||
/**
|
||||
* The TYPENAME macro is used internally to convert a type into a string.
|
||||
@@ -76,7 +75,7 @@ struct ParamData
|
||||
bool loaded;
|
||||
//! The actual value that is held. If the user has passed a different type,
|
||||
//! this may be a tuple containing multiple values.
|
||||
boost::any value;
|
||||
ANY value;
|
||||
//! The true name of the type, as it would be written in C++.
|
||||
std::string cppType;
|
||||
};
|
||||
|
||||
@@ -50,7 +50,7 @@ T& Params::Get(const std::string& identifier)
|
||||
}
|
||||
else
|
||||
{
|
||||
return *boost::any_cast<T>(&d.value);
|
||||
return *ANY_CAST<T>(&d.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,12 +162,12 @@ Convolution<
|
||||
padWRight(layer.padWRight),
|
||||
padHBottom(layer.padHBottom),
|
||||
padHTop(layer.padHTop),
|
||||
weights(layer.weights),
|
||||
inputWidth(layer.inputWidth),
|
||||
inputHeight(layer.inputHeight),
|
||||
outputWidth(layer.outputWidth),
|
||||
outputHeight(layer.outputHeight),
|
||||
padding(layer.padding),
|
||||
weights(layer.weights)
|
||||
padding(layer.padding)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -197,12 +197,12 @@ Convolution<
|
||||
padWRight(layer.padWRight),
|
||||
padHBottom(layer.padHBottom),
|
||||
padHTop(layer.padHTop),
|
||||
weights(std::move(layer.weights)),
|
||||
inputWidth(layer.inputWidth),
|
||||
inputHeight(layer.inputHeight),
|
||||
outputWidth(layer.outputWidth),
|
||||
outputHeight(layer.outputHeight),
|
||||
padding(std::move(layer.padding)),
|
||||
weights(std::move(layer.weights))
|
||||
padding(std::move(layer.padding))
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
@@ -484,9 +484,15 @@ class DecisionTree :
|
||||
std::vector<DecisionTree*> children;
|
||||
//! The dimension this node splits on.
|
||||
size_t splitDimension;
|
||||
//! The type of the dimension that we have split on (if we are not a leaf).
|
||||
//! If we are a leaf, then this is the index of the majority class.
|
||||
size_t dimensionTypeOrMajorityClass;
|
||||
|
||||
union
|
||||
{
|
||||
//! Stores the type of dimension on which the split is done for internal
|
||||
//! nodes of the tree.
|
||||
size_t dimensionType;
|
||||
//! Stores the majority class for leaf nodes of the tree.
|
||||
size_t majorityClass;
|
||||
};
|
||||
/**
|
||||
* This vector may hold different things. If the node has no children, then
|
||||
* it is guaranteed to hold the probabilities of each class. If the node has
|
||||
|
||||
@@ -270,7 +270,7 @@ DecisionTree<FitnessFunction,
|
||||
DimensionSelectionType,
|
||||
NoRecursion>::DecisionTree(const size_t numClasses) :
|
||||
splitDimension(0),
|
||||
dimensionTypeOrMajorityClass(0),
|
||||
dimensionType(0),
|
||||
classProbabilities(numClasses)
|
||||
{
|
||||
// Initialize utility vector.
|
||||
@@ -291,12 +291,16 @@ DecisionTree<FitnessFunction,
|
||||
NumericAuxiliarySplitInfo(other),
|
||||
CategoricalAuxiliarySplitInfo(other),
|
||||
splitDimension(other.splitDimension),
|
||||
dimensionTypeOrMajorityClass(other.dimensionTypeOrMajorityClass),
|
||||
classProbabilities(other.classProbabilities)
|
||||
{
|
||||
// Copy each child.
|
||||
for (size_t i = 0; i < other.children.size(); ++i)
|
||||
children.push_back(new DecisionTree(*other.children[i]));
|
||||
|
||||
if (children.size() != 0)
|
||||
dimensionType = other.dimensionType;
|
||||
else
|
||||
majorityClass = other.majorityClass;
|
||||
}
|
||||
|
||||
//! Take ownership of another tree.
|
||||
@@ -314,9 +318,13 @@ DecisionTree<FitnessFunction,
|
||||
CategoricalAuxiliarySplitInfo(std::move(other)),
|
||||
children(std::move(other.children)),
|
||||
splitDimension(other.splitDimension),
|
||||
dimensionTypeOrMajorityClass(other.dimensionTypeOrMajorityClass),
|
||||
classProbabilities(std::move(other.classProbabilities))
|
||||
{
|
||||
if (children.size() != 0)
|
||||
dimensionType = other.dimensionType;
|
||||
else
|
||||
majorityClass = other.majorityClass;
|
||||
|
||||
// Reset the other object.
|
||||
other.classProbabilities.ones(1); // One class, P(1) = 1.
|
||||
}
|
||||
@@ -348,7 +356,12 @@ DecisionTree<FitnessFunction,
|
||||
|
||||
// Copy everything from the other tree.
|
||||
splitDimension = other.splitDimension;
|
||||
dimensionTypeOrMajorityClass = other.dimensionTypeOrMajorityClass;
|
||||
|
||||
if (children.size() != 0)
|
||||
dimensionType = other.dimensionType;
|
||||
else
|
||||
majorityClass = other.majorityClass;
|
||||
|
||||
classProbabilities = other.classProbabilities;
|
||||
|
||||
// Copy the children.
|
||||
@@ -390,7 +403,12 @@ DecisionTree<FitnessFunction,
|
||||
// Take ownership of the other tree's components.
|
||||
children = std::move(other.children);
|
||||
splitDimension = other.splitDimension;
|
||||
dimensionTypeOrMajorityClass = other.dimensionTypeOrMajorityClass;
|
||||
|
||||
if (children.size() != 0)
|
||||
dimensionType = other.dimensionType;
|
||||
else
|
||||
majorityClass = other.majorityClass;
|
||||
|
||||
classProbabilities = std::move(other.classProbabilities);
|
||||
|
||||
// Reset the class probabilities of the other object.
|
||||
@@ -684,7 +702,7 @@ double DecisionTree<FitnessFunction,
|
||||
// Did we split or not? If so, then split the data and create the children.
|
||||
if (bestDim != datasetInfo.Dimensionality())
|
||||
{
|
||||
dimensionTypeOrMajorityClass = (size_t) datasetInfo.Type(bestDim);
|
||||
dimensionType = (size_t) datasetInfo.Type(bestDim);
|
||||
splitDimension = bestDim;
|
||||
|
||||
// Get the number of children we will have.
|
||||
@@ -858,7 +876,7 @@ double DecisionTree<FitnessFunction,
|
||||
size_t numChildren =
|
||||
NumericSplit::NumChildren(classProbabilities[0], *this);
|
||||
splitDimension = bestDim;
|
||||
dimensionTypeOrMajorityClass = (size_t) data::Datatype::numeric;
|
||||
dimensionType = (size_t) data::Datatype::numeric;
|
||||
|
||||
// Calculate all child assignments.
|
||||
arma::Row<size_t> childAssignments(count);
|
||||
@@ -950,7 +968,7 @@ size_t DecisionTree<FitnessFunction,
|
||||
if (children.size() == 0)
|
||||
{
|
||||
// Return cached max of probabilities.
|
||||
return dimensionTypeOrMajorityClass;
|
||||
return majorityClass;
|
||||
}
|
||||
|
||||
return children[CalculateDirection(point)]->Classify(point);
|
||||
@@ -973,7 +991,7 @@ void DecisionTree<FitnessFunction,
|
||||
{
|
||||
if (children.size() == 0)
|
||||
{
|
||||
prediction = dimensionTypeOrMajorityClass;
|
||||
prediction = majorityClass;
|
||||
probabilities = classProbabilities;
|
||||
return;
|
||||
}
|
||||
@@ -999,7 +1017,7 @@ void DecisionTree<FitnessFunction,
|
||||
predictions.set_size(data.n_cols);
|
||||
if (children.size() == 0)
|
||||
{
|
||||
predictions.fill(dimensionTypeOrMajorityClass);
|
||||
predictions.fill(majorityClass);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1044,7 @@ void DecisionTree<FitnessFunction,
|
||||
predictions.set_size(data.n_cols);
|
||||
if (children.size() == 0)
|
||||
{
|
||||
predictions.fill(dimensionTypeOrMajorityClass);
|
||||
predictions.fill(majorityClass);
|
||||
probabilities = arma::repmat(classProbabilities, 1, data.n_cols);
|
||||
return;
|
||||
}
|
||||
@@ -1071,7 +1089,8 @@ void DecisionTree<FitnessFunction,
|
||||
|
||||
// Now serialize the rest of the object.
|
||||
ar(CEREAL_NVP(splitDimension));
|
||||
ar(CEREAL_NVP(dimensionTypeOrMajorityClass));
|
||||
// Since dimensionType and majorityClass are a union, we only need to serialize one.
|
||||
ar(CEREAL_NVP(dimensionType));
|
||||
ar(CEREAL_NVP(classProbabilities));
|
||||
}
|
||||
|
||||
@@ -1087,8 +1106,7 @@ size_t DecisionTree<FitnessFunction,
|
||||
DimensionSelectionType,
|
||||
NoRecursion>::CalculateDirection(const VecType& point) const
|
||||
{
|
||||
if ((data::Datatype) dimensionTypeOrMajorityClass ==
|
||||
data::Datatype::categorical)
|
||||
if ((data::Datatype) dimensionType == data::Datatype::categorical)
|
||||
return CategoricalSplit::CalculateDirection(point[splitDimension],
|
||||
classProbabilities[0], *this);
|
||||
else
|
||||
@@ -1150,7 +1168,7 @@ void DecisionTree<FitnessFunction,
|
||||
classProbabilities /= UseWeights ? sumWeights : labels.n_elem;
|
||||
arma::uword maxIndex = 0;
|
||||
classProbabilities.max(maxIndex);
|
||||
dimensionTypeOrMajorityClass = (size_t) maxIndex;
|
||||
majorityClass = (size_t) maxIndex;
|
||||
}
|
||||
|
||||
} // namespace tree
|
||||
|
||||
@@ -450,14 +450,14 @@ class DecisionTreeRegressor :
|
||||
//! The type of the dimension that we have split on (only meaningful if this
|
||||
//! is a non-leaf in a trained tree).
|
||||
size_t dimensionType;
|
||||
/**
|
||||
* This variable may hold different things. If the node has no children, then
|
||||
* it is guaranteed to hold the prediction value for that node. If the node
|
||||
* has children, then it may be used arbitrarily by the split type's
|
||||
* CalculateDirection() and SplitIfBetter() function. In this case, it stores
|
||||
* the point at which the split was made.
|
||||
*/
|
||||
double splitPointOrPrediction;
|
||||
|
||||
union
|
||||
{
|
||||
//! Stores the split point for internal nodes of the tree.
|
||||
double splitPoint;
|
||||
//! Stores the prediction value for leaf nodes of the tree.
|
||||
double prediction;
|
||||
};
|
||||
|
||||
//! Note that this class will also hold the members of the NumericSplit and
|
||||
//! CategoricalSplit AuxiliarySplitInfo classes, since it inherits from them.
|
||||
|
||||
@@ -31,7 +31,7 @@ DecisionTreeRegressor<FitnessFunction,
|
||||
NoRecursion>::DecisionTreeRegressor() :
|
||||
splitDimension(0),
|
||||
dimensionType(0),
|
||||
splitPointOrPrediction(0.0)
|
||||
splitPoint(0.0)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -286,12 +286,16 @@ DecisionTreeRegressor<FitnessFunction,
|
||||
NumericAuxiliarySplitInfo(other),
|
||||
CategoricalAuxiliarySplitInfo(other),
|
||||
splitDimension(other.splitDimension),
|
||||
dimensionType(other.dimensionType),
|
||||
splitPointOrPrediction(other.splitPointOrPrediction)
|
||||
dimensionType(other.dimensionType)
|
||||
{
|
||||
// Copy each child.
|
||||
for (size_t i = 0; i < other.children.size(); ++i)
|
||||
children.push_back(new DecisionTreeRegressor(*other.children[i]));
|
||||
|
||||
if (children.size() != 0)
|
||||
splitPoint = other.splitPoint;
|
||||
else
|
||||
prediction = other.prediction;
|
||||
}
|
||||
|
||||
//! Take ownership of another tree.
|
||||
@@ -311,10 +315,12 @@ DecisionTreeRegressor<FitnessFunction,
|
||||
CategoricalAuxiliarySplitInfo(std::move(other)),
|
||||
children(std::move(other.children)),
|
||||
splitDimension(other.splitDimension),
|
||||
dimensionType(other.dimensionType),
|
||||
splitPointOrPrediction(other.splitPointOrPrediction)
|
||||
dimensionType(other.dimensionType)
|
||||
{
|
||||
// Nothing to do here.
|
||||
if (children.size() != 0)
|
||||
splitPoint = other.splitPoint;
|
||||
else
|
||||
prediction = other.prediction;
|
||||
}
|
||||
|
||||
//! Copy another tree.
|
||||
@@ -346,7 +352,11 @@ DecisionTreeRegressor<FitnessFunction,
|
||||
// Copy everything from the other tree.
|
||||
splitDimension = other.splitDimension;
|
||||
dimensionType = other.dimensionType;
|
||||
splitPointOrPrediction = other.splitPointOrPrediction;
|
||||
|
||||
if (other.children.size() != 0)
|
||||
splitPoint = other.splitPoint;
|
||||
else
|
||||
prediction = other.prediction;
|
||||
|
||||
// Copy the children.
|
||||
for (size_t i = 0; i < other.children.size(); ++i)
|
||||
@@ -389,7 +399,11 @@ DecisionTreeRegressor<FitnessFunction,
|
||||
children = std::move(other.children);
|
||||
splitDimension = other.splitDimension;
|
||||
dimensionType = other.dimensionType;
|
||||
splitPointOrPrediction = other.splitPointOrPrediction;
|
||||
|
||||
if (children.size() != 0)
|
||||
splitPoint = other.splitPoint;
|
||||
else
|
||||
prediction = other.prediction;
|
||||
|
||||
// Take ownership of the auxiliary info.
|
||||
NumericAuxiliarySplitInfo::operator=(std::move(other));
|
||||
@@ -643,7 +657,7 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
UseWeights ? weights.subvec(begin, begin + count - 1) : weights,
|
||||
minimumLeafSize,
|
||||
minimumGainSplit,
|
||||
splitPointOrPrediction,
|
||||
splitPoint,
|
||||
*this,
|
||||
fitnessFunction);
|
||||
}
|
||||
@@ -655,7 +669,7 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
UseWeights ? weights.subvec(begin, begin + count - 1) : weights,
|
||||
minimumLeafSize,
|
||||
minimumGainSplit,
|
||||
splitPointOrPrediction,
|
||||
splitPoint,
|
||||
*this,
|
||||
fitnessFunction);
|
||||
}
|
||||
@@ -684,10 +698,9 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
// Get the number of children we will have.
|
||||
size_t numChildren = 0;
|
||||
if (datasetInfo.Type(bestDim) == data::Datatype::categorical)
|
||||
numChildren = CategoricalSplit::NumChildren(splitPointOrPrediction,
|
||||
*this);
|
||||
numChildren = CategoricalSplit::NumChildren(splitPoint, *this);
|
||||
else
|
||||
numChildren = NumericSplit::NumChildren(splitPointOrPrediction, *this);
|
||||
numChildren = NumericSplit::NumChildren(splitPoint, *this);
|
||||
|
||||
// Calculate all child assignments.
|
||||
arma::Row<size_t> childAssignments(count);
|
||||
@@ -695,14 +708,14 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
{
|
||||
for (size_t j = begin; j < begin + count; ++j)
|
||||
childAssignments[j - begin] = CategoricalSplit::CalculateDirection(
|
||||
data(bestDim, j), splitPointOrPrediction, *this);
|
||||
data(bestDim, j), splitPoint, *this);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t j = begin; j < begin + count; ++j)
|
||||
{
|
||||
childAssignments[j - begin] = NumericSplit::CalculateDirection(
|
||||
data(bestDim, j), splitPointOrPrediction, *this);
|
||||
data(bestDim, j), splitPoint, *this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,10 +776,9 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
CategoricalAuxiliarySplitInfo::operator=(CategoricalAuxiliarySplitInfo());
|
||||
|
||||
// Calculate prediction value because we are a leaf.
|
||||
splitPointOrPrediction =
|
||||
fitnessFunction.template OutputLeafValue<UseWeights>(
|
||||
responses.cols(begin, begin + count - 1),
|
||||
UseWeights ? weights.subvec(begin, begin + count - 1) : weights);
|
||||
prediction = fitnessFunction.template OutputLeafValue<UseWeights>(
|
||||
responses.cols(begin, begin + count - 1),
|
||||
UseWeights ? weights.subvec(begin, begin + count - 1) : weights);
|
||||
}
|
||||
|
||||
return -bestGain;
|
||||
@@ -826,7 +838,7 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
weights,
|
||||
minimumLeafSize,
|
||||
minimumGainSplit,
|
||||
splitPointOrPrediction,
|
||||
splitPoint,
|
||||
*this,
|
||||
fitnessFunction);
|
||||
|
||||
@@ -848,8 +860,7 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
if (bestDim != data.n_rows)
|
||||
{
|
||||
// We know that the split is numeric.
|
||||
size_t numChildren = NumericSplit::NumChildren(splitPointOrPrediction,
|
||||
*this);
|
||||
size_t numChildren = NumericSplit::NumChildren(splitPoint, *this);
|
||||
splitDimension = bestDim;
|
||||
dimensionType = (size_t) data::Datatype::numeric;
|
||||
|
||||
@@ -859,7 +870,7 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
for (size_t j = begin; j < begin + count; ++j)
|
||||
{
|
||||
childAssignments[j - begin] = NumericSplit::CalculateDirection(
|
||||
data(bestDim, j), splitPointOrPrediction, *this);
|
||||
data(bestDim, j), splitPoint, *this);
|
||||
}
|
||||
|
||||
// Calculate counts of children in each node.
|
||||
@@ -918,10 +929,9 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
NumericAuxiliarySplitInfo::operator=(NumericAuxiliarySplitInfo());
|
||||
|
||||
// Calculate prediction value because we are a leaf.
|
||||
splitPointOrPrediction =
|
||||
fitnessFunction.template OutputLeafValue<UseWeights>(
|
||||
responses.cols(begin, begin + count - 1),
|
||||
UseWeights ? weights.subvec(begin, begin + count - 1) : weights);
|
||||
prediction = fitnessFunction.template OutputLeafValue<UseWeights>(
|
||||
responses.cols(begin, begin + count - 1),
|
||||
UseWeights ? weights.subvec(begin, begin + count - 1) : weights);
|
||||
}
|
||||
|
||||
return -bestGain;
|
||||
@@ -943,7 +953,7 @@ double DecisionTreeRegressor<FitnessFunction,
|
||||
if (children.size() == 0)
|
||||
{
|
||||
// Return cached prediction.
|
||||
return splitPointOrPrediction;
|
||||
return prediction;
|
||||
}
|
||||
|
||||
return children[CalculateDirection(point)]->Predict(point);
|
||||
@@ -967,7 +977,7 @@ void DecisionTreeRegressor<FitnessFunction,
|
||||
// If the tree's root is leaf.
|
||||
if (children.size() == 0)
|
||||
{
|
||||
predictions.fill(splitPointOrPrediction);
|
||||
predictions.fill(prediction);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -991,10 +1001,10 @@ size_t DecisionTreeRegressor<FitnessFunction,
|
||||
{
|
||||
if ((data::Datatype) dimensionType == data::Datatype::categorical)
|
||||
return CategoricalSplit::CalculateDirection(point[splitDimension],
|
||||
splitPointOrPrediction, *this);
|
||||
splitPoint, *this);
|
||||
else
|
||||
return NumericSplit::CalculateDirection(point[splitDimension],
|
||||
splitPointOrPrediction, *this);
|
||||
splitPoint, *this);
|
||||
}
|
||||
|
||||
//! Serialize the tree.
|
||||
@@ -1024,7 +1034,9 @@ void DecisionTreeRegressor<FitnessFunction,
|
||||
// Now serialize the rest of the object.
|
||||
ar(CEREAL_NVP(splitDimension));
|
||||
ar(CEREAL_NVP(dimensionType));
|
||||
ar(CEREAL_NVP(splitPointOrPrediction));
|
||||
ar(CEREAL_NVP(splitPoint));
|
||||
// Since splitPoint and prediction are a union, we only need to serialize one of them.
|
||||
ar(CEREAL_NVP(splitPoint));
|
||||
}
|
||||
|
||||
//! Return the number of leaves.
|
||||
|
||||
@@ -238,7 +238,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
|
||||
arma::Row<size_t> counters;
|
||||
|
||||
timers.Start("det_test_set_tagging");
|
||||
if (!ofs.is_open())
|
||||
if (!ofs.is_open() && tagFile != "")
|
||||
{
|
||||
Log::Warn << "Unable to open file '" << tagFile
|
||||
<< "' to save tag membership info." << std::endl;
|
||||
|
||||
@@ -45,7 +45,7 @@ class ExactSVDPolicy
|
||||
arma::mat& eigvec,
|
||||
const size_t /* rank */)
|
||||
{
|
||||
// This matrix will store the right singular values; we do not need them.
|
||||
// This matrix will store the right singular vectors; we do not need them.
|
||||
arma::mat v;
|
||||
|
||||
// Do singular value decomposition. Use the economical singular value
|
||||
|
||||
@@ -57,7 +57,7 @@ class QUICSVDPolicy
|
||||
arma::mat& eigvec,
|
||||
const size_t /* rank */)
|
||||
{
|
||||
// This matrix will store the right singular values; we do not need them.
|
||||
// This matrix will store the right singular vectors; we do not need them.
|
||||
arma::mat v, sigma;
|
||||
|
||||
// Do singular value decomposition using the QUIC-SVD algorithm.
|
||||
|
||||
@@ -60,7 +60,7 @@ class RandomizedBlockKrylovSVDPolicy
|
||||
arma::mat& eigvec,
|
||||
const size_t rank)
|
||||
{
|
||||
// This matrix will store the right singular values; we do not need them.
|
||||
// This matrix will store the right singular vectors; we do not need them.
|
||||
arma::mat v;
|
||||
|
||||
// Do singular value decomposition using the randomized block krylov SVD
|
||||
|
||||
@@ -61,7 +61,7 @@ class RandomizedSVDPolicy
|
||||
arma::mat& eigvec,
|
||||
const size_t rank)
|
||||
{
|
||||
// This matrix will store the right singular values; we do not need them.
|
||||
// This matrix will store the right singular vectors; we do not need them.
|
||||
arma::mat v;
|
||||
|
||||
// Do singular value decomposition using the randomized SVD algorithm.
|
||||
|
||||
@@ -73,6 +73,23 @@ using enable_if_t = typename enable_if<B, T>::type;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Backport std::any from C+17 to C++11 to replace boost::any.
|
||||
// Use mnmlstc backport implementation only if compiler does not
|
||||
// support C++17.
|
||||
#if __cplusplus < 201703L
|
||||
#include <mlpack/core/std_backport/any.hpp>
|
||||
#include <mlpack/core/std_backport/string_view.hpp>
|
||||
#define ANY core::v2::any
|
||||
#define ANY_CAST core::v2::any_cast
|
||||
#define STRING_VIEW core::v2::string_view
|
||||
#else
|
||||
#include <any>
|
||||
#include <string_view>
|
||||
#define ANY std::any
|
||||
#define ANY_CAST std::any_cast
|
||||
#define STRING_VIEW std::string_view
|
||||
#endif
|
||||
|
||||
// Increase the number of template arguments for the boost list class.
|
||||
#undef BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
#undef BOOST_MPL_LIMIT_LIST_SIZE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user