code: def brent_kung_add(A, B, cin=0):
      
      if len(A) != len(B):
          raise ValueError("expected A and B to be equal length")
      N = len(A)
      # generate/propagate logic
      gs = [A[i] & B[i] for i in range(N)]
      ps = [A[i] ^ B[i] for i in range(N)]
      # carry tree
      for i in range(floor(log(N, 2))):
          step = 2**i
          for start in range(2**(i+1)-1, N, 2**(i+1)):
              gs[start] = gs[start] | ps[start] & gs[start-step]
              ps[start] = ps[start] & ps[start-step]
      # inverse carry tree
      for i in range(floor(log(N, 2))-2, -1, -1):
          start = 2**(i+1)-1
          step = 2**i
          while start + step < N:
              gs[start+step] = gs[start+step] | ps[start+step] & gs[start]
              ps[start+step] = ps[start+step] & ps[start]
              start += step
      # sum logic
      ss = [A[0] ^ B[0] ^ cin]
      ss += [A[i] ^ B[i] ^ gs[i-1] for i in range(1, N)]
      return farray(ss), farray(gs)
docs: Return symbolic logic for an N-bit Brent-Kung adder.