updated code generation for compound-columns, initial support for scratchspace
This commit is contained in:
+15
-7
@@ -305,7 +305,7 @@ opor = OperatorBase('or', 2, logical, cname = '||', sqlname = ' OR ', call = bin
|
||||
opxor = OperatorBase('xor', 2, logical, cname = '^', sqlname = ' XOR ', call = binary_op_behavior)
|
||||
opgt = OperatorBase('gt', 2, logical, cname = '>', sqlname = '>', call = binary_op_behavior)
|
||||
oplt = OperatorBase('lt', 2, logical, cname = '<', sqlname = '<', call = binary_op_behavior)
|
||||
opge = OperatorBase('gte', 2, logical, cname = '>=', sqlname = '>=', call = binary_op_behavior)
|
||||
opgte = OperatorBase('gte', 2, logical, cname = '>=', sqlname = '>=', call = binary_op_behavior)
|
||||
oplte = OperatorBase('lte', 2, logical, cname = '<=', sqlname = '<=', call = binary_op_behavior)
|
||||
opneq = OperatorBase('neq', 2, logical, cname = '!=', sqlname = '!=', call = binary_op_behavior)
|
||||
opeq = OperatorBase('eq', 2, logical, cname = '==', sqlname = '=', call = binary_op_behavior)
|
||||
@@ -355,19 +355,27 @@ fnpow = OperatorBase('pow', 2, lambda *_ : DoubleT, cname = 'pow', sqlname = 'PO
|
||||
# type collections
|
||||
def _op_make_dict(*items : OperatorBase):
|
||||
return { i.name: i for i in items}
|
||||
#binary op
|
||||
builtin_binary_arith = _op_make_dict(opadd, opdiv, opmul, opsub, opmod)
|
||||
builtin_binary_logical = _op_make_dict(opand, opor, opxor, opgt, oplt,
|
||||
opge, oplte, opneq, opeq)
|
||||
opgte, oplte, opneq, opeq)
|
||||
builtin_binary_ops = {**builtin_binary_arith, **builtin_binary_logical}
|
||||
#unary op
|
||||
builtin_unary_logical = _op_make_dict(opnot)
|
||||
builtin_unary_arith = _op_make_dict(opneg)
|
||||
builtin_unary_special = _op_make_dict(spnull, opdistinct)
|
||||
# functions
|
||||
builtin_cstdlib = _op_make_dict(fnsqrt, fnlog, fnsin, fncos, fntan, fnpow)
|
||||
builtin_func = _op_make_dict(fnmax, fnmin, fnsum, fnavg, fnmaxs,
|
||||
fnmins, fndeltas, fnratios, fnlast,
|
||||
fnfirst, fnsums, fnavgs, fncnt,
|
||||
fnpack, fntrunc, fnprev, fnnext,
|
||||
fnvar, fnvars, fnstd, fnstds)
|
||||
builtin_aggfunc = _op_make_dict(fnmax, fnmin, fnsum, fnavg,
|
||||
fnlast, fnfirst, fncnt, fnvar, fnstd)
|
||||
builtin_vecfunc = _op_make_dict(fnmaxs,
|
||||
fnmins, fndeltas, fnratios, fnsums, fnavgs,
|
||||
fnpack, fntrunc, fnprev, fnnext, fnvars, fnstds)
|
||||
builtin_vecfunc = {**builtin_vecfunc, **builtin_cstdlib}
|
||||
builtin_func = {**builtin_vecfunc, **builtin_aggfunc}
|
||||
|
||||
user_module_func = {}
|
||||
|
||||
builtin_operators : Dict[str, OperatorBase] = {**builtin_binary_arith, **builtin_binary_logical,
|
||||
**builtin_unary_arith, **builtin_unary_logical, **builtin_unary_special, **builtin_func, **builtin_cstdlib,
|
||||
**user_module_func}
|
||||
|
||||
+5
-7
@@ -604,9 +604,10 @@ class groupby_c(ast_node):
|
||||
self.arr_len = 'arrlen_' + base62uuid(3)
|
||||
self.arr_values = 'arrvals_' + base62uuid(3)
|
||||
|
||||
self.context.emitc(f'auto {self.arr_len} = {self.group}.size();')
|
||||
self.context.emitc(f'auto {self.arr_values} = {self.group}.values();')
|
||||
|
||||
if len(tovec_columns):
|
||||
self.context.emitc(f'auto {self.arr_len} = {self.group}.size();')
|
||||
self.context.emitc(f'auto {self.arr_values} = {self.group}.values();')
|
||||
preproc_scanner = scan(self, self.arr_len)
|
||||
preproc_scanner_it = preproc_scanner.it_var
|
||||
for c in tovec_columns:
|
||||
@@ -674,11 +675,8 @@ class groupby_c(ast_node):
|
||||
gscanner.add(f'{ex.eval(c_code = True, y=get_var_names, materialize_builtin = materialize_builtin)};\n')
|
||||
continue
|
||||
if col_tovec[i]:
|
||||
if ex.opname == 'avgs':
|
||||
patch_expr = get_var_names_ex(ex)
|
||||
patch_expr = patch_expr[:patch_expr.rindex(')')]
|
||||
patch_expr += ', ' + f'{ce[0]}[{gscanner.it_var}]' + ')'
|
||||
gscanner.add(f'{patch_expr};\n')
|
||||
if ex.remake_binary(f'{ce[0]}[{gscanner.it_var}]'):
|
||||
gscanner.add(f'{get_var_names_ex(ex)};\n')
|
||||
else:
|
||||
gscanner.add(f'{ce[0]}[{gscanner.it_var}] = {get_var_names_ex(ex)};\n')
|
||||
else:
|
||||
|
||||
@@ -367,6 +367,19 @@ class expr(ast_node):
|
||||
self.curr_code += c.codegen(delegate)
|
||||
return self.curr_code
|
||||
|
||||
def remake_binary(self, ret_expr):
|
||||
if self.root:
|
||||
self.oldsql = self.sql
|
||||
if (self.opname in builtin_binary_ops):
|
||||
patched_opname = 'aqop_' + self.opname
|
||||
self.sql = (f'{patched_opname}({self.children[0].sql}, '
|
||||
f'{self.children[1].sql}, {ret_expr})')
|
||||
return True
|
||||
elif self.opname in builtin_vecfunc:
|
||||
self.sql = self.sql[:self.sql.rindex(')')]
|
||||
self.sql += ', ' + ret_expr + ')'
|
||||
return True
|
||||
return False
|
||||
def __str__(self):
|
||||
return self.sql
|
||||
def __repr__(self):
|
||||
|
||||
+153
-63
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "gc.h"
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <deque>
|
||||
@@ -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,51 +353,88 @@ 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;
|
||||
}
|
||||
|
||||
@@ -360,8 +452,6 @@ T first(const VT<T>& arr) {
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define __DEFAULT_AGGREGATE_FUNCTION__(NAME, RET) \
|
||||
template <class T> constexpr T NAME(const T& v) { return RET; }
|
||||
|
||||
|
||||
+47
-4
@@ -1,4 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
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__
|
||||
#include <atomic>
|
||||
class GC {
|
||||
@@ -18,7 +53,7 @@ private:;
|
||||
std::atomic<uint64_t> current_size;
|
||||
volatile bool lock;
|
||||
using gc_deallocator_t = void (*)(void*);
|
||||
|
||||
ScratchSpace scratch;
|
||||
// maybe use volatile std::thread::id instead
|
||||
protected:
|
||||
void acquire_lock();
|
||||
@@ -29,28 +64,36 @@ protected:
|
||||
void terminate_daemon();
|
||||
|
||||
public:
|
||||
void reg(void* v, uint32_t sz = 1,
|
||||
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(scratch_sz);
|
||||
} // 256 MB
|
||||
|
||||
~GC(){
|
||||
terminate_daemon();
|
||||
scratch.cleanup();
|
||||
}
|
||||
|
||||
static GC* gc_handle;
|
||||
template <class T>
|
||||
constexpr static inline gc_deallocator_t _delete(T*){
|
||||
static inline gc_deallocator_t _delete(T*) {
|
||||
return [](void* v){
|
||||
delete (T*)v;
|
||||
};
|
||||
|
||||
@@ -452,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;
|
||||
@@ -466,6 +469,71 @@ void GC::reg(void* v, uint32_t sz, void(*f)(void*)) { //~ 40ns expected v. free
|
||||
|
||||
inline GC* GC::gc_handle = 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){
|
||||
this->cnt += sz; // major cost
|
||||
ptr = this->cnt;
|
||||
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;
|
||||
ret = nullptr;
|
||||
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();
|
||||
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"
|
||||
|
||||
|
||||
|
||||
+42
-5
@@ -36,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();
|
||||
@@ -143,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;
|
||||
|
||||
@@ -475,7 +476,7 @@ struct TableInfo {
|
||||
|
||||
std::string printf_string =
|
||||
generate_printf_string<typename std::tuple_element<cols, tuple_type>::type ...>(sep, end);
|
||||
puts(printf_string.c_str());
|
||||
// puts(printf_string.c_str());
|
||||
std::string header_string = std::string();
|
||||
constexpr static int a_cols[] = { cols... };
|
||||
if (fp == nullptr){
|
||||
@@ -659,11 +660,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;
|
||||
}
|
||||
|
||||
@@ -913,6 +914,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") {
|
||||
|
||||
+16
-12
@@ -187,15 +187,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);
|
||||
}
|
||||
@@ -212,10 +212,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;
|
||||
}
|
||||
|
||||
@@ -229,7 +229,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);
|
||||
@@ -239,13 +239,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))
|
||||
@@ -258,7 +262,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
_Ty pop() {
|
||||
inline _Ty pop() {
|
||||
return container[--size];
|
||||
}
|
||||
void merge(vector_type<_Ty>& _other) {
|
||||
@@ -368,7 +372,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);\
|
||||
/*}*/\
|
||||
}
|
||||
@@ -376,7 +380,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);\
|
||||
/*}*/\
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user