Merge branch 'master' of https://git.billsun.dev/bill/AQuery
This commit is contained in:
+154
-66
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "gc.h"
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <deque>
|
||||
@@ -12,7 +13,7 @@ size_t count(const VT<T>& v) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr static inline size_t count(const T&) { return 1; }
|
||||
constexpr static size_t count(const T&) { return 1; }
|
||||
|
||||
// TODO: Specializations for dt/str/none
|
||||
template<class T, template<typename ...> class VT>
|
||||
@@ -29,14 +30,19 @@ double avg(const VT<T>& v) {
|
||||
return (sum<T>(v) / static_cast<double>(v.size));
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void sqrt(const VT<T>& v, Ret& ret) {
|
||||
for (uint32_t i = 0; i < v.size; ++i)
|
||||
ret[i] = sqrt(v[i]);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
VT<double> sqrt(const VT<T>& v) {
|
||||
VT<double> ret(v.size);
|
||||
for (uint32_t i = 0; i < v.size; ++i) {
|
||||
ret[i] = sqrt(v[i]);
|
||||
}
|
||||
sqrt(v, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T truncate(const T& v, const uint32_t precision) {
|
||||
auto multiplier = pow(10, precision);
|
||||
@@ -73,109 +79,153 @@ T min(const VT<T>& v) {
|
||||
min_v = min_v < _v ? min_v : _v;
|
||||
return min_v;
|
||||
}
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> mins(const VT<T>& arr) {
|
||||
|
||||
// simplify this using a template std::binary_function<T, T, bool> = std::less;
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void mins(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
std::deque<std::pair<T, uint32_t>> cache;
|
||||
decayed_t<VT, T> ret(len);
|
||||
T min = std::numeric_limits<T>::max();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (arr[i] < min)
|
||||
min = arr[i];
|
||||
ret[i] = min;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> mins(const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
mins(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> maxs(const VT<T>& arr) {
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void maxs(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, T> ret(len);
|
||||
T max = std::numeric_limits<T>::min();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (arr[i] > max)
|
||||
max = arr[i];
|
||||
ret[i] = max;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> minw(uint32_t w, const VT<T>& arr) {
|
||||
decayed_t<VT, T> maxs(const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
maxs(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void minw(uint32_t w, const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, T> ret(len);
|
||||
std::deque<std::pair<T, uint32_t>> cache;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (!cache.empty() && cache.front().second == i - w) cache.pop_front();
|
||||
|
||||
while (!cache.empty() && cache.back().first > arr[i]) cache.pop_back();
|
||||
cache.push_back({ arr[i], i });
|
||||
ret[i] = cache.front().first;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> maxw(uint32_t w, const VT<T>& arr) {
|
||||
decayed_t<VT, T> minw(uint32_t w, const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
minw(w, arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void maxw(uint32_t w, const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, T> ret(len);
|
||||
std::deque<std::pair<T, uint32_t>> cache;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (!cache.empty() && cache.front().second == i - w) cache.pop_front();
|
||||
while (!cache.empty() && cache.back().first > arr[i]) cache.pop_back();
|
||||
while (!cache.empty() && cache.back().first < arr[i]) cache.pop_back();
|
||||
cache.push_back({ arr[i], i });
|
||||
arr[i] = cache.front().first;
|
||||
ret[i] = cache.front().first;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetFPType<T>> ratiow(uint32_t w, const VT<T>& arr) {
|
||||
inline decayed_t<VT, T> maxw(uint32_t w, const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
maxw(w, arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void ratiow(uint32_t w, const VT<T>& arr, Ret& ret) {
|
||||
typedef std::decay_t<types::GetFPType<T>> FPType;
|
||||
uint32_t len = arr.size;
|
||||
if (arr.size <= w)
|
||||
len = 1;
|
||||
w = w > len ? len : w;
|
||||
decayed_t<VT, FPType> ret(arr.size);
|
||||
ret[0] = 0;
|
||||
for (uint32_t i = 0; i < w; ++i)
|
||||
ret[i] = arr[i] / (FPType)arr[0];
|
||||
for (uint32_t i = w; i < arr.size; ++i)
|
||||
ret[i] = arr[i] / (FPType) arr[i - w];
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
inline decayed_t<VT, types::GetFPType<T>> ratiow(uint32_t w, const VT<T>& arr) {
|
||||
typedef std::decay_t<types::GetFPType<T>> FPType;
|
||||
decayed_t<VT, FPType> ret(arr.size);
|
||||
ratiow(w, arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetFPType<T>> ratios(const VT<T>& arr) {
|
||||
inline decayed_t<VT, types::GetFPType<T>> ratios(const VT<T>& arr) {
|
||||
return ratiow(1, arr);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetLongType<T>> sums(const VT<T>& arr) {
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
inline void ratios(const VT<T>& arr, Ret& ret) {
|
||||
return ratiow(1, arr, ret);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void sums(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, types::GetLongType<T>> ret(len);
|
||||
uint32_t i = 0;
|
||||
if (len) ret[i++] = arr[0];
|
||||
for (; i < len; ++i)
|
||||
ret[i] = ret[i - 1] + arr[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgs(const VT<T>& arr) {
|
||||
inline decayed_t<VT, types::GetLongType<T>> sums(const VT<T>& arr) {
|
||||
decayed_t<VT, types::GetLongType<T>> ret(arr.size);
|
||||
sums(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void avgs(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
typedef types::GetFPType<types::GetLongType<T>> FPType;
|
||||
decayed_t<VT, FPType> ret(len);
|
||||
uint32_t i = 0;
|
||||
types::GetLongType<T> s;
|
||||
if (len) s = ret[i++] = arr[0];
|
||||
for (; i < len; ++i)
|
||||
ret[i] = (s += arr[i]) / (FPType)(i + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetLongType<T>> sumw(uint32_t w, const VT<T>& arr) {
|
||||
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgs(const VT<T>& arr) {
|
||||
typedef types::GetFPType<types::GetLongType<T>> FPType;
|
||||
decayed_t<VT, FPType> ret(arr.size);
|
||||
avgs(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void sumw(uint32_t w, const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, types::GetLongType<T>> ret(len);
|
||||
uint32_t i = 0;
|
||||
w = w > len ? len : w;
|
||||
if (len) ret[i++] = arr[0];
|
||||
@@ -183,11 +233,17 @@ decayed_t<VT, types::GetLongType<T>> sumw(uint32_t w, const VT<T>& arr) {
|
||||
ret[i] = ret[i - 1] + arr[i];
|
||||
for (; i < len; ++i)
|
||||
ret[i] = ret[i - 1] + arr[i] - arr[i - w];
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
void avgw(uint32_t w, const VT<T>& arr, decayed_t<vector_type, types::GetFPType<types::GetLongType<T>>>& ret) {
|
||||
decayed_t<VT, types::GetLongType<T>> sumw(uint32_t w, const VT<T>& arr) {
|
||||
decayed_t<VT, types::GetLongType<T>> ret(arr.size);
|
||||
sumw(w, arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void avgw(uint32_t w, const VT<T>& arr, Ret& ret) {
|
||||
typedef types::GetFPType<types::GetLongType<T>> FPType;
|
||||
const uint32_t& len = arr.size;
|
||||
uint32_t i = 0;
|
||||
@@ -201,26 +257,19 @@ void avgw(uint32_t w, const VT<T>& arr, decayed_t<vector_type, types::GetFPType<
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgw(uint32_t w, const VT<T>& arr) {
|
||||
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgw(uint32_t w, const VT<T>& arr) {
|
||||
typedef types::GetFPType<types::GetLongType<T>> FPType;
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, FPType> ret(len);
|
||||
uint32_t i = 0;
|
||||
types::GetLongType<T> s{};
|
||||
w = w > len ? len : w;
|
||||
if (len) s = ret[i++] = arr[0];
|
||||
for (; i < w; ++i)
|
||||
ret[i] = (s += arr[i]) / (FPType)(i + 1);
|
||||
for (; i < len; ++i)
|
||||
ret[i] = ret[i - 1] + (arr[i] - arr[i - w]) / (FPType)w;
|
||||
avgw(w, arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, bool sd = false>
|
||||
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> varw(uint32_t w, const VT<T>& arr) {
|
||||
template<class T, template<typename ...> class VT, class Ret, bool sd = false>
|
||||
void varw(uint32_t w, const VT<T>& arr,
|
||||
Ret& ret) {
|
||||
using FPType = types::GetFPType<types::GetLongType<T>>;
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, FPType> ret(len);
|
||||
uint32_t i = 0;
|
||||
types::GetLongType<T> s{};
|
||||
w = w > len ? len : w;
|
||||
@@ -252,7 +301,14 @@ decayed_t<VT, types::GetFPType<types::GetLongType<T>>> varw(uint32_t w, const VT
|
||||
if constexpr(sd)
|
||||
if(i)
|
||||
ret[i-1] = sqrt(ret[i-1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<class T, template<typename ...> class VT, bool sd = false>
|
||||
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> varw(uint32_t w, const VT<T>& arr) {
|
||||
using FPType = types::GetFPType<types::GetLongType<T>>;
|
||||
decayed_t<VT, FPType> ret(arr.size);
|
||||
varw<T, VT, decayed_t<VT, types::GetFPType<types::GetLongType<T>>>, sd>(w, arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -274,11 +330,10 @@ types::GetFPType<types::GetLongType<decays<T>>> var(const VT<T>& arr) {
|
||||
return (ssq - s * s / (FPType)(len + 1)) / (FPType)(len + 1);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, bool sd = false>
|
||||
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> vars(const VT<T>& arr) {
|
||||
template<class T, template<typename ...> class VT, class Ret, bool sd = false>
|
||||
void vars(const VT<T>& arr, Ret& ret) {
|
||||
typedef types::GetFPType<types::GetLongType<T>> FPType;
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, FPType> ret(len);
|
||||
uint32_t i = 0;
|
||||
types::GetLongType<T> s{};
|
||||
FPType MnX{};
|
||||
@@ -298,70 +353,103 @@ decayed_t<VT, types::GetFPType<types::GetLongType<T>>> vars(const VT<T>& arr) {
|
||||
ret[i] = MnX / (FPType)(i + 1);
|
||||
if constexpr(sd) ret[i] = sqrt(ret[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, bool sd = false>
|
||||
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> vars(const VT<T>& arr) {
|
||||
typedef types::GetFPType<types::GetLongType<T>> FPType;
|
||||
decayed_t<VT, FPType> ret(arr.size);
|
||||
vars<T, VT, decayed_t<VT, types::GetFPType<types::GetLongType<T>>>, sd>(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
types::GetFPType<types::GetLongType<decays<T>>> stddev(const VT<T>& arr) {
|
||||
inline types::GetFPType<types::GetLongType<decays<T>>> stddev(const VT<T>& arr) {
|
||||
return sqrt(var(arr));
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevs(const VT<T>& arr) {
|
||||
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevs(const VT<T>& arr) {
|
||||
return vars<T, VT, true>(arr);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevw(uint32_t w, const VT<T>& arr) {
|
||||
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevw(uint32_t w, const VT<T>& arr) {
|
||||
return varw<T, VT, true>(w, arr);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
inline auto stddevs(const VT<T>& arr, Ret& ret) {
|
||||
return vars<T, VT, Ret, true>(arr, ret);
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
inline auto stddevw(uint32_t w, const VT<T>& arr, Ret& ret) {
|
||||
return varw<T, VT, Ret, true>(w, arr, ret);
|
||||
}
|
||||
|
||||
|
||||
// use getSignedType
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> deltas(const VT<T>& arr) {
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void deltas(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, T> ret(len);
|
||||
uint32_t i = 0;
|
||||
if (len) ret[i++] = 0;
|
||||
for (; i < len; ++i)
|
||||
ret[i] = arr[i] - arr[i - 1];
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> prev(const VT<T>& arr) {
|
||||
inline decayed_t<VT, T> deltas(const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
deltas(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void prev(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, T> ret(len);
|
||||
uint32_t i = 0;
|
||||
if (len) ret[i++] = arr[0];
|
||||
for (; i < len; ++i)
|
||||
ret[i] = arr[i - 1];
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
decayed_t<VT, T> aggnext(const VT<T>& arr) {
|
||||
inline decayed_t<VT, T> prev(const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
prev(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT, class Ret>
|
||||
void aggnext(const VT<T>& arr, Ret& ret) {
|
||||
const uint32_t& len = arr.size;
|
||||
decayed_t<VT, T> ret(len);
|
||||
uint32_t i = 1;
|
||||
for (; i < len; ++i)
|
||||
ret[i - 1] = arr[i];
|
||||
if (len > 0) ret[len - 1] = arr[len - 1];
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
inline decayed_t<VT, T> aggnext(const VT<T>& arr) {
|
||||
decayed_t<VT, T> ret(arr.size);
|
||||
aggnext(arr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
T last(const VT<T>& arr) {
|
||||
if (!arr.size) return 0;
|
||||
const uint32_t& len = arr.size;
|
||||
return arr[arr.size - 1];
|
||||
}
|
||||
|
||||
template<class T, template<typename ...> class VT>
|
||||
T first(const VT<T>& arr) {
|
||||
if (!arr.size) return 0;
|
||||
const uint32_t& len = arr.size;
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define __DEFAULT_AGGREGATE_FUNCTION__(NAME, RET) \
|
||||
template <class T> constexpr T NAME(const T& v) { return RET; }
|
||||
|
||||
|
||||
+50
-7
@@ -1,9 +1,43 @@
|
||||
#pragma once
|
||||
#ifndef __AQ_USE_THREADEDGC__
|
||||
#include <atomic>
|
||||
class GC {
|
||||
private:;
|
||||
|
||||
class ScratchSpace {
|
||||
public:
|
||||
void* ret;
|
||||
char* scratchspace;
|
||||
size_t ptr;
|
||||
size_t cnt;
|
||||
size_t capacity;
|
||||
size_t initial_capacity;
|
||||
void* temp_memory_fractions;
|
||||
|
||||
//uint8_t status;
|
||||
// record maximum size
|
||||
constexpr static uint8_t Grow = 0x1;
|
||||
// no worry about overflow
|
||||
constexpr static uint8_t Use = 0x0;
|
||||
|
||||
void init(size_t initial_capacity);
|
||||
|
||||
// apply for memory
|
||||
void* alloc(uint32_t sz);
|
||||
|
||||
void register_ret(void* ret);
|
||||
|
||||
// reorganize memory space
|
||||
void release();
|
||||
|
||||
// reset status of the scratch space
|
||||
void reset();
|
||||
|
||||
// reset scratch space to initial capacity.
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
|
||||
#ifndef __AQ_USE_THREADEDGC__
|
||||
class GC {
|
||||
private:
|
||||
size_t max_slots,
|
||||
interval, forced_clean,
|
||||
forceclean_timer = 0;
|
||||
@@ -18,7 +52,6 @@ private:;
|
||||
std::atomic<uint64_t> current_size;
|
||||
volatile bool lock;
|
||||
using gc_deallocator_t = void (*)(void*);
|
||||
|
||||
// maybe use volatile std::thread::id instead
|
||||
protected:
|
||||
void acquire_lock();
|
||||
@@ -29,28 +62,38 @@ protected:
|
||||
void terminate_daemon();
|
||||
|
||||
public:
|
||||
void reg(void* v, uint32_t sz = 1,
|
||||
ScratchSpace scratch;
|
||||
void reg(void* v, uint32_t sz = 0xffffffff,
|
||||
void(*f)(void*) = free
|
||||
);
|
||||
|
||||
uint32_t get_threshold() const {
|
||||
return threshould;
|
||||
}
|
||||
|
||||
GC(
|
||||
uint64_t max_size = 0xfffffff, uint32_t max_slots = 4096,
|
||||
uint32_t interval = 10000, uint32_t forced_clean = 1000000,
|
||||
uint32_t threshould = 64 //one seconds
|
||||
uint32_t threshould = 64, //one seconds
|
||||
uint32_t scratch_sz = 0x1000000 // 16 MB
|
||||
) : max_size(max_size), max_slots(max_slots),
|
||||
interval(interval), forced_clean(forced_clean),
|
||||
threshould(threshould) {
|
||||
|
||||
start_deamon();
|
||||
GC::gc_handle = this;
|
||||
this->scratch.init(1);
|
||||
} // 256 MB
|
||||
|
||||
~GC(){
|
||||
terminate_daemon();
|
||||
scratch.cleanup();
|
||||
}
|
||||
|
||||
static GC* gc_handle;
|
||||
static ScratchSpace *scratch_space;
|
||||
template <class T>
|
||||
constexpr static inline gc_deallocator_t _delete(T*){
|
||||
static inline gc_deallocator_t _delete(T*) {
|
||||
return [](void* v){
|
||||
delete (T*)v;
|
||||
};
|
||||
|
||||
@@ -132,7 +132,3 @@ namespace ankerl::unordered_dense{
|
||||
struct hash<std::tuple<Types...>> : public hasher<Types...>{ };
|
||||
}
|
||||
|
||||
struct aq_hashtable_value_t {
|
||||
uint32_t id;
|
||||
uint32_t cnt;
|
||||
};
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
template <class ...Types>
|
||||
std::string generate_printf_string(const char* sep = " ", const char* end = "\n") {
|
||||
std::string str;
|
||||
@@ -25,6 +26,11 @@ inline decltype(auto) print_hook<bool>(const bool& v) {
|
||||
return v? "true" : "false";
|
||||
}
|
||||
|
||||
template<>
|
||||
inline decltype(auto) print_hook<std::string_view>(const std::string_view& v) {
|
||||
return v.data();
|
||||
}
|
||||
|
||||
extern char* gbuf;
|
||||
|
||||
void setgbuf(char* buf = 0);
|
||||
|
||||
@@ -55,6 +55,7 @@ void print<bool>(const bool&v, const char* delimiter){
|
||||
std::cout<< (v?"true":"false") << delimiter;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
T getInt(const char*& buf){
|
||||
T ret = 0;
|
||||
@@ -451,6 +452,9 @@ void GC::reg(void* v, uint32_t sz, void(*f)(void*)) { //~ 40ns expected v. free
|
||||
f(v);
|
||||
return;
|
||||
}
|
||||
else if (sz == 0xffffffff)
|
||||
sz = this->threshould;
|
||||
|
||||
auto _q = static_cast<memoryqueue_t>(q);
|
||||
while(lock);
|
||||
++alive_cnt;
|
||||
@@ -464,6 +468,72 @@ void GC::reg(void* v, uint32_t sz, void(*f)(void*)) { //~ 40ns expected v. free
|
||||
#endif
|
||||
|
||||
inline GC* GC::gc_handle = nullptr;
|
||||
inline ScratchSpace* GC::scratch_space = nullptr;
|
||||
|
||||
void ScratchSpace::init(size_t initial_capacity) {
|
||||
ret = nullptr;
|
||||
scratchspace = static_cast<char*>(malloc(initial_capacity));
|
||||
ptr = cnt = 0;
|
||||
capacity = initial_capacity;
|
||||
this->initial_capacity = initial_capacity;
|
||||
temp_memory_fractions = new vector_type<void*>();
|
||||
}
|
||||
|
||||
inline void* ScratchSpace::alloc(uint32_t sz){
|
||||
ptr = this->cnt;
|
||||
this->cnt += sz; // major cost
|
||||
if (this->cnt > capacity) {
|
||||
[[unlikely]]
|
||||
capacity = this->cnt + (capacity >> 1);
|
||||
auto vec_tmpmem_fractions = static_cast<vector_type<char *>*>(temp_memory_fractions);
|
||||
vec_tmpmem_fractions->emplace_back(scratchspace);
|
||||
scratchspace = static_cast<char*>(malloc(capacity));
|
||||
ptr = 0;
|
||||
}
|
||||
return scratchspace + ptr;
|
||||
}
|
||||
|
||||
inline void ScratchSpace::register_ret(void* ret){
|
||||
this->ret = ret;
|
||||
}
|
||||
|
||||
inline void ScratchSpace::release(){
|
||||
ptr = cnt = 0;
|
||||
auto vec_tmpmem_fractions =
|
||||
static_cast<vector_type<void*>*>(temp_memory_fractions);
|
||||
if (vec_tmpmem_fractions->size) {
|
||||
[[unlikely]]
|
||||
for(auto& mem : *vec_tmpmem_fractions){
|
||||
//free(mem);
|
||||
GC::gc_handle->reg(mem);
|
||||
}
|
||||
vec_tmpmem_fractions->clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline void ScratchSpace::reset() {
|
||||
this->release();
|
||||
ret = nullptr;
|
||||
if (capacity != initial_capacity){
|
||||
capacity = initial_capacity;
|
||||
scratchspace = static_cast<char*>(realloc(scratchspace, capacity));
|
||||
}
|
||||
}
|
||||
|
||||
void ScratchSpace::cleanup(){
|
||||
auto vec_tmpmem_fractions =
|
||||
static_cast<vector_type<void*>*>(temp_memory_fractions);
|
||||
if (vec_tmpmem_fractions->size) {
|
||||
for(auto& mem : *vec_tmpmem_fractions){
|
||||
free(mem);
|
||||
//GC::gc_handle->reg(mem);
|
||||
}
|
||||
vec_tmpmem_fractions->clear();
|
||||
}
|
||||
delete vec_tmpmem_fractions;
|
||||
free(this->scratchspace);
|
||||
}
|
||||
|
||||
|
||||
#include "dragonbox/dragonbox_to_chars.hpp"
|
||||
|
||||
@@ -537,4 +607,11 @@ aq_to_chars<types::timestamp_t>(void* value, char* buffer) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template<>
|
||||
char*
|
||||
aq_to_chars<std::string_view>(void* value, char* buffer){
|
||||
const auto& src = *static_cast<std::string_view*>(value);
|
||||
memcpy(buffer, src.data(), src.size());
|
||||
return buffer + src.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ template<> char* aq_to_chars<char*>(void* , char*);
|
||||
template<> char* aq_to_chars<types::date_t>(void* , char*);
|
||||
template<> char* aq_to_chars<types::time_t>(void* , char*);
|
||||
template<> char* aq_to_chars<types::timestamp_t>(void* , char*);
|
||||
template<> char* aq_to_chars<std::string_view>(void* , char*);
|
||||
typedef int (*code_snippet)(void*);
|
||||
|
||||
template <class _This_Struct>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "monetdb_conn.h"
|
||||
#include "monetdbe.h"
|
||||
#include "table.h"
|
||||
#include <thread>
|
||||
|
||||
#undef ERROR
|
||||
#undef static_assert
|
||||
|
||||
@@ -73,11 +75,11 @@ void Server::connect(Context *cxt){
|
||||
printf("Error: Server %p already connected. Restart? (Y/n). \n", server);
|
||||
char c[50];
|
||||
std::cin.getline(c, 49);
|
||||
for(int i = 0; i < 50; ++i){
|
||||
for(int i = 0; i < 50; ++i) {
|
||||
if (!c[i] || c[i] == 'y' || c[i] == 'Y'){
|
||||
monetdbe_close(*server);
|
||||
free(*server);
|
||||
this->server = 0;
|
||||
this->server = nullptr;
|
||||
break;
|
||||
}
|
||||
else if(c[i]&&!(c[i] == ' ' || c[i] == '\t'))
|
||||
@@ -86,7 +88,10 @@ void Server::connect(Context *cxt){
|
||||
}
|
||||
|
||||
server = (monetdbe_database*)malloc(sizeof(monetdbe_database));
|
||||
auto ret = monetdbe_open(server, nullptr, nullptr);
|
||||
monetdbe_options ops;
|
||||
AQ_ZeroMemory(ops);
|
||||
ops.nr_threads = std::thread::hardware_concurrency();
|
||||
auto ret = monetdbe_open(server, nullptr, &ops);
|
||||
if (ret == 0){
|
||||
status = true;
|
||||
this->server = server;
|
||||
@@ -148,8 +153,7 @@ void Server::print_results(const char* sep, const char* end){
|
||||
szs [i] = monetdbe_type_szs[cols[i]->type];
|
||||
header_string = header_string + cols[i]->name + sep + '|' + sep;
|
||||
}
|
||||
const size_t l_sep = strlen(sep) + 1;
|
||||
if (header_string.size() - l_sep >= 0)
|
||||
if (const size_t l_sep = strlen(sep) + 1; header_string.size() >= l_sep)
|
||||
header_string.resize(header_string.size() - l_sep);
|
||||
header_string += end + std::string(header_string.size(), '=') + end;
|
||||
fputs(header_string.c_str(), stdout);
|
||||
|
||||
+39
-15
@@ -191,6 +191,21 @@ constexpr prt_fn_t monetdbe_prtfns[] = {
|
||||
aq_to_chars<std::nullptr_t>
|
||||
};
|
||||
|
||||
#ifndef __AQ_USE_THREADEDGC__
|
||||
void aq_init_gc(void *handle, Context* cxt)
|
||||
{
|
||||
typedef void (*aq_gc_init_t) (Context*);
|
||||
if (handle && cxt){
|
||||
auto sym = dlsym(handle, "__AQ_Init_GC__");
|
||||
if(sym){
|
||||
((aq_gc_init_t)sym)(cxt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else //__AQ_USE_THREADEDGC__
|
||||
#define aq_init_gc(h, c)
|
||||
#endif //__AQ_USE_THREADEDGC__
|
||||
|
||||
#include "monetdbe.h"
|
||||
#undef max
|
||||
#undef min
|
||||
@@ -280,6 +295,7 @@ void initialize_module(const char* module_name, void* module_handle, Context* cx
|
||||
printf("Warning: module %s have no session support.\n", module_name);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
int dll_main(int argc, char** argv, Context* cxt){
|
||||
aq_timer timer;
|
||||
@@ -363,12 +379,7 @@ start:
|
||||
recorded_queries.emplace_back(copy_lpstr("N"));
|
||||
}
|
||||
handle = dlopen(proc_name, RTLD_NOW);
|
||||
#ifndef __AQ_USE_THREADEDGC__
|
||||
{
|
||||
typedef void (*aq_gc_init_t) (Context*);
|
||||
((aq_gc_init_t)dlsym(handle, "__AQ_Init_GC__"))(cxt);
|
||||
}
|
||||
#endif
|
||||
aq_init_gc(handle, cxt);
|
||||
if (procedure_recording) {
|
||||
recorded_libraries.emplace_back(handle);
|
||||
}
|
||||
@@ -474,11 +485,13 @@ start:
|
||||
p.__rt_loaded_modules = static_cast<void**>(
|
||||
malloc(sizeof(void*) * p.postproc_modules));
|
||||
for(uint32_t j = 0; j < p.postproc_modules; ++j){
|
||||
auto pj = dlopen(p.name, RTLD_NOW);
|
||||
auto pj = dlopen((procedure_root + p.name + std::to_string(j) + ".so").c_str(), RTLD_NOW);
|
||||
if (pj == nullptr){
|
||||
printf("Error: failed to load module %s\n", p.name);
|
||||
return true;
|
||||
}
|
||||
aq_init_gc(pj, cxt);
|
||||
|
||||
p.__rt_loaded_modules[j] = pj;
|
||||
}
|
||||
}
|
||||
@@ -503,6 +516,7 @@ start:
|
||||
};
|
||||
const auto& load_proc_fromfile = [&](StoredProcedure& p) {
|
||||
auto config_name = procedure_root + p.name + ".aqp";
|
||||
puts(p.name);
|
||||
auto fp = fopen(config_name.c_str(), "rb");
|
||||
if(fp == nullptr){
|
||||
puts("ERROR: Procedure not found on disk.");
|
||||
@@ -517,14 +531,17 @@ start:
|
||||
|
||||
p.queries = static_cast<char**>(malloc(sizeof(char*) * p.cnt));
|
||||
p.queries[0] = static_cast<char*>(malloc(sizeof(char) * queries_size));
|
||||
fread(&p.queries[0], queries_size, 1, fp);
|
||||
fread(p.queries[0], 1, queries_size, fp);
|
||||
|
||||
for(uint32_t j = 1; j < p.cnt; ++j){
|
||||
p.queries[j] = p.queries[j-1];
|
||||
while(*p.queries[j] != '\0')
|
||||
while(*(p.queries[j]) != '\0')
|
||||
++p.queries[j];
|
||||
++p.queries[j];
|
||||
puts(p.queries[j-1]);
|
||||
}
|
||||
fclose(fp);
|
||||
p.__rt_loaded_modules = 0;
|
||||
return load_modules(p);
|
||||
};
|
||||
switch(n_recvd[i][1]){
|
||||
@@ -553,18 +570,22 @@ start:
|
||||
auto _proc = cxt->stored_proc.find(proc_name);
|
||||
if (_proc == cxt->stored_proc.end()){
|
||||
printf("Procedure %s not found. Trying load from disk.\n", proc_name);
|
||||
if (load_proc_fromfile(current_procedure)){
|
||||
current_procedure.name = copy_lpstr(proc_name);
|
||||
if (!load_proc_fromfile(current_procedure)){
|
||||
cxt->stored_proc.insert_or_assign(proc_name, current_procedure);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else{
|
||||
current_procedure = _proc->second;
|
||||
n_recv = current_procedure.cnt;
|
||||
n_recvd = current_procedure.queries;
|
||||
load_modules(current_procedure);
|
||||
procedure_replaying = true;
|
||||
goto start; // yes, I know, refactor later!!
|
||||
}
|
||||
n_recv = current_procedure.cnt;
|
||||
n_recvd = current_procedure.queries;
|
||||
load_modules(current_procedure);
|
||||
procedure_replaying = true;
|
||||
goto start; // yes, I know, refactor later!!
|
||||
}
|
||||
break;
|
||||
case 'D': // delete procedure
|
||||
@@ -572,6 +593,9 @@ start:
|
||||
case 'S': //save procedure
|
||||
break;
|
||||
case 'L': //load procedure
|
||||
if (!load_proc_fromfile(current_procedure)) {
|
||||
cxt->stored_proc.insert_or_assign(proc_name, current_procedure);
|
||||
}
|
||||
break;
|
||||
case 'd': // display all procedures
|
||||
for(const auto& p : cxt->stored_proc){
|
||||
|
||||
+49
-13
@@ -10,6 +10,7 @@
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include "io.h"
|
||||
#include "hasher.h"
|
||||
|
||||
@@ -35,7 +36,8 @@ struct ColRef_cstorage {
|
||||
int ty; // what if enum is not int?
|
||||
};
|
||||
|
||||
template <template <class...> class VT, class T>
|
||||
template <template <class...> class VT, class T,
|
||||
std::enable_if_t<std::is_base_of_v<vector_base<T>, VT<T>>>* = nullptr>
|
||||
std::ostream& operator<<(std::ostream& os, const VT<T>& v)
|
||||
{
|
||||
v.out();
|
||||
@@ -142,7 +144,7 @@ public:
|
||||
vector_type<_Ty>::operator=(vt);
|
||||
return *this;
|
||||
}
|
||||
ColRef<_Ty>& operator =(ColRef<_Ty>&& vt) {
|
||||
ColRef<_Ty>& operator =(ColRef<_Ty>&& vt) noexcept {
|
||||
vector_type<_Ty>::operator=(std::move(vt));
|
||||
return *this;
|
||||
|
||||
@@ -289,6 +291,7 @@ public:
|
||||
uint32_t len = end - start;
|
||||
return ColView<_Ty>(orig, idxs.subvec(start, end));
|
||||
}
|
||||
|
||||
ColRef<_Ty> subvec_deep(uint32_t start, uint32_t end) const {
|
||||
uint32_t len = end - start;
|
||||
ColRef<_Ty> subvec(len);
|
||||
@@ -329,7 +332,7 @@ template<class ...Types> struct TableInfo;
|
||||
template<class ...Types> struct TableView;
|
||||
|
||||
template <long long _Index, bool order = true, class... _Types>
|
||||
constexpr inline auto& get(const TableInfo<_Types...>& table) noexcept {
|
||||
constexpr auto& get(const TableInfo<_Types...>& table) noexcept {
|
||||
if constexpr (order)
|
||||
return *(ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>> *) & (table.colrefs[_Index]);
|
||||
else
|
||||
@@ -337,7 +340,7 @@ constexpr inline auto& get(const TableInfo<_Types...>& table) noexcept {
|
||||
}
|
||||
|
||||
template <long long _Index, class... _Types>
|
||||
constexpr inline ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>>& get(const TableView<_Types...>& table) noexcept {
|
||||
constexpr ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>>& get(const TableView<_Types...>& table) noexcept {
|
||||
return *(ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>> *) & (table.info.colrefs[_Index]);
|
||||
}
|
||||
|
||||
@@ -348,9 +351,6 @@ struct is_vector_impl<ColView<V>> : std::true_type {};
|
||||
template <class V>
|
||||
struct is_vector_impl<vector_type<V>> : std::true_type {};
|
||||
|
||||
template<class ...Types>
|
||||
struct TableView;
|
||||
|
||||
template<class ...Types>
|
||||
struct TableInfo {
|
||||
const char* name;
|
||||
@@ -459,8 +459,7 @@ struct TableInfo {
|
||||
std::string header_string = std::string();
|
||||
for (uint32_t i = 0; i < sizeof...(Types); ++i)
|
||||
header_string += std::string(this->colrefs[i].name) + sep + '|' + sep;
|
||||
const size_t l_sep = strlen(sep) + 1;
|
||||
if (header_string.size() - l_sep >= 0)
|
||||
if (const size_t l_sep = strlen(sep) + 1; header_string.size() >= l_sep)
|
||||
header_string.resize(header_string.size() - l_sep);
|
||||
header_string += end + std::string(header_string.size(), '=') + end;
|
||||
return header_string;
|
||||
@@ -487,6 +486,7 @@ struct TableInfo {
|
||||
if (header_string.size() - l_sep >= 0)
|
||||
header_string.resize(header_string.size() - l_sep);
|
||||
}
|
||||
|
||||
const auto& prt_loop = [&fp, &view, &printf_string, *this, &limit](const auto& f) {
|
||||
#ifdef __AQ__HAS__INT128__
|
||||
constexpr auto num_hge = count_type<__int128_t, __uint128_t>((tuple_type*)(0));
|
||||
@@ -531,7 +531,7 @@ struct TableInfo {
|
||||
}
|
||||
}
|
||||
template <int ...vals> struct applier {
|
||||
inline constexpr static void apply(const TableInfo<Types...>& t, const char* __restrict sep = ",", const char* __restrict end = "\n",
|
||||
constexpr static void apply(const TableInfo<Types...>& t, const char* __restrict sep = ",", const char* __restrict end = "\n",
|
||||
const vector_type<uint32_t>* __restrict view = nullptr, FILE* __restrict fp = nullptr, uint32_t limit = std::numeric_limits<uint32_t>::max()
|
||||
)
|
||||
{
|
||||
@@ -656,11 +656,11 @@ struct TableView {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr static inline bool is_vector(const ColRef<T>&) {
|
||||
constexpr static bool is_vector(const ColRef<T>&) {
|
||||
return true;
|
||||
}
|
||||
template <class T>
|
||||
constexpr static inline bool is_vector(const vector_type<T>&) {
|
||||
constexpr static bool is_vector(const vector_type<T>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -910,6 +910,42 @@ VT<bool> operator >(const T2& lhs, const VT<T1>& rhs) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define _AQ_OP_(x) __AQ_OP__##x
|
||||
#define __AQ_OP__add +
|
||||
#define __AQ_OP__minus -
|
||||
#define __AQ_OP__div *
|
||||
#define __AQ_OP__mul /
|
||||
#define __AQ_OP__and &
|
||||
#define __AQ_OP__or |
|
||||
#define __AQ_OP__xor ^
|
||||
#define __AQ_OP__gt >
|
||||
#define __AQ_OP__lt <
|
||||
#define __AQ_OP__gte >=
|
||||
#define __AQ_OP__lte <=
|
||||
#define __AQ_OP__eq ==
|
||||
#define __AQ_OP__neq !=
|
||||
|
||||
#define __D_AQOP(x) \
|
||||
template <class T1, class T2, template<typename> class VT, class Ret>\
|
||||
void aqop_##x (const VT<T1>& lhs, const VT<T2>& rhs, Ret& ret){\
|
||||
for (uint32_t i = 0; i < ret.size; ++i)\
|
||||
ret[i] = lhs[i] _AQ_OP_(x) rhs[i];\
|
||||
}
|
||||
|
||||
__D_AQOP(add)
|
||||
__D_AQOP(minus)
|
||||
__D_AQOP(div)
|
||||
__D_AQOP(mul)
|
||||
__D_AQOP(and)
|
||||
__D_AQOP(or)
|
||||
__D_AQOP(xor)
|
||||
__D_AQOP(gt)
|
||||
__D_AQOP(lt)
|
||||
__D_AQOP(gte)
|
||||
__D_AQOP(lte)
|
||||
__D_AQOP(eq)
|
||||
__D_AQOP(neq)
|
||||
|
||||
|
||||
template <class ...Types>
|
||||
void print(const TableInfo<Types...>& v, const char* delimiter = " ", const char* endline = "\n") {
|
||||
@@ -919,6 +955,7 @@ template <class ...Types>
|
||||
void print(const TableView<Types...>& v, const char* delimiter = " ", const char* endline = "\n") {
|
||||
v.print(delimiter, endline);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void print(const T& v, const char* delimiter = " ") {
|
||||
std::cout << v << delimiter;
|
||||
@@ -933,7 +970,6 @@ void print<__uint128_t>(const __uint128_t& v, const char* delimiter);
|
||||
#endif
|
||||
template <>
|
||||
void print<bool>(const bool& v, const char* delimiter);
|
||||
|
||||
template <class T>
|
||||
void inline print_impl(const T& v, const char* delimiter, const char* endline) {
|
||||
for (const auto& vi : v) {
|
||||
|
||||
@@ -13,7 +13,7 @@ long long testing_throughput(uint32_t n_jobs, bool prompt = true){
|
||||
auto tp = ThreadPool(thread::hardware_concurrency());
|
||||
getchar();
|
||||
auto i = 0u;
|
||||
fp = fopen("tmp.tmp", "w");
|
||||
fp = fopen("tmp.tmp", "wb");
|
||||
auto time = chrono::high_resolution_clock::now();
|
||||
while(i++ < n_jobs) tp.enqueue_task({ [](void* f) {fprintf(fp, "%d ", *(int*)f); free(f); }, new int(i) });
|
||||
puts("done dispatching.");
|
||||
@@ -53,7 +53,7 @@ long long testing_transaction(uint32_t n_burst, uint32_t n_batch,
|
||||
}
|
||||
|
||||
long long testing_destruction(bool prompt = true){
|
||||
fp = fopen("tmp.tmp", "w");
|
||||
fp = fopen("tmp.tmp", "wb");
|
||||
if (prompt) {
|
||||
puts("Press any key to start.");
|
||||
getchar();
|
||||
|
||||
+38
-22
@@ -3,6 +3,9 @@
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
using std::size_t;
|
||||
|
||||
#if defined(__SIZEOF_INT128__) and not defined(_WIN32)
|
||||
@@ -13,6 +16,9 @@ using std::size_t;
|
||||
#define __restrict__ __restrict
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
struct vector_base {};
|
||||
|
||||
template <class T>
|
||||
constexpr static inline bool is_vector(const T&) {
|
||||
return false;
|
||||
@@ -32,23 +38,23 @@ struct aqis_same_impl {
|
||||
|
||||
std::conditional_t<
|
||||
std::is_same_v<T1, bool> || std::is_same_v<T2, bool>,
|
||||
std::bool_constant<std::is_same_v<T1, bool> && std::is_same_v<T2, bool>>,
|
||||
Cond(
|
||||
(std::is_same_v<T1, bool> && std::is_same_v<T2, bool>),
|
||||
std::true_type,
|
||||
std::false_type
|
||||
),
|
||||
Cond(
|
||||
std::is_signed_v<T1> == std::is_signed_v<T2>,
|
||||
Cond(
|
||||
std::is_floating_point_v<T1> == std::is_floating_point_v<T2>,
|
||||
Cond(
|
||||
aq_szof<T1> == aq_szof<T2>, // deal with sizeof(void)
|
||||
std::true_type,
|
||||
std::false_type
|
||||
),
|
||||
std::false_type
|
||||
),
|
||||
std::false_type
|
||||
!(std::is_class_v<T1> || std::is_class_v<T2>),
|
||||
Cond(
|
||||
std::is_signed_v<T1> == std::is_signed_v<T2>,
|
||||
Cond(
|
||||
std::is_floating_point_v<T1> == std::is_floating_point_v<T2>,
|
||||
std::bool_constant<aq_szof<T1> == aq_szof<T2>>, // deal with sizeof(void)
|
||||
std::false_type
|
||||
),
|
||||
std::false_type
|
||||
),
|
||||
Cond(
|
||||
(std::is_class_v<T1> && std::is_class_v<T2>),
|
||||
std::bool_constant<(std::is_base_of_v<T1, T2> || std::is_base_of_v<T2, T1>)>,
|
||||
std::false_type
|
||||
)
|
||||
)
|
||||
>::value;
|
||||
};
|
||||
@@ -63,12 +69,12 @@ constexpr bool aqis_same<T1, T2> = aqis_same_impl<T1, T2>::value;
|
||||
namespace types {
|
||||
enum Type_t {
|
||||
AINT32, AFLOAT, ASTR, ADOUBLE, ALDOUBLE, AINT64, AINT128, AINT16, ADATE, ATIME, AINT8,
|
||||
AUINT32, AUINT64, AUINT128, AUINT16, AUINT8, ABOOL, VECTOR, ATIMESTAMP, ACHAR, NONE, ERROR
|
||||
AUINT32, AUINT64, AUINT128, AUINT16, AUINT8, ABOOL, VECTOR, ATIMESTAMP, ACHAR, ASV, NONE, ERROR
|
||||
};
|
||||
static constexpr const char* printf_str[] = { "%d", "%f", "%s", "%lf", "%Lf", "%ld", "%d", "%hi", "%s", "%s", "%hhd",
|
||||
"%u", "%lu", "%s", "%hu", "%hhu", "%s", "%s", "Vector<%s>", "%s", "%c", "NULL", "ERROR" };
|
||||
static constexpr const char* printf_str[] = { "%d", "%f", "%s", "%lf", "%Lf", "%ld", "%s", "%hi", "%s", "%s", "%hhd",
|
||||
"%u", "%lu", "%s", "%hu", "%hhu", "%s", "Vector<%s>", "%s", "%c", "%s", "NULL", "ERROR" };
|
||||
static constexpr const char* SQL_Type[] = { "INT", "REAL", "TEXT", "DOUBLE", "DOUBLE", "BIGINT", "HUGEINT", "SMALLINT", "DATE", "TIME", "TINYINT",
|
||||
"INT", "BIGINT", "HUGEINT", "SMALLINT", "TINYINT", "BOOL", "HUGEINT", "TIMESTAMP", "CHAR", "NULL", "ERROR"};
|
||||
"INT", "BIGINT", "HUGEINT", "SMALLINT", "TINYINT", "BOOL", "HUGEINT", "TIMESTAMP", "CHAR", "TEXT", "NULL", "ERROR"};
|
||||
|
||||
|
||||
// TODO: deal with data/time <=> str/uint conversion
|
||||
@@ -169,6 +175,8 @@ namespace types {
|
||||
f(unsigned short, AUINT16) \
|
||||
f(bool, ABOOL) \
|
||||
f(timestamp_t, ATIMESTAMP) \
|
||||
f(std::string_view, ASV) \
|
||||
f(std::string, ASV) \
|
||||
F_INT128(f)
|
||||
|
||||
inline constexpr static Type_t getType() {
|
||||
@@ -399,7 +407,6 @@ struct transValues_s<lT<vT, T...>, vT, rT> {
|
||||
using type = rT<T...>;
|
||||
};
|
||||
|
||||
#include <utility>
|
||||
template <class vT, int i, template <vT ...> class rT>
|
||||
using transValues = typename transValues_s<std::make_integer_sequence<vT, i>, vT, rT>::type;
|
||||
template <int i, template <int ...> class rT>
|
||||
@@ -427,8 +434,17 @@ template <class ...T>
|
||||
using get_first = typename get_first_impl<T...>::first;
|
||||
template <class T>
|
||||
struct value_type_rec_impl { typedef T type; };
|
||||
|
||||
template <template <class...> class VT, class ...V>
|
||||
struct value_type_rec_impl<VT<V...>> { typedef typename value_type_rec_impl<get_first<V...>>::type type; };
|
||||
struct value_type_rec_impl<VT<V...>> {
|
||||
typedef typename
|
||||
std::conditional_t<
|
||||
std::is_base_of_v<vector_base<get_first<V...>>, VT<V...>>,
|
||||
typename value_type_rec_impl<get_first<V...>>::type,
|
||||
VT<V...>
|
||||
> type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using value_type_r = typename value_type_rec_impl<T>::type;
|
||||
|
||||
|
||||
@@ -1059,15 +1059,13 @@ public:
|
||||
return do_insert_or_assign(std::move(key), std::forward<M>(mapped)).first;
|
||||
}
|
||||
|
||||
template <class K>
|
||||
unsigned hashtable_push(K&& key) {
|
||||
auto it_isinserted = try_emplace(std::forward<K>(key), 1);
|
||||
if (!it_isinserted.second) {
|
||||
++ it_isinserted.first->second;
|
||||
return static_cast<unsigned>(it_isinserted.first - begin());
|
||||
}
|
||||
return static_cast<unsigned>(end() - begin() - 1);
|
||||
}
|
||||
// template <class K>
|
||||
// bool hashtable_push(K&& key) {
|
||||
// auto it_isinserted = try_emplace(std::forward<K>(key), 1);
|
||||
// if (!it_isinserted.second)
|
||||
// ++ it_isinserted.first->second;
|
||||
// return it_isinserted.second;
|
||||
// }
|
||||
|
||||
template <typename K,
|
||||
typename M,
|
||||
@@ -1112,6 +1110,66 @@ public:
|
||||
return {begin() + static_cast<difference_type>(value_idx), true};
|
||||
}
|
||||
|
||||
template <class K,
|
||||
typename Q = T,
|
||||
typename H = Hash,
|
||||
typename KE = KeyEqual>//,
|
||||
//std::enable_if_t<!is_map_v<Q> && is_transparent_v<H, KE>, bool> = true>
|
||||
auto hashtable_push(K&& key) -> unsigned {
|
||||
if (is_full()) {
|
||||
increase_size();
|
||||
}
|
||||
|
||||
auto hash = mixed_hash(key);
|
||||
auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash);
|
||||
auto bucket_idx = bucket_idx_from_hash(hash);
|
||||
|
||||
while (dist_and_fingerprint <= at(m_buckets, bucket_idx).m_dist_and_fingerprint) {
|
||||
if (dist_and_fingerprint == at(m_buckets, bucket_idx).m_dist_and_fingerprint &&
|
||||
m_equal(key, m_values[at(m_buckets, bucket_idx).m_value_idx])) {
|
||||
// found it, return without ever actually creating anything
|
||||
return static_cast<uint32_t>(at(m_buckets, bucket_idx).m_value_idx);
|
||||
}
|
||||
dist_and_fingerprint = dist_inc(dist_and_fingerprint);
|
||||
bucket_idx = next(bucket_idx);
|
||||
}
|
||||
|
||||
// value is new, insert element first, so when exception happens we are in a valid state
|
||||
m_values.emplace_back(std::forward<K>(key));
|
||||
// now place the bucket and shift up until we find an empty spot
|
||||
auto value_idx = static_cast<value_idx_type>(m_values.size() - 1);
|
||||
place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
|
||||
return static_cast<uint32_t>(value_idx);
|
||||
}
|
||||
// template <class... Args>
|
||||
// auto hashtable_push(Args&&... args) -> unsigned {
|
||||
// if (is_full()) {
|
||||
// increase_size();
|
||||
// }
|
||||
|
||||
// // we have to instantiate the value_type to be able to access the key.
|
||||
// // 1. emplace_back the object so it is constructed. 2. If the key is already there, pop it later in the loop.
|
||||
// auto& key = get_key(m_values.emplace_back(std::forward<Args>(args)...));
|
||||
// auto hash = mixed_hash(key);
|
||||
// auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash);
|
||||
// auto bucket_idx = bucket_idx_from_hash(hash);
|
||||
|
||||
// while (dist_and_fingerprint <= at(m_buckets, bucket_idx).m_dist_and_fingerprint) {
|
||||
// if (dist_and_fingerprint == at(m_buckets, bucket_idx).m_dist_and_fingerprint &&
|
||||
// m_equal(key, get_key(m_values[at(m_buckets, bucket_idx).m_value_idx]))) {
|
||||
// m_values.pop_back(); // value was already there, so get rid of it
|
||||
// return static_cast<uint32_t>(at(m_buckets, bucket_idx).m_value_idx);
|
||||
// }
|
||||
// dist_and_fingerprint = dist_inc(dist_and_fingerprint);
|
||||
// bucket_idx = next(bucket_idx);
|
||||
// }
|
||||
|
||||
// // value is new, place the bucket and shift up until we find an empty spot
|
||||
// auto value_idx = static_cast<value_idx_type>(m_values.size() - 1);
|
||||
// place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
|
||||
|
||||
// return static_cast<uint32_t>(value_idx);
|
||||
// }
|
||||
template <class... Args>
|
||||
auto emplace(Args&&... args) -> std::pair<iterator, bool> {
|
||||
if (is_full()) {
|
||||
|
||||
+121
-22
@@ -17,8 +17,6 @@
|
||||
#include "types.h"
|
||||
#include "gc.h"
|
||||
#pragma pack(push, 1)
|
||||
template<class T>
|
||||
struct vector_base {};
|
||||
|
||||
struct vectortype_cstorage{
|
||||
void* container;
|
||||
@@ -32,7 +30,6 @@ public:
|
||||
void inline _copy(const vector_type<_Ty>& vt) {
|
||||
// quick init while using malloc
|
||||
//if (capacity > 0) free(container);
|
||||
|
||||
this->size = vt.size;
|
||||
this->capacity = vt.capacity;
|
||||
if (capacity) {
|
||||
@@ -52,26 +49,33 @@ public:
|
||||
this->container = vt.container;
|
||||
// puts("move");
|
||||
vt.size = vt.capacity = 0;
|
||||
vt.container = 0;
|
||||
vt.container = nullptr;
|
||||
}
|
||||
public:
|
||||
_Ty* container;
|
||||
uint32_t size, capacity;
|
||||
typedef _Ty* iterator_t;
|
||||
typedef std::conditional_t<is_cstr<_Ty>(), astring_view, _Ty> value_t;
|
||||
vector_type(const uint32_t& size) : size(size), capacity(size) {
|
||||
explicit vector_type(const uint32_t& size) : size(size), capacity(size) {
|
||||
if (GC::scratch_space != nullptr) {
|
||||
[[likely]]
|
||||
container = (_Ty*)GC::scratch_space->alloc(size * sizeof(_Ty));
|
||||
}
|
||||
container = (_Ty*)malloc(size * sizeof(_Ty));
|
||||
// TODO: calloc for objects.
|
||||
}
|
||||
constexpr vector_type(std::initializer_list<_Ty> _l) {
|
||||
explicit constexpr vector_type(std::initializer_list<_Ty> _l) {
|
||||
size = capacity = _l.size();
|
||||
_Ty* _container = this->container = (_Ty*)malloc(sizeof(_Ty) * _l.size());
|
||||
this->container = (_Ty*)malloc(sizeof(_Ty) * capacity);
|
||||
_Ty* _container = this->container;
|
||||
for (const auto& l : _l) {
|
||||
*(_container++) = l;
|
||||
}
|
||||
}
|
||||
constexpr vector_type() noexcept : size(0), capacity(0), container(0) {};
|
||||
constexpr vector_type(_Ty* container, uint32_t len) noexcept : size(len), capacity(0), container(container) {};
|
||||
constexpr vector_type(const char** container, uint32_t len,
|
||||
typename std::enable_if_t<!std::is_same_v<_Ty, const char*>>* = nullptr) noexcept = delete;
|
||||
constexpr explicit vector_type(const vector_type<_Ty>& vt) noexcept : capacity(0) {
|
||||
_copy(vt);
|
||||
}
|
||||
@@ -81,8 +85,9 @@ public:
|
||||
constexpr vector_type(vector_type<_Ty>&& vt) noexcept : capacity(0) {
|
||||
_move(std::move(vt));
|
||||
}
|
||||
vector_type(vectortype_cstorage vt) noexcept : capacity(vt.capacity), size(vt.size), container((_Ty*)vt.container) {
|
||||
out(10);
|
||||
explicit vector_type(vectortype_cstorage vt) noexcept :
|
||||
capacity(vt.capacity), size(vt.size), container((_Ty*)vt.container) {
|
||||
// out(10);
|
||||
};
|
||||
// size >= capacity ==> readonly vector
|
||||
constexpr vector_type(const uint32_t size, void* data) :
|
||||
@@ -188,15 +193,15 @@ public:
|
||||
grow<false>(sz);
|
||||
}
|
||||
|
||||
void emplace_back(const _Ty& _val) {
|
||||
inline void emplace_back(const _Ty& _val) {
|
||||
grow();
|
||||
container[size++] = _val;
|
||||
}
|
||||
void emplace_back(_Ty& _val) {
|
||||
inline void emplace_back(_Ty& _val) {
|
||||
grow();
|
||||
container[size++] = std::move(_val);
|
||||
}
|
||||
void emplace_back(_Ty&& _val) {
|
||||
inline void emplace_back(_Ty&& _val) {
|
||||
grow();
|
||||
container[size++] = std::move(_val);
|
||||
}
|
||||
@@ -213,10 +218,10 @@ public:
|
||||
return _it;
|
||||
}
|
||||
|
||||
iterator_t begin() const {
|
||||
inline iterator_t begin() const {
|
||||
return container;
|
||||
}
|
||||
iterator_t end() const {
|
||||
inline iterator_t end() const {
|
||||
return container + size;
|
||||
}
|
||||
|
||||
@@ -230,7 +235,7 @@ public:
|
||||
return container[_i];
|
||||
}
|
||||
|
||||
void shrink_to_fit() {
|
||||
inline void shrink_to_fit() {
|
||||
if (size && capacity != size) {
|
||||
capacity = size;
|
||||
_Ty* _container = (_Ty*)malloc(sizeof(_Ty) * size);
|
||||
@@ -240,13 +245,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_Ty& back() {
|
||||
inline void clear() {
|
||||
this->size = 0;
|
||||
}
|
||||
|
||||
inline _Ty& back() {
|
||||
return container[size - 1];
|
||||
}
|
||||
void qpop() {
|
||||
inline void qpop() {
|
||||
size = size ? size - 1 : size;
|
||||
}
|
||||
void pop_resize() {
|
||||
inline void pop_resize() {
|
||||
if (size) {
|
||||
--size;
|
||||
if (capacity > (size << 1))
|
||||
@@ -259,7 +268,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
_Ty pop() {
|
||||
inline _Ty pop() {
|
||||
return container[--size];
|
||||
}
|
||||
void merge(vector_type<_Ty>& _other) {
|
||||
@@ -331,7 +340,7 @@ public:
|
||||
inline vector_type<_Ty> subvec_deep(uint32_t start = 0) const { return subvec_deep(start, size); }
|
||||
vector_type<_Ty> getRef() { return vector_type<_Ty>(container, size); }
|
||||
~vector_type() {
|
||||
if (capacity > 0);// GC::gc_handle->reg(container, sizeof(_Ty) * capacity);//free(container);
|
||||
if (capacity > 0) GC::gc_handle->reg(container, sizeof(_Ty) * capacity);//free(container);
|
||||
container = 0; size = capacity = 0;
|
||||
}
|
||||
#define Compare(_op) \
|
||||
@@ -369,7 +378,7 @@ public:
|
||||
#define Ops(o, x) \
|
||||
template<typename T>\
|
||||
vector_type<typename types::Coercion<_Ty, T>::type> operator o (const vector_type<T>& r) const {\
|
||||
/*[[likely]] if (r.size == size) {*/\
|
||||
/*if (r.size == size) { [[likely]] */\
|
||||
return x(r);\
|
||||
/*}*/\
|
||||
}
|
||||
@@ -377,7 +386,7 @@ public:
|
||||
#define Opseq(o, x) \
|
||||
template<typename T>\
|
||||
vector_type<typename types::Coercion<_Ty, T>::type> operator o##= (const vector_type<T>& r) {\
|
||||
/*[[likely]] if (r.size == size) {*/\
|
||||
/*if (r.size == size) { [[likely]] */\
|
||||
return x##eq(r);\
|
||||
/*}*/\
|
||||
}
|
||||
@@ -395,6 +404,52 @@ public:
|
||||
_Make_Ops(Opseq)
|
||||
};
|
||||
|
||||
template <>
|
||||
constexpr vector_type<std::string_view>::vector_type(const char** container, uint32_t len,
|
||||
typename std::enable_if_t<true>*) noexcept
|
||||
{
|
||||
size = capacity = len;
|
||||
this->container = static_cast<std::string_view*>(
|
||||
malloc(sizeof(std::string_view) * len));
|
||||
for(uint32_t i = 0; i < len; ++i){
|
||||
this->container[i] = container[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr vector_type<std::string_view>::vector_type(const uint32_t size, void* data) :
|
||||
size(size), capacity(0) {
|
||||
this->container = static_cast<std::string_view*>(
|
||||
malloc(sizeof(std::string_view) * size));
|
||||
for(uint32_t i = 0; i < size; ++i){
|
||||
this->container[i] = ((const char**)data)[i];
|
||||
}
|
||||
//std::cout<<size << container[1];
|
||||
}
|
||||
|
||||
// template<>
|
||||
// void vector_type<std::string_view>::init_from(const uint32_t size, void* data) {
|
||||
// this->size = this->capacity = size;
|
||||
// this->container = static_cast<std::string_view*>(
|
||||
// malloc(sizeof(std::string_view) * size));
|
||||
// for(uint32_t i = 0; i < size; ++i){
|
||||
// this->container[i] = container[i];
|
||||
// }
|
||||
// }
|
||||
|
||||
// template<template <typename> class VT>
|
||||
// inline void
|
||||
// prealloc_vector (VT &vt, uint32_t sz) {
|
||||
// vt.reserve(sz);
|
||||
// }
|
||||
|
||||
// template<class T>
|
||||
// inline void
|
||||
// prealloc_vector (vector_type<vector_type<T>> &vt,
|
||||
// uint32_t outer_sz, uint32_t inner_sz) {
|
||||
// vt.reserve(outer_sz);
|
||||
// auto mem = static_cast<T*>(malloc(inner_sz * sizeof(T)));
|
||||
// }
|
||||
|
||||
template <>
|
||||
class vector_type<void> {
|
||||
@@ -428,4 +483,48 @@ public:
|
||||
vector_type<void> subvec_deep(uint32_t);
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
template <class Key, class Hash>
|
||||
class AQHashTable : public ankerl::unordered_dense::set<Key, Hash> {
|
||||
public:
|
||||
uint32_t* reversemap, *mapbase, *ht_base;
|
||||
AQHashTable() = default;
|
||||
explicit AQHashTable(uint32_t sz)
|
||||
: ankerl::unordered_dense::set<Key, Hash>{} {
|
||||
this->reserve(sz);
|
||||
reversemap = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * sz * 2));
|
||||
mapbase = reversemap + sz;
|
||||
ht_base = static_cast<uint32_t *>(calloc(sz, sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
void init(uint32_t sz) {
|
||||
ankerl::unordered_dense::set<Key, Hash>::reserve(sz);
|
||||
reversemap = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * sz * 2));
|
||||
mapbase = reversemap + sz;
|
||||
ht_base = static_cast<uint32_t *>(calloc(sz, sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
inline void hashtable_push(Key&& k, uint32_t i){
|
||||
reversemap[i] = ankerl::unordered_dense::set<Key, Hash>::hashtable_push(std::move(k));
|
||||
++ht_base[reversemap[i]];
|
||||
}
|
||||
|
||||
auto ht_postproc(uint32_t sz) {
|
||||
auto& arr_values = this->values();
|
||||
const auto& len = this->size();
|
||||
|
||||
auto vecs = static_cast<vector_type<uint32_t>*>(malloc(sizeof(vector_type<uint32_t>) * len));
|
||||
vecs[0].init_from(ht_base[0], mapbase);
|
||||
for (uint32_t i = 1; i < len; ++i) {
|
||||
vecs[i].init_from(ht_base[i], mapbase + ht_base[i - 1]);
|
||||
ht_base[i] += ht_base[i - 1];
|
||||
}
|
||||
for (uint32_t i = 0; i < sz; ++i) {
|
||||
auto id = reversemap[i];
|
||||
mapbase[--ht_base[id]] = i;
|
||||
}
|
||||
return vecs;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user