def exp2_fx(a): if types.program.options.ring: sint = types.sint intbitint = types.intbitint # how many bits to use from integer part n_int_bits = int(math.ceil(math.log(a.k - a.f, 2))) n_bits = a.f + n_int_bits n_shift = int(types.program.options.ring) - a.k r_bits = [sint.get_random_bit() for i in range(a.k)] shifted = ((a.v - sint.bit_compose(r_bits)) << n_shift).reveal() masked_bits = (shifted >> n_shift).bit_decompose(a.k) lower_overflow = sint() comparison.CarryOut(lower_overflow, masked_bits[a.f - 1::-1], r_bits[a.f - 1::-1]) lower_r = sint.bit_compose(r_bits[:a.f]) lower_masked = sint.bit_compose(masked_bits[:a.f]) lower = lower_r + lower_masked - (lower_overflow << (a.f)) c = types.sfix._new(lower, k=a.k, f=a.f) higher_bits = intbitint.bit_adder(masked_bits[a.f:n_bits], r_bits[a.f:n_bits], carry_in=lower_overflow, get_carry=True) d = types.sfix.from_sint(floatingpoint.Pow2_from_bits( higher_bits[:-1]), k=a.k, f=a.f) e = p_eval(p_1045, c) g = d * e small_result = types.sfix._new(g.v.round( a.k + 1, a.f, signed=False, nearest=types.sfix.round_nearest), k=a.k, f=a.f) carry = comparison.CarryOutLE(masked_bits[n_bits:-1], r_bits[n_bits:-1], higher_bits[-1]) # should be for free highest_bits = intbitint.ripple_carry_adder(masked_bits[n_bits:-1], [0] * (a.k - n_bits), carry_in=higher_bits[-1]) bits_to_check = [ x.bit_xor(y) for x, y in zip(highest_bits[:-1], r_bits[n_bits:-1]) ] t = floatingpoint.KMul(bits_to_check) # sign s = masked_bits[-1].bit_xor(r_bits[-1]).bit_xor(carry) return s.if_else(t.if_else(small_result, 0), g) else: # obtain absolute value of a s = a < 0 a = (s * (-2) + 1) * a # isolates fractional part of number b = trunc(a) c = a - load_sint(b, type(a)) # squares integer part of a d = load_sint(b.pow2(types.sfix.k - types.sfix.f), type(a)) # evaluates fractional part of a in p_1045 e = p_eval(p_1045, c) g = d * e return (1 - s) * g + s * ((types.sfix(1)) / g)
def SqrtComp(z, old=False): f = types.sfix.f k = len(z) if isinstance(z[0], types.sint): return types.sfix._new( sum(z[i] * types.cfix(2**(-(i - f + 1) / 2)).v for i in range(k))) k_prime = k // 2 f_prime = f // 2 c1 = types.sfix(2**((f + 1) / 2 + 1)) c0 = types.sfix(2**(f / 2 + 1)) a = [z[2 * i].bit_or(z[2 * i + 1]) for i in range(k_prime)] tmp = types.sfix._new(types.sint.bit_compose(reversed(a[:2 * f_prime]))) if old: b = sum(types.sint.conv(zi).if_else(i, 0) for i, zi in enumerate(z)) % 2 else: b = util.tree_reduce(lambda x, y: x.bit_xor(y), z[::2]) return types.sint.conv(b).if_else(c1, c0) * tmp
def exp2_fx(a): # obtain absolute value of a s = a < 0 a = (s * (-2) + 1) * a # isolates fractional part of number b = trunc(a) c = a - load_sint(b, type(a)) # squares integer part of a d = load_sint(types.sint.pow2(b), type(a)) # evaluates fractional part of a in p_1045 e = p_eval(p_1045, c) g = d * e return (1 - s) * g + s * ((types.sfix(1)) / g)
def norm_SQ(b, k): # calculation of z # x in order 0 - k x_order = b.bit_decompose() x = [0] * k #x i now inverted for i in range(k - 1, -1, -1): x[k - 1 - i] = x_order[i] # y is inverted for PReOR and then restored y_order = floatingpoint.PreOR(x) # y in order (restored in orginal order y = [0] * k for i in range(k - 1, -1, -1): y[k - 1 - i] = y_order[i] # obtain z z = [0] * k for i in range(k - 1): z[i] = y[i] - y[i + 1] z[k - 1] = y[k - 1] # now reverse bits of z[i] to generate v v = types.sint() for i in range(k): v += (2**(k - i - 1)) * z[i] c = b * v # construct m m = types.sint() for i in range(k): m = m + (i + 1) * z[i] # construct w, changes from what is on the paper # and the documentation k_over_2 = k / 2 + 1 #int(math.ceil((k/2.0)))+1 w_array = [0] * (k_over_2) for i in range(1, k_over_2): w_array[i] = z[2 * i - 1 - (1 - k % 2)] + z[2 * i - (1 - k % 2)] w_array[0] = types.sfix(0) w = types.sint() for i in range(k_over_2): w += (2**i) * w_array[i] # return computed values return c, v, m, w
def sqrt_simplified_fx(x): # fix theta (number of iterations) theta = max(int(math.ceil(math.log(types.sfix.k))), 6) # process to use 2^(m/2) approximation m_odd, m, w = norm_simplified_SQ(x.v, x.k) # process to set up the precision and allocate correct 2**f if x.f % 2 == 1: m_odd = (1 - 2 * m_odd) + m_odd w = (w * 2 - w) * (1 - m_odd) + w # map number to use sfix format and instantiate the number w = types.sfix(w * 2**((x.f - (x.f % 2)) / 2)) # obtains correct 2 ** (m/2) w = (w * (types.cfix(2**(1 / 2.0))) - w) * m_odd + w # produce x/ 2^(m/2) y_0 = types.cfix(1.0) / w # from this point on it sufices to work sfix-wise g_0 = (y_0 * x) h_0 = y_0 * types.cfix(0.5) gh_0 = g_0 * h_0 ## initialization g = g_0 h = h_0 gh = gh_0 for i in range(1, theta - 2): r = (3 / 2.0) - gh g = g * r h = h * r gh = g * h # newton r = (3 / 2.0) - gh h = h * r H = 4 * (h * h) H = H * x H = (3) - H H = h * H g = H * x g = g return g