in pir_client.cpp [154:207]
Ciphertext PIRClient::compose_to_ciphertext(vector<Plaintext> plains) {
size_t encrypted_count = 2;
auto coeff_count = params_.poly_modulus_degree();
auto coeff_mod_count = params_.coeff_modulus().size();
uint64_t plainMod = params_.plain_modulus().value();
int logt = floor(log2(plainMod));
Ciphertext result(newcontext_);
result.resize(encrypted_count);
// A triple for loop. Going over polys, moduli, and decomposed index.
for (int i = 0; i < encrypted_count; i++) {
uint64_t *encrypted_pointer = result.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.
double logqj = log2(params_.coeff_modulus()[j].value());
int expansion_ratio = ceil(logqj / logt);
uint64_t cur = 1;
// cout << "Client: expansion_ratio = " << expansion_ratio << endl;
for (int k = 0; k < expansion_ratio; k++) {
// Compose here
const uint64_t *plain_coeff =
plains[k + j * (expansion_ratio) + i * (coeff_mod_count * expansion_ratio)]
.data();
for (int m = 0; m < coeff_count; m++) {
if (k == 0) {
*(encrypted_pointer + m + j * coeff_count) = *(plain_coeff + m) * cur;
} else {
*(encrypted_pointer + m + j * coeff_count) += *(plain_coeff + m) * cur;
}
}
// *(encrypted_pointer + coeff_count - 1 + j * coeff_count) = 0;
cur <<= logt;
}
// XXX: Reduction modulo qj. This is needed?
/*
for (int m = 0; m < coeff_count; m++) {
*(encrypted_pointer + m + j * coeff_count) %=
params_.coeff_modulus()[j].value();
}
*/
}
}
result.parms_id() = params_.parms_id();
return result;
}