45#include "catalog/pg_type.h"
46#include "utils/array.h"
47#include "utils/uuid.h"
57#include <unordered_map>
58#include <unordered_set>
69 std::size_t operator()(
const pg_uuid_t &u)
const {
71 std::memcpy(&h, u.
data,
sizeof(h));
76 bool operator()(
const pg_uuid_t &a,
const pg_uuid_t &b)
const {
77 return std::memcmp(a.
data, b.
data, UUID_LEN) == 0;
80using UuidSet = std::unordered_set<pg_uuid_t, UuidHash, UuidEq>;
86 std::vector<pg_uuid_t> wires;
91 const Gate &operator[](
const pg_uuid_t &u) {
92 auto it = memo.find(u);
97 pg_uuid_t *children =
nullptr;
100 g.wires.assign(children, children + n);
103 return memo.emplace(u, std::move(g)).first->second;
106 std::unordered_map<pg_uuid_t, Gate, UuidHash, UuidEq> memo;
112void collect_group_tokens(Gates &gates,
const pg_uuid_t &g,
113 UuidSet &out, UuidSet &seen)
115 if(!seen.insert(g).second)
118 const Gate &gate = gates[g];
122 const Gate &sm = gates[ch];
125 if(sm.wires.size() == 2)
126 out.insert(sm.wires[0]);
137 const std::vector<pg_uuid_t> wires = gate.wires;
139 collect_group_tokens(gates, ch, out, seen);
144bool delta_subsumed_by(Gates &gates,
const pg_uuid_t &g,
const UuidSet &group)
146 const Gate &d = gates[g];
149 if(d.wires.size() != 1)
155 std::vector<pg_uuid_t> operands;
156 const Gate &c = gates[child];
160 operands.push_back(child);
162 if(operands.size() != group.size())
165 if(group.find(o) == group.end())
174void surviving_factors(Gates &gates,
const pg_uuid_t &g,
const UuidSet &group,
175 std::vector<pg_uuid_t> &out)
177 if(delta_subsumed_by(gates, g, group))
181 const std::vector<pg_uuid_t> wires = gates[g].wires;
183 surviving_factors(gates, ch, group, out);
201 if(PG_ARGISNULL(0) || PG_ARGISNULL(1))
205 ArrayType *arr = PG_GETARG_ARRAYTYPE_P(0);
206 const pg_uuid_t cmp = *DatumGetUUIDP(PG_GETARG_DATUM(1));
211 if(ARR_NDIM(arr) > 1)
212 provsql_error(
"cmp_surviving_factors: tokens must be a 1-D array");
214 deconstruct_array(arr, UUIDOID, 16,
false,
'c', &elems, &nulls, &nelems);
218 collect_group_tokens(gates, cmp, group, seen);
220 std::vector<Datum> kept;
223 for(
int i = 0; i < nelems; ++i) {
226 std::vector<pg_uuid_t> factors;
227 surviving_factors(gates, *DatumGetUUIDP(elems[i]), group, factors);
229 if(!emitted.insert(f).second)
233 kept.push_back(UUIDPGetDatum(p));
238 ArrayType *res = construct_array(kept.data(), (
int) kept.size(),
239 UUIDOID, 16,
false,
'c');
240 PG_RETURN_ARRAYTYPE_P(res);
242 }
catch(
const std::exception &e) {
Datum cmp_surviving_factors(PG_FUNCTION_ARGS)
cmp_surviving_factors(tokens uuid[], cmp uuid) -> uuid[]
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
gate_type provsql_fetch_gate(const pg_uuid_t *token, unsigned *nb_children_out, pg_uuid_t **children_out)
PostgreSQL-callable wrapper for get_gate_type().
Background worker and IPC primitives for mmap-backed circuit storage.
Core types, constants, and utilities shared across ProvSQL.
@ gate_arith
n-ary arithmetic gate over scalar-valued children (info1 holds operator tag)