Parity Challenge Solution
The article details the solution provided by the winner of the Parity challenge.
Author: Chi-Hieu Nguyen, University of Technology Sydney, Australia.
Overview of the approach
The parity function is intimately connected to the bit extraction problem, where the goal is to determine the bit representation of a given integer the goal such that . This function can be expressed in the continuous domain using the trigonometric function . Evaluating trigonometric functions in an encrypted domain is a well-established problem, which is frequently employed in the bootstrapping process to refresh the level of an "exhausted" ciphertext [1]. A common approach to evaluating a cosine function is to utilize the double-angle formula to evaluate from an approximation of , thus narrowing down the approximation range and reduce the order of the approximated polynomial.
We adopt the same approach and try to approximate using Chebyshev basis. Initially, the input value is normalized to the interval using the linear transformation . The target function becomes . Using the double angle formula, we first approximate by a polynomial and then apply the transformation to iteratively calculate , which approximates . The approximation of can be obtained using the numpy.polyfit method in Python.
f = lambda x: np.cos(np.pi*x+np.pi/128) x = np.arange(0,257) y = (x-128)/128 p = np.polyfit(y, f(y), 8)
This method returns a list of coefficients in the monomial basis, which must be converted to the Chebyshev basis for stable evaluation in a fixed-point environment. Figure 1 shows an illustration of such approximation using a polynomial of degree 8.

Figure 1: (left) Approximation of using an 8th-degree polynomial. (right) Absolute error of the approximation.
The interpolant appears accurate at this stage. However, after applying the double-angle iteration 7 times, the accuracy degrades beyond the desired bounds. Figure 2 depicts the resulting approximation, showing significant errors at certain values (e.g., ) that exceed the acceptable threshold of .

Figure 2: (top) Approximation of after 7 double angle iterations. (bottom) Absolute error of the approximation.
To address this issue, we refined the polynomial approximation using a modified Arnoldi method as introduced in [2]. Unlike the referenced approach, which uses the error , we utilize the final error after the 7th double-angle iteration to update the weight vector for next steps. The Python code for improving the polynomial approximation is as follows:
g = lambda x: np.cos(128*np.pi*x+np.pi)
w = np.ones_like(y)
for _ in range(5):
p = np.polyfit(y, f(y), 8, w=np.sqrt(w))
z = np.polyval(p,y)
for i in range(7):
z = 2*z*z-1
w = w*np.abs(z-g(y))
w = w / np.linalg.norm(w)
w = np.abs(w)
After 5 iterations, the maximum approximation error reduced to below , indicating a satisfactory solution. Figure 3 presents the final approximation.

Figure 3: (top) The final approximation. (bottom) Absolute error of the approximation.
We can now convert the resulting polynomial to Chebyshev basis for evaluation.
print(np.polynomial.chebyshev.poly2cheb(p[::-1])) # [-3.04159700e-01 -1.39659316e-02 -9.70590161e-01 1.63649478e-02 # 3.02827581e-01 -2.56364745e-03 -2.91082990e-02 1.66592418e-04 # 1.33270778e-03]
Optimizations
To further accelerate the polynomial evaluation, we apply a simple input-shifting trick. That is, instead of directly approximating , we approximate using the same method and then evaluate to obtain . Since is an even function, its Chebyshev representation contains only even-degree terms, allowing us to omit the odd-degree terms for faster evaluation. The updated Chebyshev representation of is as follows.
# [-0.3042513777371315, 0, -0.970882602838183, 0, 0.30291864798067064, 0, -0.02911740974995488, 0, 0.0013327077835582305]
Finally, recall that our the target function is , the approximation of must be scaled by , which inccurs an extra multiplication level. To avoid this, we scale the coefficients of by to approximate . We then apply a serie of transformation to calculate . The final approximation of is obtained by adding to the resulting value. The multiplication depth of the whole computation is 12 (1 for evaluating , 4 for evaluating and 7 for the transformations ).
References
[1] J.-P. Bossuat, C. Mouchet, J. Troncoso-Pastoriza and A.-P. Hubaux, "Efficient bootstrapping for approximate homomorphic encryption with non-sparse keys", Proc. EUROCRYPT, pp. 587-617, 2021.
[2] Pablo D Brubeck, Yuji Nakatsukasa, and Lloyd N Trefethen, "Vandermonde with Arnoldi", SIAM Review, 63(2):405–415, 2021.
CITING THIS WORK
This write-up documents a component of the FHERMA library. If it informs your work, cite the two papers below rather than the article URL.
- 01FHERMA Cookbook: FHE Components for Privacy-Preserving ApplicationsJanis Adamek, Aikata Aikata, Ahmad Al Badawi, Andreea Alexandru, Armen Arakelov, Philipp Binfet, Victor Correa, Jules Dumezy, Sergey Gomenyuk, Valentina Kononova, Dmitrii Lekomtsev, Vivian Maloney, Chi-Hieu Nguyen, Yuriy Polyakov, Daria Pianykh, Hayim Shaul, Moritz Schulze Darup, Dieter Teichrib, Dmitry Tronin, Gurgen ArakelovCryptology ePrint Archive, Paper 2025/1302 · doi:10.1145/3733811.3767313
- 02FHERMA: Building the Open-Source FHE Components Library for Practical UseGurgen Arakelov, Nikita Kaskov, Daria Pianykh, Yuriy PolyakovCryptology ePrint Archive, Paper 2024/612
