#include #include #include "dpf.hpp" #include "dpf/app_flow.hpp" #include "dpf/app_plans.hpp" // A private range count. Each secret value is one comparison key. The // public interval is [lo, hi). The comparison opens to 1 at a query q // when q is strictly above the secret value, so the two endpoints // differ by 1 exactly on lo <= v < hi. The count is the sum of those // bits. The servers never see a value, and the interval is public. // // c++ -std=c++17 -march=native -I include -I thirdparty \ // examples/applications/range_count.cpp namespace { std::uint64_t inside(std::uint8_t value, std::uint8_t lo, std::uint8_t hi) { auto [k0, k1] = dpf::make_dpf(value, dpf::gt(std::uint64_t{1})); const auto above_lo = dpf::reconstruct( dpf::eval_point(dpf::cmp, k0, lo), dpf::eval_point(dpf::cmp, k1, lo)); const auto above_hi = dpf::reconstruct( dpf::eval_point(dpf::cmp, k0, hi), dpf::eval_point(dpf::cmp, k1, hi)); // eval(q) = 1 iff q > value, so eval(hi) - eval(lo) = 1{lo <= value < hi}. return above_hi - above_lo; } } // namespace int main() { constexpr std::uint8_t lo = 10; constexpr std::uint8_t hi = 20; const std::uint8_t values[] = {3, 10, 12, 19, 20, 40}; std::uint64_t count = 0; for (auto v : values) count += inside(v, lo, hi); // 10, 12, and 19. 3 and 40 are outside. 20 is the open end. if (count != 3 || inside(10, lo, hi) != 1 || inside(20, lo, hi) != 0 || inside(9, lo, hi) != 0) { std::cerr << "range count " << count << "\n"; return 1; } { if (int rc = dpf::app::run_measured("range_count", dpf::protocol::range_count_plan(0), 8)) return rc; } std::cout << count << "\n"; return 0; }