update util lib

This commit is contained in:
Patrick Brosi 2022-03-28 14:59:55 +02:00
parent a58ed3d54d
commit 361063185e
19 changed files with 440 additions and 1794 deletions

View file

@ -18,7 +18,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/build")
# set compiler flags, see http://stackoverflow.com/questions/7724569/debug-vs-release-in-cmake
set(CMAKE_CXX_FLAGS "-Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wextra -Wno-implicit-fallthrough -pedantic")
set(CMAKE_CXX_FLAGS "-Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wextra -Wno-implicit-fallthrough -pedantic -Wno-keyword-macro")
set(CMAKE_CXX_FLAGS_SANITIZE "-Og -g -fsanitize=address -fsanitize=leak -fsanitize=undefined -DLOGLEVEL=3 -DPFAEDLE_DBG=1")
set(CMAKE_CXX_FLAGS_PROFILE "-g -pg -DLOGLEVEL=3 -DPFAEDLE_DBG=1")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DLOGLEVEL=3 -DPFAEDLE_DBG=1")

View file

@ -16,57 +16,48 @@
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#define FORCE_INLINE __forceinline
#include <stdlib.h>
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#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)
#else // defined(_MSC_VER)
#define FORCE_INLINE inline __attribute__((always_inline))
#define FORCE_INLINE inline __attribute__((always_inline))
inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
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 )
{
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 ROTL32(x, y) rotl32(x, y)
#define ROTL64(x, y) rotl64(x, y)
#define BIG_CONSTANT(x) (x##LLU)
#endif // !defined(_MSC_VER)
#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 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];
}
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 )
{
FORCE_INLINE uint32_t fmix32(uint32_t h) {
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
@ -78,8 +69,7 @@ FORCE_INLINE uint32_t fmix32 ( uint32_t h )
//----------
FORCE_INLINE uint64_t fmix64 ( uint64_t k )
{
FORCE_INLINE uint64_t fmix64(uint64_t k) {
k ^= k >> 33;
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
k ^= k >> 33;
@ -91,10 +81,8 @@ FORCE_INLINE uint64_t fmix64 ( uint64_t k )
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void * key, int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
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;
@ -105,34 +93,40 @@ void MurmurHash3_x86_32 ( const void * key, int len,
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock32(blocks,i);
for (int i = -nblocks; i; i++) {
uint32_t k1 = getblock32(blocks, i);
k1 *= c1;
k1 = ROTL32(k1,15);
k1 = ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32(h1,13);
h1 = h1*5+0xe6546b64;
h1 = ROTL32(h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
uint32_t k1 = 0;
switch(len & 3)
{
case 3: k1 ^= tail[2] << 16;
case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
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;
};
//----------
@ -142,15 +136,14 @@ void MurmurHash3_x86_32 ( const void * key, int len,
h1 = fmix32(h1);
*(uint32_t*)out = 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;
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;
@ -158,104 +151,170 @@ void MurmurHash3_x86_128 ( const void * key, const int len,
uint32_t h3 = seed;
uint32_t h4 = seed;
const uint32_t c1 = 0x239b961b;
const uint32_t c1 = 0x239b961b;
const uint32_t c2 = 0xab0e9789;
const uint32_t c3 = 0x38b34ae5;
const uint32_t c3 = 0x38b34ae5;
const uint32_t c4 = 0xa1e38b93;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
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);
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;
k1 *= c1;
k1 = ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
h1 = ROTL32(h1, 19);
h1 += h2;
h1 = h1 * 5 + 0x561ccd1b;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
k2 *= c2;
k2 = ROTL32(k2, 16);
k2 *= c3;
h2 ^= k2;
h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
h2 = ROTL32(h2, 17);
h2 += h3;
h2 = h2 * 5 + 0x0bcaa747;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
k3 *= c3;
k3 = ROTL32(k3, 17);
k3 *= c4;
h3 ^= k3;
h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
h3 = ROTL32(h3, 15);
h3 += h4;
h3 = h3 * 5 + 0x96cd1c35;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
k4 *= c4;
k4 = ROTL32(k4, 18);
k4 *= c1;
h4 ^= k4;
h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
h4 = ROTL32(h4, 13);
h4 += h1;
h4 = h4 * 5 + 0x32ac3b17;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
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;
case 14: k4 ^= tail[13] << 8;
case 13: k4 ^= tail[12] << 0;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
case 12: k3 ^= tail[11] << 24;
case 11: k3 ^= tail[10] << 16;
case 10: k3 ^= tail[ 9] << 8;
case 9: k3 ^= tail[ 8] << 0;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
case 8: k2 ^= tail[ 7] << 24;
case 7: k2 ^= tail[ 6] << 16;
case 6: k2 ^= tail[ 5] << 8;
case 5: k2 ^= tail[ 4] << 0;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
case 4: k1 ^= tail[ 3] << 24;
case 3: k1 ^= tail[ 2] << 16;
case 2: k1 ^= tail[ 1] << 8;
case 1: k1 ^= tail[ 0] << 0;
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
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 ^= len;
h2 ^= len;
h3 ^= len;
h4 ^= len;
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
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;
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;
((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;
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;
@ -267,56 +326,99 @@ void MurmurHash3_x64_128 ( const void * key, const int len,
//----------
// body
const uint64_t * blocks = (const uint64_t *)(data);
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);
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;
k1 *= c1;
k1 = ROTL64(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
h1 = ROTL64(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
k2 *= c2;
k2 = ROTL64(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
h2 = ROTL64(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
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;
case 14: k2 ^= ((uint64_t)tail[13]) << 40;
case 13: k2 ^= ((uint64_t)tail[12]) << 32;
case 12: k2 ^= ((uint64_t)tail[11]) << 24;
case 11: k2 ^= ((uint64_t)tail[10]) << 16;
case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= ((uint64_t)tail[ 7]) << 56;
case 7: k1 ^= ((uint64_t)tail[ 6]) << 48;
case 6: k1 ^= ((uint64_t)tail[ 5]) << 40;
case 5: k1 ^= ((uint64_t)tail[ 4]) << 32;
case 4: k1 ^= ((uint64_t)tail[ 3]) << 24;
case 3: k1 ^= ((uint64_t)tail[ 2]) << 16;
case 2: k1 ^= ((uint64_t)tail[ 1]) << 8;
case 1: k1 ^= ((uint64_t)tail[ 0]) << 0;
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
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 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
@ -327,9 +429,8 @@ void MurmurHash3_x64_128 ( const void * key, const int len,
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
((uint64_t *)out)[0] = h1;
((uint64_t *)out)[1] = h2;
}
//-----------------------------------------------------------------------------

View file

@ -9,8 +9,10 @@
#include <cstring>
#include <chrono>
#include <sstream>
#include <iomanip>
#include <immintrin.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
@ -114,6 +116,21 @@ inline bool isFloatingPoint(const std::string& str) {
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

View file

@ -24,6 +24,9 @@ class Box {
Point<T>& getLowerLeft() { return _ll; }
Point<T>& getUpperRight() { return _ur; }
Point<T> getUpperLeft() { return {_ll.getX(), _ur.getY()}; }
Point<T> getLowerRight() { return {_ur.getX(), _ll.getY()}; }
void setLowerLeft(const Point<T>& ll) { _ll = ll; }
void setUpperRight(const Point<T>& ur) { _ur = ur; }

View file

@ -10,6 +10,7 @@
#include <math.h>
#include <algorithm>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stdexcept>
@ -742,6 +743,19 @@ inline double angBetween(const Point<T>& p1, const Point<T>& q1) {
return angBetween(p1.getX(), p1.getY(), q1.getX(), q1.getY());
}
// _____________________________________________________________________________
template <typename T>
inline double angBetween(const Point<T>& p1, const MultiPoint<T>& points) {
double sinSum = 0;
double cosSum = 0;
for (auto q1 : points) {
double a = angBetween(p1.getX(), p1.getY(), q1.getX(), q1.getY());
sinSum += sin(a);
cosSum += cos(a);
}
return atan2(sinSum / points.size(), cosSum / points.size());
}
// _____________________________________________________________________________
inline double dist(double x1, double y1, double x2, double y2) {
return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
@ -932,19 +946,19 @@ inline Line<T> lineFromWKT(std::string wkt) {
// _____________________________________________________________________________
template <typename T>
inline std::string getWKT(const Point<T>& p) {
std::stringstream ss;
ss << std::fixed << std::setprecision(6) << "POINT (" << p.getX() << " " << p.getY() << ")";
return ss.str();
return std::string("POINT (") + formatFloat(p.getX(), 6) + " " +
formatFloat(p.getY(), 6) + ")";
}
// _____________________________________________________________________________
template <typename T>
inline std::string getWKT(const std::vector<Point<T>>& p) {
std::stringstream ss;
ss << std::fixed << std::setprecision(6) << "MULTIPOINT (";
ss << "MULTIPOINT (";
for (size_t i = 0; i < p.size(); i++) {
if (i) ss << ", ";
ss << "(" << p[i].getX() << " " << p[i].getY() << ")";
ss << "(" << formatFloat(p.getX(), 6) << " " << formatFloat(p.getY(), 6)
<< ")";
}
ss << ")";
return ss.str();
@ -954,10 +968,10 @@ inline std::string getWKT(const std::vector<Point<T>>& p) {
template <typename T>
inline std::string getWKT(const Line<T>& l) {
std::stringstream ss;
ss << std::fixed << std::setprecision(6) << "LINESTRING (";
ss << "LINESTRING (";
for (size_t i = 0; i < l.size(); i++) {
if (i) ss << ", ";
ss << l[i].getX() << " " << l[i].getY();
ss << formatFloat(l[i].getX(), 6) << " " << formatFloat(l[i].getY(), 6);
}
ss << ")";
return ss.str();
@ -967,14 +981,15 @@ inline std::string getWKT(const Line<T>& l) {
template <typename T>
inline std::string getWKT(const std::vector<Line<T>>& ls) {
std::stringstream ss;
ss << std::fixed << std::setprecision(6) << "MULTILINESTRING (";
ss << "MULTILINESTRING (";
for (size_t j = 0; j < ls.size(); j++) {
if (j) ss << ", ";
ss << "(";
for (size_t i = 0; i < ls[j].size(); i++) {
if (i) ss << ", ";
ss << ls[j][i].getX() << " " << ls[j][i].getY();
ss << formatFloat(ls[j][i].getX(), 6) << " "
<< formatFloat(ls[j][i].getY(), 6);
}
ss << ")";
}
@ -994,11 +1009,16 @@ template <typename T>
inline std::string getWKT(const Box<T>& l) {
std::stringstream ss;
ss << "POLYGON ((";
ss << l.getLowerLeft().getX() << " " << l.getLowerLeft().getY();
ss << ", " << l.getUpperRight().getX() << " " << l.getLowerLeft().getY();
ss << ", " << l.getUpperRight().getX() << " " << l.getUpperRight().getY();
ss << ", " << l.getLowerLeft().getX() << " " << l.getUpperRight().getY();
ss << ", " << l.getLowerLeft().getX() << " " << l.getLowerLeft().getY();
ss << formatFloat(l.getLowerLeft().getX(), 6) << " "
<< formatFloat(l.getLowerLeft().getY(), 6);
ss << ", " << formatFloat(l.getUpperRight().getX(), 6) << " "
<< formatFloat(l.getLowerLeft().getY(), 6);
ss << ", " << formatFloat(l.getUpperRight().getX(), 6) << " "
<< formatFloat(l.getUpperRight().getY(), 6);
ss << ", " << formatFloat(l.getLowerLeft().getX(), 6) << " "
<< formatFloat(l.getUpperRight().getY(), 6);
ss << ", " << formatFloat(l.getLowerLeft().getX(), 6) << " "
<< formatFloat(l.getLowerLeft().getY(), 6);
ss << "))";
return ss.str();
}
@ -1009,9 +1029,11 @@ inline std::string getWKT(const Polygon<T>& p) {
std::stringstream ss;
ss << "POLYGON ((";
for (size_t i = 0; i < p.getOuter().size(); i++) {
ss << p.getOuter()[i].getX() << " " << p.getOuter()[i].getY() << ", ";
ss << formatFloat(p.getOuter()[i].getX(), 6) << " "
<< formatFloat(p.getOuter()[i].getY(), 6) << ", ";
}
ss << p.getOuter().front().getX() << " " << p.getOuter().front().getY();
ss << formatFloat(p.getOuter().front().getX(), 6) << " "
<< formatFloat(p.getOuter().front().getY(), 6);
ss << "))";
return ss.str();
}
@ -1026,11 +1048,11 @@ inline std::string getWKT(const std::vector<Polygon<T>>& ls) {
if (j) ss << ", ";
ss << "((";
for (size_t i = 0; i < ls[j].getOuter().size(); i++) {
ss << ls[j].getOuter()[i].getX() << " " << ls[j].getOuter()[i].getY()
<< ", ";
ss << formatFloat(ls[j].getOuter()[i].getX(), 6) << " "
<< formatFloat(ls[j].getOuter()[i].getY(), 6) << ", ";
}
ss << ls[j].getOuter().front().getX() << " "
<< ls[j].getOuter().front().getY();
ss << formatFloat(ls[j].getOuter().front().getX(), 6) << " "
<< formatFloat(ls[j].getOuter().front().getY(), 6);
ss << "))";
}
@ -1224,7 +1246,8 @@ inline double parallelity(const Box<T>& box, const MultiLine<T>& multiline) {
// _____________________________________________________________________________
template <template <typename> class Geometry, typename T>
inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol) {
inline RotatedBox<T> getOrientedEnvelope(std::vector<Geometry<T>> pol,
double step) {
// TODO: implement this nicer, works for now, but inefficient
// see
// https://geidav.wordpress.com/tag/gift-wrapping/#fn-1057-FreemanShapira1975
@ -1235,8 +1258,8 @@ inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol) {
double rotateDeg = 0;
// rotate in 1 deg steps
for (int i = 1; i < 360; i += 1) {
pol = rotate(pol, 1, center);
for (double i = step; i < 360; i += step) {
pol = rotate(pol, step, center);
Box<T> e = getBoundingBox(pol);
if (area(tmpBox) > area(e)) {
tmpBox = e;
@ -1247,6 +1270,50 @@ inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol) {
return RotatedBox<T>(tmpBox, -rotateDeg, center);
}
// _____________________________________________________________________________
template <template <typename> class Geometry, typename T>
inline RotatedBox<T> getOrientedEnvelope(std::vector<Geometry<T>> pol) {
return getOrientedEnvelope(pol, 1);
}
// _____________________________________________________________________________
template <template <typename> class Geometry, typename T>
inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol, double step) {
std::vector<Geometry<T>> mult{pol};
return getOrientedEnvelope(mult, step);
}
// _____________________________________________________________________________
template <template <typename> class Geometry, typename T>
inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol) {
std::vector<Geometry<T>> mult{pol};
return getOrientedEnvelope(mult, 1);
}
// _____________________________________________________________________________
template <typename T>
inline Polygon<T> buffer(const Line<T>& line, double d, size_t points) {
// so far only works correctly if the input polygon is convex
MultiPoint<T> pSet;
for (const auto& p : line) {
Point<T> anchor{p.getX() + d, p.getY()};
double deg = 0;
pSet.push_back(p);
for (size_t i = 0; i < points; i++) {
pSet.push_back(rotate(anchor, deg, p));
deg += 360 / (1.0 * points);
}
}
return convexHull(pSet);
}
// _____________________________________________________________________________
template <typename T>
inline Polygon<T> buffer(const Polygon<T>& pol, double d, size_t points) {
return buffer(pol.getOuter(), d, points);
}
// _____________________________________________________________________________
template <typename T>
inline Box<T> extendBox(const Box<T>& a, Box<T> b) {
@ -1799,7 +1866,6 @@ inline double haversine(const Point<T>& a, const Point<T>& b) {
return haversine(a.getY(), a.getX(), b.getY(), b.getX());
}
// _____________________________________________________________________________
template <typename T>
inline Line<T> densify(const Line<T>& l, double d) {
@ -1963,8 +2029,8 @@ inline double accFrechetDistCHav(const Line<T>& a, const Line<T>& b, double d) {
for (size_t i = 1; i < p.size(); i++) {
for (size_t j = 1; j < q.size(); j++) {
float d =
util::geo::haversine(p[i], q[j]) * util::geo::haversine(p[i], p[i - 1]);
float d = util::geo::haversine(p[i], q[j]) *
util::geo::haversine(p[i], p[i - 1]);
ca[i * q.size() + j] =
d + std::min(ca[(i - 1) * q.size() + j],
std::min(ca[i * q.size() + (j - 1)],
@ -2042,7 +2108,6 @@ inline double latLngLen(const Line<T>& g) {
return ret;
}
// _____________________________________________________________________________
template <typename G>
inline double webMercDistFactor(const G& a) {

View file

@ -71,8 +71,6 @@ class PolyLine {
double distTo(const PolyLine<T>& g) const;
double distTo(const Point<T>& p) const;
SharedSegments<T> getSharedSegments(const PolyLine<T>& pl, double dmax) const;
double getLength() const;
// return point at dist

View file

@ -188,9 +188,9 @@ PolyLine<T> PolyLine<T>::getSegment(const LinePoint<T>& start,
ret << end.p;
// find a more performant way to clear the result of above
// ret.simplify(0);
ret.simplify(0);
// assert(ret.getLine().size());
assert(ret.getLine().size());
return ret;
}
@ -478,120 +478,6 @@ void PolyLine<T>::move(double vx, double vy) {
}
}
// _____________________________________________________________________________
template <typename T>
SharedSegments<T> PolyLine<T>::getSharedSegments(const PolyLine<T>& pl,
double dmax) const {
/**
* Returns the segments this polyline share with pl
* atm, this is a very simple distance-based algorithm
*/
double STEP_SIZE = 2;
double MAX_SKIPS = 4;
double MIN_SEG_LENGTH = 0.1; // dmax / 2; // make this configurable!
SharedSegments<T> ret;
if (distTo(pl) > dmax) return ret;
bool in = false, single = true;
double curDist = 0;
double curTotalSegDist = 0;
size_t skips;
LinePoint<T> curStartCand, curEndCand, curStartCandCmp, curEndCandCmp;
double comp = 0, curSegDist = 0;
double length = getLength(), plLength = pl.getLength();
for (size_t i = 1; i < _line.size(); ++i) {
const Point<T>& s = _line[i - 1];
const Point<T>& e = _line[i];
bool lastRound = false;
double totalDist = dist(s, e);
while (curSegDist <= totalDist) {
const auto& curPointer = interpolate(s, e, curSegDist);
if (pl.distTo(curPointer) <= dmax) {
LinePoint<T> curCmpPointer = pl.projectOn(curPointer);
LinePoint<T> curBackProjectedPointer = projectOn(curCmpPointer.p);
skips = 0;
if (in) {
curEndCand = curBackProjectedPointer;
curEndCandCmp = curCmpPointer;
if (curEndCand.totalPos < curStartCand.totalPos) {
curEndCand = curStartCand;
}
single = false;
comp = fabs(curStartCand.totalPos * length -
curEndCand.totalPos * length) /
fabs(curStartCandCmp.totalPos * plLength -
curEndCandCmp.totalPos * plLength);
} else {
in = true;
curStartCand = curBackProjectedPointer;
curStartCandCmp = curCmpPointer;
}
} else {
if (in) {
skips++;
if (skips > MAX_SKIPS) { // TODO: make configurable
if (comp > 0.8 && comp < 1.2 && !single &&
(fabs(curStartCand.totalPos * length -
curEndCand.totalPos * length) > MIN_SEG_LENGTH &&
fabs(curStartCandCmp.totalPos * plLength -
curEndCandCmp.totalPos * plLength) > MIN_SEG_LENGTH)) {
ret.segments.push_back(
SharedSegment<T>(std::pair<LinePoint<T>, LinePoint<T>>(
curStartCand, curStartCandCmp),
std::pair<LinePoint<T>, LinePoint<T>>(
curEndCand, curEndCandCmp)));
// TODO: only return the FIRST one, make this configuralbe
return ret;
}
in = false;
single = true;
}
}
}
if (curSegDist + STEP_SIZE > totalDist && !lastRound) {
lastRound = true;
double finalStep = totalDist - curSegDist - 0.0005;
curSegDist += finalStep;
curDist += finalStep;
} else {
curSegDist += STEP_SIZE;
curDist += STEP_SIZE;
}
}
curSegDist = curSegDist - totalDist;
curTotalSegDist += totalDist;
}
if (comp > 0.8 && comp < 1.2 && in && !single &&
(fabs(curStartCand.totalPos * length - curEndCand.totalPos * length) >
MIN_SEG_LENGTH &&
fabs(curStartCandCmp.totalPos * plLength -
curEndCandCmp.totalPos * plLength) > MIN_SEG_LENGTH)) {
ret.segments.push_back(SharedSegment<T>(
std::pair<LinePoint<T>, LinePoint<T>>(curStartCand, curStartCandCmp),
std::pair<LinePoint<T>, LinePoint<T>>(curEndCand, curEndCandCmp)));
}
return ret;
}
// _____________________________________________________________________________
template <typename T>
std::set<LinePoint<T>, LinePointCmp<T>> PolyLine<T>::getIntersections(

View file

@ -28,7 +28,7 @@ class DirGraph : public Graph<N, E> {
Node<N, E>* addNd(const N& pl);
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p);
Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
virtual Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
};

View file

@ -114,16 +114,18 @@ class EDijkstra : public ShortestPath<EDijkstra> {
using SettledInit = tsl::robin_map<Edge<N, E>*, RouteEdgeInit<N, E, C>>;
template <typename N, typename E, typename C>
using SettledInitNoRes = tsl::robin_map<Edge<N, E>*, RouteEdgeInitNoRes<N, E, C>>;
using SettledInitNoRes =
tsl::robin_map<Edge<N, E>*, RouteEdgeInitNoRes<N, E, C>>;
template <typename N, typename E, typename C>
using PQInit = radix_heap::pair_radix_heap<C, RouteEdgeInit<N, E, C>>;
template <typename N, typename E, typename C>
using PQInitNoRes = radix_heap::pair_radix_heap<C, RouteEdgeInitNoRes<N, E, C>>;
using PQInitNoRes =
radix_heap::pair_radix_heap<C, RouteEdgeInitNoRes<N, E, C>>;
template <typename N, typename E, typename C>
static C shortestPathImpl(const std::set<Edge<N, E>*> from,
static C shortestPathImpl(const std::set<Edge<N, E>*>& from,
const std::set<Edge<N, E>*>& to,
const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc,
@ -148,6 +150,13 @@ class EDijkstra : public ShortestPath<EDijkstra> {
const util::graph::HeurFunc<N, E, C>& heurFunc,
EList<N, E>* resEdges, NList<N, E>* resNodes);
template <typename N, typename E, typename C>
static C shortestPathImpl(const std::set<Node<N, E>*>& from,
const std::set<Node<N, E>*>& to,
const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc,
EList<N, E>* resEdges, NList<N, E>* resNodes);
template <typename N, typename E, typename C>
static std::unordered_map<Edge<N, E>*, C> shortestPathImpl(
const std::set<Edge<N, E>*>& from,
@ -161,6 +170,15 @@ class EDijkstra : public ShortestPath<EDijkstra> {
std::unordered_map<Edge<N, E>*, EList<N, E>*> resEdges,
std::unordered_map<Edge<N, E>*, NList<N, E>*> resNodes);
template <typename N, typename E, typename C>
static std::unordered_map<Edge<N, E>*, C> shortestPathImpl(
const std::set<Edge<N, E>*>& from, const std::set<Edge<N, E>*>& to,
const std::unordered_map<Edge<N, E>*, C>& initCosts,
const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc,
std::unordered_map<Edge<N, E>*, EList<N, E>*> resEdges,
std::unordered_map<Edge<N, E>*, NList<N, E>*> resNodes);
template <typename N, typename E, typename C>
static std::unordered_map<Edge<N, E>*, C> shortestPathImpl(
const std::set<Edge<N, E>*>& from, const std::set<Edge<N, E>*>& to,
@ -202,11 +220,10 @@ class EDijkstra : public ShortestPath<EDijkstra> {
PQInit<N, E, C>& pq);
template <typename N, typename E, typename C>
static inline void relaxInitNoResEdgs(RouteEdgeInitNoRes<N, E, C>& cur,
const std::set<Edge<N, E>*>& to, C stall,
const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc,
PQInitNoRes<N, E, C>& pq);
static inline void relaxInitNoResEdgs(
RouteEdgeInitNoRes<N, E, C>& cur, const std::set<Edge<N, E>*>& to,
C stall, const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc, PQInitNoRes<N, E, C>& pq);
template <typename N, typename E, typename C>
static void relaxInv(RouteEdge<N, E, C>& cur,

View file

@ -47,7 +47,30 @@ C EDijkstra::shortestPathImpl(Edge<N, E>* from, const std::set<Node<N, E>*>& to,
// _____________________________________________________________________________
template <typename N, typename E, typename C>
C EDijkstra::shortestPathImpl(const std::set<Edge<N, E>*> from,
C EDijkstra::shortestPathImpl(const std::set<Node<N, E>*>& from,
const std::set<Node<N, E>*>& to,
const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc,
EList<N, E>* resEdges, NList<N, E>* resNodes) {
std::set<Edge<N, E>*> frEs;
std::set<Edge<N, E>*> toEs;
for (auto n : from) {
frEs.insert(n->getAdjListIn().begin(), n->getAdjListIn().end());
}
for (auto n : to) {
toEs.insert(n->getAdjListIn().begin(), n->getAdjListIn().end());
}
C cost = shortestPathImpl(frEs, toEs, costFunc, heurFunc, resEdges, resNodes);
return cost;
}
// _____________________________________________________________________________
template <typename N, typename E, typename C>
C EDijkstra::shortestPathImpl(const std::set<Edge<N, E>*>& from,
const std::set<Edge<N, E>*>& to,
const util::graph::CostFunc<N, E, C>& costFunc,
const util::graph::HeurFunc<N, E, C>& heurFunc,

View file

@ -5,10 +5,10 @@
#ifndef UTIL_GRAPH_GRAPH_H_
#define UTIL_GRAPH_GRAPH_H_
#include <cassert>
#include <iostream>
#include <set>
#include <string>
#include <iostream>
#include <cassert>
#include "util/graph/Edge.h"
#include "util/graph/Node.h"
@ -25,7 +25,7 @@ class Graph {
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to);
virtual Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p) = 0;
Edge<N, E>* getEdg(Node<N, E>* from, Node<N, E>* to);
const Edge<N, E>* getEdg(Node<N, E>* from, Node<N, E>* to) const;
const Edge<N, E>* getEdg(const Node<N, E>* from, const Node<N, E>* to) const;
virtual Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b) = 0;
@ -39,11 +39,11 @@ class Graph {
void delEdg(Node<N, E>* from, Node<N, E>* to);
protected:
std::set<Node<N, E>*> _nodes;
std::set<Node<N, E>*> _nodes;
};
#include "util/graph/Graph.tpp"
}
}
} // namespace graph
} // namespace util
#endif // UTIL_GRAPH_GRAPH_H_

View file

@ -22,8 +22,7 @@ const std::set<Node<N, E>*>& Graph<N, E>::getNds() const {
// _____________________________________________________________________________
template <typename N, typename E>
typename std::set<Node<N, E>*>::iterator Graph<N, E>::delNd(
Node<N, E>* n) {
typename std::set<Node<N, E>*>::iterator Graph<N, E>::delNd(Node<N, E>* n) {
return delNd(_nodes.find(n));
}
@ -69,10 +68,10 @@ Node<N, E>* Graph<N, E>::sharedNode(const Edge<N, E>* a, const Edge<N, E>* b) {
return r;
}
// _____________________________________________________________________________
template <typename N, typename E>
const Edge<N, E>* Graph<N, E>::getEdg(Node<N, E>* from, Node<N, E>* to) const {
const Edge<N, E>* Graph<N, E>::getEdg(const Node<N, E>* from,
const Node<N, E>* to) const {
for (auto e : from->getAdjList()) {
if (e->getOtherNd(from) == to) return e;
}

View file

@ -79,6 +79,16 @@ class ShortestPath {
resNodes);
}
template <typename N, typename E, typename C>
static C shortestPath(const std::set<Node<N, E>*>& from,
const std::set<Node<N, E>*>& to,
const CostFunc<N, E, C>& costFunc) {
EList<N, E>* el = 0;
NList<N, E>* nl = 0;
return D::shortestPathImpl(from, to, costFunc, ZeroHeurFunc<N, E, C>(),
el, nl);
}
template <typename N, typename E, typename C>
static C shortestPath(const std::set<Node<N, E>*> from,
const std::set<Node<N, E>*>& to,

View file

@ -30,7 +30,7 @@ class UndirGraph : public Graph<N, E> {
Node<N, E>* addNd(const N& pl);
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p);
Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
virtual Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
};

View file

@ -42,12 +42,14 @@ Edge<N, E>* UndirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to,
template <typename N, typename E>
Node<N, E>* UndirGraph<N, E>::mergeNds(Node<N, E>* a, Node<N, E>* b) {
for (auto e : a->getAdjListOut()) {
if (e->getFrom() != a) continue;
if (e->getTo() != b) {
addEdg(b, e->getTo(), e->pl());
}
}
for (auto e : a->getAdjListIn()) {
if (e->getTo() != a) continue;
if (e->getFrom() != b) {
addEdg(e->getFrom(), b, e->pl());
}

View file

@ -128,7 +128,7 @@ class pair_radix_heap {
void push(key_type key, const value_type &value) {
unsigned_key_type x = encoder_type::encode(key);
if (last_ > x) {
std::cerr << "Not monotone: " << last_ << " vs " << x << std::endl;
std::cerr << "PQ: not monotone: " << last_ << " vs " << x << std::endl;
x = last_;
}
++size_;
@ -140,7 +140,7 @@ class pair_radix_heap {
void push(key_type key, value_type &&value) {
unsigned_key_type x = encoder_type::encode(key);
if (last_ > x) {
std::cerr << "Not monotone: " << last_ << " vs " << x << std::endl;
std::cerr << "PQ: not monotone: " << last_ << " vs " << x << std::endl;
x = last_;
}
++size_;

View file

@ -30,9 +30,9 @@ struct Null {};
struct Val {
enum VAL_T { UINT, INT, FLOAT, STRING, ARRAY, DICT, BOOL, JSNULL };
VAL_T type;
int i;
uint64_t ui;
double f;
int i = 0;
uint64_t ui = 0;
double f = 0;
std::string str;
std::vector<Val> arr;
std::map<std::string, Val> dict;

View file

@ -1843,7 +1843,6 @@ int main(int argc, char** argv) {
TEST(geo::getWKT(geo::segment(DLine{{0, 0}, {0, 1}, {0, 2}}, 0.5, 1)), ==, "LINESTRING (0 1, 0 2)");
}
// inversion count
std::vector<int> test = {2, 1};
TEST(inversions(test), ==, 1);
@ -1880,4 +1879,13 @@ int main(int argc, char** argv) {
test = {9, 8, 7, 6, 5, 4, 3, 2, 1};
TEST(inversions(test), ==, 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1);
// nice float formatting
TEST(formatFloat(15.564, 3), ==, "15.564");
TEST(formatFloat(15.564, 0), ==, "16");
TEST(formatFloat(15.0000, 10), ==, "15");
TEST(formatFloat(15.0100, 10), ==, "15.01");
TEST(formatFloat(0.0000, 10), ==, "0");
TEST(formatFloat(-1.0000, 10), ==, "-1");
TEST(formatFloat(-15.000001, 10), ==, "-15.000001");
}

File diff suppressed because it is too large Load diff