Skip to content

Commit

Permalink
opt tuple compile time
Browse files Browse the repository at this point in the history
  • Loading branch information
wjr-z committed Jun 14, 2024
1 parent ba75c42 commit deca7cd
Show file tree
Hide file tree
Showing 15 changed files with 9,246 additions and 10,474 deletions.
19,439 changes: 9,084 additions & 10,355 deletions godbolt/wjr.hpp

Large diffs are not rendered by default.

49 changes: 18 additions & 31 deletions include/wjr/assert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,45 +59,32 @@ WJR_NORETURN extern void __assert_failed(const char *expr, const char *file,
// LCOV_EXCL_START

/// @private
class __assert_handler_t {
private:
WJR_NORETURN static void fn(const char *expr, const char *file, const char *func,
int line) noexcept {
__assert_failed(expr, file, func, line);
}

template <typename... Args>
WJR_NORETURN WJR_NOINLINE static void fn(const char *expr, const char *file,
const char *func, int line,
Args &&...args) noexcept {
std::cerr << "Additional information: ";
(void)(std::cerr << ... << std::forward<Args>(args));
std::cerr << '\n';
__assert_failed(expr, file, func, line);
}

public:
template <typename... Args>
WJR_NORETURN void operator()(const char *expr, const char *file, const char *func,
int line, Args &&...args) const noexcept {
fn(expr, file, func, line, std::forward<Args>(args)...);
}
};

inline constexpr __assert_handler_t __assert_handler{};
template <typename... Args>
WJR_NORETURN WJR_NOINLINE void __assert_handler(const char *expr, const char *file,
const char *func, int line,
Args &&...args) noexcept {
std::cerr << "Additional information: ";
(void)(std::cerr << ... << std::forward<Args>(args));
std::cerr << '\n';
__assert_failed(expr, file, func, line);
}

/// @private
WJR_NORETURN inline void __assert_handler(const char *expr, const char *file,
const char *func, int line) noexcept {
__assert_failed(expr, file, func, line);
}

// LCOV_EXCL_STOP

#define WJR_ASSERT_CHECK_I_HANDLER(handler, expr, ...) \
#define WJR_ASSERT_CHECK_I(expr, ...) \
do { \
if (WJR_UNLIKELY(!(expr))) { \
handler(#expr, WJR_FILE, WJR_CURRENT_FUNCTION, WJR_LINE, ##__VA_ARGS__); \
::wjr::__assert_handler(#expr, WJR_FILE, WJR_CURRENT_FUNCTION, WJR_LINE, \
##__VA_ARGS__); \
} \
} while (0)

#define WJR_ASSERT_CHECK_I(...) \
WJR_ASSERT_CHECK_I_HANDLER(::wjr::__assert_handler, __VA_ARGS__)

// do nothing
#define WJR_ASSERT_UNCHECK_I(expr, ...) \
do { \
Expand Down
24 changes: 4 additions & 20 deletions include/wjr/container/intrusive/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,6 @@ inline constexpr bool is_list_tag_v = is_list_tag<Tag>::value;
template <typename Tag>
using list_obj_t = typename Tag::obj_type;

template <typename Tag, WJR_REQUIRES(is_list_tag_v<Tag>)>
constexpr list_obj_t<Tag> *get(list_node<Tag> *node) noexcept;

template <typename Tag, WJR_REQUIRES(is_list_tag_v<Tag>)>
constexpr const list_obj_t<Tag> *get(const list_node<Tag> *node) noexcept;

template <typename T>
class list_node_const_iterator {
using node_type = list_node<T>;
Expand Down Expand Up @@ -230,22 +224,22 @@ struct list_node {

template <typename U = Tag, WJR_REQUIRES(is_list_tag_v<U>)>
constexpr list_obj_t<U> *operator->() noexcept {
return wjr::get(this);
return static_cast<list_obj_t<Tag> *>(this);
}

template <typename U = Tag, WJR_REQUIRES(is_list_tag_v<U>)>
constexpr const list_obj_t<U> *operator->() const noexcept {
return wjr::get(this);
return static_cast<const list_obj_t<Tag> *>(this);
}

template <typename U = Tag, WJR_REQUIRES(is_list_tag_v<U>)>
constexpr list_obj_t<U> &operator*() noexcept {
return *wjr::get(this);
return *operator->();
}

template <typename U = Tag, WJR_REQUIRES(is_list_tag_v<U>)>
constexpr const list_obj_t<U> &operator*() const noexcept {
return *wjr::get(this);
return *operator->();
}

list_node *m_prev;
Expand Down Expand Up @@ -316,16 +310,6 @@ constexpr void replace_uninit(list_node<T> *from, list_node<T> *to) noexcept {
from->m_next->m_prev = to;
}

template <typename Tag, WJR_REQUIRES_I(is_list_tag_v<Tag>)>
constexpr list_obj_t<Tag> *get(list_node<Tag> *node) noexcept {
return static_cast<list_obj_t<Tag> *>(node);
}

template <typename Tag, WJR_REQUIRES_I(is_list_tag_v<Tag>)>
constexpr const list_obj_t<Tag> *get(const list_node<Tag> *node) noexcept {
return static_cast<const list_obj_t<Tag> *>(node);
}

} // namespace wjr

#endif // WJR_CONTAINER_INTRUSIVE_LIST_HPP__
1 change: 1 addition & 0 deletions include/wjr/math/convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <wjr/math/div.hpp>
#include <wjr/math/precompute-chars-convert.hpp>
#include <wjr/memory/copy.hpp>
#include <wjr/math/stack_allocator.hpp>

#if defined(WJR_X86)
#include <wjr/x86/math/convert.hpp>
Expand Down
30 changes: 11 additions & 19 deletions include/wjr/math/details.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ class de_bruijn {
constexpr static uint8_t mv = digits == 32 ? 27 : 58;
constexpr de_bruijn() noexcept : lookup(), lookupr() { initialize(); }

WJR_INTRINSIC_CONSTEXPR int get(T idx) const noexcept {
return lookup[(idx * seed) >> mv];
}
WJR_INTRINSIC_CONSTEXPR int getr(T idx) const noexcept {
return lookupr[(idx * seed) >> mv];
}
constexpr int get(T idx) const noexcept { return lookup[(idx * seed) >> mv]; }
constexpr int getr(T idx) const noexcept { return lookupr[(idx * seed) >> mv]; }

private:
constexpr void initialize() noexcept {
Expand All @@ -42,7 +38,7 @@ inline constexpr de_bruijn<uint64_t, 0x03f7'9d71'b4ca'8b09> de_bruijn64 = {};
// preview ...

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR bool is_zero_or_single_bit(T n) noexcept {
WJR_CONST constexpr bool is_zero_or_single_bit(T n) noexcept {
return (n & (n - 1)) == 0;
}

Expand All @@ -52,12 +48,12 @@ WJR_CONST WJR_INTRINSIC_CONSTEXPR bool is_zero_or_single_bit(T n) noexcept {
* @note `n & -n` is the lowest bit of n.
*/
template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T lowbit(T n) noexcept {
WJR_CONST constexpr T lowbit(T n) noexcept {
return n & -n;
}

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T clear_lowbit(T n) noexcept {
WJR_CONST constexpr T clear_lowbit(T n) noexcept {
return n & (n - 1);
}

Expand All @@ -74,39 +70,35 @@ WJR_CONST constexpr decltype(auto) to_unsigned(Value value) noexcept {
// preview :

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR bool __has_high_bit(T n) noexcept {
WJR_CONST constexpr bool __has_high_bit(T n) noexcept {
return n >> (std::numeric_limits<T>::digits - 1);
}

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T __ceil_div(T n, type_identity_t<T> div) noexcept {
WJR_CONST constexpr T __ceil_div(T n, type_identity_t<T> div) noexcept {
return (n + div - 1) / div;
}

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T __align_down(T n,
type_identity_t<T> alignment) noexcept {
WJR_CONST constexpr T __align_down(T n, type_identity_t<T> alignment) noexcept {
WJR_ASSERT_ASSUME_L2(is_zero_or_single_bit(alignment));
return n & (-alignment);
}

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T
__align_down_offset(T n, type_identity_t<T> alignment) noexcept {
WJR_CONST constexpr T __align_down_offset(T n, type_identity_t<T> alignment) noexcept {
WJR_ASSERT_ASSUME_L2(is_zero_or_single_bit(alignment));
return n & (alignment - 1);
}

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T __align_up(T n,
type_identity_t<T> alignment) noexcept {
WJR_CONST constexpr T __align_up(T n, type_identity_t<T> alignment) noexcept {
WJR_ASSERT_ASSUME_L2(is_zero_or_single_bit(alignment));
return (n + alignment - 1) & (-alignment);
}

template <typename T, WJR_REQUIRES(is_nonbool_unsigned_integral_v<T>)>
WJR_CONST WJR_INTRINSIC_CONSTEXPR T
__align_up_offset(T n, type_identity_t<T> alignment) noexcept {
WJR_CONST constexpr T __align_up_offset(T n, type_identity_t<T> alignment) noexcept {
WJR_ASSERT_ASSUME_L2(is_zero_or_single_bit(alignment));
return (-n) & (alignment - 1);
}
Expand Down
13 changes: 6 additions & 7 deletions include/wjr/math/div-impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <utility>

#include <wjr/tuple.hpp>
#include <wjr/type_traits.hpp>
#include <wjr/math/integral_constant.hpp>
#include <wjr/math/uint128_t.hpp>

namespace wjr {

Expand All @@ -24,12 +24,11 @@ div128by64to64(uint64_t &rem, uint64_t lo, uint64_t hi,
WJR_INLINE_CONSTEXPR20 uint64_t div128by64to64(uint64_t &rem, uint64_t lo, uint64_t hi,
uint64_t div) noexcept;

inline tuple<uint64_t, uint64_t>
div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept;
inline uint128_t div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept;

inline tuple<uint64_t, uint64_t> div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
uint64_t div) noexcept;
inline uint128_t div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
uint64_t div) noexcept;

WJR_INTRINSIC_CONSTEXPR20 void div_qr_1(uint64_t *dst, uint64_t &rem, const uint64_t *src,
size_t n,
Expand Down
22 changes: 10 additions & 12 deletions include/wjr/math/div.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ WJR_INLINE_CONSTEXPR20 uint64_t div128by64to64(uint64_t &rem, uint64_t lo, uint6
return div128by64to64_impl(rem, lo, hi, wjr::div2by1_divider<uint64_t>(div));
}

WJR_INLINE_CONSTEXPR20 tuple<uint64_t, uint64_t>
inline uint128_t
div128by64to128_noshift(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider_noshift<uint64_t> &divider) noexcept {
const auto divisor = divider.get_divisor();
Expand All @@ -82,10 +82,10 @@ div128by64to128_noshift(uint64_t &rem, uint64_t lo, uint64_t hi,

q0 = divider.divide(lo, hi);
rem = hi;
return std::make_pair(q0, q1);
return {q0, q1};
}

inline tuple<uint64_t, uint64_t>
inline uint128_t
div128by64to128_shift(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept {
const auto shift = divider.get_shift();
Expand All @@ -101,12 +101,11 @@ div128by64to128_shift(uint64_t &rem, uint64_t lo, uint64_t hi,
q0 = div.divide(u0, u2);

rem = u2 >> shift;
return std::make_pair(q0, q1);
return {q0, q1};
}

inline tuple<uint64_t, uint64_t>
div128by64to128_impl(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept {
inline uint128_t div128by64to128_impl(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept {
if (divider.get_shift() == 0) {
return div128by64to128_noshift(rem, lo, hi, divider);
}
Expand All @@ -118,18 +117,17 @@ div128by64to128_impl(uint64_t &rem, uint64_t lo, uint64_t hi,
not optimize for divider that is power of 2,
manually consider whether it needs to be optimized
*/
inline tuple<uint64_t, uint64_t>
div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept {
inline uint128_t div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
const div2by1_divider<uint64_t> &divider) noexcept {
return div128by64to128_impl(rem, lo, hi, divider);
}

/*
not optimize for divider that is power of 2,
manually consider whether it needs to be optimized
*/
inline tuple<uint64_t, uint64_t> div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
uint64_t div) noexcept {
inline uint128_t div128by64to128(uint64_t &rem, uint64_t lo, uint64_t hi,
uint64_t div) noexcept {
return div128by64to128_impl(rem, lo, hi, div2by1_divider<uint64_t>(div));
}

Expand Down
3 changes: 1 addition & 2 deletions include/wjr/math/mul.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@
#include <wjr/math/add.hpp>
#include <wjr/math/bignum-config.hpp>
#include <wjr/math/bit.hpp>
#include <wjr/math/div-impl.hpp>
#include <wjr/math/integral_constant.hpp>
#include <wjr/math/shift.hpp>
#include <wjr/math/stack_allocator.hpp>
#include <wjr/math/sub.hpp>
#include <wjr/memory/safe_array.hpp>
#include <wjr/tuple.hpp>

#if defined(WJR_X86)
#include <wjr/x86/math/mul.hpp>
Expand Down
Loading

0 comments on commit deca7cd

Please sign in to comment.