def gf2_div_normal(dividend, divisor): N = len(dividend) - 1 D = len(divisor) - 1 if dividend[N] == 0 or divisor[D] == 0: dividend, divisor = strip_zeros(dividend), strip_zeros(divisor) if not divisor.any(): # if every element is zero raise ZeroDivisionError("polynomial division") elif D > N: q = np.array([]) return q, dividend else: u = dividend.astype("uint8") v = divisor.astype("uint8") m = len(u) - 1 n = len(v) - 1 scale = v[n].astype("uint8") q = np.zeros((max(m - n + 1, 1), ), u.dtype) r = u.astype(u.dtype) for k in range(0, m - n + 1): d = scale and r[m - k].astype("uint8") q[-1 - k] = d r[m - k - n:m - k + 1] = np.logical_xor(r[m - k - n:m - k + 1], np.logical_and(d, v)) r = strip_zeros(r) return q, r
def gf2_div(dividend, divisor,p): N = len(dividend) - 1 D = len(divisor) - 1 if dividend[N] == 0 or divisor[D] == 0: dividend, divisor = strip_zeros(dividend), strip_zeros(divisor) if not divisor.any(): # if every element is zero raise ZeroDivisionError("polynomial division") elif D > N: f_temp = dividend num_temp = Galois_Field_mod_2.gf2_mul_normal(f_temp,p) result, rem = gf2_div(num_temp,divisor,p) return rem,result else: u = dividend.astype("uint8") v = divisor.astype("uint8") m = len(u) - 1 n = len(v) - 1 scale = v[n].astype("uint8") q = np.zeros((max(m - n + 1, 1),), u.dtype) r = u.astype(u.dtype) for k in range(0, m - n + 1): d = scale and r[m - k].astype("uint8") q[-1 - k] = d r[m - k - n:m - k + 1] = np.logical_xor(r[m - k - n:m - k + 1], np.logical_and(d, v)) r = strip_zeros(r) return q, r
def gf2_add(a, b): a, b = check_type(a, b) a, b = strip_zeros(a), strip_zeros(b) N = len(a) D = len(b) if N == D: res = xor(a, b) elif N > D: res = np.concatenate((xor(a[:D], b), a[D:])) else: res = np.concatenate((xor(a, b[:N]), b[N:])) return strip_zeros(res)
def gf2_mul(a, b, p): mod_degree = len(p) - 1 fsize = len(a) + len(b) - 1 fsize = 2**np.ceil(np.log2(fsize)).astype( int) #use nearest power of two much faster fslice = slice(0, fsize) ta = np.fft.fft(a, fsize) tb = np.fft.fft(b, fsize) res = np.fft.ifft(ta * tb)[fslice].copy() k = np.mod(np.rint(np.real(res)), 2).astype('uint8') # temp = Reverse(a) # print("---") # for i in temp: # print(i,end="") # print("end---") result = strip_zeros(k) if isGreater(result, p): q, result = gf2_div_normal(result, p) return result
def gf2_mul_normal(a, b): fsize = len(a) + len(b) - 1 fsize = 2**np.ceil(np.log2(fsize)).astype( int) #use nearest power of two much faster fslice = slice(0, fsize) ta = np.fft.fft(a, fsize) tb = np.fft.fft(b, fsize) res = np.fft.ifft(ta * tb)[fslice].copy() k = np.mod(np.rint(np.real(res)), 2).astype('uint8') return strip_zeros(k)
def mul(a, b): """Performs polynomial multiplication over GF2. Parameters ---------- b : ndarray (uint8 or bool) or list Multiplicand polynomial's coefficients. a : ndarray (uint8 or bool) or list Multiplier polynomial's coefficients. Returns ------- out : ndarray of uint8 Notes ----- This function performs exactly the same operation as gf2_mul but here instead of the fft, convolution in time domain is used. This is because this function must be used multiple times in gf2_xgcd and performing the fft in that instance introduced significant overhead. """ out = np.mod(np.convolve(a, b), 2).astype("uint8") return strip_zeros(out)