heap.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. #include <functional>
  2. #include "types.hpp"
  3. #include "duoram.hpp"
  4. #include "cell.hpp"
  5. #include "rdpf.hpp"
  6. #include "shapes.hpp"
  7. #include "heap.hpp"
  8. // The optimized insertion protocol works as follows
  9. // Do a binary search from the root of the rightmost child
  10. // Binary search returns the index in the path where the new element should go to
  11. // We next do a trickle down.
  12. // Consdier a path P = [a1, a2, a3, a4, ..., a_n]
  13. // Consider a standard-basis vector [0, ... 0, 1 , 0, ... , 0] (at i)
  14. // we get a new path P = [a1, ... , ai,ai ..., a_n]
  15. // P[i] = newelement
  16. int MinHeap::insert_optimized(MPCTIO tio, yield_t & yield, RegAS val) {
  17. auto HeapArray = oram.flat(tio, yield);
  18. num_items++;
  19. //std::cout << "num_items = " << num_items << std::endl;
  20. uint64_t height = std::log2(num_items) + 1;
  21. size_t childindex = num_items;
  22. RegAS zero;
  23. zero.ashare = 0;
  24. HeapArray[childindex] = zero;
  25. typename Duoram<RegAS>::Path P(HeapArray, tio, yield, childindex);
  26. RegXS foundidx = P.binary_search(val);
  27. // std::cout << "height = " << height << std::endl;
  28. RDPF<1> dpf2(tio, yield, foundidx, height, false, false);
  29. RegBS * flags_array = new RegBS[height];
  30. RegBS * standard_basis_vector = new RegBS[height];
  31. for(size_t j = 0; j < height; ++j)
  32. {
  33. if(tio.player() !=2)
  34. {
  35. RDPF<1>::LeafNode tmp = dpf2.leaf(j, tio.aes_ops());
  36. RegBS tmp__ = dpf2.unit_bs(tmp);
  37. flags_array[j] = tmp__;
  38. standard_basis_vector[j] = tmp__;
  39. if(j > 0) flags_array[j] = flags_array[j] ^ flags_array[j-1];
  40. }
  41. }
  42. #ifdef VERBOSE
  43. for(size_t j = 0; j < height; ++j)
  44. {
  45. uint64_t reconstruction = mpc_reconstruct(tio, yield, standard_basis_vector[j], 64);
  46. std::cout << j << " --->> reconstruction [standard_basis_vector] = " << reconstruction << std::endl;
  47. }
  48. #endif
  49. RegAS * z_array2 = new RegAS[height];
  50. RegAS * z2_tmp = new RegAS[height];
  51. RegAS * standard_basis_vector_time_value = new RegAS[height];
  52. for(size_t j = 0; j < height; ++j) z_array2[j] = P[j];
  53. //print_heap(tio, yield);
  54. std::vector<coro_t> coroutines;
  55. for(size_t j = 1; j < height; ++j)
  56. {
  57. coroutines.emplace_back(
  58. [&tio, z2_tmp, flags_array, z_array2, j](yield_t &yield) {
  59. mpc_flagmult(tio, yield, z2_tmp[j], flags_array[j-1], (z_array2[j-1]-z_array2[j]), 64);
  60. });
  61. coroutines.emplace_back(
  62. [&tio, standard_basis_vector_time_value, standard_basis_vector, val, z_array2, j](yield_t &yield) {
  63. mpc_flagmult(tio, yield, standard_basis_vector_time_value[j-1], standard_basis_vector[j-1], (val - z_array2[j-1]) , 64);
  64. });
  65. }
  66. run_coroutines(tio, coroutines);
  67. #ifdef VERBOSE
  68. for(size_t j = 0; j < height; ++j)
  69. {
  70. int64_t reconstruction = mpc_reconstruct(tio, yield, z2_tmp[j], 64);
  71. std::cout << j << " --->> reconstruction [z2_tmp] = " << reconstruction << std::endl;
  72. }
  73. std::cout << std::endl << " =============== " << std::endl;
  74. for(size_t j = 0; j < height; ++j)
  75. {
  76. int64_t reconstruction = mpc_reconstruct(tio, yield, flags_array[j], 64);
  77. std::cout << j << " --->> reconstruction [flags_array] = " << reconstruction << std::endl;
  78. }
  79. std::cout << std::endl << " =============== " << std::endl;
  80. for(size_t j = 0; j < height; ++j)
  81. {
  82. int64_t reconstruction = mpc_reconstruct(tio, yield, standard_basis_vector[j], 64);
  83. std::cout << j << " --->> reconstruction [standard_basis_vector] = " << reconstruction << std::endl;
  84. }
  85. std::cout << std::endl << " =============== " << std::endl;
  86. for(size_t j = 0; j < height; ++j)
  87. {
  88. int64_t reconstruction = mpc_reconstruct(tio, yield, z_array2[j], 64);
  89. std::cout << j << " --->> reconstruction [z_array2] = " << reconstruction << std::endl;
  90. }
  91. #endif
  92. for(size_t j = 0; j < height; ++j) P[j] += (z2_tmp[j] + standard_basis_vector_time_value[j]);
  93. #ifdef VERBOSE
  94. std::cout << std::endl << " =============== " << std::endl;
  95. for(size_t j = 0; j < height; ++j)
  96. {
  97. int64_t reconstruction = mpc_reconstruct(tio, yield, P[j], 64);
  98. std::cout << j << " --->> reconstruction [P] = " << reconstruction << std::endl;
  99. }
  100. print_heap(tio, yield);
  101. #endif
  102. // for(size_t j = 1; j < height; ++j) P[j] += z2_tmp[j];
  103. // typename Duoram<RegAS>::template OblivIndex<RegXS,1> oidx(tio, yield, foundidx, height);
  104. //P[oidx] = val;
  105. return 1;
  106. }
  107. // The insert protocol works as follows:
  108. // It adds a new element in the last entry of the array
  109. // From the leaf (the element added), compare with its parent (1 oblivious compare)
  110. // If the child is larger, then we do an OSWAP.
  111. int MinHeap::insert(MPCTIO tio, yield_t & yield, RegAS val) {
  112. auto HeapArray = oram.flat(tio, yield);
  113. num_items++;
  114. //std::cout << "num_items = " << num_items << std::endl;
  115. // uint64_t val_reconstruct = mpc_reconstruct(tio, yield, val);
  116. // std::cout << "val_reconstruct = " << val_reconstruct << std::endl;
  117. size_t childindex = num_items;
  118. size_t parentindex = childindex / 2;
  119. #ifdef VERBOSE
  120. std::cout << "childindex = " << childindex << std::endl;
  121. std::cout << "parentindex = " << parentindex << std::endl;
  122. #endif
  123. HeapArray[num_items] = val;
  124. typename Duoram<RegAS>::Path P(HeapArray, tio, yield, childindex);
  125. //RegXS foundidx = P.binary_search(val);
  126. while (parentindex > 0) {
  127. RegAS sharechild = HeapArray[childindex];
  128. RegAS shareparent = HeapArray[parentindex];
  129. CDPF cdpf = tio.cdpf(yield);
  130. RegAS diff = sharechild - shareparent;
  131. auto[lt, eq, gt] = cdpf.compare(tio, yield, diff, tio.aes_ops());
  132. auto lteq = lt ^ eq;
  133. mpc_oswap(tio, yield, sharechild, shareparent, lteq, 64);
  134. HeapArray[childindex] = sharechild;
  135. HeapArray[parentindex] = shareparent;
  136. childindex = parentindex;
  137. parentindex = parentindex / 2;
  138. }
  139. return 1;
  140. }
  141. int MinHeap::verify_heap_property(MPCTIO tio, yield_t & yield) {
  142. std::cout << std::endl << std::endl << "verify_heap_property is being called " << std::endl;
  143. auto HeapArray = oram.flat(tio, yield);
  144. uint64_t heapreconstruction[num_items];
  145. for (size_t j = 0; j <= num_items; ++j) {
  146. heapreconstruction[j] = mpc_reconstruct(tio, yield, HeapArray[j]);
  147. }
  148. for (size_t j = 1; j < num_items / 2; ++j) {
  149. if (heapreconstruction[j] > heapreconstruction[2 * j]) {
  150. std::cout << "heap property failure\n\n";
  151. std::cout << "j = " << j << std::endl;
  152. std::cout << heapreconstruction[j] << std::endl;
  153. std::cout << "2*j = " << 2 * j << std::endl;
  154. std::cout << heapreconstruction[2 * j] << std::endl;
  155. }
  156. if (heapreconstruction[j] > heapreconstruction[2 * j + 1]) {
  157. std::cout << "heap property failure\n\n";
  158. std::cout << "j = " << j << std::endl;
  159. std::cout << heapreconstruction[j] << std::endl;
  160. std::cout << "2*j + 1 = " << 2 * j + 1<< std::endl;
  161. std::cout << heapreconstruction[2 * j + 1] << std::endl;
  162. }
  163. //assert(heapreconstruction[j] <= heapreconstruction[2 * j]);
  164. //assert(heapreconstruction[j] <= heapreconstruction[2 * j + 1]);
  165. }
  166. return 1;
  167. }
  168. void verify_parent_children_heaps(MPCTIO tio, yield_t & yield, RegAS parent, RegAS leftchild, RegAS rightchild) {
  169. uint64_t parent_reconstruction = mpc_reconstruct(tio, yield, parent);
  170. uint64_t leftchild_reconstruction = mpc_reconstruct(tio, yield, leftchild);
  171. uint64_t rightchild_reconstruction = mpc_reconstruct(tio, yield, rightchild);
  172. assert(parent_reconstruction <= leftchild_reconstruction);
  173. assert(parent_reconstruction <= rightchild_reconstruction);
  174. }
  175. // Let "x" be the root, and let "y" and "z" be the left and right children
  176. // For an array, we have A[i] = x, A[2i] = y, A[2i + 1] = z.
  177. // We want x \le y, and x \le z.
  178. // The steps are as follows:
  179. // Step 1: compare(y,z); (1st call to to MPC Compare)
  180. // Step 2: smaller = min(y,z); This is done with an mpcselect (1st call to mpcselect)
  181. // Step 3: if(smaller == y) then smallerindex = 2i else smalleindex = 2i + 1;
  182. // Step 4: compare(x,smaller); (2nd call to to MPC Compare)
  183. // Step 5: smallest = min(x, smaller); (2nd call to mpcselect)
  184. // Step 6: otherchild = max(x, smaller)
  185. // Step 7: A[i] \gets smallest (1st Duoam Write)
  186. // Step 8: A[smallerindex] \gets otherchild (2nd Duoam Write)
  187. // Overall restore_heap_property takes 2 MPC Comparisons, 2 MPC Selects, and 2 Duoram Writes
  188. RegXS MinHeap::restore_heap_property(MPCTIO tio, yield_t & yield, RegXS index) {
  189. RegAS smallest;
  190. auto HeapArray = oram.flat(tio, yield);
  191. RegAS parent = HeapArray[index];
  192. RegXS leftchildindex = index;
  193. leftchildindex = index << 1;
  194. RegXS rightchildindex;
  195. rightchildindex.xshare = leftchildindex.xshare ^ (tio.player());
  196. RegAS leftchild = HeapArray[leftchildindex];
  197. RegAS rightchild = HeapArray[rightchildindex];
  198. RegAS sum = parent + leftchild + rightchild;
  199. CDPF cdpf = tio.cdpf(yield);
  200. auto[lt_c, eq_c, gt_c] = cdpf.compare(tio, yield, leftchild - rightchild, tio.aes_ops());
  201. auto lteq = lt_c ^ eq_c;
  202. RegXS smallerindex;
  203. #ifdef VERBOSE
  204. uint64_t LC_rec = mpc_reconstruct(tio, yield, leftchildindex);
  205. std::cout << "LC_rec = " << LC_rec << std::endl;
  206. #endif
  207. mpc_select(tio, yield, smallerindex, lteq, rightchildindex, leftchildindex, 64);
  208. #ifdef VERBOSE
  209. uint64_t smallerindex_rec = mpc_reconstruct(tio, yield, smallerindex);
  210. std::cout << "smallerindex_rec = " << smallerindex_rec << std::endl;
  211. #endif
  212. RegAS smallerchild;
  213. mpc_select(tio, yield, smallerchild, lt_c, rightchild, leftchild, 64);
  214. CDPF cdpf0 = tio.cdpf(yield);
  215. auto[lt_p, eq_p, gt_p] = cdpf0.compare(tio, yield, smallerchild - parent, tio.aes_ops());
  216. auto lt_p_eq_p = lt_p ^ eq_p;
  217. RegBS ltlt1;
  218. mpc_and(tio, yield, ltlt1, lteq, lt_p_eq_p);
  219. RegAS z, zz;
  220. run_coroutines(tio, [&tio, &zz, ltlt1, parent, leftchild](yield_t &yield)
  221. { mpc_flagmult(tio, yield, zz, ltlt1, (parent - leftchild), 64);},
  222. [&tio, &z, lt_p, parent, smallerchild](yield_t &yield)
  223. {mpc_flagmult(tio, yield, z, lt_p, smallerchild - parent, 64);}
  224. );
  225. HeapArray[index] += z;
  226. HeapArray[leftchildindex] += zz;
  227. RegAS leftchildplusparent = RegAS(HeapArray[index]) + RegAS(HeapArray[leftchildindex]);
  228. RegAS tmp = (sum - leftchildplusparent);
  229. HeapArray[rightchildindex] += tmp - rightchild;
  230. //verify_parent_children_heaps(tio, yield, HeapArray[index], HeapArray[leftchildindex] , HeapArray[rightchildindex]);
  231. return smallerindex;
  232. }
  233. auto MinHeap::restore_heap_property_optimized(MPCTIO tio, yield_t & yield, RegXS index, size_t layer, size_t depth, typename Duoram < RegAS > ::template OblivIndex < RegXS, 3 > (oidx)) {
  234. auto HeapArray = oram.flat(tio, yield);
  235. RegXS leftchildindex = index;
  236. leftchildindex = index << 1;
  237. RegXS rightchildindex;
  238. rightchildindex.xshare = leftchildindex.xshare ^ (tio.player());
  239. typename Duoram < RegAS > ::Flat P(HeapArray, tio, yield, 1 << layer, 1 << layer);
  240. typename Duoram < RegAS > ::Flat C(HeapArray, tio, yield, 2 << layer, 2 << layer);
  241. typename Duoram < RegAS > ::Stride L(C, tio, yield, 0, 2);
  242. typename Duoram < RegAS > ::Stride R(C, tio, yield, 1, 2);
  243. RegAS parent_tmp = P[oidx];
  244. RegAS leftchild_tmp = L[oidx];
  245. RegAS rightchild_tmp = R[oidx];
  246. RegAS sum = parent_tmp + leftchild_tmp + rightchild_tmp;
  247. CDPF cdpf = tio.cdpf(yield);
  248. auto[lt, eq, gt] = cdpf.compare(tio, yield, leftchild_tmp - rightchild_tmp, tio.aes_ops());
  249. auto lteq = lt ^ eq;
  250. RegXS smallerindex;
  251. RegAS smallerchild;
  252. // mpc_select(tio, yield, smallerindex, lteq, rightchildindex, leftchildindex, 64);
  253. // mpc_select(tio, yield, smallerchild, lt, rightchild_tmp, leftchild_tmp, 64);
  254. run_coroutines(tio, [&tio, &smallerindex, lteq, rightchildindex, leftchildindex](yield_t &yield)
  255. { mpc_select(tio, yield, smallerindex, lteq, rightchildindex, leftchildindex, 64);;},
  256. [&tio, &smallerchild, lt, rightchild_tmp, leftchild_tmp](yield_t &yield)
  257. { mpc_select(tio, yield, smallerchild, lt, rightchild_tmp, leftchild_tmp, 64);;});
  258. CDPF cdpf0 = tio.cdpf(yield);
  259. auto[lt1, eq1, gt1] = cdpf0.compare(tio, yield, smallerchild - parent_tmp, tio.aes_ops());
  260. RegAS z;
  261. mpc_flagmult(tio, yield, z, lt1, smallerchild - parent_tmp, 64);
  262. P[oidx] += z;
  263. auto lt1eq1 = lt1 ^ eq1;
  264. RegBS ltlt1;
  265. RegAS zz;
  266. // mpc_and(tio, yield, ltlt1, lteq, lt1eq1);
  267. // mpc_flagmult(tio, yield, zz, ltlt1, (parent_tmp - leftchild_tmp), 64);
  268. run_coroutines(tio, [&tio, &ltlt1, lteq, lt1eq1](yield_t &yield)
  269. { mpc_and(tio, yield, ltlt1, lteq, lt1eq1);},
  270. [&tio, &zz, ltlt1, parent_tmp, leftchild_tmp](yield_t &yield)
  271. { mpc_flagmult(tio, yield, zz, ltlt1, (parent_tmp - leftchild_tmp), 64);});
  272. L[oidx] += zz;// - leftchild_tmp;
  273. RegAS leftchildplusparent = RegAS(HeapArray[index]) + RegAS(HeapArray[leftchildindex]);
  274. RegAS tmp = (sum - leftchildplusparent);
  275. R[oidx] += tmp - rightchild_tmp;
  276. return std::make_pair(smallerindex, gt);
  277. }
  278. void MinHeap::initialize(MPCTIO tio, yield_t & yield) {
  279. auto HeapArray = oram.flat(tio, yield);
  280. HeapArray.init(0x7fffffffffffff);
  281. }
  282. void MinHeap::initialize_random(MPCTIO tio, yield_t & yield) {
  283. auto HeapArray = oram.flat(tio, yield);
  284. std::cout << "initialize_random " << num_items << std::endl;
  285. for(size_t j = 1; j <= num_items; ++j)
  286. {
  287. RegAS inserted_val;
  288. inserted_val.randomize(10);
  289. inserted_val.ashare = j * tio.player();
  290. HeapArray[j] = inserted_val;
  291. }
  292. // HeapArray.init(0x7fffffffffffff);
  293. }
  294. void MinHeap::print_heap(MPCTIO tio, yield_t & yield) {
  295. auto HeapArray = oram.flat(tio, yield);
  296. uint64_t * Pjreconstruction = new uint64_t[num_items + 1];
  297. for(size_t j = 0; j <= num_items; ++j) Pjreconstruction[j] = mpc_reconstruct(tio, yield, HeapArray[j]);
  298. for(size_t j = 0; j <= num_items; ++j)
  299. {
  300. if(2 * j < num_items) {
  301. std::cout << j << "-->> HeapArray[" << j << "] = " << std::dec << Pjreconstruction[j] << ", children are: " << Pjreconstruction[2 * j] << " and " << Pjreconstruction[2 * j + 1] << std::endl;
  302. }
  303. else
  304. {
  305. std::cout << j << "-->> HeapArray[" << j << "] = " << std::dec << Pjreconstruction[j] << " is a LEAF " << std::endl;
  306. }
  307. }
  308. }
  309. auto MinHeap::restore_heap_property_at_root(MPCTIO tio, yield_t & yield, size_t index = 1) {
  310. //size_t index = 1;
  311. //std::cout << "index = " << index << std::endl;
  312. auto HeapArray = oram.flat(tio, yield);
  313. RegAS parent = HeapArray[index];
  314. RegAS leftchild = HeapArray[2 * index];
  315. RegAS rightchild = HeapArray[2 * index + 1];
  316. RegAS sum = parent + leftchild + rightchild;
  317. CDPF cdpf = tio.cdpf(yield);
  318. auto[lt, eq, gt] = cdpf.compare(tio, yield, leftchild - rightchild, tio.aes_ops()); // c_1 in the paper
  319. RegAS smallerchild;
  320. mpc_select(tio, yield, smallerchild, lt, rightchild, leftchild, 64); // smallerchild holds smaller of left and right child
  321. auto lteq = lt ^ eq;
  322. RegXS smallerindex(lt);
  323. uint64_t leftchildindex = (2 * index);
  324. uint64_t rightchildindex = (2 * index) + 1;
  325. smallerindex = (RegXS(lteq) & leftchildindex) ^ (RegXS(gt) & rightchildindex);
  326. CDPF cdpf0 = tio.cdpf(yield);
  327. auto[lt1, eq1, gt1] = cdpf0.compare(tio, yield, smallerchild - parent, tio.aes_ops());
  328. auto lt_p_eq_p = lt1 ^ eq1;
  329. RegBS ltlt1;
  330. mpc_and(tio, yield, ltlt1, lteq, lt_p_eq_p);
  331. RegAS z, zz;
  332. run_coroutines(tio, [&tio, &zz, ltlt1, parent, leftchild](yield_t &yield)
  333. { mpc_flagmult(tio, yield, zz, ltlt1, (parent - leftchild), 64);},
  334. [&tio, &z, lt1, parent, smallerchild](yield_t &yield)
  335. {mpc_flagmult(tio, yield, z, lt1, smallerchild - parent, 64);}
  336. );
  337. HeapArray[index] += z;
  338. HeapArray[leftchildindex] += zz;
  339. RegAS leftchildplusparent = RegAS(HeapArray[index]) + RegAS(HeapArray[leftchildindex]);
  340. RegAS tmp = (sum - leftchildplusparent);
  341. HeapArray[rightchildindex] += tmp - rightchild;
  342. #ifdef VERBOSE
  343. RegAS new_parent = HeapArray[index];
  344. RegAS new_left = HeapArray[leftchildindex];
  345. RegAS new_right = HeapArray[rightchildindex];
  346. uint64_t parent_R = mpc_reconstruct(tio, yield, new_parent);
  347. uint64_t left_R = mpc_reconstruct(tio, yield, new_left);
  348. uint64_t right_R = mpc_reconstruct(tio, yield, new_right);
  349. std::cout << "parent_R = " << parent_R << std::endl;
  350. std::cout << "left_R = " << left_R << std::endl;
  351. std::cout << "right_R = " << right_R << std::endl;
  352. #endif
  353. //verify_parent_children_heaps(tio, yield, HeapArray[index], HeapArray[leftchildindex] , HeapArray[rightchildindex]);
  354. return std::make_pair(smallerindex, gt);
  355. }
  356. RegAS MinHeap::extract_min(MPCTIO tio, yield_t & yield, int is_optimized) {
  357. RegAS minval;
  358. auto HeapArray = oram.flat(tio, yield);
  359. minval = HeapArray[1];
  360. HeapArray[1] = RegAS(HeapArray[num_items]);
  361. num_items--;
  362. auto outroot = restore_heap_property_at_root(tio, yield);
  363. RegXS smaller = outroot.first;
  364. // uint64_t smaller_rec = mpc_reconstruct(tio, yield, smaller, 64);
  365. // std::cout << "smaller_rec [root] = " << smaller_rec << std::endl;
  366. size_t height = std::log2(num_items);
  367. //std::cout << "height = " << height << std::endl << "===================" << std::endl;
  368. typename Duoram < RegAS > ::template OblivIndex < RegXS, 3 > oidx(tio, yield, height);
  369. oidx.incr(outroot.second);
  370. for (size_t i = 0; i < height; ++i) {
  371. if(is_optimized > 0)
  372. {
  373. auto out = restore_heap_property_optimized(tio, yield, smaller, i + 1, height, typename Duoram < RegAS > ::template OblivIndex < RegXS, 3 > (oidx));;
  374. smaller = out.first;
  375. oidx.incr(out.second);
  376. }
  377. if(is_optimized == 0)
  378. {
  379. smaller = restore_heap_property(tio, yield, smaller);
  380. }
  381. //std::cout << "\n-------\n\n";
  382. }
  383. return minval;
  384. }
  385. void MinHeap::heapify2(MPCTIO tio, yield_t & yield, size_t index = 1) {
  386. auto outroot = restore_heap_property_at_root(tio, yield, index);
  387. RegXS smaller = outroot.first;
  388. #ifdef VERBOSE
  389. uint64_t smaller_rec = mpc_reconstruct(tio, yield, smaller, 64);
  390. std::cout << "smaller_rec = " << smaller_rec << std::endl;
  391. std::cout << "num_items = " << num_items << std::endl;
  392. std::cout << "index = " << index << std::endl;
  393. #endif
  394. size_t height = std::log2(num_items) - std::floor(log2(index)) ;
  395. #ifdef VERBOSE
  396. std::cout << "height = " << height << std::endl << "===================" << std::endl;
  397. #endif
  398. for (size_t i = 0; i < height - 1; ++i) {
  399. #ifdef VERBOSE
  400. std::cout << "index = " << index << ", i = " << i << std::endl;
  401. uint64_t smaller_rec = mpc_reconstruct(tio, yield, smaller, 64);
  402. std::cout << "[inside loop] smaller_rec = " << smaller_rec << std::endl;
  403. #endif
  404. smaller = restore_heap_property(tio, yield, smaller);
  405. }
  406. }
  407. void MinHeap::heapify(MPCTIO tio, yield_t & yield) {
  408. size_t startIdx = ((num_items + 1) / 2) - 1;
  409. //std::cout << "startIdx " << startIdx << std::endl;
  410. for (size_t i = startIdx; i >= 1; i--) {
  411. heapify2(tio, yield, i);
  412. //print_heap(tio, yield);
  413. }
  414. }
  415. void Heap(MPCIO & mpcio,
  416. const PRACOptions & opts, char ** args) {
  417. nbits_t depth = atoi(args[0]);
  418. nbits_t depth2 = atoi(args[1]);
  419. size_t n_inserts = atoi(args[2]);
  420. size_t n_extracts = atoi(args[3]);
  421. int is_optimized = atoi(args[4]);
  422. std::cout << "print arguements " << std::endl;
  423. std::cout << args[0] << std::endl;
  424. if ( * args) {
  425. depth = atoi( * args);
  426. ++args;
  427. }
  428. size_t items = (size_t(1) << depth) - 1;
  429. if ( * args) {
  430. items = atoi( * args);
  431. ++args;
  432. }
  433. //
  434. std::cout << "items = " << items << std::endl;
  435. MPCTIO tio(mpcio, 0, opts.num_threads);
  436. run_coroutines(tio, [ & tio, depth, depth2, items, n_inserts, n_extracts, is_optimized, &mpcio](yield_t & yield) {
  437. size_t size = size_t(1) << depth;
  438. // std::cout << "size = " << size << std::endl;
  439. MinHeap tree(tio.player(), size);
  440. tree.initialize(tio, yield);
  441. tree.num_items = (size_t(1) << depth2) - 1;
  442. // std::cout << "num_items " << tree.num_items << std::endl;
  443. tree.initialize_random(tio, yield);
  444. // tree.print_heap(tio, yield);
  445. //tree.verify_heap_property(tio, yield);
  446. //tree.heapify(tio, yield);
  447. //tree.print_heap(tio, yield);
  448. std::cout << "\n===== Heapify Stats =====\n";
  449. tio.sync_lamport();
  450. mpcio.dump_stats(std::cout);
  451. mpcio.reset_stats();
  452. tio.reset_lamport();
  453. for (size_t j = 0; j < n_inserts; ++j) {
  454. RegAS inserted_val;
  455. inserted_val.randomize(8);
  456. #ifdef VERBOSE
  457. inserted_val.ashare = inserted_val.ashare;
  458. uint64_t inserted_val_rec = mpc_reconstruct(tio, yield, inserted_val, 64);
  459. std::cout << "inserted_val_rec = " << inserted_val_rec << std::endl << std::endl;
  460. #endif
  461. if(is_optimized > 0) tree.insert_optimized(tio, yield, inserted_val);
  462. if(is_optimized == 0) tree.insert(tio, yield, inserted_val);
  463. //tree.print_heap(tio, yield);
  464. }
  465. std::cout << "\n===== Insert Stats =====\n";
  466. tio.sync_lamport();
  467. mpcio.dump_stats(std::cout);
  468. mpcio.reset_stats();
  469. tio.reset_lamport();
  470. // tree.verify_heap_property(tio, yield);
  471. for (size_t j = 0; j < n_extracts; ++j) {
  472. tree.extract_min(tio, yield, is_optimized);
  473. //RegAS minval = tree.extract_min(tio, yield, is_optimized);
  474. // uint64_t minval_reconstruction = mpc_reconstruct(tio, yield, minval, 64);
  475. // std::cout << "minval_reconstruction = " << minval_reconstruction << std::endl;
  476. // tree.verify_heap_property(tio, yield);
  477. // tree.print_heap(tio, yield);
  478. }
  479. std::cout << "\n===== Extract Min Stats =====\n";
  480. tio.sync_lamport();
  481. mpcio.dump_stats(std::cout);
  482. // tree.verify_heap_property(tio, yield);
  483. });
  484. }