Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MB hacks, required changes and brainstorming for latest master #115

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ce227a4
Clang-CL: (quick) fixed compile-time option settings.
May 8, 2023
61f780a
Clang-CL: workaround for static-order-initialization--fiasco in TTS.
May 8, 2023
f308152
Fixed a -Wsign-conversion warning.
May 22, 2023
ac687e3
'Some change' (I guess in kumi) prevents shape from being treated as …
Jul 19, 2023
c7486c8
Quick-hack fix for MB: we need default axis type to be 16 bits (a pro…
Jul 19, 2023
6dfff49
prefilled operator[] improvement attempts and quick-fixes:
Jul 19, 2023
a0a1066
Fixed coordinates() to use the correct underlying std::array type.
Jul 19, 2023
c969e1d
Quick-hack fix for MB: we need default axis type to be 16 bits (a pro…
Jul 19, 2023
ac9cbb5
prefilled::get disambiguation.
Jul 19, 2023
fb4f448
Minor stylistic fixes.
Jul 21, 2023
76f2aae
Hack-fix for compilation errors in coordinates() for shapes created w…
Jul 22, 2023
902560d
axis_:
Jul 22, 2023
85af75c
Fixed warning-as-error on non-Clang compilers.
Jul 22, 2023
686e177
Fixed as_dimension for axis.
Aug 3, 2023
1e76764
Add operator== to tuple [to enable easier and simpler equivalents in …
Aug 3, 2023
87ad842
Ad-hoc ability to configure underlying joker integral type (its size).
Aug 3, 2023
5bc8bf7
'Fixed' KWK_DEFAULT_SHAPE_CONSTRAINTS support by adding the accompany…
Aug 3, 2023
6351533
Updated with joker changes.
Aug 3, 2023
68d2c50
Added static_axes and static_values 'accessors' to shape (should prob…
Aug 3, 2023
d27c852
New shiny CMake objects.
Aug 3, 2023
c358a4c
Replaced the configurable-joker-underlying-type ugliness with a simpl…
Aug 3, 2023
6b3271d
Simplified KWK_DEFAULT_SHAPE* logic.
Aug 3, 2023
01fa3e5
Updated the unit tests with the latest changes.
Aug 3, 2023
dd4c6e1
Made constant usable in assume statements w/o compiler warnings.
Aug 3, 2023
3649d35
Ditto extent.
Aug 3, 2023
0c34146
Missing axis_with_extent for type_info.
Aug 3, 2023
6afa7f7
Fixed (hopefully) axis == integral and joker comparisons.
Aug 3, 2023
f4cd4ed
Properly fixed the issue of shape<> not being trivially copyable.
Aug 9, 2023
07af4bd
use std::equality_comparable_with which is now fully supported
DoDoENT Jan 2, 2024
72e45da
fix narrowing cast
DoDoENT Jan 2, 2024
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
2 changes: 1 addition & 1 deletion cmake/make_unit.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include(add_target_parent)
##==================================================================================================
add_library(kiwaku_test INTERFACE)

if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
if(MSVC)
psiha marked this conversation as resolved.
Show resolved Hide resolved
target_compile_options( kiwaku_test INTERFACE /W3 /EHsc /bigobj /std:c++20)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options( kiwaku_test INTERFACE -std=c++20 -Werror -Wall -Wextra -Wconversion -Wunused-variable -Wdocumentation)
Expand Down
2 changes: 1 addition & 1 deletion include/kwk/detail/assert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace kwk
[[noreturn]] inline
void assert_termination(std::ostringstream & stream, char const * const condition, char const * const function, char const * const file, unsigned const line) noexcept
{
boost::assertion_failed_msg(condition, std::move(stream).str().c_str(), function, file, line);
boost::assertion_failed_msg(condition, std::move(stream).str().c_str(), function, file, static_cast<long>(line));
KWK_UNREACHABLE();
}

Expand Down
2 changes: 1 addition & 1 deletion include/kwk/detail/sequence/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ namespace kwk::__
// Type short-cut for internal representation of types in axis
//====================================================================================================================
template<typename T> struct stored_type : T {};
template<concepts::joker T> struct stored_type<T> { using type = std::int32_t; };
template<concepts::joker T> struct stored_type<T> { using type = std::uint16_t; };
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan to have that hardcoded. If you want it globally selectable instead of putting short everywhere in shape definition, I can live with a KWK_DEFAULT_DIMENSION_TYPE thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right right, i have a lot of other changes incoming (still strugling with fully moving to new kiwaku, quite time consuming) so please wait a day or two until i push those - then will have to have another 'facetime' i'm pretty sure 🙈 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in advance: the main problem is that if we support heterogeneous shape containers, defaulting runtime-sized dimensions to a fixed integral type defined in joker is inconsistent/incomplete: one should be able to choose that also - for now i've put in an nttp based mechanism that most resembles what you do elswhere - so you'd say shape<_[short{}]> to get a 16bit untyped runtimesized axis

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually this whole joker idea really 'broke my back', lost a lot of time on that - it made my code more complicated (as well as the changes i required in kiwaku) - the previous approach where a dynamic/runtime-specified dimension/axis was specified simply with a zero/default-constructed value (using/counting on the fact/assumption that no one will ever need or use a fixed zero statically sized axis - what would be the point of that? i.e. such a shape will always have a zero count/volume)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in advance: the main problem is that if we support heterogeneous shape containers, defaulting runtime-sized dimensions to a fixed integral type defined in joker is inconsistent/incomplete: one should be able to choose that also - for now i've put in an nttp based mechanism that most resembles what you do elswhere - so you'd say shape<_[short{}]> to get a 16bit untyped runtimesized axis

That's already available (see https://jfalcou.github.io/kiwaku/glossary.html#glossary-extent)

https://godbolt.org/z/ov5r59jh5

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually this whole joker idea really 'broke my back', lost a lot of time on that - it made my code more complicated (as well as the changes i required in kiwaku) - the previous approach where a dynamic/runtime-specified dimension/axis was specified simply with a zero/default-constructed value (using/counting on the fact/assumption that no one will ever need or use a fixed zero statically sized axis - what would be the point of that? i.e. such a shape will always have a zero count/volume)

I needed something regular for the other algorithms and shape based operation to work with less complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's already available (see https://jfalcou.github.io/kiwaku/glossary.html#glossary-extent)

https://godbolt.org/z/ov5r59jh5

ok great in one sense but in the other it makes it even more complicated :/ for example now i have to detect the as<> thingy in addition to jokers as 'dynamic axes'...

i've already spent entire days on this but will/am now changeing joker back to your initial design (almost :D) and moving to as<> thingies...will see how it goes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed something regular for the other algorithms and shape based operation to work with less complexity.

it made my 'stuff' non-trivially more complex (still haven't cleaned up all the hacks around it) - i guess will have to do a live session to sort it out

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah as I don't have a view on your use cases, I can't take them into account.
The last batch of changes was to accomodate the variadic nature of shape and stride and do the heterogeneous requirements. It has been done so that the thing was comprehensible and had a regular, predictible behavior. So, now, if your specs changed or isn't aligned with that, I need some more informations or we'll be chasing aroudn each other for years and we both have other stuff on our respective plates.


template<typename T>
using stored_t = typename stored_type<typename T::content_type>::type;
Expand Down
57 changes: 28 additions & 29 deletions include/kwk/detail/sequence/prefilled.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace kwk::__
{
struct empty_tuple
{
static constexpr bool is_homogeneous = false;
static constexpr bool is_homogeneous = true;
constexpr auto operator==(empty_tuple const&) const noexcept { return true; }
};

Expand Down Expand Up @@ -71,7 +71,7 @@ namespace kwk::__
static constexpr bool is_fully_explicit = (D.is_explicit && ... && true);

// Do we have runtime storage for a given index ?
static constexpr auto contains(int i) { return setup.index[i] != -1; }
static constexpr auto contains(int i) { return setup.index[i] != -1; }

// Default constructor
KWK_TRIVIAL constexpr prefilled() noexcept : storage_type{} {}
Expand Down Expand Up @@ -269,44 +269,29 @@ namespace kwk::__
}

// Dynamic access - We rely on KUMI internals for speed and ease of detection
KWK_TRIVIAL constexpr auto operator[](std::convertible_to<std::size_t> auto i) const noexcept
requires(is_dynamic && static_size>0)
KWK_TRIVIAL constexpr auto& operator[](std::convertible_to<std::uint32_t> auto i) noexcept
requires(is_fully_dynamic && static_size>0)
{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the change ?

static_assert(is_homogeneous, "[KWK] - Dynamic axis access requires homogeneous extent types.");
auto const idx = static_cast<std::size_t>(i);

KIWAKU_ASSERT ( idx<static_size
, "[KWK] - Out of bounds access at index: " << idx << " for a max. of " << static_size
);
auto const idx = static_cast<std::uint32_t>(i);

KIWAKU_ASSERT ( contains(idx)
, "[KWK] - Access at index " << idx
<< " overwrites a compile-time value of " << kumi::to_tuple(*this)
);

// KUMI internal shortcut
if constexpr(dynamic_size==1) return storage().impl.member0;
else return storage().impl.members[idx];
return get_indexed( idx );
}

KWK_TRIVIAL constexpr auto& operator[](std::convertible_to<std::size_t> auto i) noexcept
requires(is_dynamic && static_size>0)
KWK_TRIVIAL constexpr auto operator[](std::convertible_to<std::uint32_t> auto i) const noexcept
requires(is_fully_dynamic && static_size>0)
{
static_assert(is_homogeneous, "[KWK] - Dynamic axis access requires homogeneous extent types.");
auto const idx = static_cast<std::size_t>(i);

KIWAKU_ASSERT ( idx<static_size
, "[KWK] - Out of bounds access at index: " << idx << " for a max. of " << static_size
);

KIWAKU_ASSERT ( contains(idx)
, "[KWK] - Access at index " << idx
<< " overwrites a compile-time value of " << kumi::to_tuple(*this)
);
return const_cast<prefilled &>(*this).get_indexed(static_cast<std::uint32_t>(i));
}

// KUMI internal shortcut
if constexpr(dynamic_size==1) return storage().impl.member0;
else return storage().impl.members[idx];
KWK_TRIVIAL constexpr auto operator[](std::convertible_to<std::uint32_t> auto i) const noexcept
requires(!(is_fully_dynamic && static_size>0))
{
return as_array()[i]; // rely on std::array bounds checking
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well as_array was suboptimal. I thought this was geenrting better code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think the main issue it that the way it was implemented actually did not work (compile) so this was a quick-fix...we'll have to go through all this live i guess

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in which scenario did it din't work ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think when you used it on a shape that is only is_dynamic but not fully_dynamic (as the original constraint specified): you would index into a kumi tuple internal array that was shorter in length then the shape you were 'randomly' accessing

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I see, our tests are then incomplete.

}

// Named access via Axis
Expand Down Expand Up @@ -424,6 +409,20 @@ namespace kwk::__
KWK_TRIVIAL constexpr storage_type const& storage() const& { return static_cast<storage_type const&>(*this); }
KWK_TRIVIAL constexpr storage_type && storage() && { return static_cast<storage_type&&>(*this); }
KWK_TRIVIAL constexpr storage_type const&& storage() const&& { return static_cast<storage_type const&&>(*this); }

private:
constexpr auto& get_indexed(std::uint32_t const idx) noexcept
{
static_assert(is_homogeneous, "[KWK] - Dynamic axis access requires homogeneous extent types.");

KIWAKU_ASSERT ( idx<static_size
, "[KWK] - Out of bounds access at index: " << idx << " for a max. of " << static_size
);

// KUMI internal shortcut
if constexpr(dynamic_size==1) return storage().impl.member0;
else return storage().impl.members[idx];
}
};

//====================================================================================================================
Expand Down
10 changes: 8 additions & 2 deletions include/kwk/settings/axis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace kwk::__
using is_product_type = void;
using axis_kind = axis_<ID,joker>;
using content_type = Content;
using base_type = std::int32_t;
using base_type = std::uint16_t;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same remark that for joker

using id_type = decltype(ID);

static constexpr auto identifier = ID;
Expand Down Expand Up @@ -103,7 +103,13 @@ namespace kwk::__
return axis_<ID,decltype(v)>{v};
}

Content value = {};
KWK_PURE explicit constexpr operator Content () const noexcept { return value; }
KWK_PURE constexpr Content operator*() const noexcept { return value; }

#ifndef _WIN32 // https://github.com/llvm/llvm-project/issues/49358 Missing [[no_unique_address]] support on Windows
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be put in a macro in detail/abi.hpp ?
Also is it really necessary as axis are mainly used as constexpr entity ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i want the axis thingy to behave as a 'unit' wrapper (like boost.units)...wait for other changes..

[[no_unique_address]] // allow empty axis_ for empty Content (e.g. joker)
#endif
Content value{};
};

template<auto ID, typename C1, typename C2>
Expand Down
6 changes: 3 additions & 3 deletions include/kwk/settings/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ namespace kwk
constexpr inline auto uint8 = as<std::uint8_t>;

/// Pre-defined type settings for std::uint16_t
constexpr inline auto uint16= as<std::uint16_t>;
constexpr inline auto uint16 = as<std::uint16_t>;

/// Pre-defined type settings for std::uint32_t
constexpr inline auto uint32= as<std::uint32_t>;
constexpr inline auto uint32 = as<std::uint32_t>;

/// Pre-defined type settings for std::uint64_t
constexpr inline auto uint64= as<std::uint64_t>;
constexpr inline auto uint64 = as<std::uint64_t>;
}
10 changes: 7 additions & 3 deletions include/kwk/utility/container/shape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ namespace kwk
//! @tparam D List of @ref glossary-extent types
//====================================================================================================================
template<auto... D>
struct shape : __::prefilled_t<D...>::type
struct
#ifdef __clang__
jfalcou marked this conversation as resolved.
Show resolved Hide resolved
[[clang::trivial_abi]]
#endif
shape : __::prefilled_t<D...>::type
{
using parent = typename __::prefilled_t<D...>::type;
using constraint_t = KWK_DEFAULT_SHAPE_CONSTRAINTS;
Expand Down Expand Up @@ -323,8 +327,8 @@ namespace kwk
}

// Access to base type for internal implementation
KWK_TRIVIAL constexpr auto const& __base() const noexcept { return static_cast<parent const&>(*this); }
KWK_TRIVIAL constexpr auto & __base() noexcept { return static_cast<parent&>(*this); }
KWK_TRIVIAL constexpr auto const& __base() const noexcept { return static_cast<parent const&>(*this); }
KWK_TRIVIAL constexpr auto & __base() noexcept { return static_cast<parent &>(*this); }
};

/// Deduction guide for @ref kwk::shape
Expand Down
15 changes: 9 additions & 6 deletions include/kwk/utility/coordinates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

namespace kwk
{
namespace __ { template <typename T> struct to_int<type_::info<T>> { using type = T; }; }

//================================================================================================
//! @ingroup utility
//! @brief Computes a tuple of coordinates from a linear index and a shape
Expand All @@ -25,12 +27,12 @@ namespace kwk
//!
//! @param idx Linear index to convert into a nD coordinate set
//! @param shp Shape used as a reference
//! @return A std::array<shape<Desc>::value_type, shape<Desc>::static_order> containing the
//! @return A std::array<largest_integral<shape<D...>>, shape<D...>::static_order> containing the
//! multi-dimensional position corresponding to idx
//================================================================================================
template<std::integral Idx,auto... Desc>
template<std::integral Idx,auto... D>
KWK_CONST constexpr
auto coordinates( Idx idx, shape<Desc...> const shp) noexcept
auto coordinates(Idx const idx, shape<D...> const shp) noexcept
{
KIWAKU_ASSERT ( idx < shp.numel()
, "Converting index " << idx
Expand All @@ -44,13 +46,14 @@ namespace kwk
idx % shp[3],
*/

using coord_t = typename __::largest_integral<__::to_int_t<decltype(D)>...>::type;
return [&]<int... i>(std::integer_sequence<int, i...>)
{
auto const strides{as_stride(shp)};

return std::array { static_cast<Idx>( idx / get<0 >(strides) )
, static_cast<Idx>((idx / get<i+1>(strides)) % get<i+1>(shp))...
return std::array { static_cast<coord_t>( idx / get<0 >(strides) )
, static_cast<coord_t>((idx / get<i+1>(strides)) % get<i+1>(shp))...
};
}(std::make_integer_sequence<int, shape<Desc...>::static_order - 1 >{});
}(std::make_integer_sequence<int, shape<D...>::static_order - 1>{});
}
}
2 changes: 1 addition & 1 deletion include/kwk/utility/fixed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace kwk

template<auto Value> constexpr auto clamp()
{
if constexpr (std::bit_width(Value) <= 8) return static_cast<std::uint8_t>(Value);
if constexpr (std::bit_width(Value) <= 8) return static_cast<std::uint8_t >(Value);
else if constexpr (std::bit_width(Value) <= 19) return static_cast<std::uint16_t>(Value);
else if constexpr (std::bit_width(Value) <= 32) return static_cast<std::uint32_t>(Value);
else return Value;
Expand Down
2 changes: 1 addition & 1 deletion include/kwk/utility/joker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace kwk
//! @ingroup utility
//! @brief Joker value
//!
//! The joker value defined as @ref kwk::_ is used in various context to means 'just use the
//! The joker value defined as @ref kwk::_ is used in various context to mean 'just use the
//! most meaningful value'.
//================================================================================================
inline constexpr joker _ = {};
Expand Down
5 changes: 4 additions & 1 deletion test/tts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ namespace tts::detail
std::string name;
tts::callable behaviour;
};
inline std::vector<test> suite = {};
#ifdef __clang__ // static-initialization-order-fiasco wrkrnd (actually required only for clang-cl)
__attribute__(( init_priority( 101 ) ))
jfalcou marked this conversation as resolved.
Show resolved Hide resolved
#endif
inline std::vector<test> suite;
bool inline test::acknowledge(test&& f)
{
suite.emplace_back( std::forward<test>(f));
Expand Down
60 changes: 31 additions & 29 deletions test/utility/shape/default_ctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@

using kwk::_;

using axis_base_type = decltype(kwk::along<0>)::base_type;

TTS_CASE( "Default constructed shape behavior - Mixed 1D")
{
kwk::shape<_> shape_d;
kwk::shape<7> shape_s;

TTS_EQUAL(sizeof(shape_d) ,1*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_d) ,1*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_s) , 1UL );

TTS_EQUAL(shape_d.nbdims() , 1 );
Expand All @@ -39,10 +41,10 @@ TTS_CASE( "Default constructed shape behavior - Mixed 2D")
kwk::shape<7,_> shape_sd;
kwk::shape<7,5> shape_ss;

TTS_EQUAL(sizeof(shape_dd), 2*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_ds), 1*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_sd), 1*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_ss), 1UL);
TTS_EQUAL(sizeof(shape_dd), 2*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_ds), 1*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_sd), 1*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_ss), 1UL);

TTS_EQUAL(shape_dd.nbdims() , 2L);
TTS_EQUAL(shape_ds.nbdims() , 2L);
Expand Down Expand Up @@ -71,14 +73,14 @@ TTS_CASE( "Default constructed shape behavior - Mixed 3D")
kwk::shape<7,5,_> shape_ssd;
kwk::shape<7,5,3> shape_sss;

TTS_EQUAL(sizeof(shape_ddd) , 3*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_dds) , 2*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_dsd) , 2*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_dss) , 1*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_sdd) , 2*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_sds) , 1*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_ssd) , 1*sizeof(std::int32_t));
TTS_EQUAL(sizeof(shape_sss) , 1UL);
TTS_EQUAL(sizeof(shape_ddd) , 3*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_dds) , 2*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_dsd) , 2*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_dss) , 1*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_sdd) , 2*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_sds) , 1*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_ssd) , 1*sizeof(axis_base_type));
TTS_EQUAL(sizeof(shape_sss) , 1UL);

TTS_EQUAL(shape_ddd.nbdims(), 3L);
TTS_EQUAL(shape_dds.nbdims(), 3L);
Expand Down Expand Up @@ -127,22 +129,22 @@ TTS_CASE( "Default constructed shape behavior - Mixed 4D")
kwk::shape<9,7,5,_> shape_sssd;
kwk::shape<9,7,5,3> shape_ssss;

TTS_EQUAL(sizeof(shape_dddd) , 4*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_ddds) , 3*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_ddsd) , 3*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_ddss) , 2*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_dsdd) , 3*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_dsds) , 2*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_dssd) , 2*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_dsss) , 1*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_sddd) , 3*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_sdds) , 2*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_sdsd) , 2*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_sdss) , 1*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_ssdd) , 2*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_ssds) , 1*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_sssd) , 1*sizeof(std::int32_t) );
TTS_EQUAL(sizeof(shape_ssss) , 1UL );
TTS_EQUAL(sizeof(shape_dddd) , 4*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_ddds) , 3*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_ddsd) , 3*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_ddss) , 2*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_dsdd) , 3*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_dsds) , 2*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_dssd) , 2*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_dsss) , 1*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_sddd) , 3*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_sdds) , 2*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_sdsd) , 2*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_sdss) , 1*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_ssdd) , 2*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_ssds) , 1*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_sssd) , 1*sizeof(axis_base_type) );
TTS_EQUAL(sizeof(shape_ssss) , 1UL );

TTS_EQUAL(shape_dddd.nbdims(), 4L);
TTS_EQUAL(shape_ddds.nbdims(), 4L);
Expand Down