-rw-r--r-- 2145 mceliece-sage-20221023/fixedweight.sage raw
import parameters
def fixedweight(randombits,params):
  r'''
  Return the output of the Classic McEliece FixedWeight function
  using the specified source of random bits
  for the specified parameters.
  INPUT:
  "randombits" - a function that, on input r, returns a list of r bits
  "params" - a Classic McEliece parameter set
  '''
  assert isinstance(params,parameters.parameters)
  m = params.m
  q = params.q
  n = params.n
  t = params.t
  sigma1 = params.sigma1
  # "The integer tau is defined as t if n=q;
  #  as 2t if q/2 <= n < q; as 4t if q/4 <= n < q/2; etc."
  tau = t
  while tau*n < t*q: tau *= 2
  
  # "All of the selected parameter sets have q/2 <= n <= q,
  #  so tau in {t,2t}."
  assert q/2 <= n
  assert n <= q
  assert tau == t or tau == 2*t
  while True:
    # "Generate sigma_1 tau uniform random bits b_0,b_1,...,b_{sigma_1 tau - 1}."
    b = randombits(sigma1*tau)
    # "Define d_j = sum_{i=0}^{m-1} b_{sigma_1 j + i} 2^i for each j in {0,1,...,tau-1}."
    d = [sum(b[sigma1*j+i]<<i for i in range(m)) for j in range(tau)]
    # "Define a_0,a_1,...,a_{t-1} as the first t entries in d_0,d_1,...,d_{tau-1}
    #  in the range {0,1,...,n-1}.
    #  If there are fewer than t such entries, restart the algorithm."
    a = [dj for dj in d if dj<n]
    if len(a) < t: continue
    a = a[:t]
    # "If a_0,a_1,...,a_{t-1} are not all distinct, restart the algorithm."
    if len(set(a)) < t: continue
    # "Define e = (e_0,e_1,...,e_{n-1}) in F_2^n
    #  as the weight-t vector such that e_{a_i} = 1 for each i."
    e = [0]*n
    for ai in a: e[ai] = 1
    # "Return e."
    return e
# ----- miscellaneous tests
def test1():
  def randombits(r):
    return [randrange(2) for j in range(r)]
  for system in parameters.alltests:
    P = parameters.parameters(system,allowtestparams=True)
    n = P.n
    t = P.t
    print('fixedweight %s' % system)
    sys.stdout.flush()
    for loop in range(10):
      e = fixedweight(randombits,P)
      
      "outputs a vector e in F_2^n of weight t"
      assert len(e) == n
      assert sum(1 if ej else 0 for ej in e) == t
if __name__ == '__main__':
  test1()