Skip to content

Commit

Permalink
#1144 - Part 1 : Basic concept and forward constraining wide (#1306)
Browse files Browse the repository at this point in the history
* Implement builtin_vectorizable/vectorizable new concepts

* Make wide accept vectorizable type

* Make vectorizable works on nested product_type

* Adapt unit test becasue MSVC has 8 bytes long double

* Don't generate logical<bool>

* Renamed concept to plain_scalar/scalar

* Better plain_scalar

* Remove remaining char

* Some more char

* More char

* Split scalar produc_type concept for later reuse

* MSVC is at it again

* Final renaming
  • Loading branch information
jfalcou authored Jun 2, 2022
1 parent 625e01c commit 3b4a605
Show file tree
Hide file tree
Showing 22 changed files with 262 additions and 61 deletions.
5 changes: 0 additions & 5 deletions include/eve/arch/cardinals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ namespace eve
using combined_type = fixed<2>;
};

//================================================================================================
//! @brief Cardinal object representing the cardinal of [scalar values](@ref eve::scalar_value)
//================================================================================================
inline constexpr scalar_cardinal const scalar = {};

template<std::ptrdiff_t Cardinal>
inline constexpr fixed<Cardinal> const lane = {};

Expand Down
3 changes: 2 additions & 1 deletion include/eve/arch/cpu/wide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <eve/arch/spec.hpp>
#include <eve/conditional.hpp>
#include <eve/concept/memory.hpp>
#include <eve/concept/scalar.hpp>
#include <eve/memory/soa_ptr.hpp>
#include <eve/concept/range.hpp>
#include <eve/detail/abi.hpp>
Expand Down Expand Up @@ -56,7 +57,7 @@ namespace eve
//! @tparam Cardinal Cardinal of the register. By default, the best cardinal for current
//! architecture is selected.
//================================================================================================
template<typename Type, typename Cardinal>
template<scalar Type, typename Cardinal>
struct EVE_MAY_ALIAS wide
: detail::wide_storage<as_register_t<Type, Cardinal, abi_t<Type, Cardinal>>>
{
Expand Down
59 changes: 59 additions & 0 deletions include/eve/concept/scalar.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Contributors & Maintainers
SPDX-License-Identifier: MIT
*/
//==================================================================================================
#pragma once

#include <eve/detail/kumi.hpp>
#include <eve/detail/meta.hpp>
#include <type_traits>
#include <cstdint>
#include <cstddef>

namespace eve
{
template<typename T, typename... Ts>
concept one_of = (std::same_as<T,Ts> || ... || false);

template<typename T>
concept plain_scalar = one_of< T
, float, double
, std::int8_t , std::int16_t , std::int32_t , std::int64_t
, std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t
>;

namespace detail
{
template<typename T> constexpr bool scalar_tuple()
{
if constexpr(kumi::product_type<T>)
{
if constexpr(kumi::size<T>::value != 0)
{
using flatten_t = kumi::result::flatten_all_t<T>;
return []<std::size_t... I>( std::index_sequence<I...> )
{
return (plain_scalar<kumi::element_t<I,flatten_t>> && ... && true);
}(std::make_index_sequence<kumi::size<flatten_t>::value>{});
}
else
{
return false;
}
}
else
{
return false;
}
}
}

template<typename T>
concept product_scalar = detail::scalar_tuple<T>();

template<typename T>
concept scalar = plain_scalar<T> || product_scalar<T>;
}
3 changes: 2 additions & 1 deletion include/eve/detail/function/simd/common/to_logical.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <eve/traits/as_logical.hpp>
#include <eve/forward.hpp>
#include <bitset>
#include <type_traits>

namespace eve::detail
{
Expand Down Expand Up @@ -40,6 +41,6 @@ namespace eve::detail

template<scalar_value T> EVE_FORCEINLINE auto to_logical( T v ) noexcept
{
return logical<T>(v);
return logical<std::conditional_t<std::is_same_v<T,bool>, std::uint8_t, T>>(v);
}
}
3 changes: 2 additions & 1 deletion include/eve/forward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <eve/arch/abi.hpp>
#include <eve/arch/expected_cardinal.hpp>
#include <eve/arch/spec.hpp>
#include <eve/concept/scalar.hpp>

namespace eve
{
Expand All @@ -19,7 +20,7 @@ namespace eve
inline namespace EVE_ABI_NAMESPACE
{
// Wrapper for SIMD registers holding arithmetic types with compile-time size
template<typename Type,
template<scalar Type,
typename Size = expected_cardinal_t<Type>>
struct wide;
}
Expand Down
4 changes: 2 additions & 2 deletions test/unit/algo/array_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

TTS_CASE("eve.algo.array_utils array_map")
{
constexpr std::array<char, 4> input = { 1, 2, 3, 4 };
constexpr std::array<std::int8_t, 4> input = { 1, 2, 3, 4 };
constexpr std::array<int, 4> expected = { 2, 4, 6, 8 };
constexpr auto actual = eve::algo::array_map(input, [](char x) -> int { return x * 2; });
constexpr auto actual = eve::algo::array_map(input, [](std::int8_t x) -> int { return x * 2; });
TTS_CONSTEXPR_EXPECT(expected == actual);
};

Expand Down
4 changes: 2 additions & 2 deletions test/unit/algo/container/soa_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include "unit/api/udt/udt.hpp"
#include <memory>

using t_t = kumi::tuple<int,float,char>;
using n_t = kumi::tuple<int,kumi::tuple<float,char>,double>;
using t_t = kumi::tuple<int,float,std::int8_t>;
using n_t = kumi::tuple<int,kumi::tuple<float,std::int8_t>,double>;

TTS_CASE("Check types")
{
Expand Down
2 changes: 1 addition & 1 deletion test/unit/algo/preprocess_range.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ EVE_TEST_TYPES("cardinal/type manipulation", algo_test::selected_types)
{
auto processed = eve::algo::preprocess_range(
eve::algo::traits(),
eve::algo::views::convert(v, eve::as<eve::common_type_t<double, char>>{}));
eve::algo::views::convert(v, eve::as<eve::common_type_t<double, std::int8_t>>{}));

using I = decltype(processed.begin());
TTS_TYPE_IS(typename I::value_type, double);
Expand Down
10 changes: 5 additions & 5 deletions test/unit/algo/traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ TTS_CASE("eve.algo defaulting")

TTS_CASE("eve.algo.traits consider types")
{
eve::algo::traits expected{ eve::algo::consider_types<double, int, char> };
eve::algo::traits expected{ eve::algo::consider_types<double, int, std::int8_t> };
{
eve::algo::traits tr;
eve::algo::traits def{eve::algo::consider_types<double, int, char>};
eve::algo::traits def{eve::algo::consider_types<double, int, std::int8_t>};
auto actual = eve::algo::default_to(tr, def);
TTS_TYPE_IS(decltype(expected), decltype(actual));
}
{
eve::algo::traits tr{eve::algo::consider_types<double, int, char>};
eve::algo::traits tr{eve::algo::consider_types<double, int, std::int8_t>};
eve::algo::traits def;
auto actual = eve::algo::default_to(tr, def);
TTS_TYPE_IS(decltype(expected), decltype(actual));
}
{
eve::algo::traits tr{eve::algo::consider_types<double>};
eve::algo::traits def{eve::algo::consider_types<int, char>};
eve::algo::traits def{eve::algo::consider_types<int, std::int8_t>};
auto actual = eve::algo::default_to(tr, def);
TTS_TYPE_IS(decltype(expected), decltype(actual));
}
Expand Down Expand Up @@ -107,7 +107,7 @@ TTS_CASE("eve.algo.traits, type and cardinal")
eve::algo::traits tr;
eve::algo::traits big_step{eve::algo::force_cardinal<64>};
eve::algo::traits tr2 = eve::algo::default_to(tr, big_step);
TTS_TYPE_IS((eve::algo::iteration_cardinal_t<decltype(tr2), char*>), eve::fixed<64>);
TTS_TYPE_IS((eve::algo::iteration_cardinal_t<decltype(tr2), std::int8_t*>), eve::fixed<64>);
}
};

Expand Down
1 change: 1 addition & 0 deletions test/unit/meta/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ make_unit( "unit.meta" as_wide.cpp )

##==================================================================================================
## Concepts tests
make_unit( "unit.meta.concept" scalar.cpp )
make_unit( "unit.meta.concept" decorator.cpp )
make_unit( "unit.meta.concept" value.cpp )
make_unit( "unit.meta.concept" native_simd_for_abi.cpp )
Expand Down
2 changes: 1 addition & 1 deletion test/unit/meta/cardinal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ TTS_CASE_TPL( "Check for SIMD tuple-like type cardinals"
)
<typename T>(::tts::type<T>)
{
using tuple_t = kumi::tuple<float,double,char>;
using tuple_t = kumi::tuple<float,double,std::int8_t>;

TTS_TYPE_IS( (eve::cardinal_t<eve::wide<tuple_t, T>>), T );
TTS_EQUAL ( (eve::cardinal_v<eve::wide<tuple_t, T>>), T::value );
Expand Down
2 changes: 1 addition & 1 deletion test/unit/meta/element_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

TTS_CASE( "Check for element_type")
{
using tuple_t = kumi::tuple<int,float,char>;
using tuple_t = kumi::tuple<int,float, std::uint8_t>;

TTS_TYPE_IS( eve::element_type_t<bool> , bool);
TTS_TYPE_IS( eve::element_type_t<int> , int);
Expand Down
6 changes: 3 additions & 3 deletions test/unit/meta/max_scalar_size.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
TTS_CASE( "Check max_scalar_size" )
{
TTS_CONSTEXPR_EQUAL(sizeof(int), eve::max_scalar_size_v<int>);
TTS_CONSTEXPR_EQUAL(sizeof(char), eve::max_scalar_size_v<char>);
TTS_CONSTEXPR_EQUAL(sizeof(char), (eve::max_scalar_size_v<kumi::tuple<char, char>>));
TTS_CONSTEXPR_EQUAL(sizeof(std::int8_t), eve::max_scalar_size_v<std::int8_t>);
TTS_CONSTEXPR_EQUAL(sizeof(std::int8_t), (eve::max_scalar_size_v<kumi::tuple<std::int8_t, std::int8_t>>));
TTS_CONSTEXPR_EQUAL(sizeof(int), (eve::max_scalar_size_v<kumi::tuple<
int, kumi::tuple<char, char>>>));
int, kumi::tuple<std::int8_t, std::int8_t>>>));
};
143 changes: 143 additions & 0 deletions test/unit/meta/scalar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//==================================================================================================
/**
EVE - Expressive Vector Engine
Copyright : EVE Contributors & Maintainers
SPDX-License-Identifier: MIT
**/
//==================================================================================================
#include "test.hpp"
#include <eve/concept/scalar.hpp>

TTS_CASE("Check for plain_scalar on regular types" )
{
TTS_EXPECT( eve::plain_scalar<signed char>);
TTS_EXPECT( eve::plain_scalar<short> );
TTS_EXPECT( eve::plain_scalar<int> );

TTS_EXPECT( eve::plain_scalar<unsigned char> );
TTS_EXPECT( eve::plain_scalar<unsigned short> );
TTS_EXPECT( eve::plain_scalar<unsigned int> );

TTS_EXPECT( eve::plain_scalar<float> );
TTS_EXPECT( eve::plain_scalar<double> );
};

TTS_CASE("Check for plain_scalar on cstdint/def types" )
{
TTS_EXPECT( eve::plain_scalar<std::int8_t> );
TTS_EXPECT( eve::plain_scalar<std::int16_t> );
TTS_EXPECT( eve::plain_scalar<std::int32_t> );
TTS_EXPECT( eve::plain_scalar<std::int64_t> );

TTS_EXPECT( eve::plain_scalar<std::uint8_t> );
TTS_EXPECT( eve::plain_scalar<std::uint16_t> );
TTS_EXPECT( eve::plain_scalar<std::uint32_t> );
TTS_EXPECT( eve::plain_scalar<std::uint64_t> );

TTS_EXPECT( eve::plain_scalar<std::size_t> );
TTS_EXPECT( eve::plain_scalar<std::ptrdiff_t> );
};

TTS_CASE("Check for plain_scalar on unsupported types" )
{
TTS_EXPECT_NOT( eve::plain_scalar<long double> );
TTS_EXPECT_NOT( eve::plain_scalar<bool> );
TTS_EXPECT_NOT( eve::plain_scalar<void*> );
TTS_EXPECT_NOT((eve::plain_scalar<kumi::tuple<int,float,std::int8_t>> ));
};

TTS_CASE("Check for product_scalar on product_type" )
{
TTS_EXPECT((eve::product_scalar<kumi::tuple<int>>));
TTS_EXPECT((eve::product_scalar<kumi::tuple<int,float>>));
TTS_EXPECT((eve::product_scalar<kumi::tuple<int,std::int8_t,double>>));
TTS_EXPECT((eve::product_scalar<kumi::tuple<int,kumi::tuple<std::int8_t,double>,float>>));
};

TTS_CASE("Check for product_scalar on unsupported types" )
{
TTS_EXPECT_NOT( eve::product_scalar<long double> );
TTS_EXPECT_NOT( eve::product_scalar<std::int8_t> );
TTS_EXPECT_NOT( eve::product_scalar<void*> );
TTS_EXPECT_NOT((eve::product_scalar<float> ) );
TTS_EXPECT_NOT((eve::product_scalar<kumi::tuple<void*, int, long double>>) );
};

TTS_CASE("Check for scalar on plain_scalar" )
{
TTS_EXPECT( eve::scalar<signed char> );
TTS_EXPECT( eve::scalar<short> );
TTS_EXPECT( eve::scalar<int> );
TTS_EXPECT( eve::scalar<unsigned char> );
TTS_EXPECT( eve::scalar<unsigned short> );
TTS_EXPECT( eve::scalar<unsigned int> );
TTS_EXPECT( eve::scalar<float> );
TTS_EXPECT( eve::scalar<double> );

TTS_EXPECT( eve::scalar<std::int8_t> );
TTS_EXPECT( eve::scalar<std::int16_t> );
TTS_EXPECT( eve::scalar<std::int32_t> );
TTS_EXPECT( eve::scalar<std::int64_t> );
TTS_EXPECT( eve::scalar<std::uint8_t> );
TTS_EXPECT( eve::scalar<std::uint16_t> );
TTS_EXPECT( eve::scalar<std::uint32_t> );
TTS_EXPECT( eve::scalar<std::uint64_t> );
TTS_EXPECT( eve::scalar<std::size_t> );
TTS_EXPECT( eve::scalar<std::ptrdiff_t> );
};

TTS_CASE("Check for scalar on product_type" )
{
TTS_EXPECT((eve::scalar<kumi::tuple<int>>));
TTS_EXPECT((eve::scalar<kumi::tuple<int,float>>));
TTS_EXPECT((eve::scalar<kumi::tuple<int,std::int8_t,double>>));
TTS_EXPECT((eve::scalar<kumi::tuple<int,kumi::tuple<std::int8_t,double>,float>>));
};

TTS_CASE("Check for scalar on unsupported types" )
{
TTS_EXPECT_NOT( eve::scalar<long double> );
TTS_EXPECT_NOT( eve::scalar<bool> );
TTS_EXPECT_NOT( eve::scalar<void*> );
TTS_EXPECT_NOT( (eve::scalar<kumi::tuple<>>) );
TTS_EXPECT_NOT( (eve::scalar<kumi::tuple<int,bool>>) );
};

template<eve::plain_scalar T> auto check_overload(T) { return +1; }
template<eve::scalar T> auto check_overload(T) { return +2; }
template<eve::scalar T> auto check_overload2(T) { return +3; }
template<eve::product_scalar T> auto check_overload3(T) { return +10; }
template<typename T> auto check_overload(T) { return -1; }
template<typename T> auto check_overload2(T) { return -3; }
template<typename T> auto check_overload3(T) { return -10; }

TTS_CASE("Check for scalar/plain_scalar overload relationship" )
{
TTS_EQUAL(check_overload(4) , +1);
TTS_EQUAL(check_overload(4.f) , +1);
TTS_EQUAL(check_overload(kumi::tuple{4}) , +2);
TTS_EQUAL(check_overload(kumi::tuple{3,5.f}) , +2);

TTS_EQUAL(check_overload(nullptr) , -1);
TTS_EQUAL(check_overload(kumi::tuple<>{}) , -1);
TTS_EQUAL(check_overload(kumi::tuple{nullptr}) , -1);

TTS_EQUAL(check_overload2(4) , +3);
TTS_EQUAL(check_overload2(4.f) , +3);
TTS_EQUAL(check_overload2(kumi::tuple{4}) , +3);
TTS_EQUAL(check_overload2(kumi::tuple{3,5.f}) , +3);

TTS_EQUAL(check_overload2(nullptr) , -3);
TTS_EQUAL(check_overload2(kumi::tuple<>{}) , -3);
TTS_EQUAL(check_overload2(kumi::tuple{nullptr}) , -3);

TTS_EQUAL(check_overload3(kumi::tuple{4}) , +10);
TTS_EQUAL(check_overload3(kumi::tuple{3,5.f}) , +10);
TTS_EQUAL(check_overload3(kumi::tuple{3,kumi::tuple{4.},5.f}) , +10);

TTS_EQUAL(check_overload3(4) , -10);
TTS_EQUAL(check_overload3(4.f) , -10);
TTS_EQUAL(check_overload3(nullptr) , -10);
TTS_EQUAL(check_overload3(kumi::tuple<>{}) , -10);
TTS_EQUAL(check_overload3(kumi::tuple{nullptr}) , -10);
};
4 changes: 2 additions & 2 deletions test/unit/meta/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TTS_CASE("Check validation of the scalar_value concept" )

TTS_EXPECT_NOT( (eve::scalar_value<wide<int>> ) );
TTS_EXPECT_NOT( (eve::scalar_value<logical<wide<int>>> ) );
TTS_EXPECT_NOT( (eve::scalar_value<wide<char,fixed<16>>>) );
TTS_EXPECT_NOT( (eve::scalar_value<wide<std::int8_t,fixed<16>>>) );
TTS_EXPECT_NOT( (eve::scalar_value<wide<kumi::tuple<int,float>>>) );
};

Expand All @@ -49,6 +49,6 @@ TTS_CASE("Check validation of the simd_value" )

TTS_EXPECT( (eve::simd_value<wide<int>> ) );
TTS_EXPECT( (eve::simd_value<logical<wide<int>>> ) );
TTS_EXPECT( (eve::simd_value<wide<char,fixed<16>>>) );
TTS_EXPECT( (eve::simd_value<wide<std::int8_t,fixed<16>>>) );
TTS_EXPECT( (eve::simd_value<wide<kumi::tuple<int,float>>>) );
};
Loading

0 comments on commit 3b4a605

Please sign in to comment.