/* * Input.cpp * */ #ifndef PROCESSOR_INPUT_HPP_ #define PROCESSOR_INPUT_HPP_ #include "Input.h" #include "Processor.h" #include "IntInput.h" #include "FixInput.h" #include "FloatInput.h" template InputBase::InputBase(ArithmeticProcessor* proc) : P(0), values_input(0) { if (proc) buffer.setup(&proc->private_input, -1, proc->private_input_filename); } template Input::Input(SubProcessor& proc, MAC_Check& mc) : InputBase(&proc.Proc), proc(&proc), MC(mc), prep(proc.DataF), P(proc.P), shares(proc.P.num_players()) { } template Input::Input(SubProcessor* proc, Player& P) : InputBase(&proc->Proc), proc(proc), MC(proc->MC), prep(proc->DataF), P( proc->P), shares(P.num_players()) { assert (proc != 0); } template Input::Input(MAC_Check& MC, Preprocessing& prep, Player& P) : proc(0), MC(MC), prep(prep), P(P), shares(P.num_players()) { } template InputBase::~InputBase() { #ifdef VERBOSE if (timer.elapsed() > 0) cerr << T::type_string() << " inputs: " << timer.elapsed() << endl; #endif } template void Input::reset(int player) { InputBase::reset(player); shares[player].clear(); } template void InputBase::reset(int player) { os.resize(max(os.size(), player + 1UL)); os[player].reset_write_head(); } template void InputBase::reset_all(Player& P) { this->P = &P; os.resize(P.num_players()); for (int i = 0; i < P.num_players(); i++) reset(i); } template void Input::add_mine(const open_type& input, int n_bits) { (void) n_bits; int player = P.my_num(); shares[player].push_back({}); T& share = shares[player].back(); prep.get_input(share, rr, player); t = input - rr; t.pack(this->os[player]); share += T::constant(t, 0, MC.get_alphai()); this->values_input++; } template void Input::add_other(int player) { open_type t; shares[player].push_back({}); prep.get_input(shares[player].back(), t, player); } template void InputBase::add_from_all(const clear& input) { for (int i = 0; i < P->num_players(); i++) if (i == P->my_num()) add_mine(input); else add_other(i); } template void Input::send_mine() { P.send_all(this->os[P.my_num()], true); } template void InputBase::exchange() { for (int i = 0; i < P->num_players(); i++) if (i == P->my_num()) send_mine(); else P->receive_player(i, os[i], true); } template void Input::start(int player, int n_inputs) { reset(player); if (player == P.my_num()) { for (int i = 0; i < n_inputs; i++) { clear t; try { this->buffer.input(t); } catch (not_enough_to_buffer& e) { throw runtime_error("Insufficient input data to buffer"); } add_mine(t); } send_mine(); } else { for (int i = 0; i < n_inputs; i++) add_other(player); } } template void Input::stop(int player, const vector& targets) { assert(proc != 0); if (P.my_num() == player) for (unsigned int i = 0; i < targets.size(); i++) proc->get_S_ref(targets[i]) = finalize_mine(); else { octetStream o; this->timer.start(); P.receive_player(player, o, true); this->timer.stop(); for (unsigned int i = 0; i < targets.size(); i++) { finalize_other(player, proc->get_S_ref(targets[i]), o); } } } template T Input::finalize_mine() { return shares[P.my_num()].next(); } template void Input::finalize_other(int player, T& target, octetStream& o, int n_bits) { (void) n_bits; target = shares[player].next(); t.unpack(o); target += T::constant(t, 1, MC.get_alphai()); } template T InputBase::finalize(int player, int n_bits) { if (player == P->my_num()) return finalize_mine(); else { T res; finalize_other(player, res, os[player], n_bits); return res; } } template template void InputBase::prepare(SubProcessor& Proc, int player, const int* params, int size) { auto& input = Proc.input; if (player == Proc.P.my_num()) { for (int j = 0; j < size; j++) { U tuple = Proc.Proc.template get_input(Proc.Proc.use_stdin(), params); for (auto x : tuple.items) input.add_mine(x); } } else { for (int j = 0; j < U::N_DEST * size; j++) input.add_other(player); } } template template void InputBase::finalize(SubProcessor& Proc, int player, const int* dest, int size) { auto& input = Proc.input; for (int k = 0; k < size; k++) for (int j = 0; j < U::N_DEST; j++) Proc.get_S_ref(dest[j] + k) = input.finalize(player); } template template void InputBase::input(SubProcessor& Proc, const vector& args, int size) { auto& input = Proc.input; input.reset_all(Proc.P); int n_arg_tuple = U::N_DEST + U::N_PARAM + 1; assert(args.size() % n_arg_tuple == 0); int n_from_me = 0; if (Proc.Proc.use_stdin()) { for (size_t i = n_arg_tuple - 1; i < args.size(); i += n_arg_tuple) n_from_me += (args[i] == Proc.P.my_num()) * size; if (n_from_me > 0) cout << "Please input " << n_from_me << " " << U::NAME << "(s):" << endl; } for (size_t i = U::N_DEST; i < args.size(); i += n_arg_tuple) { int n = args[i + U::N_PARAM]; InputBase::prepare(Proc, n, &args[i], size); } if (n_from_me > 0) cout << "Thank you" << endl; input.exchange(); for (size_t i = 0; i < args.size(); i += n_arg_tuple) { int player = args[i + n_arg_tuple - 1]; finalize(Proc, player, &args[i], size); } } template void InputBase::input_mixed(SubProcessor& Proc, const vector& args, int size) { auto& input = Proc.input; input.reset_all(Proc.P); int last_type = -1; for (size_t i = 0; i < args.size();) { int n_arg_tuple; int type = args[i]; int player; switch (type) { #undef X #define X(U) \ case U::TYPE: \ n_arg_tuple = U::N_DEST + U::N_PARAM + 2; \ player = args[i + n_arg_tuple - 1]; \ if (type != last_type and Proc.Proc.use_stdin()) \ cout << "Please input " << U::NAME << "s:" << endl; \ prepare(Proc, player, &args[i + U::N_DEST + 1], size); \ break; X(IntInput) X(FixInput) X(FloatInput) #undef X default: throw runtime_error("unknown input type: " + to_string(type)); } i += n_arg_tuple; last_type = type; } input.exchange(); for (size_t i = 0; i < args.size();) { int n_arg_tuple; int type = args[i]; switch (type) { #define X(U) \ case U::TYPE: \ n_arg_tuple = U::N_DEST + U::N_PARAM + 2; \ finalize(Proc, args[i + n_arg_tuple - 1], &args[i + 1], size); \ break; X(IntInput) X(FixInput) X(FloatInput) #undef X default: throw runtime_error("unknown input type: " + to_string(type)); } i += n_arg_tuple; } } #endif