shapes.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #ifndef __SHAPES_HPP__
  2. #define __SHAPES_HPP__
  3. // Various Shapes beyond the standard Flat (in duoram.hpp)
  4. #include "duoram.hpp"
  5. // A Pad is a Shape that pads an underlying Shape so that read accesses
  6. // past the end return a fixed constant value. Do _not_ write into a
  7. // Pad!
  8. template <typename T>
  9. class Duoram<T>::Pad : public Duoram<T>::Shape {
  10. // These are pointers because we need to be able to return a
  11. // (non-const) T& even from a const Pad.
  12. T *padvalp;
  13. T *peerpadvalp;
  14. T *zerop;
  15. address_t padded_size;
  16. inline size_t indexmap(size_t idx) const override {
  17. return idx;
  18. }
  19. Pad &operator=(const Pad &) = delete;
  20. public:
  21. // Constructor for the Pad shape. The parent must _not_ be in
  22. // explicit-only mode.
  23. Pad(Shape &parent, MPCTIO &tio, yield_t &yield,
  24. address_t padded_size, value_t padval = 0x7fffffffffffffff);
  25. // Copy the given Pad except for the tio and yield
  26. Pad(const Pad &copy_from, MPCTIO &tio, yield_t &yield);
  27. // Destructor
  28. ~Pad();
  29. // Update the context (MPCTIO and yield if you've started a new
  30. // thread, or just yield if you've started a new coroutine in the
  31. // same thread). Returns a new Shape with an updated context.
  32. Pad context(MPCTIO &new_tio, yield_t &new_yield) const {
  33. return Pad(*this, new_tio, new_yield);
  34. }
  35. Pad context(yield_t &new_yield) const {
  36. return Pad(*this, this->tio, new_yield);
  37. }
  38. // Get a pair (for the server) of references to the underlying
  39. // Duoram entries at share virtual index idx. (That is, it gets
  40. // duoram.p0_blind[indexmap(idx)], etc.)
  41. inline std::tuple<T&,T&> get_server(size_t idx,
  42. std::nullopt_t null = std::nullopt) const override {
  43. size_t parindex = indexmap(idx);
  44. if (parindex < this->parent.shape_size) {
  45. return this->parent.get_server(parindex, null);
  46. } else {
  47. return std::tie(*zerop, *zerop);
  48. }
  49. }
  50. // Get a triple (for the computational players) of references to the
  51. // underlying Duoram entries at share virtual index idx. (That is,
  52. // it gets duoram.database[indexmap(idx)], etc.)
  53. inline std::tuple<T&,T&,T&> get_comp(size_t idx,
  54. std::nullopt_t null = std::nullopt) const override {
  55. size_t parindex = indexmap(idx);
  56. if (parindex < this->parent.shape_size) {
  57. return this->parent.get_comp(parindex, null);
  58. } else {
  59. return std::tie(*padvalp, *zerop, *peerpadvalp);
  60. }
  61. }
  62. // Index into this Pad in various ways
  63. typename Duoram::Shape::template MemRefS<RegAS,T,std::nullopt_t,Pad,1>
  64. operator[](const RegAS &idx) {
  65. typename Duoram<T>::Shape::
  66. template MemRefS<RegAS,T,std::nullopt_t,Pad,1>
  67. res(*this, idx, std::nullopt);
  68. return res;
  69. }
  70. typename Duoram::Shape::template MemRefS<RegXS,T,std::nullopt_t,Pad,1>
  71. operator[](const RegXS &idx) {
  72. typename Duoram<T>::Shape::
  73. template MemRefS<RegXS,T,std::nullopt_t,Pad,1>
  74. res(*this, idx, std::nullopt);
  75. return res;
  76. }
  77. template <typename U, nbits_t WIDTH>
  78. typename Duoram::Shape::template MemRefS<U,T,std::nullopt_t,Pad,WIDTH>
  79. operator[](OblivIndex<U,WIDTH> &obidx) {
  80. typename Duoram<T>::Shape::
  81. template MemRefS<RegXS,T,std::nullopt_t,Pad,WIDTH>
  82. res(*this, obidx, std::nullopt);
  83. return res;
  84. }
  85. typename Duoram::Shape::template MemRefExpl<T,std::nullopt_t>
  86. operator[](address_t idx) {
  87. typename Duoram<T>::Shape::
  88. template MemRefExpl<T,std::nullopt_t>
  89. res(*this, idx, std::nullopt);
  90. return res;
  91. }
  92. template <typename U>
  93. Duoram::Shape::MemRefInd<U, Pad>
  94. operator[](const std::vector<U> &indcs) {
  95. typename Duoram<T>::Shape::
  96. template MemRefInd<U,Pad>
  97. res(*this, indcs);
  98. return res;
  99. }
  100. template <typename U, size_t N>
  101. Duoram::Shape::MemRefInd<U, Pad>
  102. operator[](const std::array<U,N> &indcs) {
  103. typename Duoram<T>::Shape::
  104. template MemRefInd<U,Pad>
  105. res(*this, indcs);
  106. return res;
  107. }
  108. };
  109. // A Stride is a Shape that represents evenly spaced elements of its
  110. // parent Shape, starting with some offset, and then every stride
  111. // elements.
  112. template <typename T>
  113. class Duoram<T>::Stride : public Duoram<T>::Shape {
  114. size_t offset;
  115. size_t stride;
  116. inline size_t indexmap(size_t idx) const override {
  117. size_t paridx = offset + idx*stride;
  118. return paridx;
  119. }
  120. public:
  121. // Constructor
  122. Stride(Shape &parent, MPCTIO &tio, yield_t &yield, size_t offset,
  123. size_t stride);
  124. // Copy the given Stride except for the tio and yield
  125. Stride(const Stride &copy_from, MPCTIO &tio, yield_t &yield) :
  126. Shape(copy_from, tio, yield), offset(copy_from.offset),
  127. stride(copy_from.stride) {}
  128. // Update the context (MPCTIO and yield if you've started a new
  129. // thread, or just yield if you've started a new coroutine in the
  130. // same thread). Returns a new Shape with an updated context.
  131. Stride context(MPCTIO &new_tio, yield_t &new_yield) const {
  132. return Stride(*this, new_tio, new_yield);
  133. }
  134. Stride context(yield_t &new_yield) const {
  135. return Stride(*this, this->tio, new_yield);
  136. }
  137. // Index into this Stride in various ways
  138. typename Duoram::Shape::template MemRefS<RegAS,T,std::nullopt_t,Stride,1>
  139. operator[](const RegAS &idx) {
  140. typename Duoram<T>::Shape::
  141. template MemRefS<RegAS,T,std::nullopt_t,Stride,1>
  142. res(*this, idx, std::nullopt);
  143. return res;
  144. }
  145. typename Duoram::Shape::template MemRefS<RegXS,T,std::nullopt_t,Stride,1>
  146. operator[](const RegXS &idx) {
  147. typename Duoram<T>::Shape::
  148. template MemRefS<RegXS,T,std::nullopt_t,Stride,1>
  149. res(*this, idx, std::nullopt);
  150. return res;
  151. }
  152. template <typename U, nbits_t WIDTH>
  153. typename Duoram::Shape::template MemRefS<U,T,std::nullopt_t,Stride,WIDTH>
  154. operator[](OblivIndex<U,WIDTH> &obidx) {
  155. typename Duoram<T>::Shape::
  156. template MemRefS<RegXS,T,std::nullopt_t,Stride,WIDTH>
  157. res(*this, obidx, std::nullopt);
  158. return res;
  159. }
  160. typename Duoram::Shape::template MemRefExpl<T,std::nullopt_t>
  161. operator[](address_t idx) {
  162. typename Duoram<T>::Shape::
  163. template MemRefExpl<T,std::nullopt_t>
  164. res(*this, idx, std::nullopt);
  165. return res;
  166. }
  167. template <typename U>
  168. Duoram::Shape::MemRefInd<U, Stride>
  169. operator[](const std::vector<U> &indcs) {
  170. typename Duoram<T>::Shape::
  171. template MemRefInd<U,Stride>
  172. res(*this, indcs);
  173. return res;
  174. }
  175. template <typename U, size_t N>
  176. Duoram::Shape::MemRefInd<U, Stride>
  177. operator[](const std::array<U,N> &indcs) {
  178. typename Duoram<T>::Shape::
  179. template MemRefInd<U,Stride>
  180. res(*this, indcs);
  181. return res;
  182. }
  183. };
  184. // A Path is a Shape that represents a path from the root of a complete
  185. // binary tree down to a given node.
  186. // We assume this layout for the tree (the _parent_ shape of the Path):
  187. // A[0] is unused
  188. // A[1] is the root (layer 0)
  189. // A[2..3] is layer 1
  190. // A[4..7] is layer 2
  191. // ...
  192. // A[(1<<j)..((2<<j)-1)] is layer j
  193. //
  194. // So the parent of x is at location (x/2) and the children of x
  195. // are at locations 2*x and 2*x+1
  196. template <typename T>
  197. class Duoram<T>::Path : public Duoram<T>::Shape {
  198. size_t target_node;
  199. inline size_t indexmap(size_t idx) const override {
  200. size_t paridx = target_node >> (this->shape_size - idx - 1);
  201. return paridx;
  202. }
  203. public:
  204. // Constructor
  205. Path(Shape &parent, MPCTIO &tio, yield_t &yield,
  206. size_t target_node);
  207. // Copy the given Path except for the tio and yield
  208. Path(const Path &copy_from, MPCTIO &tio, yield_t &yield) :
  209. Shape(copy_from, tio, yield),
  210. target_node(copy_from.target_node) {}
  211. // Update the context (MPCTIO and yield if you've started a new
  212. // thread, or just yield if you've started a new coroutine in the
  213. // same thread). Returns a new Shape with an updated context.
  214. Path context(MPCTIO &new_tio, yield_t &new_yield) const {
  215. return Path(*this, new_tio, new_yield);
  216. }
  217. Path context(yield_t &new_yield) const {
  218. return Path(*this, this->tio, new_yield);
  219. }
  220. // Index into this Path in various ways
  221. typename Duoram::Shape::template MemRefS<RegAS,T,std::nullopt_t,Path,1>
  222. operator[](const RegAS &idx) {
  223. typename Duoram<T>::Shape::
  224. template MemRefS<RegAS,T,std::nullopt_t,Path,1>
  225. res(*this, idx, std::nullopt);
  226. return res;
  227. }
  228. typename Duoram::Shape::template MemRefS<RegXS,T,std::nullopt_t,Path,1>
  229. operator[](const RegXS &idx) {
  230. typename Duoram<T>::Shape::
  231. template MemRefS<RegXS,T,std::nullopt_t,Path,1>
  232. res(*this, idx, std::nullopt);
  233. return res;
  234. }
  235. template <typename U, nbits_t WIDTH>
  236. typename Duoram::Shape::template MemRefS<U,T,std::nullopt_t,Path,WIDTH>
  237. operator[](OblivIndex<U,WIDTH> &obidx) {
  238. typename Duoram<T>::Shape::
  239. template MemRefS<RegXS,T,std::nullopt_t,Path,WIDTH>
  240. res(*this, obidx, std::nullopt);
  241. return res;
  242. }
  243. typename Duoram::Shape::template MemRefExpl<T,std::nullopt_t>
  244. operator[](address_t idx) {
  245. typename Duoram<T>::Shape::
  246. template MemRefExpl<T,std::nullopt_t>
  247. res(*this, idx, std::nullopt);
  248. return res;
  249. }
  250. template <typename U>
  251. Duoram::Shape::MemRefInd<U, Path>
  252. operator[](const std::vector<U> &indcs) {
  253. typename Duoram<T>::Shape::
  254. template MemRefInd<U,Path>
  255. res(*this, indcs);
  256. return res;
  257. }
  258. template <typename U, size_t N>
  259. Duoram::Shape::MemRefInd<U, Path>
  260. operator[](const std::array<U,N> &indcs) {
  261. typename Duoram<T>::Shape::
  262. template MemRefInd<U,Path>
  263. res(*this, indcs);
  264. return res;
  265. }
  266. };
  267. #include "shapes.tcc"
  268. #endif