diff --git a/Makefile b/Makefile index eea1d1a..022c4d8 100644 --- a/Makefile +++ b/Makefile @@ -13,11 +13,11 @@ info: $(info $(OS)) $(info "test") server.bin: - $(CXX) server/server.cpp $(OS_SUPPORT) --std=c++1z -O3 -march=native -o server.bin + $(CXX) server/server.cpp server/io.cpp server/table.cpp $(OS_SUPPORT) -flto --std=c++1z -O3 -march=native -o server.bin server.so: # $(CXX) server/server.cpp server/monetdb_conn.cpp -fPIC -shared $(OS_SUPPORT) monetdb/msvc/monetdbe.dll --std=c++1z -O3 -march=native -o server.so -I./monetdb/msvc - $(CXX) -shared -fPIC server/server.cpp $(OS_SUPPORT) server/monetdb_conn.cpp $(MonetDB_LIB) --std=c++1z -o server.so -O3 + $(CXX) -shared -fPIC -flto server/server.cpp server/io.cpp server/table.cpp $(OS_SUPPORT) server/monetdb_conn.cpp $(MonetDB_LIB) --std=c++1z -o server.so -O3 snippet: - $(CXX) -shared -fPIC --std=c++1z out.cpp server/monetdb_conn.cpp $(MonetDB_LIB) -O3 -march=native -o dll.so + $(CXX) -shared -fPIC -flto --std=c++1z out.cpp server/monetdb_conn.cpp server/table.cpp server/io.cpp $(MonetDB_LIB) -O3 -march=native -o dll.so clean: rm *.shm -rf diff --git a/aquery_config.py b/aquery_config.py index 60d6773..1992699 100644 --- a/aquery_config.py +++ b/aquery_config.py @@ -4,8 +4,9 @@ import os # os.environ['CXX'] = 'C:/Program Files/LLVM/bin/clang.exe' add_path_to_ldpath = True -rebuild_backend = False -run_backend = False +rebuild_backend = True +run_backend = True +have_hge = False os_platform = 'unkown' diff --git a/engine/types.py b/engine/types.py index 6f213e4..4bb71cf 100644 --- a/engine/types.py +++ b/engine/types.py @@ -1,4 +1,5 @@ from engine.utils import defval +from aquery_config import have_hge from typing import Dict, List type_table: Dict[str, "Types"] = {} @@ -75,6 +76,8 @@ LazyT = Types(240, name = 'Lazy', cname = '', sqlname = '', ctype_name = '') DoubleT = Types(17, name = 'double', cname='double', sqlname = 'DOUBLE', is_fp = True) FloatT = Types(16, name = 'float', cname = 'float', sqlname = 'REAL', long_type = DoubleT, is_fp = True) +HgeT = Types(9, name = 'int128',cname='__int128_t', sqlname = 'HUGEINT', fp_type = DoubleT) +UHgeT = Types(10, name = 'uint128', cname='__uint128_t', sqlname = 'HUGEINT', fp_type = DoubleT) LongT = Types(4, name = 'int64', sqlname = 'BIGINT', fp_type = DoubleT) ByteT = Types(1, name = 'int8', sqlname = 'TINYINT', long_type=LongT, fp_type=FloatT) ShortT = Types(2, name = 'int16', sqlname='SMALLINT', long_type=LongT, fp_type=FloatT) @@ -167,7 +170,7 @@ def binary_op_behavior(op:OperatorBase, c_code, x, y): def unary_op_behavior(op:OperatorBase, c_code, x): name = op.cname if c_code else op.sqlname - return f'({x} {name})' + return f'({name} {x})' def fn_behavior(op:OperatorBase, c_code, *x): name = op.cname if c_code else op.sqlname diff --git a/out.cpp b/out.cpp index 22b8a1a..afc14ae 100644 --- a/out.cpp +++ b/out.cpp @@ -1,31 +1,17 @@ -#include "./server/aggregations.h" #include "./udf.hpp" -#include "./server/hasher.h" -#include #include "./server/monetdb_conn.h" +#include "./server/aggregations.h" #include "./server/libaquery.h" extern "C" int __DLLEXPORT__ dllmain(Context* cxt) { using namespace std; using namespace types; auto server = static_cast(cxt->alt_server); - auto len_4fxytV = server->cnt; -auto b_3pr = ColRef(len_4fxytV, server->getCol(0)); -auto a_65L = ColRef(len_4fxytV, server->getCol(1)); -auto out_2UnEpP = new TableInfo>>("out_2UnEpP"); -auto col_C9QF0Z = out_2UnEpP->get_col<0>(); -for (uint32_t i41 = 0; i41 < t1K4f4I0.size; ++i41){ -g1zdpLFa[forward_as_tuple(t1K4f4I0[i41])].emplace_back(i41); -} -for (const auto& i40 : g1zdpLFa){ -auto &len_5NTOM6m = val_2423Z8E.size; -auto &key_6fZPUDS = i4O.first; -auto &val_2423Z8E = i4O.second; -col_C9QF0Z.emplace_back({len_5NTOM6m}); - -covariances2(a_65L[val_2423Z8E], b_3pr[val_2423Z8E], 4, len_5NTOM6m, col_C9QF0Z.back()); - -} -print(*out_2UnEpP); + auto len_6SzLPm = server->cnt; +auto sales_5fe = ColRef(len_6SzLPm, server->getCol(0)); +auto a_yJz = ColRef(len_6SzLPm, server->getCol(1)); +auto out_4UoFb5 = new TableInfo>>("out_4UoFb5"); +out_4UoFb5->get_col<0>() = (sd(a_yJz) + sales_5fe); +print(*out_4UoFb5); return 0; } \ No newline at end of file diff --git a/prompt.py b/prompt.py index 8fcef75..9b60527 100644 --- a/prompt.py +++ b/prompt.py @@ -165,6 +165,7 @@ def init_threaded(): server_so = ctypes.CDLL('./'+server_bin) global cfg, th, send send = server_so['receive_args'] + aquery_config.have_hge = server_so['have_hge']() th = threading.Thread(target=server_so['main'], args=(-1, ctypes.POINTER(ctypes.c_char_p)(cfg.c)), daemon=True) th.start() @@ -256,7 +257,7 @@ while test_parser: sh.interact(banner = 'debugging session began.', exitmsg = 'debugging session ended.') except BaseException as e: # don't care about anything happened in interactive console - print(e.with_traceback()) + print(e) elif q.startswith('log'): qs = re.split(r'[ \t]', q) if len(qs) > 1: diff --git a/reconstruct/ast.py b/reconstruct/ast.py index 1ad03eb..fb9c3b8 100644 --- a/reconstruct/ast.py +++ b/reconstruct/ast.py @@ -80,12 +80,12 @@ class projection(ast_node): # deal with projections self.out_table = TableInfo('out_'+base62uuid(4), [], self.context) cols = [] - col_ext : Set[ColRef]= set() + self.col_ext : Set[ColRef]= set() col_exprs : List[Tuple[str, Types]] = [] proj_map : Dict[int, List[Union[Types, int, str, expr]]]= dict() - var_table = dict() - self.sp_refs = set() + self.var_table = dict() + # self.sp_refs = set() for i, proj in enumerate(self.projections): compound = False self.datasource.rec = set() @@ -101,21 +101,20 @@ class projection(ast_node): if not proj_expr.is_special: y = lambda x:x name = eval('f\'' + name + '\'') - if name not in var_table: - var_table[name] = len(col_exprs) + if name not in self.var_table: + self.var_table[name] = len(col_exprs) proj_map[i] = [this_type, len(col_exprs), proj_expr] col_exprs.append((name, proj_expr.type)) else: self.context.headers.add('"./server/aggregations.h"') if self.datasource.rec is not None: - col_ext = col_ext.union(self.datasource.rec) # TODO: make this one var? - self.sp_refs = self.sp_refs.union(self.datasource.rec) + self.col_ext = self.col_ext.union(self.datasource.rec) proj_map[i] = [this_type, proj_expr.sql, proj_expr] if 'name' in proj: # renaming column by AS keyword name += ' AS ' + proj['name'] if not proj_expr.is_special: - var_table[proj['name']] = len(col_exprs) + self.var_table[proj['name']] = len(col_exprs) disp_name = get_legal_name(name) @@ -126,26 +125,30 @@ class projection(ast_node): self.datasource.rec = None # TODO: Type deduction in Python cols.append(ColRef(this_type, self.out_table, None, disp_name, i, compound=compound)) - col_ext = [c for c in col_ext if c.name not in var_table] # remove duplicates in var_table - col_ext_names = [c.name for c in col_ext] + + if 'groupby' in node: + self.group_node = groupby(self, node['groupby']) + else: + self.group_node = None + + self.col_ext = [c for c in self.col_ext if c.name not in self.var_table] # remove duplicates in self.var_table + col_ext_names = [c.name for c in self.col_ext] self.add(', '.join([c[0] for c in col_exprs] + col_ext_names)) _base_offset = len(col_exprs) for i, col in enumerate(col_ext_names): - if col not in var_table: - var_table[col] = i + _base_offset + if col not in self.var_table: + self.var_table[col] = i + _base_offset def finialize(astnode:ast_node): if(astnode is not None): self.add(astnode.sql) - self.add('FROM') + self.add('FROM') finialize(self.datasource) finialize(self.where) - if 'groupby' in node: - self.group_node = groupby(self, node['groupby']) - else: - self.group_node = None + finialize(self.group_node) + if 'orderby' in node: self.add(orderby(self, node['orderby']).sql) if 'outfile' in node: @@ -160,15 +163,15 @@ class projection(ast_node): # cpp module codegen self.context.has_dll = True # extract typed-columns from result-set - vid2cname = [0]*len(var_table) - pyname2cname = dict() - typenames = [c[1] for c in col_exprs] + [c.type for c in col_ext] + vid2cname = [0]*len(self.var_table) + self.pyname2cname = dict() + typenames = [c[1] for c in col_exprs] + [c.type for c in self.col_ext] length_name = 'len_' + base62uuid(6) self.context.emitc(f'auto {length_name} = server->cnt;') - for v, idx in var_table.items(): + for v, idx in self.var_table.items(): vname = get_legal_name(v) + '_' + base62uuid(3) - pyname2cname[v] = vname + self.pyname2cname[v] = vname self.context.emitc(f'auto {vname} = ColRef<{typenames[idx].cname}>({length_name}, server->getCol({idx}));') vid2cname[idx] = vname # Create table into context @@ -178,14 +181,18 @@ class projection(ast_node): for key, val in proj_map.items(): if type(val[1]) is str: x = True - y = lambda t: pyname2cname[t] + y = lambda t: self.pyname2cname[t] val[1] = val[2].eval(x, y, gettype=True) if callable(val[1]): val[1] = val[1](True) decltypestring = val[1] if val[0] == LazyT: - out_typenames[key] = f'value_type>' + decltypestring = f'value_type>' + if type(val[2].udf) is udf and val[2].udf.return_pattern == udf.ReturnPattern.elemental_return: + out_typenames[key] = f'ColRef<{decltypestring}>' + else: + out_typenames[key] = decltypestring else: out_typenames[key] = val[0].cname @@ -193,13 +200,13 @@ class projection(ast_node): self.context.emitc(f'auto {outtable_name} = new TableInfo<{",".join(out_typenames)}>("{outtable_name}");') # TODO: Inject custom group by code here and flag them in proj_map # Type of UDFs? Complex UDFs, ones with static vars? - if self.group_node is not None: - gb_vartable : Dict[str, Union[str, int]] = deepcopy(pyname2cname) + if self.group_node is not None and self.group_node.use_sp_gb: + gb_vartable : Dict[str, Union[str, int]] = deepcopy(self.pyname2cname) gb_cexprs : List[str] = [] for key, val in proj_map.items(): col_name = 'col_' + base62uuid(6) - self.context.emitc(f'auto {col_name} = {outtable_name}->get_col<{key}>();') + self.context.emitc(f'decltype(auto) {col_name} = {outtable_name}->get_col<{key}>();') gb_cexprs.append((col_name, val[2])) self.group_node.finalize(gb_cexprs, gb_vartable) else: @@ -231,6 +238,17 @@ class orderby(ast_node): class scan(ast_node): + class Position(Enum): + init = auto() + front = auto() + body = auto() + back = auto() + fin = auto() + # TODO: use this for positions for scanner + class LoopStyle(Enum): + forloop = auto() + foreach = auto() + name = 'scan' def __init__(self, parent: "ast_node", node, loop_style = 'for', context: Context = None, const = False): self.const = "const " if const else "" @@ -253,7 +271,7 @@ class scan(ast_node): def produce(self, node): if self.loop_style == 'for_each': self.colref = node - self.start += f'for ({self.const}auto& {self.it_ver} : {node.cobj}) {{\n' + self.start += f'for ({self.const}auto& {self.it_ver} : {node}) {{\n' else: self.start += f"for (uint32_t {self.it_ver} = 0; {self.it_ver} < {node}; ++{self.it_ver}){{\n" @@ -270,7 +288,9 @@ class scan(ast_node): class groupby_c(ast_node): name = '_groupby' - + def init(self, _): + self.proj : projection = self.parent + return super().init(_) def produce(self, node : List[Tuple[expr, Set[ColRef]]]): self.context.headers.add('"./server/hasher.h"') self.context.headers.add('unordered_map') @@ -285,19 +305,19 @@ class groupby_c(ast_node): first_col = '' for g in node: - e = g[0] - g_str = e.eval(c_code = True) + e = expr(self, g[0].node, c_code=True) + g_str = e.eval(c_code = True, y = lambda c: self.proj.pyname2cname[c]) # if v is compound expr, create tmp cols if e.is_ColExpr: tmpcol = 't' + base62uuid(7) - self.emit(f'auto {tmpcol} = {g_str};') + self.context.emitc(f'auto {tmpcol} = {g_str};') e = tmpcol g_contents_list.append(e) first_col = g_contents_list[0] - g_contents_decltype = [f'decays' for c in g_contents_list] + g_contents_decltype = [f'decays' for c in g_contents_list] g_contents = ','.join(g_contents_list) - self.emit(f'typedef record<{",".join(g_contents_decltype)}> {self.group_type};') - self.emit(f'unordered_map<{self.group_type}, vector_type, ' + self.context.emitc(f'typedef record<{",".join(g_contents_decltype)}> {self.group_type};') + self.context.emitc(f'unordered_map<{self.group_type}, vector_type, ' f'transTypes<{self.group_type}, hasher>> {self.group};') self.n_grps = len(node) self.scanner = scan(self, first_col + '.size') @@ -314,12 +334,12 @@ class groupby_c(ast_node): # gscanner.finalize() def finalize(self, cexprs : List[Tuple[str, expr]], var_table : Dict[str, Union[str, int]]): - gscanner = scan(self, self.group) + gscanner = scan(self, self.group, loop_style = 'for_each') key_var = 'key_'+base62uuid(7) val_var = 'val_'+base62uuid(7) - gscanner.add(f'auto &{key_var} = {gscanner.it_ver}.first;') - gscanner.add(f'auto &{val_var} = {gscanner.it_ver}.second;') + gscanner.add(f'auto &{key_var} = {gscanner.it_ver}.first;', position = 'front') + gscanner.add(f'auto &{val_var} = {gscanner.it_ver}.second;', position = 'front') len_var = None def define_len_var(): nonlocal len_var @@ -356,29 +376,22 @@ class groupby_c(ast_node): class groupby(ast_node): name = 'group by' - @property - def use_sp_gb (self): - return len(self.sp_refs) > 0 def produce(self, node): if type(self.parent) is not projection: raise ValueError('groupby can only be used in projection') - sp_refs = self.parent.sp_refs node = enlist(node) o_list = [] - self.dedicated_glist = [] - self.refs : Set[ColRef] = set() - self.sp_refs : Set[ColRef] = set() + self.dedicated_glist : List[Tuple[expr, Set[ColRef]]] = [] + self.use_sp_gb = False for g in node: self.datasource.rec = set() g_expr = expr(self, g['value']) refs : Set[ColRef] = self.datasource.rec self.datasource.rec = None - this_sp_ref = refs.difference(sp_refs) - this_ref = refs.intersection(this_sp_ref) - # TODO: simplify this - self.refs = self.refs.union(this_ref) - self.sp_refs = self.sp_refs.union(this_sp_ref) + if self.parent.col_ext: + this_sp_ref = refs.difference(self.parent.col_ext) + self.use_sp_gb = self.use_sp_gb or len(this_sp_ref) > 0 self.dedicated_glist.append((g_expr, refs)) g_str = g_expr.eval(c_code = False) @@ -389,7 +402,13 @@ class groupby(ast_node): if not self.use_sp_gb: self.dedicated_gb = None self.add(', '.join(o_list)) - + else: + for l in self.dedicated_glist: + # l_exist = l[1].difference(self.parent.col_ext) + # for l in l_exist: + # self.parent.var_table. + self.parent.col_ext.update(l[1]) + def finalize(self, cexprs : List[Tuple[str, expr]], var_table : Dict[str, Union[str, int]]): if self.use_sp_gb: self.dedicated_gb = groupby_c(self.parent, self.dedicated_glist) diff --git a/reconstruct/expr.py b/reconstruct/expr.py index acf8e9f..6c9fcd7 100644 --- a/reconstruct/expr.py +++ b/reconstruct/expr.py @@ -37,7 +37,7 @@ class expr(ast_node): self.codlets : list = [] self.codebuf : Optional[str] = None self._udf_decltypecall = None - + self.node = node self.supress_undefined = supress_undefined if(type(parent) is expr): self.inside_agg = parent.inside_agg diff --git a/reconstruct/storage.py b/reconstruct/storage.py index 0d47b37..963a9fa 100644 --- a/reconstruct/storage.py +++ b/reconstruct/storage.py @@ -100,6 +100,7 @@ class Context: self.print = print self.has_dll = False self.dialect = 'MonetDB' + self.have_hge = False self.new() diff --git a/server/io.cpp b/server/io.cpp new file mode 100644 index 0000000..b05907f --- /dev/null +++ b/server/io.cpp @@ -0,0 +1,11 @@ +#include "io.h" + +char* gbuf = 0; + +void setgbuf(char* buf){ + static char* b = 0; + if (buf == 0) + gbuf = b; + else + gbuf = buf; +} \ No newline at end of file diff --git a/server/io.h b/server/io.h index 43be108..4f7e01a 100644 --- a/server/io.h +++ b/server/io.h @@ -2,6 +2,7 @@ #include "types.h" #include #include +#include template std::string generate_printf_string(const char* sep = " ", const char* end = "\n") { std::string str; @@ -13,3 +14,51 @@ std::string generate_printf_string(const char* sep = " ", const char* end = "\n" return str; } +#ifdef __SIZEOF_INT128__ +inline const char* get_int128str(__int128_t v, char* buf){ + bool neg = false; + if (v < 0) { + if(v == std::numeric_limits<__int128_t>::min()) + return "-170141183460469231731687303715884105728"; + v = -v; + neg = true; + } + do { + *--buf = v%10 + '0'; + v /= 10; + } while(v); + if (neg) *--buf = '-'; + return buf; +} + +inline const char* get_uint128str(__uint128_t v, char* buf){ + do { + *--buf = v%10 + '0'; + v /= 10; + } while(v); + return buf; +} +extern char* gbuf; + +void setgbuf(char* buf = 0); + +template +inline decltype(auto) printi128(const T& v){ + return v; +} + +template<> +inline decltype(auto) printi128<__int128_t>(const __int128_t& v) { + *(gbuf+=40) = 0; + return get_int128str(v, gbuf++); +} + +template<> +inline decltype(auto) printi128<__uint128_t>(const __uint128_t& v) { + *(gbuf+=40) = 0; + return get_uint128str(v, gbuf++); +} + +#else +#define printi128(x) x +#endif diff --git a/server/libaquery.h b/server/libaquery.h index 263c6b9..e3f8af7 100644 --- a/server/libaquery.h +++ b/server/libaquery.h @@ -48,9 +48,10 @@ struct Context{ }; #ifdef _WIN32 -#define __DLLEXPORT__ __declspec(dllexport) __stdcall +#define __DLLEXPORT__ __declspec(dllexport) __stdcall #else #define __DLLEXPORT__ #endif +#define __AQEXPORT__(_Ty) extern "C" _Ty __DLLEXPORT__ #endif \ No newline at end of file diff --git a/server/monetdb_conn.h b/server/monetdb_conn.h index bfc0ead..c543437 100644 --- a/server/monetdb_conn.h +++ b/server/monetdb_conn.h @@ -24,4 +24,4 @@ struct Server{ void *getCol(int col_idx); void close(); ~Server(); -}; \ No newline at end of file +}; diff --git a/server/server.cpp b/server/server.cpp index 9d49d14..9a624aa 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -28,6 +28,7 @@ struct SharedMemory } }; #endif + struct thread_context{ }v; @@ -59,6 +60,15 @@ extern "C" int __DLLEXPORT__ binary_info() { return AppleClang; #endif } + +__AQEXPORT__(bool) have_hge(){ +#if defined(_MONETDBE_LIB_) and defined(HAVE_HGE) + return HAVE_HGE; +#else + return false; +#endif +} + int dll_main(int argc, char** argv, Context* cxt){ Config *cfg = reinterpret_cast(argv[0]); @@ -111,50 +121,50 @@ int dll_main(int argc, char** argv, Context* cxt){ return 0; } -// -//extern "C" int __DLLEXPORT__ main(int argc, char** argv) { -// -// puts("running"); -// Context* cxt = new Context(); -// cxt->log("%d %s\n", argc, argv[1]); -// -// const char* shmname; -// if (argc < 0) -// return dll_main(argc, argv, cxt); -// else if (argc <= 1) -// return test_main(); -// else -// shmname = argv[1]; -// SharedMemory shm = SharedMemory(shmname); -// if (!shm.pData) -// return 1; -// bool &running = static_cast(shm.pData)[0], -// &ready = static_cast(shm.pData)[1]; -// using namespace std::chrono_literals; -// cxt->log("running: %s\n", running? "true":"false"); -// cxt->log("ready: %s\n", ready? "true":"false"); -// while (running) { -// std::this_thread::sleep_for(1ms); -// if(ready){ -// cxt->log("running: %s\n", running? "true":"false"); -// cxt->log("ready: %s\n", ready? "true":"false"); -// void* handle = dlopen("./dll.so", RTLD_LAZY); -// cxt->log("handle: %lx\n", handle); -// if (handle) { -// cxt->log("inner\n"); -// code_snippet c = reinterpret_cast(dlsym(handle, "dllmain")); -// cxt->log("routine: %lx\n", c); -// if (c) { -// cxt->log("inner\n"); -// cxt->err("return: %d\n", c(cxt)); -// } -// } -// ready = false; -// } -// } -// shm.FreeMemoryMap(); -// return 0; -//} + +extern "C" int __DLLEXPORT__ main(int argc, char** argv) { + + puts("running"); + Context* cxt = new Context(); + cxt->log("%d %s\n", argc, argv[1]); + + const char* shmname; + if (argc < 0) + return dll_main(argc, argv, cxt); + else if (argc <= 1) + return test_main(); + else + shmname = argv[1]; + SharedMemory shm = SharedMemory(shmname); + if (!shm.pData) + return 1; + bool &running = static_cast(shm.pData)[0], + &ready = static_cast(shm.pData)[1]; + using namespace std::chrono_literals; + cxt->log("running: %s\n", running? "true":"false"); + cxt->log("ready: %s\n", ready? "true":"false"); + while (running) { + std::this_thread::sleep_for(1ms); + if(ready){ + cxt->log("running: %s\n", running? "true":"false"); + cxt->log("ready: %s\n", ready? "true":"false"); + void* handle = dlopen("./dll.so", RTLD_LAZY); + cxt->log("handle: %lx\n", handle); + if (handle) { + cxt->log("inner\n"); + code_snippet c = reinterpret_cast(dlsym(handle, "dllmain")); + cxt->log("routine: %lx\n", c); + if (c) { + cxt->log("inner\n"); + cxt->err("return: %d\n", c(cxt)); + } + } + ready = false; + } + } + shm.FreeMemoryMap(); + return 0; +} #include "utils.h" int test_main() { @@ -200,6 +210,7 @@ int test_main() dlclose(handle); } //static_assert(std::is_same_v()), std::integer_sequence>, ""); + return 0; std::unordered_map a; } diff --git a/server/table.cpp b/server/table.cpp index c0ab579..2ba2f3d 100644 --- a/server/table.cpp +++ b/server/table.cpp @@ -1 +1,28 @@ #include "table.h" + + +#ifdef __SIZEOF_INT128__ +template <> +void print<__int128_t>(const __int128_t& v, const char* delimiter){ + char s[41]; + s[40] = 0; + std::cout<< get_int128str(v, s+40); +} +template <> +void print<__uint128_t>(const __uint128_t&v, const char* delimiter){ + char s[41]; + s[40] = 0; + std::cout<< get_uint128str(v, s+40); + +} +std::ostream& operator<<(std::ostream& os, __int128 & v) +{ + print(v); + return os; +} +std::ostream& operator<<(std::ostream& os, __uint128_t & v) +{ + print(v); + return os; +} +#endif \ No newline at end of file diff --git a/server/table.h b/server/table.h index cb80da3..8d4fd7d 100644 --- a/server/table.h +++ b/server/table.h @@ -63,14 +63,19 @@ public: using vector_type<_Ty>::operator[]; using vector_type<_Ty>::operator=; using vector_type<_Ty>::subvec; - using vector_type<_Ty>::subvec_view; + using vector_type<_Ty>::subvec_memcpy; using vector_type<_Ty>::subvec_deep; ColView<_Ty> operator [](const vector_type&idxs) const { return ColView<_Ty>(*this, idxs); } void out(uint32_t n = 4, const char* sep = " ") const { - n = n > this->size ? this->size : n; + const char* more = ""; + if (n < this->size) + more = " ... "; + else + n = this->size; + std::cout << '('; if (n > 0) { @@ -79,6 +84,7 @@ public: std::cout << this->operator[](i) << sep; std::cout << this->operator[](i); } + std::cout<< more; std::cout << ')'; } template @@ -90,7 +96,7 @@ class ColView { public: typedef ColRef<_Ty> Decayed_t; const vector_type& idxs; - const ColRef<_Ty>& orig; + const ColRef<_Ty> orig; const uint32_t& size; ColView(const ColRef<_Ty>& orig, const vector_type& idxs) : orig(orig), idxs(idxs), size(idxs.size) {} ColView(const ColView<_Ty>& orig, const vector_type& idxs) : orig(orig.orig), idxs(idxs), size(idxs.size) { @@ -135,6 +141,10 @@ public: ret[i] = orig[idxs[i]]; return ret; } + ColView<_Ty> subvec(uint32_t start, uint32_t end) { + uint32_t len = end - start; + return ColView<_Ty>(orig, idxs.subvec(start, end)); + } ColRef<_Ty> subvec_deep(uint32_t start, uint32_t end) { uint32_t len = end - start; ColRef<_Ty> subvec(len); @@ -142,7 +152,7 @@ public: subvec[i] = operator[](i); return subvec; } - inline ColRef<_Ty> subvec_deep(uint32_t start = 0) { return subvec_deep(start, size); } + inline ColRef<_Ty> subvec(uint32_t start = 0) { return subvec_deep(start, size); } }; template