in pir_server.cpp [412:451]
vector<Plaintext> PIRServer::decompose_to_plaintexts(const Ciphertext &encrypted) {
vector<Plaintext> result;
auto coeff_count = params_.poly_modulus_degree();
auto coeff_mod_count = params_.coeff_modulus().size();
auto plain_bit_count = params_.plain_modulus().bit_count();
auto encrypted_count = encrypted.size();
// Generate powers of t.
uint64_t plainMod = params_.plain_modulus().value();
// A triple for loop. Going over polys, moduli, and decomposed index.
for (int i = 0; i < encrypted_count; i++) {
const uint64_t *encrypted_pointer = encrypted.data(i);
for (int j = 0; j < coeff_mod_count; j++) {
// populate one poly at a time.
// create a polynomial to store the current decomposition value
// which will be copied into the array to populate it at the current
// index.
int logqj = log2(params_.coeff_modulus()[j].value());
int expansion_ratio = ceil(logqj / log2(plainMod));
// cout << "expansion ratio = " << expansion_ratio << endl;
uint64_t cur = 1;
for (int k = 0; k < expansion_ratio; k++) {
// Decompose here
Plaintext temp(coeff_count);
transform(encrypted_pointer + (j * coeff_count),
encrypted_pointer + ((j + 1) * coeff_count),
temp.data(),
[cur, &plainMod](auto &in) { return (in / cur) % plainMod; }
);
result.emplace_back(move(temp));
cur *= plainMod;
}
}
}
return result;
}