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
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ set_property(CACHE LINALG_CXX_STANDARD PROPERTY STRINGS DETECT 14 17 20 23)
option(LINALG_ENABLE_CONCEPTS "Try to enable concepts support by giving extra flags." On)
option(LINALG_ENABLE_ATOMIC_REF "Try to enable atomic_ref support" OFF)

option(LINALG_FIX_TRANSPOSED_FOR_PADDED_LAYOUTS "Enable implementation of P3222 (Fix transposed for P2642 padded layouts). OFF by default, though this will change if P3222 is voted into the C++ Standard Working Draft." OFF)

option(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX "Enable implementation of P3050 (Fix conjugated for noncomplex value types). OFF by default, though this will change if P3050 is voted into the C++ Standard Working Draft." OFF)

################################################################################

# Decide on the standard to use
Expand Down
32 changes: 25 additions & 7 deletions include/experimental/__p1673_bits/conjugated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,34 @@ class conjugated_accessor {
template<class ElementType, class Extents, class Layout, class Accessor>
auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a)
{
if constexpr (std::is_arithmetic_v<std::remove_cv_t<ElementType>>) {
using value_type = typename decltype(a)::value_type;

// Current status of [linalg] only optimizes if Accessor is
// conjugated_accessor<Accessor> for some Accessor.
// There's a separate specialization for that case below.

#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
// P3050 optimizes conjugated's accessor type for when
// we know that it can't be complex: arithmetic types,
// and types for which `conj` is not ADL-findable.
if constexpr (std::is_arithmetic_v<value_type>) {
Comment thread
mhoemmen marked this conversation as resolved.
return mdspan<ElementType, Extents, Layout, Accessor>
(a.data_handle(), a.mapping(), a.accessor());
} else {
using return_element_type =
typename conjugated_accessor<Accessor>::element_type;
using return_accessor_type = conjugated_accessor<Accessor>;
return mdspan<return_element_type, Extents, Layout, return_accessor_type>
(a.data_handle(), a.mapping(), return_accessor_type(a.accessor()));
}
else if constexpr (! impl::has_conj<value_type>::value) {
return mdspan<ElementType, Extents, Layout, Accessor>
(a.data_handle(), a.mapping(), a.accessor());
}
else {
#endif // LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX
using return_element_type =
typename conjugated_accessor<Accessor>::element_type;
using return_accessor_type = conjugated_accessor<Accessor>;
return mdspan<return_element_type, Extents, Layout, return_accessor_type>
(a.data_handle(), a.mapping(), return_accessor_type(a.accessor()));
#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
}
#endif // LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX
}

// Conjugation is self-annihilating
Expand Down
2 changes: 2 additions & 0 deletions include/experimental/__p1673_bits/linalg_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
#cmakedefine LINALG_ENABLE_KOKKOS
#cmakedefine LINALG_ENABLE_KOKKOS_DEFAULT
#cmakedefine LINALG_ENABLE_TBB
#cmakedefine LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX
#cmakedefine LINALG_FIX_TRANSPOSED_FOR_PADDED_LAYOUTS
46 changes: 45 additions & 1 deletion include/experimental/__p1673_bits/transposed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ template<class Layout>
class layout_transpose {
public:
using nested_layout_type = Layout;

template<class Extents>
struct mapping {
private:
Expand Down Expand Up @@ -270,6 +270,50 @@ namespace impl {
}
};

#if defined(LINALG_FIX_TRANSPOSED_FOR_PADDED_LAYOUTS)
template<size_t PaddingValue>
struct transposed_layout<layout_left_padded<PaddingValue>> {
using layout_type = layout_right_padded<PaddingValue>;

template<class OriginalExtents>
static auto mapping(const typename layout_left_padded<PaddingValue>::template mapping<OriginalExtents>& orig_map) {
using input_mapping_type =
typename layout_left_padded<PaddingValue>::template mapping<OriginalExtents>;
using output_extents_type =
transpose_extents_t<typename input_mapping_type::extents_type>;
using output_mapping_type =
typename layout_type::template mapping<output_extents_type>;

const auto padding_value = orig_map.stride(1);
return output_mapping_type{
transpose_extents(orig_map.extents()),
padding_value
};
}
};

template<size_t PaddingValue>
struct transposed_layout<layout_right_padded<PaddingValue>> {
using layout_type = layout_left_padded<PaddingValue>;

template<class OriginalExtents>
static auto mapping(const typename layout_right_padded<PaddingValue>::template mapping<OriginalExtents>& orig_map) {
using input_mapping_type =
typename layout_right_padded<PaddingValue>::template mapping<OriginalExtents>;
using output_extents_type =
transpose_extents_t<typename input_mapping_type::extents_type>;
using output_mapping_type =
typename layout_type::template mapping<output_extents_type>;

const auto padding_value = orig_map.stride(0);
return output_mapping_type{
transpose_extents(orig_map.extents()),
padding_value
};
}
};
#endif // LINALG_FIX_TRANSPOSED_FOR_PADDED_LAYOUTS

template<class StorageOrder>
using opposite_storage_t = std::conditional_t<
std::is_same_v<StorageOrder, column_major_t>,
Expand Down
109 changes: 84 additions & 25 deletions tests/native/conjugated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,36 @@ namespace {
using layout_type = layout_right;

{
using input_accessor_type = default_accessor<float>;
using expected_accessor_type = default_accessor<float>;
mdspan<float, extents_type, layout_type, input_accessor_type> x_nc{x_storage.data()};
using input_element_type = float;
using input_accessor_type = default_accessor<input_element_type>;
#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = input_accessor_type;
using expected_element_type = input_element_type;
#else
using expected_accessor_type = conjugated_accessor<input_accessor_type>;
using expected_element_type = std::add_const_t<input_element_type>;
#endif // LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX

mdspan<input_element_type, extents_type, layout_type, input_accessor_type> x_nc{x_storage.data()};
auto x_nc_conj = conjugated(x_nc);
static_assert(std::is_same_v<decltype(x_nc_conj),
mdspan<float, extents_type, layout_type, expected_accessor_type>>);
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
EXPECT_EQ(x_nc_conj.mapping(), x_nc.mapping());
}
{
using input_accessor_type = default_accessor<const float>;
using expected_accessor_type = default_accessor<const float>;
mdspan<const float, extents_type, layout_type, input_accessor_type> x_c{x_storage.data()};
using input_element_type = const float;
using input_accessor_type = default_accessor<input_element_type>;
#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = default_accessor<input_element_type>;
#else
using expected_accessor_type = conjugated_accessor<input_accessor_type>;
#endif // LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX
using expected_element_type = input_element_type;

mdspan<input_element_type, extents_type, layout_type, input_accessor_type> x_c{x_storage.data()};
auto x_c_conj = conjugated(x_c);
static_assert(std::is_same_v<decltype(x_c_conj),
mdspan<const float, extents_type, layout_type, expected_accessor_type>>);
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
EXPECT_EQ(x_c_conj.mapping(), x_c.mapping());
}
}
Expand All @@ -66,23 +81,36 @@ namespace {
using layout_type = layout_right;

{
using input_accessor_type = nondefault_accessor<float>;
// Implementation currently is more like P3050R0 than P1673R13.
using expected_accessor_type = nondefault_accessor<float>;
mdspan<float, extents_type, layout_type, input_accessor_type> x_nc{x_storage.data()};
using input_element_type = float;
using input_accessor_type = nondefault_accessor<input_element_type>;
#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = input_accessor_type;
using expected_element_type = input_element_type;
#else
using expected_accessor_type = conjugated_accessor<input_accessor_type>;
using expected_element_type = std::add_const_t<input_element_type>;
#endif // LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX

mdspan<input_element_type, extents_type, layout_type, input_accessor_type> x_nc{x_storage.data()};
auto x_nc_conj = conjugated(x_nc);
static_assert(std::is_same_v<decltype(x_nc_conj),
mdspan<float, extents_type, layout_type, expected_accessor_type>>);
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
EXPECT_EQ(x_nc_conj.mapping(), x_nc.mapping());
}
{
using input_accessor_type = nondefault_accessor<const float>;
// Implementation currently is more like P3050R0 than P1673R13.
using expected_accessor_type = nondefault_accessor<const float>;
using input_element_type = const float;
using input_accessor_type = nondefault_accessor<input_element_type>;
#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = input_accessor_type;
#else
using expected_accessor_type = conjugated_accessor<input_accessor_type>;
#endif // LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX
using expected_element_type = input_element_type;

mdspan<const float, extents_type, layout_type, input_accessor_type> x_c{x_storage.data()};
auto x_c_conj = conjugated(x_c);
static_assert(std::is_same_v<decltype(x_c_conj),
mdspan<const float, extents_type, layout_type, expected_accessor_type>>);
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
EXPECT_EQ(x_c_conj.mapping(), x_c.mapping());
}
}
Expand All @@ -103,21 +131,38 @@ namespace {
mdspan<value_type, extents_type, layout_type, input_accessor_type> x_nc{x_storage.data()};
auto x_nc_conj = conjugated(x_nc);

#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = default_accessor<value_type>;
using expected_element_type = value_type;
#else
using expected_accessor_type = conjugated_accessor<default_accessor<value_type>>;
using expected_element_type = std::add_const_t<value_type>;
static_assert(std::is_same_v<decltype(x_nc_conj),
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
#endif
static_assert(std::is_same_v<typename decltype(x_nc_conj)::element_type, expected_element_type>);
static_assert(std::is_same_v<typename decltype(x_nc_conj)::extents_type, extents_type>);
static_assert(std::is_same_v<typename decltype(x_nc_conj)::layout_type, layout_type>);
static_assert(std::is_same_v<typename decltype(x_nc_conj)::accessor_type, expected_accessor_type>);
using expected_mdspan_type = mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>;
static_assert(std::is_same_v<decltype(x_nc_conj), expected_mdspan_type>);
EXPECT_EQ(x_nc_conj.mapping(), x_nc.mapping());
}
{
using input_accessor_type = default_accessor<const value_type>;
mdspan<const value_type, extents_type, layout_type, input_accessor_type> x_c{x_storage.data()};
auto x_c_conj = conjugated(x_c);

#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = default_accessor<const value_type>;
#else
using expected_accessor_type = conjugated_accessor<default_accessor<const value_type>>;
using expected_element_type = std::add_const_t<value_type>;
static_assert(std::is_same_v<decltype(x_c_conj),
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
#endif
using expected_element_type = const value_type;
static_assert(std::is_same_v<typename decltype(x_c_conj)::element_type, expected_element_type>);
static_assert(std::is_same_v<typename decltype(x_c_conj)::extents_type, extents_type>);
static_assert(std::is_same_v<typename decltype(x_c_conj)::layout_type, layout_type>);
static_assert(std::is_same_v<typename decltype(x_c_conj)::accessor_type, expected_accessor_type>);
using expected_mdspan_type = mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>;
static_assert(std::is_same_v<decltype(x_c_conj), expected_mdspan_type>);
EXPECT_EQ(x_c_conj.mapping(), x_c.mapping());
}
}
Expand All @@ -136,19 +181,33 @@ namespace {
mdspan<value_type, extents_type, layout_type, input_accessor_type> x_nc{x_storage.data()};
auto x_nc_conj = conjugated(x_nc);

#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = nondefault_accessor<value_type>;
using expected_element_type = value_type;
#else
using expected_accessor_type = conjugated_accessor<nondefault_accessor<value_type>>;
using expected_element_type = std::add_const_t<value_type>;
static_assert(std::is_same_v<decltype(x_nc_conj),
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
#endif
static_assert(std::is_same_v<typename decltype(x_nc_conj)::element_type, expected_element_type>);
static_assert(std::is_same_v<typename decltype(x_nc_conj)::extents_type, extents_type>);
static_assert(std::is_same_v<typename decltype(x_nc_conj)::layout_type, layout_type>);
static_assert(std::is_same_v<typename decltype(x_nc_conj)::accessor_type, expected_accessor_type>);
using expected_mdspan_type =
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>;
static_assert(std::is_same_v<decltype(x_nc_conj), expected_mdspan_type>);
EXPECT_EQ(x_nc_conj.mapping(), x_nc.mapping());
}
{
using input_accessor_type = nondefault_accessor<const value_type>;
mdspan<const value_type, extents_type, layout_type, input_accessor_type> x_c{x_storage.data()};
auto x_c_conj = conjugated(x_c);

#if defined(LINALG_FIX_CONJUGATED_FOR_NONCOMPLEX)
using expected_accessor_type = nondefault_accessor<const value_type>;
#else
using expected_accessor_type = conjugated_accessor<nondefault_accessor<const value_type>>;
using expected_element_type = std::add_const_t<value_type>;
#endif
using expected_element_type = const value_type;
static_assert(std::is_same_v<decltype(x_c_conj),
mdspan<expected_element_type, extents_type, layout_type, expected_accessor_type>>);
EXPECT_EQ(x_c_conj.mapping(), x_c.mapping());
Expand Down
Loading