Skip to content
Open
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
2 changes: 1 addition & 1 deletion include/camp/list/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace detail

template <typename T, T... Args>
struct _as_list<int_seq<T, Args...>> {
using type = list<integral_constant<T, Args>...>;
using type = list<constant<Args>...>;
};
} // namespace detail

Expand Down
43 changes: 23 additions & 20 deletions include/camp/number.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,46 @@ using idx_seq = int_seq<idx_t, vs...>;

namespace detail
{
template <typename T, typename N>
template <typename T, T N>
struct gen_seq;

#if CAMP_USE_MAKE_INTEGER_SEQ

template <typename T, T N>
struct gen_seq<T, integral_constant<T, N>> {
struct gen_seq {
using type = __make_integer_seq<int_seq, T, N>;
};

#elif CAMP_USE_INTEGER_PACK

template <typename T, T N>
struct gen_seq<T, integral_constant<T, N>> {
struct gen_seq {
using type = int_seq<T, __integer_pack(N)...>;
};

#else
template <typename T, typename S1, typename S2>
struct concat;

template <typename T, typename S1, typename S2>
struct gen_seq_concat;
template <typename T, T... I1, T... I2>
struct concat<T, int_seq<T, I1...>, int_seq<T, I2...>> {
using type = typename int_seq<T, I1..., (sizeof...(I1) + I2)...>::type;
struct gen_seq_concat<T, int_seq<T, I1...>, int_seq<T, I2...>> {
using type = int_seq<T, I1..., (sizeof...(I1) + I2)...>;
};

template <typename T, typename N_t>
struct gen_seq
: concat<T,
typename gen_seq<T, integral_constant<T, N_t::value / 2>>::type,
typename gen_seq<
T,
integral_constant<T, N_t::value - N_t::value / 2>>::type>::
type {
template <typename T>
struct gen_seq<T, 0> : int_seq<T> {
};

template <typename T>
struct gen_seq<T, integral_constant<T, 0>> : int_seq<T> {
struct gen_seq<T, 1> : int_seq<T, 0> {
};

template <typename T>
struct gen_seq<T, integral_constant<T, 1>> : int_seq<T, 0> {
template <typename T, T N_t>
struct gen_seq
: gen_seq_concat<T,
typename gen_seq<T, N_t / 2>::type,
typename gen_seq<T, N_t - N_t / 2>::type
>::type {
};
#endif
} // namespace detail
Expand All @@ -77,7 +80,7 @@ namespace detail
template <idx_t Upper>
struct make_idx_seq {
using type =
typename detail::gen_seq<idx_t, integral_constant<idx_t, Upper>>::type;
typename detail::gen_seq<idx_t, Upper>::type;
};

// TODO: document
Expand Down Expand Up @@ -108,7 +111,7 @@ using idx_seq_from_t = typename idx_seq_from<camp::decay<T>>::type;

// TODO: document
template <typename T, T Upper>
struct make_int_seq : detail::gen_seq<T, integral_constant<T, Upper>>::type {
struct make_int_seq : detail::gen_seq<T, Upper>::type {
};

// TODO: document
Expand Down
257 changes: 254 additions & 3 deletions include/camp/number/number.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,276 @@
namespace camp
{

// TODO: document, consider making use/match std::integral_constant
//

/**
* @brief class that represents a compile time constant value
*
* TODO: consider making use/match std::integral_constant
*/
template <class NumT, NumT v>
struct integral_constant {
struct [[deprecated("use constant<val> instead of integral_constant<T, val>")]]
integral_constant {
static constexpr NumT value = v;
using value_type = NumT;
using type = integral_constant;

CAMP_HOST_DEVICE
constexpr operator value_type() const noexcept { return value; }

CAMP_HOST_DEVICE
constexpr value_type operator()() const noexcept { return value; }
};

/**
* @brief class that represents a compile time constant value.
*
* Some arithmetic operators are supported for this class so compile-time
* arithmetic may be done transparently. In addition, this class is implicitly
* convertible to its value type so it is usable in arithmetic with other types.
*/
template < auto t_value >
struct constant
{
using type = constant;
using value_type = decltype(t_value);
static constexpr value_type value = t_value;

CAMP_HOST_DEVICE
constexpr operator value_type() const noexcept { return value; }

CAMP_HOST_DEVICE
constexpr value_type operator()() const noexcept { return value; }
};

/**
* @brief constant yielding unary plus for a constant value
*/
template < auto value >
CAMP_HOST_DEVICE
constexpr auto operator+(constant<value>)
{
return constant<+value>{};
}

/**
* @brief constant yielding unary minus for a constant value
*/
template < auto value >
CAMP_HOST_DEVICE
constexpr auto operator-(constant<value>)
{
return constant<-value>{};
}

/**
* @brief constant yielding bitwise not for a constant value
*/
template < auto value >
CAMP_HOST_DEVICE
constexpr auto operator~(constant<value>)
{
return constant<~value>{};
}

/**
* @brief constant yielding logical not for a constant value
*/
template < auto value >
CAMP_HOST_DEVICE
constexpr auto operator!(constant<value>)
{
return constant<!value>{};
}

/**
* @brief constant yielding plus for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator+(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value+rhs_value>{};
}

/**
* @brief constant yielding minus for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator-(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value-rhs_value>{};
}

/**
* @brief constant yielding times for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator*(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value*rhs_value>{};
}

/**
* @brief constant yielding divide for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator/(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value/rhs_value>{};
}

/**
* @brief constant yielding remainder for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator%(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value%rhs_value>{};
}

/**
* @brief constant yielding bitwise and for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator&(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value&rhs_value>{};
}

/**
* @brief constant yielding bitwise or for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator|(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value|rhs_value>{};
}

/**
* @brief constant yielding bitwise xor for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator^(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value^rhs_value>{};
}

/**
* @brief constant yielding left shift for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator<<(constant<lhs_value>, constant<rhs_value>)
{
return constant<(lhs_value<<rhs_value)>{};
}

/**
* @brief constant yielding right shift for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator>>(constant<lhs_value>, constant<rhs_value>)
{
return constant<(lhs_value>>rhs_value)>{};
}

/**
* @brief constant yielding logical and for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator&&(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value&&rhs_value>{};
}

/**
* @brief constant yielding logical or for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator||(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value||rhs_value>{};
}
Comment on lines +200 to +218

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This overloads logical and and or so operations between constants remain constants. However this does break short-circuiting if both operands are constants. I'm not sure if this is a big deal or not since presumably constants are generated in constant expressions. Though of course could always return constant from a function with side-effects. So I'm not sure if I'm going to keep these overloads.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@trws Are there additional concerns related to template instantiations in constant expressions and things like that that short-circuiting also has a bearing on?


/**
* @brief constant yielding equals for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator==(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value==rhs_value>{};
}

/**
* @brief constant yielding not equals for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator!=(constant<lhs_value>, constant<rhs_value>)
{
return constant<lhs_value!=rhs_value>{};
}

/**
* @brief constant yielding less than for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator<(constant<lhs_value>, constant<rhs_value>)
{
return constant<(lhs_value<rhs_value)>{};
}

/**
* @brief constant yielding less than equals for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator<=(constant<lhs_value>, constant<rhs_value>)
{
return constant<(lhs_value<=rhs_value)>{};
}

/**
* @brief constant yielding greater than for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator>(constant<lhs_value>, constant<rhs_value>)
{
return constant<(lhs_value>rhs_value)>{};
}

/**
* @brief constant yielding greater than equals for constant values
*/
template < auto lhs_value, auto rhs_value >
CAMP_HOST_DEVICE
constexpr auto operator>=(constant<lhs_value>, constant<rhs_value>)
{
return constant<(lhs_value>=rhs_value)>{};
}


/**
* @brief Short-form for a whole number
*
* @tparam N The integral value
*/
template <idx_t N>
using num = integral_constant<idx_t, N>;
using num = constant<N>;

using true_type = num<true>;
using false_type = num<false>;
Expand Down
Loading