void replicate0(const EncryptedArray& ea, Ctxt& ctxt, long pos) { long dim = ea.dimension(); for (long d = 0; d < dim; d++) { if (!ea.nativeDimension(d)) { long shamt = -ea.coordinate(d, pos); ea.rotate1D(ctxt, d, shamt, true); // "don't care" } Ctxt ctxt_orig = ctxt; long sz = ea.sizeOfDimension(d); long k = NumBits(sz); long e = 1; // now process bits k-2 down to 0 for (long j = k-2; j >= 0; j--) { // e -> 2*e Ctxt tmp = ctxt; ea.rotate1D(tmp, d, e, true); // "don't care" ctxt += tmp; e = 2*e; long b = bit(sz, j); // bit j of sz // e -> e+b if (b) { ea.rotate1D(ctxt, d, 1, true); // "don't care" ctxt += ctxt_orig; e++; } } } }
static void replicateOneBlock(const EncryptedArray& ea, Ctxt& ctxt, long pos, long blockSize, long d) { long dSize = ea.sizeOfDimension(d); // Move this block to position 0. We can skip this step in // "good dimensions" of size divisible by the block size if (pos != 0 && (!ea.nativeDimension(d) || dSize % blockSize != 0) ) { ea.rotate1D(ctxt, d, -pos*blockSize, true); } long sz = dSize/blockSize; // how many blocks fit in this dimension if (sz == 1) return; // nothing to do, only one block in this dimension // do the actual replication using "shift and add" long k = NumBits(sz); long e = 1; Ctxt ctxt_orig = ctxt; // now process bits k-2 down to 0 for (long j = k-2; j >= 0; j--) { // e -> 2*e Ctxt tmp = ctxt; ea.rotate1D(tmp, d, e*blockSize, /*don't-care-flag=*/true); ctxt += tmp; e = 2*e; long b = bit(sz, j); // bit j of sz // e -> e+b if (b) { ea.rotate1D(ctxt, d, 1*blockSize, /*don't-care-flag=*/true); ctxt += ctxt_orig; e++; } } }