Annotate noexcept and constexpr with HEDLEY, and add interval containment, ChaCha, and the dyadic range tables.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
875f09fec1
commit
0d8a5a8131
97 changed files with 9212 additions and 1159 deletions
|
|
@ -1,54 +1,114 @@
|
|||
#include <chrono>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
using std::chrono::high_resolution_clock;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::duration;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
/// A sorted point list. `return_output_only_tag_` stores one share per point.
|
||||
/// A `sequence_recipe` compiled from that list is reusable across keys.
|
||||
int main()
|
||||
{
|
||||
using input_type = uint8_t;
|
||||
using prg = dpf::prg::counter_wrapper<dpf::prg::dummy>;
|
||||
const std::uint8_t alpha = 42;
|
||||
const std::uint64_t beta = 7;
|
||||
auto [k0, k1] = dpf::make_dpf(alpha, beta);
|
||||
using key_t = dpf::unwrap_party_key_t<std::decay_t<decltype(k0)>>;
|
||||
|
||||
constexpr int N = 50;
|
||||
std::array<input_type, N> keys{};
|
||||
for(int i=0; i<N; i++) keys[i] = i; // Create an array of keys
|
||||
//! [eval-sequence]
|
||||
// Nondecreasing. An unsorted range throws std::runtime_error.
|
||||
std::array<std::uint8_t, 5> points{1, 7, 42, 100, 200};
|
||||
|
||||
// eval_sequence with recipe
|
||||
input_type x = 42;
|
||||
auto [dpf0, dpf1] = dpf::make_dpf<prg>(x); // First DPF to be able to create the recipe
|
||||
auto t1 = high_resolution_clock::now(); // To measure the time of execution
|
||||
auto before = prg::count(); // To count the number of PRG invocations
|
||||
auto recipe0 = dpf::make_sequence_recipe(dpf0, std::begin(keys), std::end(keys)); // Create a recipe
|
||||
auto recipe1 = dpf::make_sequence_recipe(dpf1, std::begin(keys), std::end(keys)); // Create a recipe
|
||||
for (int i=0; i<N; i++)
|
||||
auto [buf0, iter0] = dpf::eval_sequence(k0, points.begin(), points.end(),
|
||||
dpf::return_output_only_tag_{});
|
||||
auto [buf1, iter1] = dpf::eval_sequence(k1, points.begin(), points.end(),
|
||||
dpf::return_output_only_tag_{});
|
||||
|
||||
auto it0 = std::begin(iter0);
|
||||
auto it1 = std::begin(iter1);
|
||||
for (std::uint8_t x : points)
|
||||
{
|
||||
auto [dpf00, dpf11] = dpf::make_dpf<prg>(i); // Make 50 DPFs
|
||||
dpf::eval_sequence(dpf0, recipe0); // Evaluate the DPFs with the recipe
|
||||
dpf::eval_sequence(dpf1, recipe0); // Evaluate the DPFs with the recipe
|
||||
std::uint64_t got = dpf::reconstruct(*it0, *it1);
|
||||
std::uint64_t expect = (x == alpha) ? beta : 0;
|
||||
if (got != expect)
|
||||
{
|
||||
std::cerr << "eval_sequence\n";
|
||||
return 1;
|
||||
}
|
||||
++it0;
|
||||
++it1;
|
||||
}
|
||||
auto after = prg::count(); // Count the number of PRG invocations
|
||||
std::cout << "dpf::eval_sequence with recipe " << (after-before) << "\n";
|
||||
//! [eval-sequence]
|
||||
|
||||
// eval_sequence without the recipe
|
||||
auto t2 = high_resolution_clock::now();
|
||||
duration<double, std::milli> ms_double = t2 - t1;
|
||||
std::cout << "Time of execution: " << ms_double.count() << "ms\n";
|
||||
auto t3 = high_resolution_clock::now();
|
||||
before = prg::count();
|
||||
for (int i=0; i<N; i++)
|
||||
//! [eval-sequence-recipe]
|
||||
// The recipe is a property of the point list and the key's input type.
|
||||
// Bind the memoizer to this recipe object and pass that same object back.
|
||||
auto recipe = dpf::make_sequence_recipe<key_t>(points.begin(), points.end());
|
||||
auto memo0 = dpf::make_double_space_sequence_memoizer<key_t>(recipe);
|
||||
auto memo1 = dpf::make_double_space_sequence_memoizer<key_t>(recipe);
|
||||
auto sbuf0 = dpf::make_output_buffer_for_recipe_subsequence(k0, recipe,
|
||||
dpf::return_output_only_tag_{});
|
||||
auto sbuf1 = dpf::make_output_buffer_for_recipe_subsequence(k1, recipe,
|
||||
dpf::return_output_only_tag_{});
|
||||
auto seq0 = dpf::eval_sequence(k0, recipe, sbuf0, memo0,
|
||||
dpf::return_output_only_tag_{});
|
||||
auto seq1 = dpf::eval_sequence(k1, recipe, sbuf1, memo1,
|
||||
dpf::return_output_only_tag_{});
|
||||
//! [eval-sequence-recipe]
|
||||
|
||||
// Omitting the memoizer allocates a double-space workspace for that call.
|
||||
seq0 = dpf::eval_sequence(k0, recipe, sbuf0, dpf::return_output_only_tag_{});
|
||||
seq1 = dpf::eval_sequence(k1, recipe, sbuf1, dpf::return_output_only_tag_{});
|
||||
it0 = std::begin(seq0);
|
||||
it1 = std::begin(seq1);
|
||||
for (std::uint8_t x : points)
|
||||
{
|
||||
auto [dpf00, dpf11] = dpf::make_dpf<prg>(i);
|
||||
dpf::eval_sequence(dpf00, std::begin(keys), std::end(keys));
|
||||
dpf::eval_sequence(dpf11, std::begin(keys), std::end(keys));
|
||||
if (dpf::reconstruct(*it0, *it1) != ((x == alpha) ? beta : 0))
|
||||
{
|
||||
std::cerr << "eval_sequence recipe, default memoizer\n";
|
||||
return 1;
|
||||
}
|
||||
++it0;
|
||||
++it1;
|
||||
}
|
||||
after = prg::count();
|
||||
std::cout << "dpf::eval_sequence used " << (after-before) << "\n";
|
||||
auto t4 = high_resolution_clock::now();
|
||||
duration<double, std::milli> ms_double2 = t4 - t3;
|
||||
std::cout << "Time of execution with the memoizers: " << ms_double2.count() << "ms\n";
|
||||
|
||||
seq0 = dpf::eval_sequence(k0, recipe, sbuf0, memo0, dpf::return_output_only_tag_{});
|
||||
seq1 = dpf::eval_sequence(k1, recipe, sbuf1, memo1, dpf::return_output_only_tag_{});
|
||||
|
||||
it0 = std::begin(seq0);
|
||||
it1 = std::begin(seq1);
|
||||
for (std::uint8_t x : points)
|
||||
{
|
||||
std::uint64_t got = dpf::reconstruct(*it0, *it1);
|
||||
std::uint64_t expect = (x == alpha) ? beta : 0;
|
||||
if (got != expect)
|
||||
{
|
||||
std::cerr << "eval_sequence recipe\n";
|
||||
return 1;
|
||||
}
|
||||
++it0;
|
||||
++it1;
|
||||
}
|
||||
|
||||
// Same recipe, same memoizers, same buffers: a second key overwrites them.
|
||||
auto [k0b, k1b] = dpf::make_dpf(std::uint8_t{100}, std::uint64_t{9});
|
||||
seq0 = dpf::eval_sequence(k0b, recipe, sbuf0, memo0, dpf::return_output_only_tag_{});
|
||||
seq1 = dpf::eval_sequence(k1b, recipe, sbuf1, memo1, dpf::return_output_only_tag_{});
|
||||
it0 = std::begin(seq0);
|
||||
it1 = std::begin(seq1);
|
||||
for (std::uint8_t x : points)
|
||||
{
|
||||
std::uint64_t got = dpf::reconstruct(*it0, *it1);
|
||||
std::uint64_t expect = (x == 100) ? 9 : 0;
|
||||
if (got != expect)
|
||||
{
|
||||
std::cerr << "eval_sequence recipe reuse\n";
|
||||
return 1;
|
||||
}
|
||||
++it0;
|
||||
++it1;
|
||||
}
|
||||
|
||||
std::cout << beta << "\n";
|
||||
(void)buf0;
|
||||
(void)buf1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue