Skip to content
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

feat: add crt support #10

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

feat: add crt support #10

wants to merge 3 commits into from

Conversation

enricobottazzi
Copy link
Collaborator

@enricobottazzi enricobottazzi commented Jan 5, 2024

  • Support Crt based decomposition of big modulus Q to achieve RNS (https://eprint.iacr.org/2018/117)
  • Rename RLWE class to BFV (and corresponding files)
  • Simplify PolynomialRing class
  • Added poly_div, poly_mul and poly_add operations as performing them with numpy was losing precision when dealing with large integers
  • Fix Gaussian Distribution. Now The lower and upper bounds of the range of the discrete Gaussian distribution are rounded to the nearest integer (check section 4 https://inferati.azureedge.net/docs/inferati-fhe-bfv.pdf)

Copy link
Owner

@yuriko627 yuriko627 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments!

"""
self.sigma = sigma

# The lower and upper bounds of the range of the discrete Gaussian distribution are rounded to the nearest integer (check section 4 https://inferati.azureedge.net/docs/inferati-fhe-bfv.pdf)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trivial, but indentation


def recover_with_centered_remainder(self):
"""
Recover the integer x from its CRT representation. The integer x is in (-q/2, q/2].
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what situation would x lie in the range of (-q/2, q/2], rather than [0, q)? And can operations on x in this range be implemented by applying the same operation to each CRT component xi?

xi = self.xis[i]
qi_star = self.q.q // self.q.qis[i]
qi_tilde = pow(
qi_star, -1, self.q.qis[i]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow python is so useful, didn't know there is a built-in function to get multiplicative inverse like this 👀

for j in range(len(rqi_polynomials)):
coeff_crt_components.append(rqi_polynomials[j].coefficients[i])
coeff_crt_integer = CRTInteger(q, coeff_crt_components)
coeff = coeff_crt_integer.recover_with_centered_remainder()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is recover_with_centered_remainder() rather than recover() particularly used here?

class CRTPolynomial:
def from_rq_polynomial_to_rqi_polynomials(rq_polynomial: Polynomial, q: Q):
"""
Reduce polynomial `a` coefficients to its CRT representations
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is a here? Did you maybe mean rq_polynomial coefficients?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I got it after reading the test, but it might be better to not name the resulting/initial polynomial a in the functions here

# Initialize quotient and remainder
quotient = [0] * (len(dividend) - len(divisor) + 1)
remainder = list(dividend)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a good practice to check if the leading coefficient of divisor is non-zero.

@@ -69,5 +74,59 @@ def get_centered_remainder(x, modulus):
return r if r <= modulus / 2 else r - modulus


def poly_div(dividend: list[int], divisor: list[int]):
dividend = [int(x) for x in dividend]

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to check that the degree of dividend is greater than or equal to the degree of the divisor first. otherwise initialization of the quotient in line 81 won't be valid.

remainder[i + j] = rem

# Remove leading zeroes in remainder, if any
while remainder and remainder[0] == 0:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the entire remainder is zero, then it will remove all elements of it and returning an empty list. we still want it to return remainder filled with all zeros.


fx = [1] + [0] * (n-1) + [1]
self.denominator = fx
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you wanna rename denominator => divisor to make it aligned with them in poly_div?

return quotient, remainder


def poly_mul(poly1: list[int], poly2: list[int]):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a better practice to check poly1 and poly2's leading coefficients are non-zero (assuming that 0th element = highest degree coefficient)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants