Merge remote-tracking branch 'origin/master' into lr-doc-workaround

This commit is contained in:
Ryan Curtin
2021-11-02 12:44:56 -04:00
111 changed files with 6334 additions and 1256 deletions
+3 -3
View File
@@ -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
View File
@@ -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.
+4 -9
View File
@@ -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'
+8 -4
View File
@@ -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
View File
@@ -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}")
+1
View File
@@ -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.
+3
View File
@@ -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.
+5
View File
@@ -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.
+1 -1
View File
@@ -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
+3 -3
View File
@@ -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 + "\"";
}
+1 -1
View File
@@ -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;
+64 -22
View File
@@ -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", {
+4 -4
View File
@@ -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);
+6 -6
View File
@@ -47,8 +47,8 @@ void AddToCLI11(const std::string& cliName,
[&param](const std::string& value)
{
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
TupleType& tuple = *boost::any_cast<TupleType>(&param.value);
std::get<0>(std::get<1>(tuple)) = boost::any_cast<std::string>(value);
TupleType& tuple = *ANY_CAST<TupleType>(&param.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,
[&param](const std::string& value)
{
using TupleType = std::tuple<T*, typename ParameterType<T>::type>;
TupleType& tuple = *boost::any_cast<TupleType>(&param.value);
std::get<1>(tuple) = boost::any_cast<std::string>(value);
TupleType& tuple = *ANY_CAST<TupleType>(&param.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,
[&param](const std::string& value)
{
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
TupleType& tuple = *boost::any_cast<TupleType>(&param.value);
std::get<0>(std::get<1>(tuple)) = boost::any_cast<std::string>(value);
TupleType& tuple = *ANY_CAST<TupleType>(&param.value);
std::get<0>(std::get<1>(tuple)) = ANY_CAST<std::string>(value);
param.wasPassed = true;
},
param.desc.c_str());
+2 -2
View File
@@ -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>
+4 -4
View File
@@ -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);
+3 -3
View File
@@ -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;
}
+4 -4
View File
@@ -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()
+9 -9
View File
@@ -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
View File
@@ -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 + "\"";
}
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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.
+3 -3
View File
@@ -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
+4 -4
View File
@@ -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 + "\"";
}
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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
+29
View File
@@ -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>>(
+4 -4
View File
@@ -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);
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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 + "'";
}
+1 -1
View File
@@ -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)
{
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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
+4 -5
View File
@@ -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++)
{
+12
View File
@@ -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.
+15
View File
@@ -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
+337
View File
@@ -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 */
+435
View File
@@ -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 */
+156
View File
@@ -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 */
+272
View File
@@ -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 */
+325
View File
@@ -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 */
+355
View File
@@ -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 */
+79
View File
@@ -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 */
+180
View File
@@ -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 */
-2
View File
@@ -18,8 +18,6 @@
#include <map>
#include <string>
#include <boost/any.hpp>
#include <mlpack/prereqs.hpp>
#include "timers.hpp"
+1 -2
View File
@@ -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;
};
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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.
+17
View File
@@ -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