diff --git a/libcudacxx/include/cuda/__device/arch_id.h b/libcudacxx/include/cuda/__device/arch_id.h index 65f4d6f455c..1e37c7fd65e 100644 --- a/libcudacxx/include/cuda/__device/arch_id.h +++ b/libcudacxx/include/cuda/__device/arch_id.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -142,6 +143,40 @@ enum class arch_id : int _CCCL_END_NAMESPACE_CUDA +#if __cpp_lib_format >= 201907L +_CCCL_BEGIN_NAMESPACE_STD + +template +struct formatter<::cuda::arch_id, _CharT> : private formatter<::cuda::compute_capability, _CharT> +{ + template + _CCCL_HOST_API constexpr auto parse(_ParseCtx& __ctx) + { + return __ctx.begin(); + } + + template + _CCCL_HOST_API auto format(const ::cuda::arch_id& __arch, _FmtCtx& __ctx) const + { + auto __it = __ctx.out(); + *__it++ = _CharT{'s'}; + *__it++ = _CharT{'m'}; + *__it++ = _CharT{'_'}; + __ctx.advance_to(__it); + __it = formatter<::cuda::compute_capability, _CharT>::format(::cuda::compute_capability{__arch}, __ctx); + if (::cuda::__is_specific_arch(__arch)) + { + *__it++ = _CharT{'a'}; + } + return __it; + } +}; + +_CCCL_END_NAMESPACE_STD +#endif // __cpp_lib_format >= 201907L + +// todo: specialize cuda::std::formatter for cuda::arch_id + #if _CCCL_CUDA_COMPILATION() _CCCL_BEGIN_NAMESPACE_CUDA_DEVICE diff --git a/libcudacxx/include/cuda/__device/compute_capability.h b/libcudacxx/include/cuda/__device/compute_capability.h index 7e73e986034..6ef414b5976 100644 --- a/libcudacxx/include/cuda/__device/compute_capability.h +++ b/libcudacxx/include/cuda/__device/compute_capability.h @@ -22,6 +22,7 @@ #endif // no system header #include +#include #include #include @@ -172,6 +173,30 @@ class compute_capability _CCCL_END_NAMESPACE_CUDA +#if __cpp_lib_format >= 201907L +_CCCL_BEGIN_NAMESPACE_STD + +template +struct formatter<::cuda::compute_capability, _CharT> : private formatter +{ + template + _CCCL_HOST_API constexpr auto parse(_ParseCtx& __ctx) + { + return __ctx.begin(); + } + + template + _CCCL_HOST_API auto format(const ::cuda::compute_capability& __cc, _FmtCtx& __ctx) const + { + return formatter::format(__cc.get(), __ctx); + } +}; + +_CCCL_END_NAMESPACE_STD +#endif // __cpp_lib_format >= 201907L + +// todo: specialize cuda::std::formatter for cuda::compute_capability + #if _CCCL_CUDA_COMPILATION() _CCCL_BEGIN_NAMESPACE_CUDA_DEVICE diff --git a/libcudacxx/include/cuda/std/__fwd/format.h b/libcudacxx/include/cuda/std/__fwd/format.h index 98e9253c2aa..b9371dc5a26 100644 --- a/libcudacxx/include/cuda/std/__fwd/format.h +++ b/libcudacxx/include/cuda/std/__fwd/format.h @@ -24,6 +24,17 @@ #include +#if __cpp_lib_format >= 201907L + +_CCCL_BEGIN_NAMESPACE_STD + +template +struct formatter; + +_CCCL_END_NAMESPACE_STD + +#endif // __cpp_lib_format >= 201907L + _CCCL_BEGIN_NAMESPACE_CUDA_STD template diff --git a/libcudacxx/test/libcudacxx/cuda/ccclrt/device/arch_id_fmt.pass.cpp b/libcudacxx/test/libcudacxx/cuda/ccclrt/device/arch_id_fmt.pass.cpp new file mode 100644 index 00000000000..b1b86b7cf89 --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/ccclrt/device/arch_id_fmt.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// Part of libcu++, the C++ Standard Library for your entire system, +// under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +#include + +#if __cpp_lib_format >= 201907L +# include +#endif // __cpp_lib_format >= 201907L + +#include "literal.h" + +#if __cpp_lib_format >= 201907L +template +void test() +{ + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_60) == TEST_STRLIT(C, "sm_60")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_61) == TEST_STRLIT(C, "sm_61")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_62) == TEST_STRLIT(C, "sm_62")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_70) == TEST_STRLIT(C, "sm_70")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_75) == TEST_STRLIT(C, "sm_75")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_80) == TEST_STRLIT(C, "sm_80")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_86) == TEST_STRLIT(C, "sm_86")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_87) == TEST_STRLIT(C, "sm_87")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_88) == TEST_STRLIT(C, "sm_88")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_89) == TEST_STRLIT(C, "sm_89")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_90) == TEST_STRLIT(C, "sm_90")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_100) == TEST_STRLIT(C, "sm_100")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_103) == TEST_STRLIT(C, "sm_103")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_110) == TEST_STRLIT(C, "sm_110")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_120) == TEST_STRLIT(C, "sm_120")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_121) == TEST_STRLIT(C, "sm_121")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_90a) == TEST_STRLIT(C, "sm_90a")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_100a) == TEST_STRLIT(C, "sm_100a")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_103a) == TEST_STRLIT(C, "sm_103a")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_110a) == TEST_STRLIT(C, "sm_110a")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_120a) == TEST_STRLIT(C, "sm_120a")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::arch_id::sm_121a) == TEST_STRLIT(C, "sm_121a")); +} + +void test() +{ + test(); + test(); +} +#endif // __cpp_lib_format >= 201907L + +int main(int, char**) +{ +#if __cpp_lib_format >= 201907L + NV_IF_TARGET(NV_IS_HOST, (test();)) +#endif // __cpp_lib_format >= 201907L + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/ccclrt/device/compute_capability_fmt.pass.cpp b/libcudacxx/test/libcudacxx/cuda/ccclrt/device/compute_capability_fmt.pass.cpp new file mode 100644 index 00000000000..8039c4c20e2 --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/ccclrt/device/compute_capability_fmt.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of libcu++, the C++ Standard Library for your entire system, +// under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +#include + +#if __cpp_lib_format >= 201907L +# include +#endif // __cpp_lib_format >= 201907L + +#include "literal.h" + +#if __cpp_lib_format >= 201907L +template +void test() +{ + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{0}) == TEST_STRLIT(C, "0")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{60}) == TEST_STRLIT(C, "60")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{61}) == TEST_STRLIT(C, "61")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{62}) == TEST_STRLIT(C, "62")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{70}) == TEST_STRLIT(C, "70")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{75}) == TEST_STRLIT(C, "75")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{80}) == TEST_STRLIT(C, "80")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{86}) == TEST_STRLIT(C, "86")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{87}) == TEST_STRLIT(C, "87")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{88}) == TEST_STRLIT(C, "88")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{89}) == TEST_STRLIT(C, "89")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{90}) == TEST_STRLIT(C, "90")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{100}) == TEST_STRLIT(C, "100")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{103}) == TEST_STRLIT(C, "103")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{110}) == TEST_STRLIT(C, "110")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{120}) == TEST_STRLIT(C, "120")); + assert(std::format(TEST_STRLIT(C, "{}"), cuda::compute_capability{121}) == TEST_STRLIT(C, "121")); +} + +void test() +{ + test(); + test(); +} +#endif // __cpp_lib_format >= 201907L + +int main(int, char**) +{ +#if __cpp_lib_format >= 201907L + NV_IF_TARGET(NV_IS_HOST, (test();)) +#endif // __cpp_lib_format >= 201907L + return 0; +}