Program Listing for File TypeTraits.hpp

Return to documentation for file (nvcv_types/include/nvcv/cuda/TypeTraits.hpp)

std::cout << pix;
/*
 * SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file 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 NVCV_CUDA_TYPE_TRAITS_HPP
#define NVCV_CUDA_TYPE_TRAITS_HPP

#include "detail/Metaprogramming.hpp" // for detail::TypeTraits, etc.

#include <cassert> // for assert, etc.
#include <ostream> // for std::ostream, etc.

namespace nvcv::cuda {

using detail::TypeTraits;

// Metatype to serve as a requirement for a template object to meet the given boolean expression.
template<bool B>
using Require = std::enable_if_t<B>;

// Metavariable to check if one or more types have type traits.
template<typename... Ts>
constexpr bool HasTypeTraits = (detail::HasTypeTraits_t<Ts>::value && ...);

// Metavariable to check if a type is a CUDA compound type.
template<class T, class = Require<HasTypeTraits<T>>>
constexpr bool IsCompound = TypeTraits<T>::components >= 1;

// Metavariable to check if a CUDA compound type T has N or more components.
template<typename T, int N, class = Require<HasTypeTraits<T>>>
constexpr bool HasEnoughComponents = N <= TypeTraits<T>::components;

template<class T, class = Require<HasTypeTraits<T>>>
using BaseType = typename TypeTraits<T>::base_type;

template<class T, class = Require<HasTypeTraits<T>>>
constexpr int NumComponents = TypeTraits<T>::components;

template<class T, class = Require<HasTypeTraits<T>>>
constexpr int NumElements = TypeTraits<T>::elements;

// Metavariable to get the lowest value from a regular C or CUDA compound type T.
template<typename T, class = Require<HasTypeTraits<T>>>
constexpr BaseType<T> Lowest = std::is_floating_point_v<BaseType<T>> ? -TypeTraits<T>::max : TypeTraits<T>::min;

template<class T, int C, class = Require<HasTypeTraits<T>>>
using MakeType = detail::MakeType_t<T, C>;

template<class BT, class T, class = Require<HasTypeTraits<BT, T>>>
using ConvertBaseTypeTo = detail::ConvertBaseTypeTo_t<BT, T>;

template<typename T, typename RT = detail::CopyConstness_t<T, std::conditional_t<IsCompound<T>, BaseType<T>, T>>,
         class = Require<HasTypeTraits<T>>>
__host__ __device__ RT &GetElement(T &v, int eidx)
{
    if constexpr (IsCompound<T>)
    {
        assert(eidx < NumElements<T>);
        return reinterpret_cast<RT *>(&v)[eidx];
    }
    else
    {
        return v;
    }
}

template<typename T, class = Require<HasTypeTraits<T>>>
__host__ __device__ T SetAll(BaseType<T> x)
{
    T out{};

#pragma unroll
    for (int e = 0; e < NumElements<T>; ++e)
    {
        GetElement(out, e) = x;
    }

    return out;
}

template<int N, typename BT, typename RT = MakeType<BT, N>, class = Require<HasTypeTraits<BT>>>
__host__ __device__ RT SetAll(BT x)
{
    return SetAll<RT>(x);
}

template<class T, class = Require<HasTypeTraits<T>>>
__host__ const char *GetTypeName()
{
    return TypeTraits<T>::name;
}

} // namespace nvcv::cuda

template<class T, class = nvcv::cuda::Require<nvcv::cuda::IsCompound<T>>>
__host__ std::ostream &operator<<(std::ostream &out, const T &v)
{
    using BT         = nvcv::cuda::BaseType<T>;
    using OutType    = std::conditional_t<sizeof(BT) == 1, int, BT>;
    constexpr int NC = nvcv::cuda::NumComponents<T>;

    out << nvcv::cuda::GetTypeName<T>() << "(";

    for (int c = 0; c < NC; ++c)
    {
        if (c > 0)
        {
            out << ", ";
        }
        out << static_cast<OutType>(nvcv::cuda::GetElement(v, c));
    }

    out << ")";

    return out;
}

#endif // NVCV_CUDA_TYPE_TRAITS_HPP