diff --git a/.gitignore b/.gitignore index 3819313..5612b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ *.swp *.swo +*.swn +*.ttl +*.bz2 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3dff248 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/util"] + path = src/util + url = https://github.com/ad-freiburg/util.git diff --git a/src/util b/src/util new file mode 160000 index 0000000..60810bc --- /dev/null +++ b/src/util @@ -0,0 +1 @@ +Subproject commit 60810bc3515a18a42e4a262749d0a600d62734f0 diff --git a/src/util/3rdparty/MurmurHash3.cpp b/src/util/3rdparty/MurmurHash3.cpp deleted file mode 100644 index 23ac4fb..0000000 --- a/src/util/3rdparty/MurmurHash3.cpp +++ /dev/null @@ -1,436 +0,0 @@ -//----------------------------------------------------------------------------- -// MurmurHash3 was written by Austin Appleby, and is placed in the public -// domain. The author hereby disclaims copyright to this source code. - -// Note - The x86 and x64 versions do _not_ produce the same results, as the -// algorithms are optimized for their respective platforms. You can still -// compile and run any of them on any platform, but your performance with the -// non-native version will be less than optimal. - -#include "MurmurHash3.h" - -//----------------------------------------------------------------------------- -// Platform-specific functions and macros - -// Microsoft Visual Studio - -#if defined(_MSC_VER) - -#define FORCE_INLINE __forceinline - -#include - -#define ROTL32(x, y) _rotl(x, y) -#define ROTL64(x, y) _rotl64(x, y) - -#define BIG_CONSTANT(x) (x) - -// Other compilers - -#else // defined(_MSC_VER) - -#define FORCE_INLINE inline __attribute__((always_inline)) - -inline uint32_t rotl32(uint32_t x, int8_t r) { - return (x << r) | (x >> (32 - r)); -} - -inline uint64_t rotl64(uint64_t x, int8_t r) { - return (x << r) | (x >> (64 - r)); -} - -#define ROTL32(x, y) rotl32(x, y) -#define ROTL64(x, y) rotl64(x, y) - -#define BIG_CONSTANT(x) (x##LLU) - -#endif // !defined(_MSC_VER) - -//----------------------------------------------------------------------------- -// Block read - if your platform needs to do endian-swapping or can only -// handle aligned reads, do the conversion here - -FORCE_INLINE uint32_t getblock32(const uint32_t *p, int i) { return p[i]; } - -FORCE_INLINE uint64_t getblock64(const uint64_t *p, int i) { return p[i]; } - -//----------------------------------------------------------------------------- -// Finalization mix - force all bits of a hash block to avalanche - -FORCE_INLINE uint32_t fmix32(uint32_t h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - - return h; -} - -//---------- - -FORCE_INLINE uint64_t fmix64(uint64_t k) { - k ^= k >> 33; - k *= BIG_CONSTANT(0xff51afd7ed558ccd); - k ^= k >> 33; - k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); - k ^= k >> 33; - - return k; -} - -//----------------------------------------------------------------------------- - -void MurmurHash3_x86_32(const void *key, int len, uint32_t seed, void *out) { - const uint8_t *data = (const uint8_t *)key; - const int nblocks = len / 4; - - uint32_t h1 = seed; - - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; - - //---------- - // body - - const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4); - - for (int i = -nblocks; i; i++) { - uint32_t k1 = getblock32(blocks, i); - - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; - - h1 ^= k1; - h1 = ROTL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } - - //---------- - // tail - - const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); - - uint32_t k1 = 0; - - switch (len & 3) { - case 3: - k1 ^= tail[2] << 16; - // fall through - case 2: - k1 ^= tail[1] << 8; - // fall through - case 1: - k1 ^= tail[0]; - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; - h1 ^= k1; - }; - - //---------- - // finalization - - h1 ^= len; - - h1 = fmix32(h1); - - *(uint32_t *)out = h1; -} - -//----------------------------------------------------------------------------- - -void MurmurHash3_x86_128(const void *key, const int len, uint32_t seed, - void *out) { - const uint8_t *data = (const uint8_t *)key; - const int nblocks = len / 16; - - uint32_t h1 = seed; - uint32_t h2 = seed; - uint32_t h3 = seed; - uint32_t h4 = seed; - - const uint32_t c1 = 0x239b961b; - const uint32_t c2 = 0xab0e9789; - const uint32_t c3 = 0x38b34ae5; - const uint32_t c4 = 0xa1e38b93; - - //---------- - // body - - const uint32_t *blocks = (const uint32_t *)(data + nblocks * 16); - - for (int i = -nblocks; i; i++) { - uint32_t k1 = getblock32(blocks, i * 4 + 0); - uint32_t k2 = getblock32(blocks, i * 4 + 1); - uint32_t k3 = getblock32(blocks, i * 4 + 2); - uint32_t k4 = getblock32(blocks, i * 4 + 3); - - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; - h1 ^= k1; - - h1 = ROTL32(h1, 19); - h1 += h2; - h1 = h1 * 5 + 0x561ccd1b; - - k2 *= c2; - k2 = ROTL32(k2, 16); - k2 *= c3; - h2 ^= k2; - - h2 = ROTL32(h2, 17); - h2 += h3; - h2 = h2 * 5 + 0x0bcaa747; - - k3 *= c3; - k3 = ROTL32(k3, 17); - k3 *= c4; - h3 ^= k3; - - h3 = ROTL32(h3, 15); - h3 += h4; - h3 = h3 * 5 + 0x96cd1c35; - - k4 *= c4; - k4 = ROTL32(k4, 18); - k4 *= c1; - h4 ^= k4; - - h4 = ROTL32(h4, 13); - h4 += h1; - h4 = h4 * 5 + 0x32ac3b17; - } - - //---------- - // tail - - const uint8_t *tail = (const uint8_t *)(data + nblocks * 16); - - uint32_t k1 = 0; - uint32_t k2 = 0; - uint32_t k3 = 0; - uint32_t k4 = 0; - - switch (len & 15) { - case 15: - k4 ^= tail[14] << 16; - // fall through - case 14: - k4 ^= tail[13] << 8; - // fall through - case 13: - k4 ^= tail[12] << 0; - k4 *= c4; - k4 = ROTL32(k4, 18); - k4 *= c1; - h4 ^= k4; - // fall through - case 12: - k3 ^= tail[11] << 24; - // fall through - case 11: - k3 ^= tail[10] << 16; - // fall through - case 10: - k3 ^= tail[9] << 8; - // fall through - case 9: - k3 ^= tail[8] << 0; - k3 *= c3; - k3 = ROTL32(k3, 17); - k3 *= c4; - h3 ^= k3; - // fall through - case 8: - k2 ^= tail[7] << 24; - // fall through - case 7: - k2 ^= tail[6] << 16; - // fall through - case 6: - k2 ^= tail[5] << 8; - // fall through - case 5: - k2 ^= tail[4] << 0; - k2 *= c2; - k2 = ROTL32(k2, 16); - k2 *= c3; - h2 ^= k2; - // fall through - case 4: - k1 ^= tail[3] << 24; - // fall through - case 3: - k1 ^= tail[2] << 16; - // fall through - case 2: - k1 ^= tail[1] << 8; - // fall through - case 1: - k1 ^= tail[0] << 0; - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; - h1 ^= k1; - }; - - //---------- - // finalization - - h1 ^= len; - h2 ^= len; - h3 ^= len; - h4 ^= len; - - h1 += h2; - h1 += h3; - h1 += h4; - h2 += h1; - h3 += h1; - h4 += h1; - - h1 = fmix32(h1); - h2 = fmix32(h2); - h3 = fmix32(h3); - h4 = fmix32(h4); - - h1 += h2; - h1 += h3; - h1 += h4; - h2 += h1; - h3 += h1; - h4 += h1; - - ((uint32_t *)out)[0] = h1; - ((uint32_t *)out)[1] = h2; - ((uint32_t *)out)[2] = h3; - ((uint32_t *)out)[3] = h4; -} - -//----------------------------------------------------------------------------- - -void MurmurHash3_x64_128(const void *key, const int len, const uint32_t seed, - void *out) { - const uint8_t *data = (const uint8_t *)key; - const int nblocks = len / 16; - - uint64_t h1 = seed; - uint64_t h2 = seed; - - const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); - const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); - - //---------- - // body - - const uint64_t *blocks = (const uint64_t *)(data); - - for (int i = 0; i < nblocks; i++) { - uint64_t k1 = getblock64(blocks, i * 2 + 0); - uint64_t k2 = getblock64(blocks, i * 2 + 1); - - k1 *= c1; - k1 = ROTL64(k1, 31); - k1 *= c2; - h1 ^= k1; - - h1 = ROTL64(h1, 27); - h1 += h2; - h1 = h1 * 5 + 0x52dce729; - - k2 *= c2; - k2 = ROTL64(k2, 33); - k2 *= c1; - h2 ^= k2; - - h2 = ROTL64(h2, 31); - h2 += h1; - h2 = h2 * 5 + 0x38495ab5; - } - - //---------- - // tail - - const uint8_t *tail = (const uint8_t *)(data + nblocks * 16); - - uint64_t k1 = 0; - uint64_t k2 = 0; - - switch (len & 15) { - case 15: - k2 ^= ((uint64_t)tail[14]) << 48; - // fall through - case 14: - k2 ^= ((uint64_t)tail[13]) << 40; - // fall through - case 13: - k2 ^= ((uint64_t)tail[12]) << 32; - // fall through - case 12: - k2 ^= ((uint64_t)tail[11]) << 24; - // fall through - case 11: - k2 ^= ((uint64_t)tail[10]) << 16; - // fall through - case 10: - k2 ^= ((uint64_t)tail[9]) << 8; - // fall through - case 9: - k2 ^= ((uint64_t)tail[8]) << 0; - k2 *= c2; - k2 = ROTL64(k2, 33); - k2 *= c1; - h2 ^= k2; - // fall through - case 8: - k1 ^= ((uint64_t)tail[7]) << 56; - // fall through - case 7: - k1 ^= ((uint64_t)tail[6]) << 48; - // fall through - case 6: - k1 ^= ((uint64_t)tail[5]) << 40; - // fall through - case 5: - k1 ^= ((uint64_t)tail[4]) << 32; - // fall through - case 4: - k1 ^= ((uint64_t)tail[3]) << 24; - // fall through - case 3: - k1 ^= ((uint64_t)tail[2]) << 16; - // fall through - case 2: - k1 ^= ((uint64_t)tail[1]) << 8; - // fall through - case 1: - k1 ^= ((uint64_t)tail[0]) << 0; - k1 *= c1; - k1 = ROTL64(k1, 31); - k1 *= c2; - h1 ^= k1; - }; - - //---------- - // finalization - - h1 ^= len; - h2 ^= len; - - h1 += h2; - h2 += h1; - - h1 = fmix64(h1); - h2 = fmix64(h2); - - h1 += h2; - h2 += h1; - - ((uint64_t *)out)[0] = h1; - ((uint64_t *)out)[1] = h2; -} - -//----------------------------------------------------------------------------- diff --git a/src/util/3rdparty/MurmurHash3.h b/src/util/3rdparty/MurmurHash3.h deleted file mode 100644 index e1c6d34..0000000 --- a/src/util/3rdparty/MurmurHash3.h +++ /dev/null @@ -1,37 +0,0 @@ -//----------------------------------------------------------------------------- -// MurmurHash3 was written by Austin Appleby, and is placed in the public -// domain. The author hereby disclaims copyright to this source code. - -#ifndef _MURMURHASH3_H_ -#define _MURMURHASH3_H_ - -//----------------------------------------------------------------------------- -// Platform-specific functions and macros - -// Microsoft Visual Studio - -#if defined(_MSC_VER) && (_MSC_VER < 1600) - -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned __int64 uint64_t; - -// Other compilers - -#else // defined(_MSC_VER) - -#include - -#endif // !defined(_MSC_VER) - -//----------------------------------------------------------------------------- - -void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); - -void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out ); - -void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out ); - -//----------------------------------------------------------------------------- - -#endif // _MURMURHASH3_H_ diff --git a/src/util/3rdparty/dtoa_milo.h b/src/util/3rdparty/dtoa_milo.h deleted file mode 100644 index 1ed2670..0000000 --- a/src/util/3rdparty/dtoa_milo.h +++ /dev/null @@ -1,454 +0,0 @@ -// based on -// https://github.com/miloyip/dtoa-benchmark/blob/master/src/milo/dtoa_milo.h - -#pragma once -#include -#include -#include - -#if defined(_MSC_VER) -#include -#include "msinttypes/stdint.h" -#else -#include -#endif - -namespace gcc_ints { -__extension__ typedef __int128 int128; -__extension__ typedef unsigned __int128 uint128; -} // namespace gcc_ints - -#define UINT64_C2(h, l) \ - ((static_cast(h) << 32) | static_cast(l)) - -namespace util { - -struct DiyFp { - DiyFp() {} - - DiyFp(uint64_t f, int e) : f(f), e(e) {} - - DiyFp(double d) { - union { - double d; - uint64_t u64; - } u = {d}; - - int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; - uint64_t significand = (u.u64 & kDpSignificandMask); - if (biased_e != 0) { - f = significand + kDpHiddenBit; - e = biased_e - kDpExponentBias; - } else { - f = significand; - e = kDpMinExponent + 1; - } - } - - DiyFp operator-(const DiyFp& rhs) const { - assert(e == rhs.e); - assert(f >= rhs.f); - return DiyFp(f - rhs.f, e); - } - - DiyFp operator*(const DiyFp& rhs) const { -#if defined(_MSC_VER) && defined(_M_AMD64) - uint64_t h; - uint64_t l = _umul128(f, rhs.f, &h); - if (l & (uint64_t(1) << 63)) // rounding - h++; - return DiyFp(h, e + rhs.e + 64); -#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && \ - defined(__x86_64__) - gcc_ints::uint128 p = static_cast(f) * - static_cast(rhs.f); - uint64_t h = p >> 64; - uint64_t l = static_cast(p); - if (l & (uint64_t(1) << 63)) // rounding - h++; - return DiyFp(h, e + rhs.e + 64); -#else - const uint64_t M32 = 0xFFFFFFFF; - const uint64_t a = f >> 32; - const uint64_t b = f & M32; - const uint64_t c = rhs.f >> 32; - const uint64_t d = rhs.f & M32; - const uint64_t ac = a * c; - const uint64_t bc = b * c; - const uint64_t ad = a * d; - const uint64_t bd = b * d; - uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); - tmp += 1U << 31; /// mult_round - return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); -#endif - } - - DiyFp Normalize() const { -#if defined(_MSC_VER) && defined(_M_AMD64) - unsigned long index; - _BitScanReverse64(&index, f); - return DiyFp(f << (63 - index), e - (63 - index)); -#elif defined(__GNUC__) - int s = __builtin_clzll(f); - return DiyFp(f << s, e - s); -#else - DiyFp res = *this; - while (!(res.f & kDpHiddenBit)) { - res.f <<= 1; - res.e--; - } - res.f <<= (kDiySignificandSize - kDpSignificandSize - 1); - res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1); - return res; -#endif - } - - DiyFp NormalizeBoundary() const { -#if defined(_MSC_VER) && defined(_M_AMD64) - unsigned long index; - _BitScanReverse64(&index, f); - return DiyFp(f << (63 - index), e - (63 - index)); -#else - DiyFp res = *this; - while (!(res.f & (kDpHiddenBit << 1))) { - res.f <<= 1; - res.e--; - } - res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); - res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); - return res; -#endif - } - - void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { - DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); - DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) - : DiyFp((f << 1) - 1, e - 1); - mi.f <<= mi.e - pl.e; - mi.e = pl.e; - *plus = pl; - *minus = mi; - } - - static const int kDiySignificandSize = 64; - static const int kDpSignificandSize = 52; - static const int kDpExponentBias = 0x3FF + kDpSignificandSize; - static const int kDpMinExponent = -kDpExponentBias; - static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000); - static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF); - static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000); - - uint64_t f; - int e; -}; - -inline DiyFp GetCachedPower(int e, int* K) { - // 10^-348, 10^-340, ..., 10^340 - static const uint64_t kCachedPowers_F[] = { - UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76), - UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea), - UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df), - UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f), - UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c), - UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5), - UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d), - UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637), - UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7), - UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5), - UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b), - UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996), - UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6), - UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8), - UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053), - UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd), - UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94), - UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b), - UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac), - UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3), - UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb), - UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c), - UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000), - UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984), - UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70), - UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245), - UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8), - UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a), - UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea), - UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85), - UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2), - UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3), - UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25), - UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece), - UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5), - UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a), - UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c), - UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a), - UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129), - UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429), - UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d), - UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841), - UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9), - UINT64_C2(0xaf87023b, 0x9bf0ee6b)}; - static const int16_t kCachedPowers_E[] = { - -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, - -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, - -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, - -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, - -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, - 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, - 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, - 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066}; - - // int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; - double dk = (-61 - e) * 0.30102999566398114 + - 347; // dk must be positive, so can do ceiling in positive - int k = static_cast(dk); - if (dk - k > 0.0) k++; - - unsigned index = static_cast((k >> 3) + 1); - *K = -(-348 + static_cast( - index << 3)); // decimal exponent no need lookup table - - assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0])); - return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); -} - -inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, - uint64_t ten_kappa, uint64_t wp_w) { - while (rest < wp_w && delta - rest >= ten_kappa && - (rest + ten_kappa < wp_w || /// closer - wp_w - rest > rest + ten_kappa - wp_w)) { - buffer[len - 1]--; - rest += ten_kappa; - } -} - -inline unsigned CountDecimalDigit32(uint32_t n) { - // Simple pure C++ implementation was faster than __builtin_clz version in - // this situation. - if (n < 10) return 1; - if (n < 100) return 2; - if (n < 1000) return 3; - if (n < 10000) return 4; - if (n < 100000) return 5; - if (n < 1000000) return 6; - if (n < 10000000) return 7; - if (n < 100000000) return 8; - if (n < 1000000000) return 9; - return 10; -} - -inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, - char* buffer, int* len, int* K) { - static const uint64_t kPow10[] = {1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000, - 100000000000, - 1000000000000, - 10000000000000, - 100000000000000}; - const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); - const DiyFp wp_w = Mp - W; - uint32_t p1 = static_cast(Mp.f >> -one.e); - uint64_t p2 = Mp.f & (one.f - 1); - int kappa = static_cast(CountDecimalDigit32(p1)); - *len = 0; - - while (kappa > 0) { - uint32_t d; - switch (kappa) { - case 10: - d = p1 / 1000000000; - p1 %= 1000000000; - break; - case 9: - d = p1 / 100000000; - p1 %= 100000000; - break; - case 8: - d = p1 / 10000000; - p1 %= 10000000; - break; - case 7: - d = p1 / 1000000; - p1 %= 1000000; - break; - case 6: - d = p1 / 100000; - p1 %= 100000; - break; - case 5: - d = p1 / 10000; - p1 %= 10000; - break; - case 4: - d = p1 / 1000; - p1 %= 1000; - break; - case 3: - d = p1 / 100; - p1 %= 100; - break; - case 2: - d = p1 / 10; - p1 %= 10; - break; - case 1: - d = p1; - p1 = 0; - break; - default: -#if defined(_MSC_VER) - __assume(0); -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) - __builtin_unreachable(); -#else - d = 0; -#endif - } - if (d || *len) buffer[(*len)++] = '0' + static_cast(d); - kappa--; - uint64_t tmp = (static_cast(p1) << -one.e) + p2; - if (tmp <= delta) { - *K += kappa; - GrisuRound(buffer, *len, delta, tmp, - static_cast(kPow10[kappa]) << -one.e, wp_w.f); - return; - } - } - - // kappa = 0 - for (;;) { - p2 *= 10; - delta *= 10; - char d = static_cast(p2 >> -one.e); - if (d || *len) buffer[(*len)++] = '0' + d; - p2 &= one.f - 1; - kappa--; - if (p2 < delta) { - *K += kappa; - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); - return; - } - } -} - -inline void Grisu2(double value, char* buffer, int* length, int* K) { - const DiyFp v(value); - DiyFp w_m, w_p; - v.NormalizedBoundaries(&w_m, &w_p); - - const DiyFp c_mk = GetCachedPower(w_p.e, K); - const DiyFp W = v.Normalize() * c_mk; - DiyFp Wp = w_p * c_mk; - DiyFp Wm = w_m * c_mk; - Wm.f++; - Wp.f--; - DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); -} - -inline const char* GetDigitsLut() { - static const char cDigitsLut[200] = { - '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', - '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', - '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', - '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', - '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', - '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', - '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5', - '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', - '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', - '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', - '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', - '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', - '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', - '7', '9', '8', '9', '9'}; - return cDigitsLut; -} - -inline void WriteExponent(int K, char* buffer) { - if (K < 0) { - *buffer++ = '-'; - K = -K; - } - - if (K >= 100) { - *buffer++ = '0' + static_cast(K / 100); - K %= 100; - const char* d = GetDigitsLut() + K * 2; - *buffer++ = d[0]; - *buffer++ = d[1]; - } else if (K >= 10) { - const char* d = GetDigitsLut() + K * 2; - *buffer++ = d[0]; - *buffer++ = d[1]; - } else - *buffer++ = '0' + static_cast(K); - - *buffer = '\0'; -} - -inline void Prettify(char* buffer, int length, int k) { - const int kk = length + k; // 10^(kk-1) <= v < 10^kk - - if (length <= kk && kk <= 21) { - // 1234e7 -> 12340000000 - for (int i = length; i < kk; i++) buffer[i] = '0'; - buffer[kk] = '.'; - buffer[kk + 1] = '0'; - buffer[kk + 2] = '\0'; - } else if (0 < kk && kk <= 21) { - // 1234e-2 -> 12.34 - memmove(&buffer[kk + 1], &buffer[kk], length - kk); - buffer[kk] = '.'; - buffer[length + 1] = '\0'; - } else if (-6 < kk && kk <= 0) { - // 1234e-6 -> 0.001234 - const int offset = 2 - kk; - memmove(&buffer[offset], &buffer[0], length); - buffer[0] = '0'; - buffer[1] = '.'; - for (int i = 2; i < offset; i++) buffer[i] = '0'; - buffer[length + offset] = '\0'; - } else if (length == 1) { - // 1e30 - buffer[1] = 'e'; - WriteExponent(kk - 1, &buffer[2]); - } else { - // 1234e30 -> 1.234e33 - memmove(&buffer[2], &buffer[1], length - 1); - buffer[1] = '.'; - buffer[length + 1] = 'e'; - WriteExponent(kk - 1, &buffer[0 + length + 2]); - } -} - -inline void dtoa_milo(double value, char* buffer) { - // Not handling NaN and inf - assert(!std::isnan(value)); - assert(!std::isinf(value)); - - if (value == 0) { - buffer[0] = '0'; - buffer[1] = '.'; - buffer[2] = '0'; - buffer[3] = '\0'; - } else { - if (value < 0) { - *buffer++ = '-'; - value = -value; - } - int length, K; - Grisu2(value, buffer, &length, &K); - Prettify(buffer, length, K); - } -} -} // namespace util diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt deleted file mode 100644 index 7888cd6..0000000 --- a/src/util/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -file(GLOB_RECURSE util_SRC *.cpp) -list(REMOVE_ITEM util_SRC TestMain.cpp) -add_library(util ${util_SRC}) - -find_package( ZLIB ) -if (ZLIB_FOUND) - include_directories( ${ZLIB_INCLUDE_DIRS} ) - target_link_libraries( util ${ZLIB_LIBRARIES} ) - add_definitions( -DZLIB_FOUND=${ZLIB_FOUND} ) -endif( ZLIB_FOUND ) - -add_subdirectory(tests) diff --git a/src/util/JobQueue.h b/src/util/JobQueue.h deleted file mode 100644 index 1a12598..0000000 --- a/src/util/JobQueue.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2024, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_JOBQUEUE_H_ -#define UTIL_JOBQUEUE_H_ - -#include -#include -#include -#include - -namespace util { - -template -class JobQueue { - public: - JobQueue() : _maxSize(std::numeric_limits::max()) {} - JobQueue(size_t maxSize) : _maxSize(maxSize) {} - - size_t size() { - std::unique_lock lock(_mut); - return _jobs.size(); - } - - void add(const T& job) { - std::unique_lock lockWait(_mutWait); - _notFull.wait(lockWait, [this] { return _jobs.size() < _maxSize; }); - { - std::unique_lock lock(_mut); - _jobs.push(job); - } - _hasNew.notify_one(); - } - - void add(T&& job) { - std::unique_lock lockWait(_mutWait); - _notFull.wait(lockWait, [this] { return _jobs.size() < _maxSize; }); - - { - std::unique_lock lock(_mut); - _jobs.push(std::move(job)); - } - _hasNew.notify_one(); - } - - T get() { - T next; - { - std::unique_lock lockWaitHave(_mutWaitHave); - // wait until a job arrives, but only block iff we do not have job - _hasNew.wait(lockWaitHave, [this] { return !_jobs.empty(); }); - - - std::unique_lock lock(_mut); - next = _jobs.front(); - if (next != T()) _jobs.pop(); - } - - // notify that we are not full anymore, but only if this is not the - // DONE element - if (next != T()) _notFull.notify_one(); - else _hasNew.notify_one(); - return next; - } - - JobQueue(const JobQueue &) = delete; - JobQueue(JobQueue &&) = delete; - JobQueue &operator=(const JobQueue &) = delete; - JobQueue &operator=(JobQueue &&) = delete; - - private: - std::mutex _mut; - std::mutex _mutWait; - std::mutex _mutWaitHave; - std::queue _jobs; - std::condition_variable _hasNew; - std::condition_variable _notFull; - - size_t _maxSize; -}; -} // namespace util - #endif diff --git a/src/util/Misc.h b/src/util/Misc.h deleted file mode 100644 index dd4821c..0000000 --- a/src/util/Misc.h +++ /dev/null @@ -1,574 +0,0 @@ -// Copyright 2017, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_MISC_H_ -#define UTIL_MISC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "3rdparty/dtoa_milo.h" - -static const size_t SORT_BUFFER_S = 64 * 128 * 1024; - -#define UNUSED(expr) do { (void)(expr); } while (0) -#define TIME() std::chrono::high_resolution_clock::now() -#define TOOK_UNTIL(t1, t2) (std::chrono::duration_cast(t2 - t1).count()) -#define TOOK(t1) (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - t1).count()) -#define T_START(n) auto _tstart_##n = std::chrono::high_resolution_clock::now() -#define T_STOP(n) (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - _tstart_##n).count()) - -#define _TEST3(s, o, e) if (!(s o e)) { std::cerr << "\n" << __FILE__ << ":" << __LINE__ << ": Test failed!\n Expected " << #s << " " << #o " " << (e) << ", got " << (s) << std::endl; exit(1);} -#define _TEST2(s, e) _TEST3(s, ==, o) -#define _TEST1(s) _TEST3(static_cast(s), ==, true) - -#define _GET_TEST_MACRO(_1,_2,_3,NAME,...) NAME -#define TEST(...) _GET_TEST_MACRO(__VA_ARGS__, _TEST3, _TEST2, _TEST1, UNUSED)(__VA_ARGS__) - -#define TODO(msg) std::cerr << "\n" __FILE__ << ":" << __LINE__ << ": TODO: " << #msg << std::endl; - -#if defined(_WIN32) -#include -#include -#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) -#include -#include -#if defined(__APPLE__) && defined(__MACH__) -#include -#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) -#include -#include -#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) -#include -#endif -#else -#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS." -#endif - -namespace util { - -struct hashPair { - template - size_t operator()(const std::pair& p) const { - auto h1 = std::hash{}(p.first); - auto h2 = std::hash{}(p.second); - return h1 ^ h2; - } -}; - -template -class SparseMatrix { - public: - Val get(const Key& x, const Key& y) const { - auto a = _m.find(std::pair(x, y)); - if (a == _m.end()) return Def; - return a->second; - } - - void set(Key x, Key y, Val v) { - _m[std::pair(x, y)] = v; - } - - const std::map, Val>& vals() const { - return _m; - } - - private: - std::map, Val> _m; -}; - -// cached first 10 powers of 10 -static int pow10[10] = { - 1, 10, 100, 1000, 10000, - 100000, 1000000, 10000000, 100000000, 1000000000}; - -// _____________________________________________________________________________ -inline uint64_t factorial(uint64_t n) { - if (n < 2) return 1; - return n * factorial(n - 1); -} - -// _____________________________________________________________________________ -inline uint64_t atoul(const char* p) { - uint64_t ret = 0; - - while (*p) { - ret = ret * 10 + (*p++ - '0'); - } - - return ret; -} - -// _____________________________________________________________________________ -inline bool isFloatingPoint(const std::string& str) { - std::stringstream ss(str); - double f; - ss >> std::noskipws >> f; - return ss.eof() && ! ss.fail(); -} - -// _____________________________________________________________________________ -inline std::string formatFloat(double f, size_t digits) { - std::stringstream ss; - ss << std::fixed << std::setprecision(digits) << f; - std::string ret = ss.str(); - - if (ret.find('.') != std::string::npos) { - auto p = ret.find_last_not_of('0'); - if (ret[p] == '.') return ret.substr(0, p); - return ret.substr(0, p + 1); - } - - return ret; -} - -// _____________________________________________________________________________ -inline double atof(const char* p, uint8_t mn) { - // this atof implementation works only on "normal" float strings like - // 56.445 or -345.00, but should be faster than std::atof - while (*p && isspace(*p)) p++; - - double ret = 0.0; - bool neg = false; - if (*p == '-') { - neg = true; - p++; - } - - while (*p >= '0' && *p <= '9') { - ret = ret * 10.0 + (*p - '0'); - p++; - } - - if (*p == '.') { - p++; - double f = 0; - uint8_t n = 0; - - for (; n < mn && *p >= '0' && *p <= '9'; n++, p++) { - f = f * 10.0 + (*p - '0'); - } - - if (n < 10) - ret += f / pow10[n]; - else - ret += f / std::pow(10, n); - } - - if (neg) return -ret; - return ret; -} - -// _____________________________________________________________________________ -inline double atof(const char* p) { return atof(p, 38); } - -// _____________________________________________________________________________ -template -int merge(V* lst, V* tmpLst, size_t l, size_t m, size_t r) { - size_t ret = 0; - - size_t lp = l; - size_t rp = m; - size_t outp = l; - - while (lp < m && rp < r + 1) { - if (lst[lp] <= lst[rp]) { - // if left element is smaller or equal, add it to return list, - // increase left pointer - tmpLst[outp] = lst[lp]; - lp++; - } else { - // if left element is bigger, add the right element, add it to ret, - // increase right pointer - tmpLst[outp] = lst[rp]; - rp++; - - // if the left element was bigger, everything to the right in the - // left list is also bigger, and all these m - i elements were - // initially in the wrong order! Count these inversions. - ret += m - lp; - } - - outp++; - } - - // fill in remaining values - if (lp < m) std::memcpy(tmpLst + outp, lst + lp, (m - lp) * sizeof(V)); - if (rp <= r) std::memcpy(tmpLst + outp, lst + rp, ((r + 1) - rp) * sizeof(V)); - - // copy to output - std::memcpy(lst + l, tmpLst + l, ((r + 1) - l) * sizeof(V)); - - return ret; -} - -// _____________________________________________________________________________ -template -size_t mergeInvCount(V* lst, V* tmpLst, size_t l, size_t r) { - size_t ret = 0; - if (l < r) { - size_t m = (r + l) / 2; - - ret += mergeInvCount(lst, tmpLst, l, m); - ret += mergeInvCount(lst, tmpLst, m + 1, r); - - ret += merge(lst, tmpLst, l, m + 1, r); - } - return ret; -} - -// _____________________________________________________________________________ -template -size_t inversions(const std::vector& v) { - if (v.size() < 2) return 0; // no inversions possible - - // unroll some simple cases - if (v.size() == 2) return v[1] < v[0]; - if (v.size() == 3) return (v[0] > v[1]) + (v[0] > v[2]) + (v[1] > v[2]); - - auto tmpLst = new V[v.size()]; - auto lst = new V[v.size()]; - - for (size_t i = 0; i < v.size(); i++) lst[i] = v[i]; - - size_t ret = mergeInvCount(lst, tmpLst, 0, v.size() - 1); - delete[] tmpLst; - delete[] lst; - return ret; -} - - -// _____________________________________________________________________________ -inline std::string getHomeDir() { - // parse implicit paths - const char* homedir = 0; - char* buf = 0; - - if ((homedir = getenv("HOME")) == 0) { - homedir = ""; - struct passwd pwd; - struct passwd* result; - size_t bufsize; - bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (bufsize == static_cast(-1)) bufsize = 0x4000; - buf = static_cast(malloc(bufsize)); - if (buf != 0) { - getpwuid_r(getuid(), &pwd, buf, bufsize, &result); - if (result != NULL) homedir = result->pw_dir; - } - } - - std::string ret(homedir); - if (buf) free(buf); - - return ret; -} - -// _____________________________________________________________________________ -inline std::string getTmpDir() { - // first, check if an env variable is set - const char* tmpdir = getenv("TMPDIR"); - if (tmpdir && std::strlen(tmpdir)) return std::string(tmpdir); - - // second, check if /tmp is writable - if (access("/tmp/", W_OK) == 0) return "/tmp"; - - // third, check if the cwd is writable - if (access(".", W_OK) == 0) return "."; - - // lastly, return the users home directory as a fallback - return getHomeDir(); -} - -// _____________________________________________________________________________ -inline std::string getTmpFName(std::string dir, std::string name, - std::string postf) { - if (postf.size()) postf = "-" + postf; - if (dir == "") dir = util::getTmpDir(); - if (dir.size() && dir.back() != '/') dir = dir + "/"; - - std::string f = dir + name + postf; - - size_t c = 0; - - while (access(f.c_str(), F_OK) != -1) { - c++; - if (c > 10000) { - // giving up... - std::cerr << "Could not find temporary file name!" << std::endl; - exit(1); - } - std::stringstream ss; - ss << dir << name << postf << "-" << std::rand(); - f = ss.str().c_str(); - } - - return f; -} - -// _____________________________________________________________________________ -inline char* readableSize(double size, char* buf) { - int i = 0; - const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB"}; - while (size > 1024 && i < 5) { - size /= 1024; - i++; - } - sprintf(buf, "%.*f %s", i, size, units[i]); - return buf; -} - -// _____________________________________________________________________________ -inline std::string readableSize(double size) { - char buffer[30]; - return readableSize(size, buffer); -} - -// _____________________________________________________________________________ -inline void externalSort(int file, int newFile, size_t size, size_t numobjs, - int (*cmpf)(const void*, const void*)) { - // sort a file via an external sort - - size_t fsize = size * numobjs; - - size_t bufferSize = SORT_BUFFER_S * size; - - size_t parts = fsize / bufferSize + 1; - size_t partsBufSize = ((bufferSize / size) / parts + 1) * size; - unsigned char* buf = new unsigned char[bufferSize]; - unsigned char** partbufs = new unsigned char*[parts]; - size_t* partpos = new size_t[parts]; - size_t* partsize = new size_t[parts]; - - auto pqComp = [cmpf](const std::pair& a, - const std::pair& b) { - return cmpf(a.first, b.first) != -1; - }; - std::priority_queue, - std::vector>, - decltype(pqComp)> - pq(pqComp); - - // sort the 'parts' number of file parts independently - for (size_t i = 0; i < parts; i++) { - partbufs[i] = new unsigned char[partsBufSize]; - partpos[i] = 0; - partsize[i] = 0; - lseek(file, bufferSize * i, SEEK_SET); - ssize_t n = read(file, buf, bufferSize); - if (n < 0) continue; - qsort(buf, n / size, size, cmpf); - lseek(file, bufferSize * i, SEEK_SET); - write(file, buf, n); - - memcpy(partbufs[i], buf, std::min(n, partsBufSize)); - partsize[i] = n; - } - - for (size_t j = 0; j < parts; j++) { - if (partpos[j] == partsize[j]) continue; // bucket already empty - pq.push({&partbufs[j][partpos[j] % partsBufSize], j}); - } - - for (size_t i = 0; i < fsize; i += size) { - auto top = pq.top(); - pq.pop(); - - const void* smallest = top.first; - ssize_t smallestP = top.second; - - memcpy(buf + (i % bufferSize), smallest, size); - - if ((i % bufferSize) == bufferSize - size || i == fsize - size) { - // write to output file - write(newFile, buf, i % bufferSize + size); - } - - partpos[smallestP] += size; - - if (partpos[smallestP] % partsBufSize == 0) { - lseek(file, bufferSize * smallestP + partpos[smallestP], SEEK_SET); - read(file, partbufs[smallestP], partsBufSize); - } - pq.push( - {&partbufs[smallestP][partpos[smallestP] % partsBufSize], smallestP}); - } - - // cleanup - delete[] buf; - for (size_t j = 0; j < parts; j++) delete[] partbufs[j]; - delete[] partbufs; - delete[] partpos; - delete[] partsize; -} - -// _____________________________________________________________________________ -inline float f_rsqrt(float x) { - return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); -} - -// _____________________________________________________________________________ -class approx { - public: - explicit approx(double magnitude) - : _epsilon{std::numeric_limits::epsilon() * 100}, - _magnitude{magnitude} {} - - friend bool operator==(double lhs, approx const& rhs) { - return std::abs(lhs - rhs._magnitude) < rhs._epsilon; - } - - friend bool operator==(approx const& lhs, double rhs) { - return operator==(rhs, lhs); - } - - friend bool operator!=(double lhs, approx const& rhs) { - return !operator==(lhs, rhs); - } - - friend bool operator!=(approx const& lhs, double rhs) { - return !operator==(rhs, lhs); - } - - friend bool operator<=(double lhs, approx const& rhs) { - return lhs < rhs._magnitude || lhs == rhs; - } - - friend bool operator<=(approx const& lhs, double rhs) { - return lhs._magnitude < rhs || lhs == rhs; - } - - friend bool operator>=(double lhs, approx const& rhs) { - return lhs > rhs._magnitude || lhs == rhs; - } - - friend bool operator>=(approx const& lhs, double rhs) { - return lhs._magnitude > rhs || lhs == rhs; - } - - friend std::ostream& operator<< (std::ostream &out, const approx &a) { - out << "~" << a._magnitude; - return out; - } - - private: - double _epsilon; - double _magnitude; -}; - -/* - * Author: David Robert Nadeau - * Site: http://NadeauSoftware.com/ - * License: Creative Commons Attribution 3.0 Unported License - * http://creativecommons.org/licenses/by/3.0/deed.en_US - */ - -/** - * Returns the peak (maximum so far) resident set size (physical - * memory use) measured in bytes, or zero if the value cannot be - * determined on this OS. - */ - -// _____________________________________________________________________________ -inline size_t getPeakRSS() { -#if defined(_WIN32) - /* Windows -------------------------------------------------- */ - PROCESS_MEMORY_COUNTERS info; - GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); - return (size_t)info.PeakWorkingSetSize; - -#elif (defined(_AIX) || defined(__TOS__AIX__)) || \ - (defined(__sun__) || defined(__sun) || \ - defined(sun) && (defined(__SVR4) || defined(__svr4__))) - /* AIX and Solaris ------------------------------------------ */ - struct psinfo psinfo; - int fd = -1; - if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1) - return (size_t)0L; /* Can't open? */ - if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) { - close(fd); - return (size_t)0L; /* Can't read? */ - } - close(fd); - return (size_t)(psinfo.pr_rssize * 1024L); - -#elif defined(__unix__) || defined(__unix) || defined(unix) || \ - (defined(__APPLE__) && defined(__MACH__)) - /* BSD, Linux, and OSX -------------------------------------- */ - struct rusage rusage; - getrusage(RUSAGE_SELF, &rusage); -#if defined(__APPLE__) && defined(__MACH__) - return (size_t)rusage.ru_maxrss; -#else - return (size_t)(rusage.ru_maxrss * 1024L); -#endif - -#else - /* Unknown OS ----------------------------------------------- */ - return (size_t)0L; /* Unsupported. */ -#endif -} - -/* - * Returns the current resident set size (physical memory use) measured - * in bytes, or zero if the value cannot be determined on this OS. - */ - -// _____________________________________________________________________________ -inline size_t getCurrentRSS() { -#if defined(_WIN32) - /* Windows -------------------------------------------------- */ - PROCESS_MEMORY_COUNTERS info; - GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); - return (size_t)info.WorkingSetSize; - -#elif defined(__APPLE__) && defined(__MACH__) - /* OSX ------------------------------------------------------ */ - struct mach_task_basic_info info; - mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; - if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, - &infoCount) != KERN_SUCCESS) - return (size_t)0L; /* Can't access? */ - return (size_t)info.resident_size; - -#elif defined(__linux__) || defined(__linux) || defined(linux) || \ - defined(__gnu_linux__) - /* Linux ---------------------------------------------------- */ - long rss = 0L; - FILE* fp = NULL; - if ((fp = fopen("/proc/self/statm", "r")) == NULL) - return (size_t)0L; /* Can't open? */ - if (fscanf(fp, "%*s%ld", &rss) != 1) { - fclose(fp); - return (size_t)0L; /* Can't read? */ - } - fclose(fp); - return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE); - -#else - /* AIX, BSD, Solaris, and Unknown OS ------------------------ */ - return (size_t)0L; /* Unsupported. */ -#endif -} - -} // namespace util - -#endif // UTIL_MISC_H_ diff --git a/src/util/Nullable.h b/src/util/Nullable.h deleted file mode 100644 index 069426f..0000000 --- a/src/util/Nullable.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2017, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#include - -#ifndef UTIL_NULLABLE_H_ -#define UTIL_NULLABLE_H_ - -namespace util { - -template -class Nullable { - public: - Nullable() - : val(), null(true) {} - Nullable(T* valPointer) - : val(), null(true) { - if (valPointer) { - assign(*valPointer); - } - } - Nullable(const T& value) - : val(value), null(false) {} - Nullable(const Nullable& other) - : val(other.val), null(other.isNull()) {} - - Nullable& operator=(const Nullable& other) { - if (!other.isNull()) val = other.get(); - null = other.isNull(); - return *this; - } - - T operator=(const T& other) { - assign(other); - return val; - } - - /** - * Passing through comparision operators - */ - - bool operator==(const Nullable& other) const { - return (other.isNull() && isNull()) || other.get() == get(); - } - - bool operator!=(const Nullable& other) const { - return !(*this == other); - } - - bool operator<(const Nullable& other) const { - return !other.isNull() && !isNull() && get() < other.get(); - } - - bool operator>(const Nullable& other) const { - return !(*this < other || *this == other); - } - - bool operator<=(const Nullable& other) const { - return *this < other || *this == other; - } - - bool operator>=(const Nullable& other) const { - return *this > other || *this == other; - } - - bool operator==(const T& other) const { - return !isNull() && other == get(); - } - - bool operator!=(const T& other) const { - return !(*this == other); - } - - bool operator<(const T& other) const { - return !isNull() && get() < other; - } - - bool operator>(const T& other) const { - return !(*this < other || *this == other); - } - - bool operator<=(const T& other) const { - return *this < other || *this == other; - } - - bool operator>=(const T& other) const { - return *this > other || *this == other; - } - - operator T() const { - return get(); - } - - bool isNull() const { - return null; - } - - T get() const { - if (!isNull()) return val; - else throw std::runtime_error("Trying to retrieve value of NULL object."); - } - -private: - void assign(T v) { - val = v; - null = false; - } - - T val; - bool null; -}; - -} - -#endif // UTIL_NULLABLE_H_ diff --git a/src/util/PriorityQueue.h b/src/util/PriorityQueue.h deleted file mode 100644 index 13bd973..0000000 --- a/src/util/PriorityQueue.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_PRIORITYQUEUE_H_ -#define UTIL_PRIORITYQUEUE_H_ - -#include -#include -#include - -namespace util { -template -class PriorityQueue { - struct _ByFirst { - bool operator()(const std::pair& a, const std::pair& b) { - return a.first > b.first; - } - }; - - - public: - PriorityQueue() : _last(std::numeric_limits::lowest()) {} - void push(K k, const V& v); - const K topKey() ; - const V& topVal() ; - void pop(); - - bool empty() const; - - private: - K _last; - std::priority_queue, std::vector>, _ByFirst> - _pq; -}; -#include "util/PriorityQueue.tpp" -} // namespace util - -#endif diff --git a/src/util/PriorityQueue.tpp b/src/util/PriorityQueue.tpp deleted file mode 100644 index 611b5c2..0000000 --- a/src/util/PriorityQueue.tpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2019, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -// _____________________________________________________________________________ -template -void PriorityQueue::push(K key, const V& val) { - if (key < _last) key = _last; - _pq.emplace(std::pair(key, val)); -} - -// _____________________________________________________________________________ -template -const K PriorityQueue::topKey() { - _last = _pq.top().first; - return _pq.top().first; -} - -// _____________________________________________________________________________ -template -const V& PriorityQueue::topVal() { - _last = _pq.top().first; - return _pq.top().second; -} - -// _____________________________________________________________________________ -template -bool PriorityQueue::empty() const { - return _pq.empty(); -} - -// _____________________________________________________________________________ -template -void PriorityQueue::pop() { - _pq.pop(); -} diff --git a/src/util/String.h b/src/util/String.h deleted file mode 100644 index e523d0f..0000000 --- a/src/util/String.h +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2017, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_STRING_H_ -#define UTIL_STRING_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace util { - -// _____________________________________________________________________________ -inline bool endsWith(const std::string& a, const std::string& suff) { - if (suff.size() > a.size()) return false; - return a.compare(a.length() - suff.length(), suff.length(), suff) == 0; -} - -// _____________________________________________________________________________ -inline std::string urlDecode(const std::string& encoded) { - std::string decoded; - for (size_t i = 0; i < encoded.size(); ++i) { - char c = encoded[i]; - if (c == '%') { - std::string ah = encoded.substr(i + 1, 2); - char* nonProced = 0; - char hexVal = strtol(ah.c_str(), &nonProced, 16); - - if (ah.find_first_of("+-") > 1 && ah.size() - strlen(nonProced) == 2) { - c = hexVal; - i += 2; - } - } else if (c == '+') { - c = ' '; - } - decoded += c; - } - return decoded; -} - -// _____________________________________________________________________________ -inline std::string jsonStringEscape(const std::string& unesc) { - // modified code from - // http://stackoverflow.com/questions/7724448/simple-json-string-escape-for-c - std::ostringstream o; - for (auto c = unesc.cbegin(); c != unesc.cend(); c++) { - switch (*c) { - case '"': - o << "\\\""; - break; - case '\\': - o << "\\\\"; - break; - case '\b': - o << "\\b"; - break; - case '\f': - o << "\\f"; - break; - case '\n': - o << "\\n"; - break; - case '\r': - o << "\\r"; - break; - case '\t': - o << "\\t"; - break; - default: - if ('\x00' <= *c && *c <= '\x1f') { - o << "\\u" << std::hex << std::setw(4) << std::setfill('0') - << static_cast(*c); - } else { - o << *c; - } - } - } - return o.str(); -} - -// _____________________________________________________________________________ -inline bool replace(std::string& subj, const std::string& from, - const std::string& to) { - if (from.empty()) return false; - size_t start_pos = subj.find(from); - if (start_pos != std::string::npos) { - subj.replace(start_pos, from.length(), to); - return true; - } - - return false; -} - -// _____________________________________________________________________________ -inline bool replaceAll(std::string& subj, const std::string& from, - const std::string& to) { - if (from.empty()) return false; - bool found = false; - size_t s = subj.find(from, 0); - for (; s != std::string::npos; s = subj.find(from, s + to.length())) { - found = true; - subj.replace(s, from.length(), to); - } - - return found; -} - -// _____________________________________________________________________________ -inline std::string unixBasename(const std::string& pathname) { - return {std::find_if(pathname.rbegin(), pathname.rend(), - [](char c) { return c == '/'; }) - .base(), - pathname.end()}; -} - -// _____________________________________________________________________________ -template -inline std::string toString(T obj) { - std::stringstream ss; - ss << obj; - return ss.str(); -} - -// _____________________________________________________________________________ -inline std::vector split(std::string in, char sep) { - std::stringstream ss(in); - std::vector ret(1); - while (std::getline(ss, ret.back(), sep)) { - ret.push_back(""); - } - ret.pop_back(); - return ret; -} - -// _____________________________________________________________________________ -inline std::string ltrim(std::string str) { - str.erase(0, str.find_first_not_of(" \t\n\v\f\r")); - return str; -} - -// _____________________________________________________________________________ -inline std::string rtrim(std::string str) { - str.erase(str.find_last_not_of(" \t\n\v\f\r") + 1); - return str; -} - -// _____________________________________________________________________________ -inline std::string trim(std::string str) { return ltrim(rtrim(str)); } - -// _____________________________________________________________________________ -inline size_t editDist(const std::string& s1, const std::string& s2) { - // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++ - size_t len1 = s1.size(); - size_t len2 = s2.size(); - std::vector cur(len2 + 1); - std::vector prev(len2 + 1); - - for (size_t i = 0; i < prev.size(); i++) prev[i] = i; - - for (size_t i = 0; i < len1; i++) { - cur[0] = i + 1; - for (size_t j = 0; j < len2; j++) { - cur[j + 1] = - std::min(prev[1 + j] + 1, - std::min(cur[j] + 1, prev[j] + (s1[i] == s2[j] ? 0 : 1))); - } - std::swap(cur, prev); - } - - return prev[len2]; -} - -// _____________________________________________________________________________ -template -inline size_t prefixEditDist(const String& prefix, const String& s, - size_t deltaMax) { - // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++ - size_t len1 = prefix.size(); - size_t len2 = std::min(s.size(), prefix.size() + deltaMax + 1); - std::vector d((len1 + 1) * (len2 + 1)); - - d[0] = 0; - for (size_t i = 1; i <= len1; ++i) d[i * (len2 + 1)] = i; - for (size_t i = 1; i <= len2; ++i) d[i] = i; - - for (size_t i = 1; i <= len1; i++) { - for (size_t j = 1; j <= len2; j++) { - d[i * (len2 + 1) + j] = std::min(std::min(d[(i - 1) * (len2 + 1) + j] + 1, - d[i * (len2 + 1) + j - 1] + 1), - d[(i - 1) * (len2 + 1) + j - 1] + - (prefix[i - 1] == s[j - 1] ? 0 : 1)); - } - } - - // take min of last row - size_t deltaMin = std::max(std::max(deltaMax + 1, prefix.size()), s.size()); - for (size_t i = 0; i <= len2; i++) { - if (d[len1 * (len2 + 1) + i] < deltaMin) - deltaMin = d[len1 * (len2 + 1) + i]; - } - - return deltaMin; -} - -// _____________________________________________________________________________ -template -inline size_t prefixEditDist(const String& prefix, const String& s) { - return prefixEditDist(prefix, s, s.size()); -} - -// _____________________________________________________________________________ -inline size_t prefixEditDist(const char* prefix, const char* s) { - return prefixEditDist(std::string(prefix), std::string(s)); -} - -// _____________________________________________________________________________ -inline size_t prefixEditDist(const char* prefix, const char* s, - size_t deltaMax) { - return prefixEditDist(std::string(prefix), std::string(s), - deltaMax); -} - -// _____________________________________________________________________________ -inline size_t prefixEditDist(const char* prefix, const std::string& s) { - return prefixEditDist(std::string(prefix), s); -} - -// _____________________________________________________________________________ -inline size_t prefixEditDist(const char* prefix, const std::string& s, - size_t deltaMax) { - return prefixEditDist(std::string(prefix), s, deltaMax); -} - -// _____________________________________________________________________________ -inline size_t prefixEditDist(const std::string& prefix, const char* s) { - return prefixEditDist(prefix, std::string(s)); -} - -// _____________________________________________________________________________ -inline size_t prefixEditDist(const std::string& prefix, const char* s, - size_t deltaMax) { - return prefixEditDist(prefix, std::string(s), deltaMax); -} - -// _____________________________________________________________________________ -inline std::string toUpper(std::string str) { - std::transform(str.begin(), str.end(), str.begin(), toupper); - return str; -} - -// _____________________________________________________________________________ -inline std::string toLower(std::string str) { - std::transform(str.begin(), str.end(), str.begin(), tolower); - return str; -} - -// _____________________________________________________________________________ -template -inline std::string implode(Iter begin, const Iter& end, const char* del) { - std::stringstream ss; - size_t i = 0; - while (begin != end) { - if (i != 0) ss << del; - ss << *begin; - begin++; - i++; - } - - return ss.str(); -} - -// _____________________________________________________________________________ -template -inline std::string implode(const std::vector& vec, const char* del) { - return implode(vec.begin(), vec.end(), del); -} - -// _____________________________________________________________________________ -inline std::string normalizeWhiteSpace(const std::string& input) { - std::string ret; - bool ws = false; - for (size_t i = 0; i < input.size(); i++) { - if (std::isspace(input[i])) { - if (!ws) { - ret += " "; - ws = true; - } - continue; - } else { - ws = false; - ret += input[i]; - } - } - return ret; -} - -// _____________________________________________________________________________ -inline std::wstring toWStr(const std::string& str) { - std::wstring_convert> converter; - return converter.from_bytes(str); -} - -// _____________________________________________________________________________ -inline std::string toNStr(const std::wstring& wstr) { - std::wstring_convert> converter; - return converter.to_bytes(wstr); -} - -// _____________________________________________________________________________ -inline std::vector tokenize(const std::string& str) { - std::vector ret; - std::wstring wStr = toWStr(str); - - std::wstring cur; - for (size_t i = 0; i < wStr.size(); ++i) { - if (!std::iswalnum(wStr[i])) { - if (cur.size()) ret.push_back(toNStr(cur)); - cur = L""; - continue; - } - cur += wStr[i]; - } - if (cur.size()) ret.push_back(toNStr(cur)); - - return ret; -} - -// _____________________________________________________________________________ -inline double jaccardSimi(const std::string& a, const std::string& b) { - if (a == b) return 1; - - std::set sa, sb; - - auto toksA = tokenize(a); - auto toksB = tokenize(b); - - // 0 if both are empty - if (toksA.size() == 0 && toksB.size() == 0) return 0; - - sa.insert(toksA.begin(), toksA.end()); - sb.insert(toksB.begin(), toksB.end()); - - std::set isect; - - std::set_intersection(sa.begin(), sa.end(), sb.begin(), sb.end(), - std::inserter(isect, isect.begin())); - - double sInter = isect.size(); - double s1 = sa.size(); - double s2 = sb.size(); - return sInter / (s1 + s2 - sInter); -} - -// _____________________________________________________________________________ -inline double btsSimiInner(const std::vector& toks, - const std::string& b, double best) { - std::set toksSet; - toksSet.insert(toks.begin(), toks.end()); - std::vector toksUniqSorted; - toksUniqSorted.insert(toksUniqSorted.begin(), toksSet.begin(), toksSet.end()); - - assert(toksUniqSorted.size() <= 8); - - for (uint8_t v = 1; v <= pow(2, toksUniqSorted.size()); v++) { - std::bitset<8> bs(v); - std::vector cur(bs.count()); - - size_t i = 0; - for (size_t j = 0; j < toksUniqSorted.size(); j++) { - if (bs[j]) { - cur[i] = toksUniqSorted[j]; - i++; - } - } - - double tmp = util::implode(cur, " ").size(); - - // ed between the two string will always be at least their length - // difference - if this is already too big, skip it right now - double dt = 1 - (fabs(tmp - b.size()) * 1.0) / (fmax(tmp, b.size()) * 1.0); - - if (dt <= best) continue; - - // cur is guaranteed to be sorted now - do { - const auto& comb = util::implode(cur, " "); - - double d = - 1 - ((editDist(comb, b) * 1.0) / (fmax(comb.size(), b.size()) * 1.0)); - - if (fabs(d - 1) < 0.0001) return 1; - - if (d > best) best = d; - } while (std::next_permutation(cur.begin(), cur.end())); - } - - return best; -} - -// _____________________________________________________________________________ -inline double btsSimi(std::string a, std::string b) { - // this follows the implementation for the station similarity paper in - // https://github.com/ad-freiburg/statsimi/ - if (a == b) return 1; - - std::set sa, sb; - - auto toksA = tokenize(a); - auto toksB = tokenize(b); - - // fallback to jaccard if the token set is too large - if (toksA.size() > 6 || toksB.size() > 6) { - return jaccardSimi(a, b); - } - - if (toksA.size() > toksB.size()) { - std::swap(a, b); - std::swap(toksA, toksB); - } - - // this is already our best known value - simply the edit - // distance similarity between the strings - double best = 1 - (editDist(a, b) * 1.0) / std::fmax(a.size(), b.size()); - - if (fabs(best) < 0.0001) return 0; - - best = btsSimiInner(toksA, b, best); - - if (fabs(best - 1) < 0.0001) return 1; - - return btsSimiInner(toksB, a, best); -} -} // namespace util - -#endif // UTIL_STRING_H_ diff --git a/src/util/geo/BezierCurve.h b/src/util/geo/BezierCurve.h deleted file mode 100644 index 23f3263..0000000 --- a/src/util/geo/BezierCurve.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_GEO_BEZIERCURVE_H_ -#define UTIL_GEO_BEZIERCURVE_H_ - -#include -#include "util/geo/Geo.h" -#include "util/geo/PolyLine.h" - -namespace util { -namespace geo { - -struct CubicPolynom { - CubicPolynom(double a, double b, double c, double d, double x) - : a(a), b(b), c(c), d(d), x(x) {} - CubicPolynom() : a(0), b(0), c(0), d(0), x(0) {} - double a, b, c, d, x; - - double valueAt(double x) const; -}; - -/** - * Bezier curve - */ -template -class BezierCurve { - public: - BezierCurve(const Point& a, const Point& b, const Point& c, - const Point& d); - - const PolyLine& render(double d); - - private: - double _d; - - // the x and y polynoms for this spline - CubicPolynom _xp, _yp; - - // store the rendered polyline for quicker access - PolyLine _rendered; - bool _didRender; - - void recalcPolynoms(const Point& x, const Point& b, const Point& c, - const Point& d); - - Point valueAt(double t) const; -}; - -#include "util/geo/BezierCurve.tpp" -} -} - -#endif // UTIL_GEO_BEZIERCURVE_H_ diff --git a/src/util/geo/BezierCurve.tpp b/src/util/geo/BezierCurve.tpp deleted file mode 100644 index 4f08a31..0000000 --- a/src/util/geo/BezierCurve.tpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2016, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -// _____________________________________________________________________________ -template -BezierCurve::BezierCurve(const Point& a, const Point& b, - const Point& c, const Point& d) - : _d(dist(a, d)) { - assert(_d > 0); - recalcPolynoms(a, b, c, d); -} - -// _____________________________________________________________________________ -template -void BezierCurve::recalcPolynoms(const Point& a, const Point& b, - const Point& c, const Point& d) { - _xp.a = a.getX(); - _xp.b = 3.0 * (b.getX() - a.getX()); - _xp.c = 3.0 * (c.getX() - b.getX()) - _xp.b; - _xp.d = d.getX() - a.getX() - _xp.c - _xp.b; - - _yp.a = a.getY(); - _yp.b = 3.0 * (b.getY() - a.getY()); - _yp.c = 3.0 * (c.getY() - b.getY()) - _yp.b; - _yp.d = d.getY() - a.getY() - _yp.c - _yp.b; - - _didRender = false; -} - -// _____________________________________________________________________________ -template -Point BezierCurve::valueAt(double t) const { - return Point(_xp.valueAt(t), _yp.valueAt(t)); -} - -// _____________________________________________________________________________ -template -const PolyLine& BezierCurve::render(double d) { - assert(d > 0); - if (_didRender) return _rendered; - - if (_d == 0) { - _rendered << Point(_xp.a, _yp.a) << Point(_xp.a, _yp.a); - return _rendered; - } - - _rendered.empty(); - double n = _d / d, dt = 1 / n, t = 0; - - bool cancel = false; - while (true) { - _rendered << valueAt(t); - t += dt; - if (cancel) break; - if (t > 1) { - t = 1; - cancel = true; - } - } - - _didRender = true; - return _rendered; -} - -// _____________________________________________________________________________ -inline double CubicPolynom::valueAt(double atx) const { - double dx = atx - x; - return a + b * dx + c * dx * dx + d * dx * dx * dx; -} diff --git a/src/util/geo/Box.h b/src/util/geo/Box.h deleted file mode 100644 index cf4d0ee..0000000 --- a/src/util/geo/Box.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2016, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Author: Patrick Brosi - -#ifndef UTIL_GEO_BOX_H_ -#define UTIL_GEO_BOX_H_ - -#include "./Point.h" - -namespace util { -namespace geo { - -template -class Box { - public: - // maximum inverse box as default value of box - Box() - : _ll(std::numeric_limits::max(), std::numeric_limits::max()), - _ur(std::numeric_limits::lowest(), std::numeric_limits::lowest()) {} - Box(const Point& ll, const Point& ur) : _ll(ll), _ur(ur) {} - const Point& getLowerLeft() const { return _ll; } - const Point& getUpperRight() const { return _ur; } - - Point& getLowerLeft() { return _ll; } - Point& getUpperRight() { return _ur; } - - Point getUpperLeft() const { return {_ll.getX(), _ur.getY()}; } - Point getLowerRight() const { return {_ur.getX(), _ll.getY()}; } - - void setLowerLeft(const Point& ll) { _ll = ll; } - void setUpperRight(const Point& ur) { _ur = ur; } - - void isNull() { return _ll.getX() > _ur.getX(); } - - bool operator==(const Box& b) const { - return getLowerLeft() == b.getLowerLeft() && - getUpperRight() == b.getUpperRight(); - } - - bool operator!=(const Box& p) const { return !(*this == p); } - - private: - Point _ll, _ur; -}; - -template -class RotatedBox { - public: - RotatedBox() : _box(), _deg(0), _center() {} - RotatedBox(const Box& box) - : _box(box), - _deg(0), - _center(Point( - (box.getUpperRight().getX() - box.getLowerLeft().getX()) / T(2), - (box.getUpperRight().getY() - box.getLowerLeft().getY()) / T(2))) {} - RotatedBox(const Point& ll, const Point& ur) - : _box(ll, ur), - _deg(0), - _center(Point((ur.getX() - ll.getX()) / T(2), - (ur.getY() - ll.getY()) / T(2))) {} - RotatedBox(const Box& box, double deg) - : _box(box), - _deg(deg), - _center(Point( - (box.getUpperRight().getX() - box.getLowerLeft().getX()) / T(2), - (box.getUpperRight().getY() - box.getLowerLeft().getY()) / T(2))) {} - RotatedBox(const Point& ll, const Point& ur, double deg) - : _box(ll, ur), - _deg(deg), - _center(Point((ur.getX() - ll.getX()) / T(2), - (ur.getY() - ll.getY()) / T(2))) {} - RotatedBox(const Box& box, double deg, const Point& center) - : _box(box), _deg(deg), _center(center) {} - RotatedBox(const Point& ll, const Point& ur, double deg, - const Point& center) - : _box(ll, ur), _deg(deg), _center(center) {} - - const Box& getBox() const { return _box; } - Box& getBox() { return _box; } - - double getDegree() const { return _deg; } - const Point& getCenter() const { return _center; } - Point& getCenter() { return _center; } - - void setDegree(double deg) { _deg = deg; } - - private: - Box _box; - double _deg; - Point _center; -}; - -// _____________________________________________________________________________ -template -inline Box extendBox(const Point& p, Box b) { - if (p.getX() < b.getLowerLeft().getX()) b.getLowerLeft().setX(p.getX()); - if (p.getY() < b.getLowerLeft().getY()) b.getLowerLeft().setY(p.getY()); - - if (p.getX() > b.getUpperRight().getX()) b.getUpperRight().setX(p.getX()); - if (p.getY() > b.getUpperRight().getY()) b.getUpperRight().setY(p.getY()); - return b; -} - -} // namespace geo -} // namespace util - -#endif // UTIL_GEO_BOX_H_ diff --git a/src/util/geo/CircularSegment.h b/src/util/geo/CircularSegment.h deleted file mode 100644 index b80e60d..0000000 --- a/src/util/geo/CircularSegment.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_GEO_CIRCULARSEGMENT_H_ -#define UTIL_GEO_CIRCULARSEGMENT_H_ - -#include -#include "util/geo/Geo.h" -#include "util/geo/PolyLine.h" - -namespace util { -namespace geo { - -/** - * Circular segment - */ -template -class CircularSegment { - public: - CircularSegment(const Point& a, double ang, const Point& c); - - const PolyLine& render(double d); - - private: - // store the rendered polyline for quicker access - PolyLine _rendered; - - const Point& _a, _c; - double _renderD; - - double _ang, _rad, _s, _initAng; - - Point valueAt(double t) const; -}; - -#include "util/geo/CircularSegment.tpp" -} -} - -#endif // UTIL_GEO_BEZIERCURVE_H_ diff --git a/src/util/geo/CircularSegment.tpp b/src/util/geo/CircularSegment.tpp deleted file mode 100644 index 6058c68..0000000 --- a/src/util/geo/CircularSegment.tpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -// _____________________________________________________________________________ -template -CircularSegment::CircularSegment(const Point& a, double ang, - const Point& c) : _a(a), _c(c), _renderD(0), _ang(ang) - { - - _rad = dist(a, c); - _s = fabs(_ang * _rad); - _initAng = angBetween(c, a); -} - -// _____________________________________________________________________________ -template -Point CircularSegment::valueAt(double ang) const { - double xPos = _c.getX() + _rad * cos(ang); - double yPos = _c.getY() + _rad * sin(ang); - return Point(xPos, yPos); -} - -// _____________________________________________________________________________ -template -const PolyLine& CircularSegment::render(double d) { - assert(d > 0); - if (fabs(d - _renderD) < 0.001) return _rendered; - _renderD = d; - - if (_s == 0) { - _rendered << _a << _a; - return _rendered; - } - - _rendered.empty(); - double n = _s / d, dt = 1 / n, t = 0; - - bool cancel = false; - while (true) { - _rendered << valueAt(_initAng + t * _ang); - t += dt; - if (cancel) break; - if (t > 1) { - t = 1; - cancel = true; - } - } - - return _rendered; -} diff --git a/src/util/geo/Geo.h b/src/util/geo/Geo.h deleted file mode 100644 index fcd695b..0000000 --- a/src/util/geo/Geo.h +++ /dev/null @@ -1,3052 +0,0 @@ -// Copyright 2016, University of Freiburg, -// Chair of Algorithms and Data Structures. -// Authors: Patrick Brosi - -#ifndef UTIL_GEO_GEO_H_ -#define UTIL_GEO_GEO_H_ - -#define _USE_MATH_DEFINES - -#include - -#include -#include -#include -#include -#include -#include - -#include "util/Misc.h" -#include "util/String.h" -#include "util/geo/Box.h" -#include "util/geo/Line.h" -#include "util/geo/Point.h" -#include "util/geo/Polygon.h" - -// ------------------- -// Geometry stuff -// ------------------ - -namespace util { -namespace geo { - -// convenience aliases - -typedef Point DPoint; -typedef Point FPoint; -typedef Point IPoint; -typedef Point I32Point; -typedef Point I64Point; - -typedef MultiPoint DMultiPoint; -typedef MultiPoint FMultiPoint; -typedef MultiPoint IMultiPoint; -typedef MultiPoint I32MultiPoint; -typedef MultiPoint I64MultiPoint; - -typedef LineSegment DLineSegment; -typedef LineSegment FLineSegment; -typedef LineSegment ILineSegment; -typedef LineSegment I32LineSegment; -typedef LineSegment I64LineSegment; - -typedef Line DLine; -typedef Line FLine; -typedef Line ILine; -typedef Line I32Line; -typedef Line I64Line; - -typedef MultiLine DMultiLine; -typedef MultiLine FMultiLine; -typedef MultiLine IMultiLine; -typedef MultiLine I32MultiLine; -typedef MultiLine I64MultiLine; - -typedef XSortedLine DXSortedLine; -typedef XSortedLine FXSortedLine; -typedef XSortedLine IXSortedLine; -typedef XSortedLine I32XSortedLine; -typedef XSortedLine I64XSortedLine; - -typedef Box DBox; -typedef Box FBox; -typedef Box IBox; -typedef Box I32Box; -typedef Box I64Box; - -typedef Polygon DPolygon; -typedef Polygon FPolygon; -typedef Polygon IPolygon; -typedef Polygon I32Polygon; -typedef Polygon I64Polygon; - -typedef XSortedPolygon DXSortedPolygon; -typedef XSortedPolygon FXSortedPolygon; -typedef XSortedPolygon IXSortedPolygon; -typedef XSortedPolygon I32XSortedPolygon; -typedef XSortedPolygon I64XSortedPolygon; - -typedef MultiPolygon DMultiPolygon; -typedef MultiPolygon FMultiPolygon; -typedef MultiPolygon IMultiPolygon; -typedef MultiPolygon I32MultiPolygon; -typedef MultiPolygon I64MultiPolygon; - -typedef XSortedMultiPolygon DXSortedMultiPolygon; -typedef XSortedMultiPolygon FXSortedMultiPolygon; -typedef XSortedMultiPolygon IXSortedMultiPolygon; -typedef XSortedMultiPolygon I32XSortedMultiPolygon; -typedef XSortedMultiPolygon I64XSortedMultiPolygon; - -const static double EPSILON = 0.0000001; -const static double RAD = 0.017453292519943295; // PI/180 -const static double IRAD = 180.0 / M_PI; // 180 / PI -const static double AVERAGING_STEP = 20; - -const static double M_PER_DEG = 111319.4; - -// _____________________________________________________________________________ -template -inline Box pad(const Box& box, double padding) { - return Box(Point(box.getLowerLeft().getX() - padding, - box.getLowerLeft().getY() - padding), - Point(box.getUpperRight().getX() + padding, - box.getUpperRight().getY() + padding)); -} - -// _____________________________________________________________________________ -template -inline Point centroid(const Point p) { - return p; -} - -// _____________________________________________________________________________ -template -inline Point centroid(const LineSegment ls) { - return Point((1.0 * ls.first.getX() + ls.second.getX()) / T(2), - (1.0 * ls.first.getY() + ls.second.getY()) / T(2)); -} - -// _____________________________________________________________________________ -template -inline Point centroid(const Line ls) { - double x = 0, y = 0; - for (const auto& p : ls) { - x += p.getX(); - y += p.getY(); - } - return Point(x / T(ls.size()), y / T(ls.size())); -} - -// _____________________________________________________________________________ -template -inline Point centroid(const Polygon ls) { - return centroid(ls.getOuter()); -} - -// _____________________________________________________________________________ -template -inline Point centroid(const Box box) { - return centroid(LineSegment(box.getLowerLeft(), box.getUpperRight())); -} - -// _____________________________________________________________________________ -template class Geometry> -inline Point centroid(std::vector> multigeo) { - Line a; - for (const auto& g : multigeo) a.push_back(centroid(g)); - return centroid(a); -} - -// _____________________________________________________________________________ -template -inline Point rotate(const Point& p, double deg) { - UNUSED(deg); - return p; -} - -// _____________________________________________________________________________ -template -inline Point rotate(Point p, double deg, const Point& c) { - deg *= -RAD; - double si = sin(deg); - double co = cos(deg); - p = p - c; - - return Point(p.getX() * co - p.getY() * si, - p.getX() * si + p.getY() * co) + - c; -} - -// _____________________________________________________________________________ -template -inline LineSegment rotate(LineSegment geo, double deg, - const Point& c) { - geo.first = rotate(geo.first, deg, c); - geo.second = rotate(geo.second, deg, c); - return geo; -} - -// _____________________________________________________________________________ -template -inline LineSegment rotate(LineSegment geo, double deg) { - return (geo, deg, centroid(geo)); -} - -// _____________________________________________________________________________ -template -inline Line rotate(Line geo, double deg, const Point& c) { - for (size_t i = 0; i < geo.size(); i++) geo[i] = rotate(geo[i], deg, c); - return geo; -} - -// _____________________________________________________________________________ -template -inline Polygon rotate(Polygon geo, double deg, const Point& c) { - for (size_t i = 0; i < geo.getOuter().size(); i++) - geo.getOuter()[i] = rotate(geo.getOuter()[i], deg, c); - return geo; -} - -// _____________________________________________________________________________ -template