-
-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CKKSVector Polynomial Evaluation #99
Changes from all commits
b45ac2b
836dc2a
ffc75cd
3167218
b86f7b1
1d0d4f9
6360f20
f2a035d
c3ea803
65313f9
43bf886
1240096
943647c
d9d6084
ddb34a3
78ce95a
c77957f
0250390
530ae62
e8be408
ad24085
2ebc1cd
8161d22
d97e953
8cb55ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -316,8 +316,11 @@ CKKSVector& CKKSVector::_mul_plain_inplace(const T& to_mul) { | |
this->context->evaluator->multiply_plain_inplace(this->ciphertext, | ||
plaintext); | ||
} catch (const std::logic_error& e) { // result ciphertext is transparent | ||
// TODO: chech if error e is exactly a "ciphertext is transparent" error | ||
// replace by encryption of zero | ||
this->context->encryptor->encrypt_zero(this->ciphertext); | ||
this->ciphertext.scale() = this->init_scale; | ||
return *this; | ||
} | ||
|
||
if (this->context->auto_rescale()) { | ||
|
@@ -412,4 +415,59 @@ CKKSVector& CKKSVector::replicate_first_slot_inplace(size_t n) { | |
return *this; | ||
} | ||
|
||
CKKSVector CKKSVector::polyval(const vector<double>& coefficients) { | ||
CKKSVector new_vector = *this; | ||
return new_vector.polyval_inplace(coefficients); | ||
} | ||
|
||
CKKSVector& CKKSVector::polyval_inplace(const vector<double>& coefficients) { | ||
if (coefficients.size() == 0) { | ||
throw invalid_argument( | ||
"the coefficients vector need to have at least one element"); | ||
} | ||
|
||
int degree = static_cast<int>(coefficients.size()) - 1; | ||
while (degree >= 0) { | ||
if (coefficients[degree] == 0.0) | ||
degree--; | ||
else | ||
break; | ||
} | ||
|
||
// null polynomial: output should be an encrypted 0 | ||
// we can multiply by 0, or return the encryption of zero | ||
if (degree == -1) { | ||
// we set the vector to the encryption of zero | ||
this->context->encryptor->encrypt_zero(this->ciphertext); | ||
this->ciphertext.scale() = this->init_scale; | ||
return *this; | ||
} | ||
|
||
// set result accumulator to the constant coefficient | ||
vector<double> cst_coeff(this->size(), coefficients[0]); | ||
CKKSVector result(this->context, cst_coeff, this->init_scale); | ||
|
||
// pre-compute squares of x | ||
CKKSVector x = *this; | ||
int max_square = static_cast<int>(floor(log2(degree))); | ||
vector<CKKSVector> x_squares; | ||
x_squares.reserve(max_square + 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not directly resize? and access the vector directly using [] instead of push_back operations There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update: So it's a little complicated for this, reserve is more convenient for our usage, as resize need to init the objects in the vector, and we doesn't want this, however, reserve will only allocate the necessary memory and push_back won't have to allocate memory dynamically. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, my observation made more sense with vector of pointers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! |
||
x_squares.push_back(x); // x | ||
for (int i = 1; i <= max_square; i++) { | ||
// TODO: use square | ||
x.mul_inplace(x); | ||
x_squares.push_back(x); // x^(2^i) | ||
} | ||
|
||
// coefficients[1] * x + ... + coefficients[degree] * x^(degree) | ||
for (int i = 1; i <= degree; i++) { | ||
if (coefficients[i] == 0.0) continue; | ||
x = compute_polynomial_term(i, coefficients[i], x_squares); | ||
result.add_inplace(x); | ||
} | ||
|
||
this->ciphertext = result.ciphertext; | ||
return *this; | ||
} | ||
|
||
} // namespace tenseal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this creates a vector of size this->size() with all the values set to coefficients[0]. is that the expected behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, to encrypt it later and have operations done element-wise