Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -765,3 +765,62 @@ jobs:

- name: Run tests
run: ci/build.sh


cuda-cmake-test:
strategy:
fail-fast: false

runs-on: gpu-runner-1

steps:
- uses: Jimver/cuda-toolkit@v0.2.25
id: cuda-toolkit
with:
cuda: '12.8.0'
method: 'network'
sub-packages: '["nvcc"]'

- name: Output CUDA information
run: |
echo "Installed cuda version is: ${{steps.cuda-toolkit.outputs.cuda}}"+
echo "Cuda install location: ${{steps.cuda-toolkit.outputs.CUDA_PATH}}"
nvcc -V
- uses: actions/checkout@v4

- name: Install Packages
run: |
sudo apt-get install -y cmake make
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
mkdir -p libs/$LIBRARY
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DBOOST_CHARCONV_ENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="75;86" -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-12.8 -DCMAKE_CUDA_STANDARD=17 ..
- name: Build tests
run: |
cd ../boost-root/__build__
cmake --build . --target tests -j $(nproc)
- name: Run tests
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error
7 changes: 6 additions & 1 deletion include/boost/charconv/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#endif

// Use 128-bit integers and suppress warnings for using extensions
#if defined(BOOST_HAS_INT128)
#if defined(BOOST_HAS_INT128) && !defined(__NVCC__)
# define BOOST_CHARCONV_HAS_INT128
# define BOOST_CHARCONV_INT128_MAX static_cast<boost::int128_type>((static_cast<boost::uint128_type>(1) << 127) - 1)
# define BOOST_CHARCONV_INT128_MIN (-BOOST_CHARCONV_INT128_MAX - 1)
Expand Down Expand Up @@ -201,5 +201,10 @@ static_assert(std::is_same<long double, __float128>::value, "__float128 should b

#endif

#ifdef __NVCC__
# define BOOST_CHARCONV_HOST_DEVICE __host__ __device__
#else
# define BOOST_CHARCONV_HOST_DEVICE
#endif

#endif // BOOST_CHARCONV_DETAIL_CONFIG_HPP
108 changes: 101 additions & 7 deletions include/boost/charconv/detail/from_chars_integer_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

namespace boost { namespace charconv { namespace detail {

#ifndef __NVCC__

static constexpr unsigned char uchar_values[] =
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
Expand Down Expand Up @@ -83,9 +85,33 @@ static constexpr double log_2_table[] =
0.193426403617
};

#endif // __NVCC__

// Convert characters for 0-9, A-Z, a-z to 0-35. Anything else is 255
constexpr unsigned char digit_from_char(char val) noexcept
BOOST_CHARCONV_HOST_DEVICE constexpr unsigned char digit_from_char(const char val) noexcept
{
#ifdef __NVCC__

constexpr unsigned char uchar_values[] =
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};

#endif // __NVCC__

return uchar_values[static_cast<unsigned char>(val)];
}

Expand All @@ -111,9 +137,75 @@ constexpr unsigned char digit_from_char(char val) noexcept

#endif

#ifdef __NVCC__

template <typename T>
__host__ __device__ constexpr T get_max_value()
{
using UT = typename std::make_unsigned<T>::type;
return std::is_signed<T>::value
? static_cast<T>(static_cast<UT>(-1) >> 1)
: static_cast<T>(static_cast<UT>(-1));
}

#else

template <typename T>
constexpr T get_max_value()
{
return (std::numeric_limits<T>::max)();
}

#endif

template <typename Integer, typename Unsigned_Integer>
BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept
{
#ifdef __NVCC__

constexpr double log_2_table[] =
{
0.0,
0.0,
1.0,
0.630929753571,
0.5,
0.430676558073,
0.386852807235,
0.356207187108,
0.333333333333,
0.315464876786,
0.301029995664,
0.289064826318,
0.278942945651,
0.270238154427,
0.262649535037,
0.255958024810,
0.25,
0.244650542118,
0.239812466568,
0.235408913367,
0.231378213160,
0.227670248697,
0.224243824218,
0.221064729458,
0.218104291986,
0.215338279037,
0.212746053553,
0.210309917857,
0.208014597677,
0.205846832460,
0.203795047091,
0.201849086582,
0.2,
0.198239863171,
0.196561632233,
0.194959021894,
0.193426403617
};

#endif // __NVCC__

Unsigned_Integer result = 0;
Unsigned_Integer overflow_value = 0;
Unsigned_Integer max_digit = 0;
Expand Down Expand Up @@ -155,8 +247,8 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
else
#endif
{
overflow_value = static_cast<Unsigned_Integer>((std::numeric_limits<Integer>::max)());
max_digit = static_cast<Unsigned_Integer>((std::numeric_limits<Integer>::max)());
overflow_value = static_cast<Unsigned_Integer>(get_max_value<Integer>());
max_digit = static_cast<Unsigned_Integer>(get_max_value<Integer>());
}

if (is_negative)
Expand All @@ -181,8 +273,8 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs
else
#endif
{
overflow_value = (std::numeric_limits<Unsigned_Integer>::max)();
max_digit = (std::numeric_limits<Unsigned_Integer>::max)();
overflow_value = get_max_value<Unsigned_Integer>();
max_digit = get_max_value<Unsigned_Integer>();
}
}

Expand Down Expand Up @@ -310,7 +402,7 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs

// Only from_chars for integer types is constexpr (as of C++23)
template <typename Integer>
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept
{
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
return detail::from_chars_integer_impl<Integer, Unsigned_Integer>(first, last, value, base);
Expand All @@ -325,10 +417,12 @@ BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars128(const char* first,
}
#endif

#ifndef __NVCC__
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars128(const char* first, const char* last, uint128& value, int base = 10) noexcept
{
return from_chars_integer_impl<uint128, uint128>(first, last, value, base);
}
#endif

}}} // Namespaces

Expand Down
7 changes: 4 additions & 3 deletions include/boost/charconv/detail/from_chars_result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP
#define BOOST_CHARCONV_DETAIL_FROM_CHARS_RESULT_HPP

#include <boost/charconv/detail/config.hpp>
#include <system_error>

namespace boost { namespace charconv {
Expand All @@ -22,17 +23,17 @@ struct from_chars_result_t
// ERANGE = result_out_of_range
std::errc ec;

friend constexpr bool operator==(const from_chars_result_t<UC>& lhs, const from_chars_result_t<UC>& rhs) noexcept
BOOST_CHARCONV_HOST_DEVICE friend constexpr bool operator==(const from_chars_result_t<UC>& lhs, const from_chars_result_t<UC>& rhs) noexcept
{
return lhs.ptr == rhs.ptr && lhs.ec == rhs.ec;
}

friend constexpr bool operator!=(const from_chars_result_t<UC>& lhs, const from_chars_result_t<UC>& rhs) noexcept
BOOST_CHARCONV_HOST_DEVICE friend constexpr bool operator!=(const from_chars_result_t<UC>& lhs, const from_chars_result_t<UC>& rhs) noexcept
{
return !(lhs == rhs); // NOLINT : Expression can not be simplified since this is the definition
}

constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
BOOST_CHARCONV_HOST_DEVICE constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
};
using from_chars_result = from_chars_result_t<char>;

Expand Down
24 changes: 12 additions & 12 deletions include/boost/charconv/from_chars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,48 @@ namespace boost { namespace charconv {

// integer overloads

BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, bool& value, int base = 10) noexcept = delete;
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, char& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, bool& value, int base = 10) noexcept = delete;
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, char& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, signed char& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, signed char& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned char& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned char& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, short& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, short& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned short& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned short& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned int& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned int& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long long& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long long& value, int base = 10) noexcept
BOOST_CHARCONV_HOST_DEVICE BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long long& value, int base = 10) noexcept
{
return detail::from_chars(first, last, value, base);
}
Expand Down
22 changes: 19 additions & 3 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,24 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)

if(HAVE_BOOST_TEST)

# https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/
set(CMAKE_CXX_EXTENSIONS OFF)
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::charconv Boost::core Boost::assert)
enable_testing()

if(BOOST_CHARCONV_ENABLE_CUDA)

message(STATUS "Building Boost.charconv with CUDA")

find_package(CUDA REQUIRED)
enable_language(CUDA)
set(CMAKE_CUDA_EXTENSIONS OFF)

boost_test_jamfile(FILE cuda_jamfile LINK_LIBRARIES Boost::charconv Boost::core Boost::assert ${CUDA_LIBRARIES} INCLUDE_DIRECTORIES ${CUDA_INCLUDE_DIRS} )

else()

# https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/
set(CMAKE_CXX_EXTENSIONS OFF)
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::charconv Boost::core Boost::assert)

endif()

endif()
Loading
Loading