def approximate_reciprocal(divisor, k, f, theta): """ returns aproximation of 1/divisor where type(divisor) = cint """ def twos_complement(x): bits = x.bit_decompose(k)[::-1] bit_array = Array(k, cint) bit_array.assign(bits) twos_result = MemValue(cint(0)) @for_range(k) def block(i): val = twos_result.read() val <<= 1 val += 1 - bit_array[i] twos_result.write(val) return twos_result.read() + 1 bit_array = Array(k, cint) bits = divisor.bit_decompose(k)[::-1] bit_array.assign(bits) cnt_leading_zeros = MemValue(regint(0)) flag = MemValue(regint(0)) cnt_leading_zeros = MemValue(regint(0)) normalized_divisor = MemValue(divisor) @for_range(k) def block(i): flag.write(flag.read() | bit_array[i] == 1) @if_(flag.read() == 0) def block(): cnt_leading_zeros.write(cnt_leading_zeros.read() + 1) normalized_divisor.write(normalized_divisor << 1) q = MemValue(two_power(k)) e = MemValue(twos_complement(normalized_divisor.read())) qr = q.read() er = e.read() for i in range(theta): qr = qr + shift_two(qr * er, k) er = shift_two(er * er, k) q = qr res = shift_two(q, (2 * k - 2 * f - cnt_leading_zeros)) return res
def approximate_reciprocal(divisor, k, f, theta): """ returns aproximation of 1/divisor where type(divisor) = cint """ def twos_complement(x): bits = x.bit_decompose(k)[::-1] bit_array = Array(k, cint) bit_array.assign(bits) twos_result = MemValue(cint(0)) @for_range(k) def block(i): val = twos_result.read() val <<= 1 val += 1 - bit_array[i] twos_result.write(val) return twos_result.read() + 1 bit_array = Array(k, cint) bits = divisor.bit_decompose(k)[::-1] bit_array.assign(bits) cnt_leading_zeros = MemValue(regint(0)) flag = MemValue(regint(0)) cnt_leading_zeros = MemValue(regint(0)) normalized_divisor = MemValue(divisor) @for_range(k) def block(i): flag.write(flag.read() | bit_array[i] == 1) @if_(flag.read() == 0) def block(): cnt_leading_zeros.write(cnt_leading_zeros.read() + 1) normalized_divisor.write(normalized_divisor << 1) q = MemValue(two_power(k)) e = MemValue(twos_complement(normalized_divisor.read())) qr = q.read() er = e.read() for i in range(theta): qr = qr + shift_two(qr * er, k) er = shift_two(er * er, k) q = qr res = shift_two(q, (2*k - 2*f - cnt_leading_zeros)) return res
def int2FL_plain(a, gamma, l, kappa): lam = gamma - 1 a_abs = 0 v = cint(0) p = cint(0) s = cint(0) z = cint(0) # extracts the sign and calculates the abs s = cint(a < 0) a_abs = a * (1 - 2 * s) # isolates most significative bit a_bits = a_abs.bit_decompose() b = 0 b_c = 1 blen = 0 for a_i in range(len(a_bits) - 1, -1, -1): # enumerate(a_bits): b = (a_bits[a_i]) * (b == 0) * ((b_c) / 2) + b blen = (a_bits[a_i]) * (blen == 0) * ((a_i + 1)) + blen b_c = b_c * 2 # obtains p # blen= len(a_bits) - blen v = a_abs * b # (2 ** (b))#scale a p = - (lam - blen) # (len(a_bits)-blen)) # reduces v v_l = MemValue(v) z_l = MemValue(z) if_then(a_abs > 0) if (lam > l): v_l.write(v_l.read() / (2 ** (gamma - l - 1))) else: v_l.write(v_l.read() * (2 ** l - lam)) else_then() z_l.write(cint(1)) end_if() # corrects output # s is coming from the abs extraction v = cint(v_l.read()) z = cint(z_l.read()) p = cint((p + lam - l) * (1 - z)) return v, p, z, s
def twos_complement(x): bits = x.bit_decompose(k)[::-1] bit_array = Array(k, cint) bit_array.assign(bits) twos_result = MemValue(cint(0)) @for_range(k) def block(i): val = twos_result.read() val <<= 1 val += 1 - bit_array[i] twos_result.write(val) return twos_result.read() + 1