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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Vscode does not like to build outside of the source tree
# (multiple glitches)

.vscode
test/.vscode
40 changes: 40 additions & 0 deletions compiler_bugs/msvc/sfinae.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <type_traits>
#include <new>
#include <utility>

template<typename T, typename... Args>
constexpr auto Constructible_v = std::is_constructible_v<T, Args...>;

template<typename Q>
struct ATemplate {
alignas(alignof(Q)) char space_[sizeof(Q)];

template<typename T>
constexpr static auto FitsInSpace_v = sizeof(T) <= sizeof(Q);

template<typename T, typename... Args>
std::enable_if_t<
FitsInSpace_v<T>
&&
#ifndef TRIGGER_MSVC_SFINAE_BUG
bool(
#endif
Constructible_v<T, Args...>
#ifndef TRIGGER_MSVC_SFINAE_BUG
)
#endif
,
T *
>
sfinaeFunction(Args &&...args) {
T *rv = new(static_cast<void *>(space_)) T(std::forward<Args>(args)...);
return rv;
}

};

auto triggerError(ATemplate<void *[2]> &m) {
return m.sfinaeFunction<void *>(nullptr);
}

int main(int, const char *[]) { return 0; }
14 changes: 11 additions & 3 deletions inc/zoo/AlignedStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,21 @@ struct AlignedStorage {

template<typename T, typename... Args>
#define PP_ZOO_BUILD_EXPRESSION \
impl::build(*as<T>(), std::forward<Args>(args)...)
auto build(Args &&...args) noexcept(noexcept(PP_ZOO_BUILD_EXPRESSION)) ->
impl::build(*this->as<T>(), std::forward<Args>(args)...)
std::enable_if_t<
SuitableType<T>() &&
impl::Constructible_v<T, Args...>,
#ifdef _MSC_VER
bool(
#endif
impl::Constructible_v<T, Args...>
#ifdef _MSC_VER
)
#endif
,

T *
>
build(Args &&...args) noexcept(noexcept(PP_ZOO_BUILD_EXPRESSION))
{
PP_ZOO_BUILD_EXPRESSION;
#undef PP_ZOO_BUILD_EXPRESSION
Expand Down
23 changes: 11 additions & 12 deletions inc/zoo/algorithm/cfs.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
#ifndef ZOO_CFS_CACHE_FRIENDLY_SEARCH
#define ZOO_CFS_CACHE_FRIENDLY_SEARCH

#include <zoo/algorithm/less.h>
#include "zoo/algorithm/less.h"
#include "zoo/meta/log.h"

#ifndef SIMPLIFY_INCLUDES
// because of std::declval needed to default comparator
#include <utility>
// because of std::decay needed to decay deferenced iterator
#include <type_traits>
#endif

namespace zoo {
#ifdef _MSC_VER
#include <iso646.h>
#endif

constexpr unsigned long long log2Floor(unsigned long long arg) {
return 63 - __builtin_clzll(arg);
}
#endif

constexpr unsigned long long log2Ceiling(unsigned long long arg) {
return 63 - __builtin_clzll(2*arg - 1);
}
namespace zoo {

template<typename Output, typename Input>
void transformToCFS(Output output, Input base, Input end) {
auto s = end - base;
auto logP = log2Floor(s + 1); // n
auto logP = meta::logFloor(s + 1); // n
auto power2 = 1ul << logP;
auto fullSubtreeSize = power2 - 1;
// Full tree has (2^n) - 1 elements
Expand Down Expand Up @@ -52,7 +50,8 @@ void transformToCFS(Output output, Input base, Input end) {
}

// now just write the excess leaves
for(auto ndx = 0ul, top = 2*excess; ndx < top; ndx += 2) {
auto top = 2*excess;
for(auto ndx = 0ll; ndx < top; ndx += 2) {
*output++ = *(base + ndx);
}
}
Expand Down Expand Up @@ -167,7 +166,7 @@ struct ValidResult {

template<typename I, typename Comparator = Less>
auto validHeap(
I base, int current, int max, Comparator c = Comparator{}
I base, long current, long max, Comparator c = Comparator{}
) -> ValidResult {
for(;;) {
auto higherSubtree = current*2 + 2;
Expand Down
4 changes: 4 additions & 0 deletions inc/zoo/algorithm/quicksort.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include <array> // for temporary storage
#include <stdexcept>

#ifdef _MSC_VER
#include <iso646.h>
#endif

namespace zoo {

template<typename FI>
Expand Down
33 changes: 22 additions & 11 deletions inc/zoo/meta/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,39 @@

namespace zoo { namespace meta {

constexpr int logFloor(uint64_t arg) {
return 63 - __builtin_clzll(arg);
}

constexpr int logCeiling(uint64_t arg) {
auto floorLog = logFloor(arg);
return floorLog + ((arg ^ (1ull << floorLog)) ? 1 : 0);
}

/// The algorithm is, from the perspective of the most significant bit set, to copy it
/// downward to all positions.
/// First copy it once, meaning a group of two copies of the two most significant bit
/// Then copy it again, making a group of four copies, then 8 copies...
template<typename T>
constexpr int logCeiling_WithoutIntrinsic(T value) {
constexpr int logFloor_WithoutIntrinsic(T value) {
constexpr auto NBitsTotal = sizeof(T) * 8;
for(auto groupSize = 1; groupSize < NBitsTotal; groupSize <<= 1) {
value |= (value >> groupSize);
}
return PopcountLogic<detail::BitWidthLog<T>, T>::execute(value) - 1;
}


#ifdef _MSC_VER
// change to use the relevant functions in C++ 20's <bit> header
// when bumping to C++ 20
constexpr int logFloor(uint64_t arg) {
return logFloor_WithoutIntrinsic(arg);
}
#else
constexpr int logFloor(uint64_t arg) {
return 63 - __builtin_clzll(arg);
}
#endif

constexpr int logCeiling(uint64_t arg) {
auto floorLog = logFloor(arg);
return
floorLog +
// turn off the most significant bit and convert to 1 or 0
((arg ^ (1ull << floorLog)) ? 1 : 0);
}

}}

#endif
5 changes: 5 additions & 0 deletions inc/zoo/meta/popcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ constexpr T PopcountLogic<LogarithmOfGroupSize, T>::execute(T input) {
Recursion::execute((input >> HalvedGroupSize) & CombiningMask);
}

#ifdef _MSC_VER
template<int LogarithmOfGroupSize, typename T = uint64_t>
using PopcountIntrinsic = PopcountLogic<LogarithmOfGroupSize, T>;
#else
template<int LogarithmOfGroupSize, typename T = uint64_t>
struct PopcountIntrinsic {
constexpr static T execute(T input) {
Expand All @@ -84,6 +88,7 @@ struct PopcountIntrinsic {
return rv;
}
};
#endif

}}

Expand Down
43 changes: 25 additions & 18 deletions inc/zoo/swar/SWAR.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

#include <type_traits>

#ifdef _MSC_VER
#include <iso646.h>
#endif

namespace zoo { namespace swar {

using u64 = uint64_t;
Expand All @@ -27,13 +31,14 @@ constexpr uint64_t popcount(uint64_t a) noexcept {
/// Index into the bits of the type T that contains the MSB.
template<typename T>
constexpr std::make_unsigned_t<T> msbIndex(T v) noexcept {
return 8*sizeof(T) - 1 - __builtin_clzll(v);
return meta::logFloor(v);
}

/// Index into the bits of the type T that contains the LSB.
template<typename T>
constexpr std::make_unsigned_t<T> lsbIndex(T v) noexcept {
return __builtin_ctzll(v) + 1;
// ~v & (v - 1) turns on all trailing zeroes, zeroes the rest
return meta::logFloor(1 + (~v & (v - 1)));
}

/// Core abstraction around SIMD Within A Register (SWAR). Specifies 'lanes'
Expand All @@ -44,12 +49,14 @@ constexpr std::make_unsigned_t<T> lsbIndex(T v) noexcept {
template<int NBits_, typename T = uint64_t>
struct SWAR {
using type = T;
constexpr static inline auto NBits = NBits_;
constexpr static inline auto Lanes = sizeof(T) * 8 / NBits;
constexpr static inline auto NSlots = Lanes;
constexpr static T BitMod = sizeof(T)*8 % NBits;
constexpr static T ValidBitsCount = sizeof(T)*8 - BitMod;
constexpr static T AllOnes = (BitMod == 0) ? ~(T(0)) : ((T(1) << ValidBitsCount) -1);
constexpr static inline std::make_unsigned_t<T>
NBits = NBits_,
BitWidth = sizeof(T) * 8,
Lanes = BitWidth / NBits,
NSlots = Lanes,
PaddingBitsCount = BitWidth % NBits,
SignificantBitsCount = BitWidth - PaddingBitsCount,
AllOnes = ~std::make_unsigned_t<T>{0} >> PaddingBitsCount;

SWAR() = default;
constexpr explicit SWAR(T v): m_v(v) {}
Expand Down Expand Up @@ -92,13 +99,21 @@ struct SWAR {

/// The SWAR lane index that contains the MSB. It is not the bit index of the MSB.
/// IE: 4 bit wide 32 bit SWAR: 0x0040'0000 will return 5, not 22 (0 indexed).
constexpr int top() const noexcept { return msbIndex(m_v) / NBits; }
constexpr int lsbIndex() const noexcept { return __builtin_ctzll(m_v) / NBits; }
constexpr auto top() const noexcept { return msbIndex(m_v) / NBits; }
constexpr auto lsbIndex() const noexcept { return swar::lsbIndex(m_v) / NBits; }

constexpr SWAR setBit(int index, int bit) const noexcept {
return SWAR(m_v | (T(1) << (index * NBits + bit)));
}

constexpr SWAR shiftLanesLeft(int laneCount) const noexcept {
return SWAR(value() << (NBits * laneCount));
}

constexpr SWAR shiftLanesRight(int laneCount) const noexcept {
return SWAR(value() >> (NBits * laneCount));
}

constexpr auto blitElement(int index, T value) const noexcept {
auto elementMask = ((T(1) << NBits) - 1) << (index * NBits);
return SWAR((m_v & ~elementMask) | (value << (index * NBits)));
Expand All @@ -110,14 +125,6 @@ struct SWAR {
return (*this & ~IsolationMask) | (other & IsolationMask);
}

constexpr SWAR shiftLanesLeft(int laneCount) const noexcept {
return SWAR(value() << (NBits * laneCount));
}

constexpr SWAR shiftLanesRight(int laneCount) const noexcept {
return SWAR(value() >> (NBits * laneCount));
}

T m_v;
};

Expand Down
5 changes: 5 additions & 0 deletions inc/zoo/traits/is_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

#ifndef SIMPLIFY_INCLUDES
#include <type_traits>

#ifdef _MSC_VER
#include <iso646.h>
#endif

#endif

namespace zoo {
Expand Down
4 changes: 2 additions & 2 deletions inc/zoo/util/range_equivalence.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace zoo {
template<typename C1, typename C2>
auto operator==(const C1 &l, const C2 &r)
-> std::enable_if_t<
zoo::is_container_v<C1> and
zoo::is_container_v<C2>,
bool(zoo::is_container_v<C1>) and
bool(zoo::is_container_v<C2>),
bool
>
{
Expand Down
5 changes: 3 additions & 2 deletions test/AlignedStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ static_assert(alignof(A1::space_) == 1, "specific alignment not honored");
template<typename Class, typename T>
std::false_type MayCallBuild(...);
template<typename Class, typename T, typename... As>
auto MayCallBuild(int, As &&...as) ->
auto MayCallBuild(As &&...as) ->
decltype(
std::declval<Class &>().template build<T>(std::forward<As>(as)...),
std::true_type{}
);
template<typename Class, typename T, typename... As>
constexpr auto MayCallBuild_(As &&...as) {
return decltype(MayCallBuild<Class, T>(0, std::forward<As>(as)...))::value;
return decltype(MayCallBuild<Class, T>(std::forward<As>(as)...))::value;
}

static_assert(
Expand Down Expand Up @@ -160,6 +160,7 @@ struct Typical {
Typical() = default;
Typical(const Typical &) = default;
Typical(Typical &&) = default;
Typical(long s): state_(s) {}
long state_;
};

Expand Down
Loading