123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- /* 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
|