/*
//@HEADER
// ************************************************************************
//
//                        Kokkos v. 2.0
//              Copyright (2019) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
//
// ************************************************************************
//@HEADER
*/

#ifndef _LIBCUDACXX___MDSPAN_EXTENTS_HPP
#define _LIBCUDACXX___MDSPAN_EXTENTS_HPP

#include <cuda/std/detail/__config>

#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
#  pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
#  pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
#  pragma system_header
#endif // no system header

#include <cuda/std/__mdspan/macros.h>
#ifdef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
#  include <cuda/std/__mdspan/no_unique_address.h>
#endif // _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
#include <cuda/std/__mdspan/standard_layout_static_array.h>
#include <cuda/std/__mdspan/static_array.h>
#include <cuda/std/__type_traits/conditional.h>
#include <cuda/std/__type_traits/fold.h>
#include <cuda/std/__type_traits/integral_constant.h>
#include <cuda/std/__type_traits/is_convertible.h>
#include <cuda/std/__type_traits/is_nothrow_constructible.h>
#include <cuda/std/__type_traits/make_unsigned.h>
#include <cuda/std/__utility/integer_sequence.h>
#include <cuda/std/array>
#include <cuda/std/cstddef>
#include <cuda/std/span>

_CCCL_PUSH_MACROS

_LIBCUDACXX_BEGIN_NAMESPACE_STD

#if _CCCL_STD_VER > 2011

namespace __detail
{

template <size_t... _Extents>
struct __count_dynamic_extents;

template <size_t _Ep, size_t... _Extents>
struct __count_dynamic_extents<_Ep, _Extents...>
{
  static constexpr size_t val = (_Ep == dynamic_extent ? 1 : 0) + __count_dynamic_extents<_Extents...>::val;
};

template <>
struct __count_dynamic_extents<>
{
  static constexpr size_t val = 0;
};

template <size_t... _Extents, size_t... _OtherExtents>
_CCCL_HOST_DEVICE static constexpr false_type __check_compatible_extents(
  false_type,
  _CUDA_VSTD::integer_sequence<size_t, _Extents...>,
  _CUDA_VSTD::integer_sequence<size_t, _OtherExtents...>) noexcept
{
  return {};
}

// This helper prevents ICE's on MSVC.
template <size_t _Lhs, size_t _Rhs>
struct __compare_extent_compatible
    : integral_constant<bool, _Lhs == dynamic_extent || _Rhs == dynamic_extent || _Lhs == _Rhs>
{};

template <size_t... _Extents, size_t... _OtherExtents>
static integral_constant<bool,
                         __fold_and_v<(__compare_extent_compatible<_Extents, _OtherExtents>::value)...>> _CCCL_HOST_DEVICE
__check_compatible_extents(true_type,
                           _CUDA_VSTD::integer_sequence<size_t, _Extents...>,
                           _CUDA_VSTD::integer_sequence<size_t, _OtherExtents...>) noexcept
{
  return {};
}

struct __extents_tag
{};

} // end namespace __detail

template <class _ThisIndexType, size_t... _Extents>
class extents
#  ifdef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
    : private __detail::__no_unique_address_emulation<
        __detail::__partially_static_sizes_tagged<__detail::__extents_tag, _ThisIndexType, size_t, _Extents...>>
#  endif
{
public:
  using rank_type  = size_t;
  using index_type = _ThisIndexType;
  using size_type  = make_unsigned_t<index_type>;

  // internal typedefs which for technical reasons are public
  using __storage_t =
    __detail::__partially_static_sizes_tagged<__detail::__extents_tag, index_type, size_t, _Extents...>;
  using __indices_t = _CUDA_VSTD::integer_sequence<size_t, _Extents...>;

#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
  _CCCL_NO_UNIQUE_ADDRESS __storage_t __storage_;
#  else
  using __base_t = __detail::__no_unique_address_emulation<__storage_t>;
#  endif

  // private members dealing with the way we internally store dynamic extents

private:
  __MDSPAN_FORCE_INLINE_FUNCTION constexpr __storage_t& __storage() noexcept
  {
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
    return __storage_;
#  else
    return this->__base_t::__ref();
#  endif
  }
  __MDSPAN_FORCE_INLINE_FUNCTION
  constexpr __storage_t const& __storage() const noexcept
  {
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
    return __storage_;
#  else
    return this->__base_t::__ref();
#  endif
  }

  template <size_t... _Idxs>
  __MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t
  _static_extent_impl(size_t __n, _CUDA_VSTD::integer_sequence<size_t, _Idxs...>) noexcept
  {
    return __MDSPAN_FOLD_PLUS_RIGHT(((_Idxs == __n) ? _Extents : 0), /* + ... + */ 0);
  }

  template <class, size_t...>
  friend class extents;

  template <class _OtherIndexType, size_t... _OtherExtents, size_t... _Idxs>
  _LIBCUDACXX_HIDE_FROM_ABI constexpr bool
  _eq_impl(_CUDA_VSTD::extents<_OtherIndexType, _OtherExtents...>,
           false_type,
           _CUDA_VSTD::index_sequence<_Idxs...>) const noexcept
  {
    return false;
  }
  template <class _OtherIndexType, size_t... _OtherExtents, size_t... _Idxs>
  _LIBCUDACXX_HIDE_FROM_ABI constexpr bool
  _eq_impl(_CUDA_VSTD::extents<_OtherIndexType, _OtherExtents...> __other,
           true_type,
           _CUDA_VSTD::index_sequence<_Idxs...>) const noexcept
  {
    return __MDSPAN_FOLD_AND(
      (__storage().template __get_n<_Idxs>() == __other.__storage().template __get_n<_Idxs>()) /* && ... */
    );
  }

  template <class _OtherIndexType, size_t... _OtherExtents, size_t... _Idxs>
  _LIBCUDACXX_HIDE_FROM_ABI constexpr bool
  _not_eq_impl(_CUDA_VSTD::extents<_OtherIndexType, _OtherExtents...>,
               false_type,
               _CUDA_VSTD::index_sequence<_Idxs...>) const noexcept
  {
    return true;
  }
  template <class _OtherIndexType, size_t... _OtherExtents, size_t... _Idxs>
  _LIBCUDACXX_HIDE_FROM_ABI constexpr bool
  _not_eq_impl(_CUDA_VSTD::extents<_OtherIndexType, _OtherExtents...> __other,
               true_type,
               _CUDA_VSTD::index_sequence<_Idxs...>) const noexcept
  {
    return __MDSPAN_FOLD_OR(
      (__storage().template __get_n<_Idxs>() != __other.__storage().template __get_n<_Idxs>()) /* || ... */
    );
  }

#  ifdef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
  _LIBCUDACXX_HIDE_FROM_ABI constexpr explicit extents(__base_t&& __b) noexcept
      : __base_t(_CUDA_VSTD::move(__b))
  {}
#  endif

  // public interface:

public:
  /* Defined above for use in the private code
  using rank_type = size_t;
  using index_type = _ThisIndexType;
  */

  _LIBCUDACXX_HIDE_FROM_ABI static constexpr rank_type rank() noexcept
  {
    return sizeof...(_Extents);
  }
  _LIBCUDACXX_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept
  {
    return __MDSPAN_FOLD_PLUS_RIGHT((rank_type(_Extents == dynamic_extent)), /* + ... + */ 0);
  }

  //--------------------------------------------------------------------------------
  // Constructors, Destructors, and Assignment

  // Default constructor
  _CCCL_HIDE_FROM_ABI constexpr extents() noexcept = default;

  // Converting constructor
  _CCCL_TEMPLATE(class _OtherIndexType, size_t... _OtherExtents)
  _CCCL_REQUIRES(
    /* multi-stage check to protect from invalid pack expansion when sizes don't match? */
    (decltype(__detail::__check_compatible_extents(
      integral_constant<bool, sizeof...(_Extents) == sizeof...(_OtherExtents)>{},
      __indices_t{}, // _CUDA_VSTD::integer_sequence<size_t, _Extents...>{}
      _CUDA_VSTD::integer_sequence<size_t, _OtherExtents...>{}))::value))
  _LIBCUDACXX_HIDE_FROM_ABI __MDSPAN_CONDITIONAL_EXPLICIT(
    (((_Extents != dynamic_extent) && (_OtherExtents == dynamic_extent)) || ...)
    || (_CUDA_VSTD::numeric_limits<index_type>::max() < _CUDA_VSTD::numeric_limits<
          _OtherIndexType>::max())) constexpr extents(const extents<_OtherIndexType, _OtherExtents...>& __other) noexcept
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      : __storage_{
#  else
      : __base_t(__base_t {
        __storage_t
        {
#  endif
          __other.__storage().__enable_psa_conversion()
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
        }
#  else
        }
      })
#  endif
  {
    /* TODO: precondition check
     * __other.extent(r) equals Er for each r for which Er is a static extent, and
     * either
     *   - sizeof...(_OtherExtents) is zero, or
     *   - __other.extent(r) is a representable value of type index_type for all rank index r of __other
     */
  }

#  ifdef __NVCC__
  _CCCL_TEMPLATE(class... _Integral)
  _CCCL_REQUIRES(
    // TODO: check whether the other version works with newest NVCC, doesn't with 11.4
    // NVCC seems to pick up rank_dynamic from the wrong extents type???
    __fold_and_v<_CCCL_TRAIT(_CUDA_VSTD::is_convertible, _Integral, index_type)...> _CCCL_AND
      __fold_and_v<_CCCL_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _Integral)...> _CCCL_AND
    // NVCC chokes on the fold thingy here so wrote the workaround
    ((sizeof...(_Integral) == __detail::__count_dynamic_extents<_Extents...>::val)
     || (sizeof...(_Integral) == sizeof...(_Extents))))
#  else
  _CCCL_TEMPLATE(class... _Integral)
  _CCCL_REQUIRES(__fold_and_v<_CCCL_TRAIT(_CUDA_VSTD::is_convertible, _Integral, index_type)...> _CCCL_AND
                   __fold_and_v<_CCCL_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _Integral)...> _CCCL_AND(
                     (sizeof...(_Integral) == rank_dynamic()) || (sizeof...(_Integral) == rank())))
#  endif
  _LIBCUDACXX_HIDE_FROM_ABI explicit constexpr extents(_Integral... __exts) noexcept
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      : __storage_{
#  else
      : __base_t(__base_t {
        typename __base_t::__stored_type
        {
#  endif
          _CUDA_VSTD::conditional_t<sizeof...(_Integral) == rank_dynamic(),
                                    __detail::__construct_psa_from_dynamic_exts_values_tag_t,
                                    __detail::__construct_psa_from_all_exts_values_tag_t>(),
          static_cast<index_type>(__exts)...
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
        }
#  else
        }
      })
#  endif
  {
    /* TODO: precondition check
     * If sizeof...(_IndexTypes) != rank_dynamic() is true, exts_arr[r] equals Er for each r for which Er is a
     * static extent, and either
     *   - sizeof...(__exts) == 0 is true, or
     *   - each element of __exts is nonnegative and is a representable value of type index_type.
     */
  }

  // TODO: check whether this works with newest NVCC, doesn't with 11.4
#  ifdef __NVCC__
  // NVCC seems to pick up rank_dynamic from the wrong extents type???
  // NVCC chokes on the fold thingy here so wrote the workaround
  _CCCL_TEMPLATE(class _IndexType, size_t _Np)
  _CCCL_REQUIRES(
    _CCCL_TRAIT(_CUDA_VSTD::is_convertible, _IndexType, index_type)
      _CCCL_AND _CCCL_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _IndexType)
        _CCCL_AND((_Np == __detail::__count_dynamic_extents<_Extents...>::val) || (_Np == sizeof...(_Extents))))
#  else
  _CCCL_TEMPLATE(class _IndexType, size_t _Np)
  _CCCL_REQUIRES(_CCCL_TRAIT(_CUDA_VSTD::is_convertible, _IndexType, index_type)
                   _CCCL_AND _CCCL_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _IndexType)
                     _CCCL_AND(_Np == rank() || _Np == rank_dynamic()))
#  endif
  __MDSPAN_CONDITIONAL_EXPLICIT(_Np != rank_dynamic())
  _LIBCUDACXX_HIDE_FROM_ABI constexpr extents(_CUDA_VSTD::array<_IndexType, _Np> const& __exts) noexcept
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      : __storage_{
#  else
      : __base_t(__base_t {
        typename __base_t::__stored_type
        {
#  endif
          _CUDA_VSTD::conditional_t<_Np == rank_dynamic(),
                                    __detail::__construct_psa_from_dynamic_exts_array_tag_t<0>,
                                    __detail::__construct_psa_from_all_exts_array_tag_t>(),
          _CUDA_VSTD::array<_IndexType, _Np>{__exts}
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
        }
#  else
        }
      })
#  endif
  {
    /* TODO: precondition check
     * If _Np != rank_dynamic() is true, __exts[r] equals Er for each r for which Er is a static extent, and
     * either
     *   - _Np is zero, or
     *   - __exts[r] is nonnegative and is a representable value of type index_type for all rank index r
     */
  }

  // TODO: check whether the below works with newest NVCC, doesn't with 11.4
#  ifdef __NVCC__
  // NVCC seems to pick up rank_dynamic from the wrong extents type???
  // NVCC chokes on the fold thingy here so wrote the workaround
  _CCCL_TEMPLATE(class _IndexType, size_t _Np)
  _CCCL_REQUIRES(
    _CCCL_TRAIT(_CUDA_VSTD::is_convertible, _IndexType, index_type)
      _CCCL_AND _CCCL_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _IndexType)
        _CCCL_AND((_Np == __detail::__count_dynamic_extents<_Extents...>::val) || (_Np == sizeof...(_Extents))))
#  else
  _CCCL_TEMPLATE(class _IndexType, size_t _Np)
  _CCCL_REQUIRES(_CCCL_TRAIT(_CUDA_VSTD::is_convertible, _IndexType, index_type)
                   _CCCL_AND _CCCL_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _IndexType)
                     _CCCL_AND(_Np == rank() || _Np == rank_dynamic()))
#  endif
  __MDSPAN_CONDITIONAL_EXPLICIT(_Np != rank_dynamic())
  _LIBCUDACXX_HIDE_FROM_ABI constexpr extents(_CUDA_VSTD::span<_IndexType, _Np> __exts) noexcept
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      : __storage_{
#  else
      : __base_t(__base_t {
        typename __base_t::__stored_type
        {
#  endif
          _CUDA_VSTD::conditional_t<_Np == rank_dynamic(),
                                    __detail::__construct_psa_from_dynamic_exts_array_tag_t<0>,
                                    __detail::__construct_psa_from_all_exts_array_tag_t>(),
          __exts
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
        }
#  else
        }
      })
#  endif
  {
    /* TODO: precondition check
     * If _Np != rank_dynamic() is true, __exts[r] equals Er for each r for which Er is a static extent, and
     * either
     *   - _Np is zero, or
     *   - __exts[r] is nonnegative and is a representable value of type index_type for all rank index r
     */
  }

  // Need this constructor for some submdspan implementation stuff
  // for the layout_stride case where I use an extents object for strides
  _LIBCUDACXX_HIDE_FROM_ABI constexpr explicit extents(__storage_t const& __sto) noexcept
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      : __storage_{
#  else
      : __base_t(__base_t {
#  endif
          __sto
#  ifndef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
        }
#  else
      })
#  endif
  {}

  //--------------------------------------------------------------------------------

  _LIBCUDACXX_HIDE_FROM_ABI static constexpr size_t static_extent(size_t __n) noexcept
  {
    // Can't do assert here since that breaks true constexpr ness
    // assert(__n<rank());
    return _static_extent_impl(__n, _CUDA_VSTD::make_integer_sequence<size_t, sizeof...(_Extents)>{});
  }

  _LIBCUDACXX_HIDE_FROM_ABI constexpr index_type extent(size_t __n) const noexcept
  {
    // Can't do assert here since that breaks true constexpr ness
    // assert(__n<rank());
    return __storage().__get(__n);
  }

  //--------------------------------------------------------------------------------

  template <class _OtherIndexType, size_t... _RHS>
  _LIBCUDACXX_HIDE_FROM_ABI friend constexpr bool
  operator==(extents const& lhs, extents<_OtherIndexType, _RHS...> const& __rhs) noexcept
  {
    return lhs._eq_impl(__rhs,
                        integral_constant<bool, (sizeof...(_RHS) == rank())>{},
                        _CUDA_VSTD::make_index_sequence<sizeof...(_RHS)>{});
  }

#  if !(__MDSPAN_HAS_CXX_20)
  template <class _OtherIndexType, size_t... _RHS>
  _LIBCUDACXX_HIDE_FROM_ABI friend constexpr bool
  operator!=(extents const& lhs, extents<_OtherIndexType, _RHS...> const& __rhs) noexcept
  {
    return lhs._not_eq_impl(__rhs,
                            integral_constant<bool, (sizeof...(_RHS) == rank())>{},
                            _CUDA_VSTD::make_index_sequence<sizeof...(_RHS)>{});
  }
#  endif

  // End of public interface

public: // (but not really)
  _LIBCUDACXX_HIDE_FROM_ABI static constexpr extents
  __make_extents_impl(__detail::__partially_static_sizes<index_type, size_t, _Extents...>&& __bs) noexcept
  {
    // This effectively amounts to a sideways cast that can be done in a constexpr
    // context, but we have to do it to handle the case where the extents and the
    // strides could accidentally end up with the same types in their hierarchies
    // somehow (which would cause layout_stride::mapping to not be standard_layout)
    return extents(
#  ifdef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      __base_t{
#  endif
        _CUDA_VSTD::move(__bs.template __with_tag<__detail::__extents_tag>())
#  ifdef _CCCL_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS
      }
#  endif
    );
  }

  template <size_t _Np>
  __MDSPAN_FORCE_INLINE_FUNCTION constexpr index_type __extent() const noexcept
  {
    return __storage().template __get_n<_Np>();
  }

  template <size_t _Np, size_t _Default = dynamic_extent>
  _LIBCUDACXX_HIDE_FROM_ABI static constexpr index_type __static_extent() noexcept
  {
    return __storage_t::template __get_static_n<_Np, _Default>();
  }
};

namespace __detail
{

template <class _IndexType, size_t _Rank, class _Extents = _CUDA_VSTD::extents<_IndexType>>
struct __make_dextents;

template <class _IndexType, size_t _Rank, size_t... _ExtentsPack>
struct __make_dextents<_IndexType, _Rank, _CUDA_VSTD::extents<_IndexType, _ExtentsPack...>>
{
  using type =
    typename __make_dextents<_IndexType,
                             _Rank - 1,
                             _CUDA_VSTD::extents<_IndexType, _CUDA_VSTD::dynamic_extent, _ExtentsPack...>>::type;
};

template <class _IndexType, size_t... _ExtentsPack>
struct __make_dextents<_IndexType, 0, _CUDA_VSTD::extents<_IndexType, _ExtentsPack...>>
{
  using type = _CUDA_VSTD::extents<_IndexType, _ExtentsPack...>;
};

} // end namespace __detail

template <class _IndexType, size_t _Rank>
using dextents = typename __detail::__make_dextents<_IndexType, _Rank>::type;

template <size_t _Rank, class _IndexType = size_t>
using dims = dextents<_IndexType, _Rank>;

#  if defined(__MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
template <class... _IndexTypes>
_CCCL_HOST_DEVICE extents(_IndexTypes...)
  // Workaround for nvcc
  //-> extents<size_t, __detail::__make_dynamic_extent<_IndexTypes>()...>;
  // Adding "(void)" so that clang doesn't complain this is unused
  -> extents<size_t, size_t(((void) _IndexTypes(), -1))...>;
#  endif

namespace __detail
{

template <class _Tp>
struct __is_extents : false_type
{};

template <class _IndexType, size_t... _ExtentsPack>
struct __is_extents<_CUDA_VSTD::extents<_IndexType, _ExtentsPack...>> : true_type
{};

template <class _Tp>
static constexpr bool __is_extents_v = __is_extents<_Tp>::value;

template <typename _Extents>
struct __extents_to_partially_static_sizes;

template <class _IndexType, size_t... _ExtentsPack>
struct __extents_to_partially_static_sizes<_CUDA_VSTD::extents<_IndexType, _ExtentsPack...>>
{
  using type = __detail::__partially_static_sizes<typename _CUDA_VSTD::extents<_IndexType, _ExtentsPack...>::index_type,
                                                  size_t,
                                                  _ExtentsPack...>;
};

template <typename _Extents>
using __extents_to_partially_static_sizes_t = typename __extents_to_partially_static_sizes<_Extents>::type;

} // end namespace __detail

#endif // _CCCL_STD_VER > 2011

_LIBCUDACXX_END_NAMESPACE_STD

_CCCL_POP_MACROS

#endif // _LIBCUDACXX___MDSPAN_EXTENTS_HPP
