26template <
class Scalar>
28 std::same_as<Scalar, uni20::cfloat> || std::same_as<Scalar, uni20::cdouble>;
33template <
class Scalar>
struct ProviderComplex;
37 using type = cuComplex;
42 using type = cuDoubleComplex;
45template <
class Scalar>
using provider_complex_t =
typename ProviderComplex<Scalar>::type;
47template <
class Scalar>
consteval void require_complex_provider_abi()
49 using provider_type = provider_complex_t<Scalar>;
50 static_assert(
sizeof(
Scalar) ==
sizeof(provider_type));
51 static_assert(std::is_trivially_copyable_v<Scalar>);
52 static_assert(std::is_trivially_copyable_v<provider_type>);
61template <CublasLevelOneScalar Scalar>
65 CHECK(size >= 0, size);
66 if (size == 0)
return Scalar{};
67 CHECK(lhs !=
nullptr && rhs !=
nullptr);
70 cublasStatus_t status = CUBLAS_STATUS_INTERNAL_ERROR;
71 if constexpr (std::same_as<Scalar, float>)
75 status = cublasSdot(execution.handle().native_handle(), size, lhs, 1, rhs, 1, &result);
76 check(status,
"cublasSdot", execution.stream().device());
77 execution.stream().synchronize();
80 else if constexpr (std::same_as<Scalar, double>)
84 status = cublasDdot(execution.handle().native_handle(), size, lhs, 1, rhs, 1, &result);
85 check(status,
"cublasDdot", execution.stream().device());
86 execution.stream().synchronize();
89 else if constexpr (std::same_as<Scalar, uni20::cfloat>)
91 detail::require_complex_provider_abi<Scalar>();
94 status = cublasCdotc(execution.handle().native_handle(), size,
reinterpret_cast<cuComplex const*
>(lhs), 1,
95 reinterpret_cast<cuComplex const*
>(rhs), 1, &result);
96 check(status,
"cublasCdotc", execution.stream().device());
97 execution.stream().synchronize();
98 return Scalar{result.x, result.y};
102 static_assert(std::same_as<Scalar, uni20::cdouble>);
103 detail::require_complex_provider_abi<Scalar>();
104 cuDoubleComplex result{};
106 status = cublasZdotc(execution.handle().native_handle(), size,
reinterpret_cast<cuDoubleComplex const*
>(lhs), 1,
107 reinterpret_cast<cuDoubleComplex const*
>(rhs), 1, &result);
108 check(status,
"cublasZdotc", execution.stream().device());
109 execution.stream().synchronize();
110 return Scalar{result.x, result.y};
116template <CublasLevelOneScalar Scalar>
120 CHECK(size >= 0, size);
122 if (size == 0)
return result_type{};
123 CHECK(input !=
nullptr);
126 result_type result{};
127 cublasStatus_t status = CUBLAS_STATUS_INTERNAL_ERROR;
128 if constexpr (std::same_as<Scalar, float>)
131 status = cublasSnrm2(execution.handle().native_handle(), size, input, 1, &result);
132 check(status,
"cublasSnrm2", execution.stream().device());
134 else if constexpr (std::same_as<Scalar, double>)
137 status = cublasDnrm2(execution.handle().native_handle(), size, input, 1, &result);
138 check(status,
"cublasDnrm2", execution.stream().device());
140 else if constexpr (std::same_as<Scalar, uni20::cfloat>)
142 detail::require_complex_provider_abi<Scalar>();
145 cublasScnrm2(execution.handle().native_handle(), size,
reinterpret_cast<cuComplex const*
>(input), 1, &result);
146 check(status,
"cublasScnrm2", execution.stream().device());
150 static_assert(std::same_as<Scalar, uni20::cdouble>);
151 detail::require_complex_provider_abi<Scalar>();
153 status = cublasDznrm2(execution.handle().native_handle(), size,
reinterpret_cast<cuDoubleComplex const*
>(input), 1,
155 check(status,
"cublasDznrm2", execution.stream().device());
157 execution.stream().synchronize();
Move-only dynamic pairing of one cuBLAS handle slot and one idle stream.
Definition cublas/execution.hpp:56
Temporarily select one CUDA device and restore the previous device on destruction.
Definition runtime.hpp:44
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
Scalar types supported by the cuBLAS level-one wrappers.
Definition level1.hpp:27
cuBLAS handle slots and dynamically paired stream execution leases.
Structured cuBLAS failures and checked-call helpers.
#define UNI20_EXTERNAL_API_CALL(module, func,...)
Emits a trace log entry for an outgoing backend API call.
Definition backend.hpp:90
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
Definition cublas_error.cpp:11
auto nrm2(ExecutionLease &execution, int size, Scalar const *input) -> uni20::make_real_t< Scalar >
Compute a Euclidean norm and return a host real scalar.
Definition level1.hpp:117
auto dotc(ExecutionLease &execution, int size, Scalar const *lhs, Scalar const *rhs) -> Scalar
Compute the conjugate-linear dot product and return a host scalar.
Definition level1.hpp:62
void check(cublasStatus_t status, std::string_view operation, int device, std::source_location where)
Raise unless a cuBLAS call returned CUBLAS_STATUS_SUCCESS.
Definition cublas_error.cpp:52
Definition async/async.hpp:26
complex< double > cdouble
Definition types.hpp:76
complex< float > cfloat
Definition types.hpp:75
#define CHECK(cond,...)
Definition trace.hpp:299