|
@@ -1,431 +0,0 @@
|
|
|
-/* Copyright (C) 2019 Anonymous
|
|
|
- *
|
|
|
- * This is a pre-release version of the DPF++ library distributed anonymously
|
|
|
- * for peer review. A public release of the software will be published under the
|
|
|
- * LPGL v2.1 license in the near future. Please do not redistribute this version
|
|
|
- * of the software.
|
|
|
- */
|
|
|
-
|
|
|
-// #ifndef DPFPP_DPF_H__
|
|
|
-// #define DPFPP_DPF_H__
|
|
|
-
|
|
|
-// #include <type_traits> // std::is_same<>
|
|
|
-// #include <limits> // std::numeric_limits<>
|
|
|
-// #include <climits> // CHAR_BIT
|
|
|
-// #include <cmath> // std::log2, std::ceil, std::floor
|
|
|
-// #include <stdexcept> // std::runtime_error
|
|
|
-// #include <array> // std::array<>
|
|
|
-// #include <iostream> // std::istream and std::ostream
|
|
|
-// #include <vector> // std::vector<>
|
|
|
-// #include <memory> // std::shared_ptr<>
|
|
|
-// #include <utility> // std::move
|
|
|
-// #include <algorithm> // std::copy
|
|
|
-// #include <cstring> // std::memcpy
|
|
|
-
|
|
|
-// #include <bsd/stdlib.h> // arc4random_buf
|
|
|
-// #include <x86intrin.h> // SSE and AVX intrinsics
|
|
|
-// #include <boost/asio/thread_pool.hpp>
|
|
|
-// #include "bitutils.h"
|
|
|
-// #include "../block.h"
|
|
|
-// #include "prg.h"
|
|
|
-
|
|
|
-// #include "prg_aes_impl.h"
|
|
|
-
|
|
|
-
|
|
|
-// constexpr int L = 0;
|
|
|
-// constexpr int R = 1;
|
|
|
-// const size_t ncores = 16;
|
|
|
-// uint64_t progress[ncores] = {0};
|
|
|
-// namespace dpf
|
|
|
-// {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// template <typename node_t>
|
|
|
-// node_t init_val(uint64_t val);
|
|
|
-// template <> __m128i init_val(uint64_t val) { return _mm_set_epi64x(0, val); }
|
|
|
-// template <> __m256i init_val(uint64_t val) { return _mm256_set_epi64x(0, 0, 0, val); }
|
|
|
-
|
|
|
-
|
|
|
-// // template<typename leaf_t = bool, typename node_t = __m128i, typename prgkey_t = lowmc::lowmc<128,29, 11>>
|
|
|
-// // struct dpf_key;
|
|
|
-// template<typename leaf_t = __m128i, typename node_t = __m128i, typename leaf_type = __m128i, typename prgkey_t = AES_KEY>
|
|
|
-// struct dpf_key;
|
|
|
-// template<typename leaf_t = bool, typename node_t = __m128i, typename prgkey_t = lowmc::bitsliced_lowmc<128,29, 11,256>>
|
|
|
-// struct bitsliced_dpf_key;
|
|
|
-
|
|
|
-
|
|
|
-// using slicerow_t = block<__m256i>;
|
|
|
-// using sliceblock_t = std::array<slicerow_t, 128>;
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline leaf_t eval(const dpf_key <leaf_t, node_t, prgkey_t> & dpfkey, const size_t input);
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline void evalinterval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t from, const size_t to, leaf_t * output, uint8_t * t = NULL);
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline void evalfull(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, leaf_t * output, uint8_t * t = NULL);
|
|
|
-
|
|
|
-// template<typename node_t, typename prgkey_t>
|
|
|
-// static inline void expand(const prgkey_t & prgkey, const node_t & seed, node_t s[2], uint8_t t[2], int lsbmask = 0b11)
|
|
|
-// {
|
|
|
-// dpf::PRG(prgkey, clear_lsb(seed, 0b11), s, 2);
|
|
|
-// t[L] = get_lsb(s[L]);
|
|
|
-// s[L] = clear_lsb(s[L], lsbmask);
|
|
|
-// t[R] = get_lsb(s[R]);
|
|
|
-// s[R] = clear_lsb(s[R], lsbmask);
|
|
|
-// } // dpf::expand
|
|
|
-
|
|
|
-// template<typename node_t, typename prgkey_t>
|
|
|
-// static inline void traverse2(const prgkey_t & prgkey, const node_t & seed,
|
|
|
-// const uint8_t cw_t[2], const node_t & cw, const uint8_t prev_t,
|
|
|
-// node_t s[2], uint8_t t[2], int lsbmask = 0b11)
|
|
|
-// {
|
|
|
-// dpf::PRG(prgkey, clear_lsb(seed, 0b11), s, 2);
|
|
|
-// t[L] = get_lsb(s[L]) ^ (cw_t[L] & prev_t);;
|
|
|
-// s[L] = clear_lsb(xor_if(s[L], cw, !prev_t), lsbmask);
|
|
|
-// t[R] = get_lsb(s[R]) ^ (cw_t[R] & prev_t);;
|
|
|
-// s[R] = clear_lsb(xor_if(s[R], cw, !prev_t), lsbmask);
|
|
|
-// } // dpf::expand
|
|
|
-
|
|
|
-// template<typename node_t, typename prgkey_t>
|
|
|
-// static inline void traverse(const prgkey_t & prgkey, const node_t & seed, const bool direction,
|
|
|
-// const uint8_t cw_t, const node_t & cw, const uint8_t prev_t,
|
|
|
-// node_t & s, uint8_t & t, int lsbmask = 0b11)
|
|
|
-// {
|
|
|
-// dpf::PRG(prgkey, clear_lsb(seed, 0b11), &s, 1, direction);
|
|
|
-// t = get_lsb(s) ^ (cw_t & prev_t);
|
|
|
-// s = clear_lsb(xor_if(s, cw, !prev_t), lsbmask);
|
|
|
-// } // dpf::traverse
|
|
|
-
|
|
|
-// template<typename finalizer_t, typename prgkey_t>
|
|
|
-// static inline void stretch_leaf(const prgkey_t & prgkey, const typename finalizer_t::value_type & seed, finalizer_t & s)
|
|
|
-// {
|
|
|
-// dpf::PRG(prgkey, clear_lsb(seed, 0b11), &s, s.size());
|
|
|
-// } // dpf::stretch_leaf
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename leaf_type, typename prgkey_t>
|
|
|
-// struct dpf_key final
|
|
|
-// {
|
|
|
-// public:
|
|
|
- // static constexpr size_t bits_per_leaf = std::is_same<leaf_t, bool>::value ? 1 : sizeof(leaf_t) * CHAR_BIT;
|
|
|
- // static constexpr bool is_packed = (sizeof(leaf_t) < sizeof(node_t));
|
|
|
- // static constexpr size_t leaves_per_node = dpf_key::is_packed ? sizeof(node_t) * CHAR_BIT / bits_per_leaf : 1;
|
|
|
- // static constexpr size_t nodes_per_leaf = dpf_key::is_packed ? 1 : std::ceil(static_cast<double>(bits_per_leaf) / (sizeof(node_t) * CHAR_BIT));
|
|
|
- // static_assert(leaves_per_node * bits_per_leaf == sizeof(node_t) * CHAR_BIT
|
|
|
- // || nodes_per_leaf * sizeof(node_t) == sizeof(leaf_t));
|
|
|
-
|
|
|
- // using finalizer_t = std::array<node_t, nodes_per_leaf>;
|
|
|
- // typedef std::pair<finalizer_t, finalizer_t> (*finalizer_callback)(const prgkey_t &, const size_t, const leaf_t &, const node_t[2], const uint8_t[2]);
|
|
|
-
|
|
|
- // inline static constexpr size_t depth(const size_t nitems) { return std::ceil(std::log2(std::ceil(static_cast<double>(nitems) / dpf_key::leaves_per_node))); }
|
|
|
- // inline constexpr size_t depth() const { return dpf_key::depth(nitems); }
|
|
|
-
|
|
|
- // inline static constexpr size_t input_bits(const size_t nitems) { return std::ceil(std::log2(nitems)); }
|
|
|
- // inline constexpr size_t input_bits() const { return dpf_key::input_bits(nitems); }
|
|
|
-
|
|
|
- // inline static constexpr size_t nodes_in_interval(const size_t from, const size_t to) { return (to < from) ? 0 : std::max(1.0, std::ceil(static_cast<double>(to+1) / leaves_per_node) - std::floor(static_cast<double>(from) / leaves_per_node)); }
|
|
|
-
|
|
|
- // inline static constexpr size_t interval_bytes(const size_t from, const size_t to) { return nodes_in_interval(from, to) * (is_packed ? sizeof(node_t) : sizeof(leaf_t)); }
|
|
|
- // inline constexpr size_t full_bytes() { return interval_bytes(0, nitems-1); }
|
|
|
-
|
|
|
- // inline static constexpr size_t nodes_at_leaf_layer(const size_t nitems) { return std::ceil(static_cast<double>(nitems) / dpf_key::leaves_per_node); }
|
|
|
- // inline constexpr size_t nodes_at_leaf_layer() const { return dpf_key::nodes_at_leaf_layer(nitems); }
|
|
|
-
|
|
|
- // inline dpf_key(dpf_key &&) = default;
|
|
|
- // inline dpf_key & operator=(dpf_key &&) = default;
|
|
|
- // inline dpf_key(const dpf_key &) = default;
|
|
|
- // inline dpf_key & operator=(const dpf_key &) = default;
|
|
|
-
|
|
|
- // inline bool operator==(const dpf_key & rhs) const { return nitems == rhs.nitems && root == rhs.root && cw == rhs.cw && finalizer == rhs.finalizer; }
|
|
|
- // inline bool operator!=(const dpf_key & rhs) const { return !(*this == rhs); }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // static auto default_make_finalizer(const prgkey_t & prgkey, const size_t target, const leaf_t & val, const node_t s[2], const uint8_t t[2])
|
|
|
- // {
|
|
|
-
|
|
|
- // finalizer_t finalizer;
|
|
|
- // finalizer_t stretched[2];
|
|
|
- // stretch_leaf(prgkey, s[L], stretched[L]);
|
|
|
- // stretch_leaf(prgkey, s[R], stretched[R]);
|
|
|
-
|
|
|
- // if constexpr(dpf_key::is_packed)
|
|
|
- // {
|
|
|
- // auto finalizer0 = reinterpret_cast<node_t *>(&finalizer[0]);
|
|
|
- // if constexpr(std::numeric_limits<leaf_t>::is_integer)
|
|
|
- // {
|
|
|
- // if constexpr(std::is_same<leaf_t, bool>::value)
|
|
|
- // {
|
|
|
- // *finalizer0 = (node_t)init_val<__m128i>(val ? 1 : 0);
|
|
|
- // //*finalizer0 = init_val<node_t>(val ? 1 : 0);
|
|
|
- // }
|
|
|
- // else
|
|
|
- // {
|
|
|
- // typedef typename std::make_unsigned_t<leaf_t> unsigned_leaf_t;
|
|
|
- // *finalizer0 = init_val<node_t>(static_cast<unsigned_leaf_t>(val));
|
|
|
- // }
|
|
|
- // auto tmp = reinterpret_cast<std::bitset<8*sizeof(node_t)> *>(finalizer0);
|
|
|
- // *tmp <<= bits_per_leaf * (target % leaves_per_node);
|
|
|
- // }
|
|
|
- // else
|
|
|
- // {
|
|
|
- // *finalizer0 = val;
|
|
|
- // }
|
|
|
- // }
|
|
|
- // else
|
|
|
- // {
|
|
|
- // std::memcpy(&finalizer[0], &val, sizeof(finalizer_t));
|
|
|
- // }
|
|
|
- // for (size_t j = 0; j < nodes_per_leaf; ++j)
|
|
|
- // {
|
|
|
- // finalizer[j] ^= stretched[L][j] ^ stretched[R][j];
|
|
|
- // }
|
|
|
- // return std::make_pair(finalizer, finalizer);
|
|
|
- // } // dpf_key::default_make_finalizer
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // static auto gen(const prgkey_t & prgkey, size_t nitems, size_t target, const leaf_t & val = 1, const finalizer_callback make_finalizer = default_make_finalizer)
|
|
|
- // {
|
|
|
- // if (nitems <= target)
|
|
|
- // {
|
|
|
- // throw std::runtime_error("target point out of range");
|
|
|
- // }
|
|
|
-
|
|
|
- // node_t root[2];
|
|
|
-
|
|
|
- // srand(1);
|
|
|
- // arc4random_buf(root, sizeof(root));
|
|
|
- // root[0][0] = rand();
|
|
|
- // root[0][1] = rand();
|
|
|
-
|
|
|
-
|
|
|
- // root[1][0] = rand();
|
|
|
- // root[1][1] = rand();
|
|
|
-
|
|
|
-
|
|
|
- // uint8_t t[2] = { get_lsb(root[0]), !t[0] };
|
|
|
- // root[1] = set_lsb(root[1], t[1]);
|
|
|
- // node_t s[2] = { root[0], root[1] };
|
|
|
-
|
|
|
- // const size_t depth = dpf_key::depth(nitems);
|
|
|
- // std::vector<node_t> cw;
|
|
|
- // cw.reserve(depth);
|
|
|
-
|
|
|
- // node_t s0[2], s1[2];
|
|
|
- // uint8_t t0[2], t1[2];
|
|
|
- // const size_t nbits = input_bits(nitems);
|
|
|
- // for (size_t layer = 0; layer < depth; ++layer)
|
|
|
- // {
|
|
|
- // const uint8_t bit = (target >> (nbits - layer - 1)) & 1U;
|
|
|
-
|
|
|
- // expand(prgkey, s[0], s0, t0);
|
|
|
- // expand(prgkey, s[1], s1, t1);
|
|
|
-
|
|
|
- // const uint8_t keep = (bit == 0) ? L : R, lose = 1 - keep;
|
|
|
- // bool cwt[2] = {
|
|
|
- // cwt[L] = t0[L] ^ t1[L] ^ bit ^ 1,
|
|
|
- // cwt[R] = t0[R] ^ t1[R] ^ bit
|
|
|
- // };
|
|
|
- // auto nextcw = s0[lose] ^ s1[lose];
|
|
|
-
|
|
|
- // s[L] = xor_if(s0[keep], nextcw, !t[L]);
|
|
|
- // t[L] = t0[keep] ^ (t[L] & cwt[keep]);
|
|
|
-
|
|
|
- // s[R] = xor_if(s1[keep], nextcw, !t[R]);
|
|
|
- // t[R] = t1[keep] ^ (t[R] & cwt[keep]);
|
|
|
-
|
|
|
- // cw.emplace_back(set_lsbs(nextcw, cwt));
|
|
|
- // }
|
|
|
- // cw.shrink_to_fit();
|
|
|
-
|
|
|
- // auto [finalizer0, finalizer1] = make_finalizer(prgkey, target, val, s, t);
|
|
|
- // return std::make_pair(
|
|
|
- // std::forward<dpf_key>(dpf_key(nitems, root[0], cw, finalizer0, prgkey)),
|
|
|
- // std::forward<dpf_key>(dpf_key(nitems, root[1], cw, finalizer1, prgkey)));
|
|
|
- // } // dpf_key::gen
|
|
|
-
|
|
|
- // inline leaf_t eval(const size_t input) const { return std::forward<leaf_t>(dpf::eval(*this, input)); }
|
|
|
- // inline void evalinterval(const size_t from, const size_t to, leaf_t * output, uint8_t * t = NULL) const { dpf::evalinterval(*this, from, to, output, t); }
|
|
|
- // inline void evalfull(leaf_t * output, uint8_t * t = NULL) const { dpf::evalfull(*this, output, t); }
|
|
|
-
|
|
|
- // const size_t nitems;
|
|
|
- // const node_t root;
|
|
|
- // const std::vector<node_t> cw;
|
|
|
- // const finalizer_t finalizer;
|
|
|
- // const prgkey_t prgkey;
|
|
|
-
|
|
|
- // private:
|
|
|
- // dpf_key(size_t nitems_, const node_t & root_, const std::vector<node_t> cw_,
|
|
|
- // const finalizer_t & finalizer_, const prgkey_t & prgkey_)
|
|
|
- // : nitems(nitems_),
|
|
|
- // root(root_),
|
|
|
- // cw(cw_),
|
|
|
- // finalizer(finalizer_),
|
|
|
- // prgkey(prgkey_) { }
|
|
|
-//}; // struct dpf::dpf_key
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t>
|
|
|
-// inline leaf_t getword(const node_t & S, const size_t input)
|
|
|
-// {
|
|
|
-// auto S_ = reinterpret_cast<const leaf_t *>(&S);
|
|
|
-// if constexpr(sizeof(leaf_t) >= sizeof(node_t)) return *S_;
|
|
|
-
|
|
|
-// return S_[input];
|
|
|
-// } // dpf::getword
|
|
|
-
|
|
|
-// template<>
|
|
|
-// inline bool getword(const __m128i & S, const size_t input)
|
|
|
-// {
|
|
|
-// const __m128i mask = bool128_mask[input / 64];
|
|
|
-// __m128i vcmp = _mm_xor_si128(_mm_and_si128(S >> (input % 64), mask), mask);
|
|
|
-
|
|
|
-// return static_cast<bool>(_mm_testz_si128(vcmp, vcmp));
|
|
|
-// } // dpf::getword<__m128i,bool>
|
|
|
-
|
|
|
-// template<>
|
|
|
-// inline bool getword(const __m256i & S, const size_t input)
|
|
|
-// {
|
|
|
-// const __m256i mask = bool256_mask[input / 64];
|
|
|
-// __m256i vcmp = _mm256_xor_si256(_mm256_and_si256(S >> (input % 64), mask), mask);
|
|
|
-
|
|
|
-// return static_cast<bool>(_mm256_testz_si256(vcmp, vcmp));
|
|
|
-// } // dpf::getword<__m256i,bool>
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline void finalize(const prgkey_t & prgkey, std::array<node_t, dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf> finalizer, leaf_t * output, node_t * s, size_t nnodes, uint8_t * t)
|
|
|
-// {
|
|
|
-// auto output_ = reinterpret_cast<std::array<node_t, dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf> *>(output);
|
|
|
-
|
|
|
-// for (size_t i = 0; i < nnodes; ++i)
|
|
|
-// {
|
|
|
-// stretch_leaf(prgkey, s[i], output_[i]);
|
|
|
-// for (size_t j = 0; j < dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf; ++j)
|
|
|
-// {
|
|
|
-// output_[i][j] = xor_if(output_[i][j], finalizer[j], t[i]);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// } // dpf::finalize
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline void __evalinterval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t from, const size_t to, leaf_t * output, uint8_t * _t)
|
|
|
-// {
|
|
|
-// auto nodes_per_leaf = dpfkey.nodes_per_leaf;
|
|
|
-// auto depth = dpfkey.depth();
|
|
|
-// auto nbits = dpfkey.input_bits();
|
|
|
-// auto nodes_in_interval = dpfkey.nodes_in_interval(from, to);
|
|
|
-// auto root = dpfkey.root;
|
|
|
-// auto prgkey = dpfkey.prgkey;
|
|
|
-
|
|
|
-// const size_t from_node = std::floor(static_cast<double>(from) / nodes_per_leaf);
|
|
|
-
|
|
|
-// node_t * s[2] = {
|
|
|
-// reinterpret_cast<node_t *>(output) + nodes_in_interval * (nodes_per_leaf - 1),
|
|
|
-// s[0] + nodes_in_interval / 2
|
|
|
-// };
|
|
|
-// uint8_t * t[2] = { _t, _t + nodes_in_interval / 2};
|
|
|
-
|
|
|
-// int curlayer = depth % 2;
|
|
|
-
|
|
|
-// s[curlayer][0] = root;
|
|
|
-// t[curlayer][0] = get_lsb(root, 0b01);
|
|
|
-
|
|
|
-// //printf("depth = %u\n", depth);
|
|
|
-
|
|
|
-// for (size_t layer = 0; layer < depth; ++layer)
|
|
|
-// {
|
|
|
-// auto & cw = dpfkey.cw[layer];
|
|
|
-// uint8_t cw_t[2] = { get_lsb(cw, 0b01), get_lsb(cw, 0b10) };
|
|
|
-// curlayer = 1-curlayer;
|
|
|
-
|
|
|
-// size_t i=0, j=0;
|
|
|
-// auto nextbit = (from_node >> (nbits-layer-1)) & 1;
|
|
|
-// size_t nodes_in_prev_layer = std::ceil(static_cast<double>(nodes_in_interval) / (1ULL << (depth-layer)));
|
|
|
-// size_t nodes_in_cur_layer = std::ceil(static_cast<double>(nodes_in_interval) / (1ULL << (depth-layer-1)));
|
|
|
-
|
|
|
-// //printf("nextbit = %u\n", (from_node >> (nbits-layer-1)));
|
|
|
-
|
|
|
-// if (nextbit == 1) traverse(prgkey, s[1-curlayer][0], R, cw_t[R], cw, t[1-curlayer][j], s[curlayer][0], t[curlayer][0]); // these will not be called in evalfull
|
|
|
-// for (i = nextbit, j = nextbit; j < nodes_in_prev_layer-1; ++j, i+=2)
|
|
|
-// {
|
|
|
-// //printf("j = %u\n", j );
|
|
|
-// traverse2(prgkey, s[1-curlayer][j], cw_t, cw, t[1-curlayer][j], &s[curlayer][i], &t[curlayer][i]);
|
|
|
-// }
|
|
|
-// if (nodes_in_prev_layer > j)
|
|
|
-// {
|
|
|
-// //printf("jj' = %u\n", j );
|
|
|
-// if (i < nodes_in_cur_layer - 1)
|
|
|
-// {
|
|
|
-// traverse2(prgkey, s[1-curlayer][j], cw_t, cw, t[1-curlayer][j], &s[curlayer][i], &t[curlayer][i]);
|
|
|
-// //printf("If\n");
|
|
|
-// }
|
|
|
-// else
|
|
|
-// {
|
|
|
-// traverse(prgkey, s[1-curlayer][j], L, cw_t[L], cw, t[1-curlayer][j], s[curlayer][i], t[curlayer][i]); // will not be called in evalfull
|
|
|
-// // printf("else\n");
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// finalize(prgkey, dpfkey.finalizer, output, s[0], nodes_in_interval, t[0]);
|
|
|
-// } // dpf::__evalinterval
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline void evalinterval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t from, const size_t to, leaf_t * output, uint8_t * t)
|
|
|
-// {
|
|
|
-// uint8_t * tt = t ? t : reinterpret_cast<uint8_t *>(malloc(dpfkey.nodes_in_interval(from, to) * sizeof(uint8_t)));
|
|
|
-// __evalinterval(dpfkey, from, to, output, tt);
|
|
|
-// if (!t) free(tt);
|
|
|
-// } // dpf::evalinterval
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline void evalfull(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, leaf_t * output, uint8_t * t)
|
|
|
-// {
|
|
|
-// uint8_t * tt = t ? t : reinterpret_cast<uint8_t *>(malloc(dpfkey.nodes_at_leaf_layer() * sizeof(uint8_t)));
|
|
|
-// __evalinterval(dpfkey, 0, dpfkey.nitems-1, output, tt);
|
|
|
-// if (!t) free(tt);
|
|
|
-// } // dpf::evalfull
|
|
|
-
|
|
|
-// template<typename leaf_t, typename node_t, typename prgkey_t>
|
|
|
-// inline leaf_t eval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t input)
|
|
|
-// {
|
|
|
-// auto prgkey = dpfkey.prgkey;
|
|
|
-// auto root = dpfkey.root;
|
|
|
-// auto depth = dpfkey.depth();
|
|
|
-// auto nbits = dpfkey.input_bits();
|
|
|
-
|
|
|
-// node_t S = root;
|
|
|
-// uint8_t T = get_lsb(root, 0b01);
|
|
|
-
|
|
|
-// for (size_t layer = 0; layer < depth; ++layer)
|
|
|
-// {
|
|
|
-// auto & cw = dpfkey.cw[layer];
|
|
|
-// const uint8_t nextbit = (input >> (nbits-layer-1)) & 1;
|
|
|
-// traverse(prgkey, S, nextbit, get_lsb(cw, nextbit ? 0b10 : 0b01), cw, T, S, T);
|
|
|
-// }
|
|
|
-// std::array<node_t, dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf> final;
|
|
|
-// finalize(prgkey, dpfkey.finalizer, &final, &S, 1, &T);
|
|
|
-
|
|
|
-// if constexpr(dpfkey.is_packed)
|
|
|
-// {
|
|
|
-// auto S_ = reinterpret_cast<node_t *>(&final);
|
|
|
-// return std::forward<leaf_t>(getword<leaf_t>(*S_, input % dpfkey.leaves_per_node));
|
|
|
-// }
|
|
|
-// else
|
|
|
-// {
|
|
|
-// auto ret = reinterpret_cast<leaf_t *>(&final);
|
|
|
-// return *ret;
|
|
|
-// }
|
|
|
-// // } // dpf::eval
|
|
|
-
|
|
|
-// } // namespace dpf
|
|
|
-
|
|
|
-//#endif // DPFPP_DPF_H
|