231 lines
6.3 KiB
Python
231 lines
6.3 KiB
Python
# Copyright (c) 2013, Kevin Greenan (kmgreen2@gmail.com)
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# Redistributions of source code must retain the above copyright notice, this
|
|
# list of conditions and the following disclaimer.
|
|
#
|
|
# Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution. THIS SOFTWARE IS
|
|
# PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
|
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
|
# NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
import optparse
|
|
import mpmath
|
|
import itertools
|
|
import sys
|
|
import random
|
|
|
|
|
|
def get_combinations(list, k):
|
|
return itertools.combinations(list, k)
|
|
|
|
|
|
def list_to_bm(list):
|
|
bm = 0
|
|
for elm in list:
|
|
bm = bm | (1 << elm)
|
|
return bm
|
|
|
|
|
|
def bm_to_list(bm):
|
|
list = []
|
|
tmp_bm = bm
|
|
count = 0
|
|
while tmp_bm != 0:
|
|
if tmp_bm & 1:
|
|
list.append(count)
|
|
count = count + 1
|
|
tmp_bm = tmp_bm >> 1
|
|
return list
|
|
|
|
|
|
def list_of_list_to_bm_list(list):
|
|
bm_list = []
|
|
for elm in list:
|
|
bm_list.append(list_to_bm(elm))
|
|
|
|
return bm_list
|
|
|
|
|
|
def bm_list_to_list_of_list(bm_list):
|
|
list_of_list = []
|
|
for bm in bm_list:
|
|
list_of_list.append(bm_to_list(bm))
|
|
|
|
return list_of_list
|
|
|
|
|
|
def bm_in(elm, bm):
|
|
if bm & (1 << elm):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def bm(elm):
|
|
return (1 << elm)
|
|
|
|
|
|
def bm_insert(bm, elm):
|
|
bm = bm | (1 << elm)
|
|
return bm
|
|
|
|
|
|
def bm_rm(bm, elm):
|
|
if bm_in(elm, bm):
|
|
bm = bm ^ (1 << elm)
|
|
return bm
|
|
|
|
|
|
def bm_is_subset(bm1, bm2):
|
|
if (bm1 & bm2) ^ bm1 == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def bm_intersection(bm1, bm2):
|
|
return bm1 & bm2
|
|
|
|
|
|
def bm_hw(bm):
|
|
hw = 0
|
|
if bm == 0:
|
|
return hw
|
|
|
|
while bm != 0:
|
|
if (bm & 1) == 1:
|
|
hw += 1
|
|
bm = bm >> 1
|
|
return hw
|
|
|
|
|
|
def create_full_bm(num_bits):
|
|
bm = (1 << num_bits) - 1
|
|
return bm
|
|
|
|
|
|
def find_first(list, find_func):
|
|
for i in range(len(list)):
|
|
if find_func(list[i]):
|
|
elm = list.pop(i)
|
|
return elm
|
|
|
|
return None
|
|
|
|
|
|
def get_num_data_in_parity(parity_bm_list):
|
|
num_data_in_parity = [0 for i in range(m)]
|
|
|
|
for parity_bm in parity_bm_list:
|
|
for i in range(len(num_data_in_parity)):
|
|
if bm_in(i, parity_bm):
|
|
num_data_in_parity[i] += 1
|
|
|
|
return num_data_in_parity
|
|
|
|
|
|
def get_parity_eqns(bm_parity_combinations):
|
|
parity_bms = [0 for i in range(m)]
|
|
data_num = 0
|
|
for parity_comb in bm_parity_combinations:
|
|
for i in range(m):
|
|
if bm_in(i, parity_comb):
|
|
parity_bms[i] = bm_insert(parity_bms[i], data_num)
|
|
data_num += 1
|
|
|
|
return parity_bms
|
|
|
|
if len(sys.argv) != 3:
|
|
print("Usage: %s <num_parities> <num_bits = 2|3>")
|
|
sys.exit(1)
|
|
|
|
m = int(sys.argv[1])
|
|
num_bits = int(sys.argv[2])
|
|
|
|
if m is None or num_bits not in [2, 3]:
|
|
print("Usage: %s <num_parities> <num_bits = 2|3>")
|
|
sys.exit(1)
|
|
|
|
parity_list = [i for i in range(m)]
|
|
parity_combinations = get_combinations(parity_list, num_bits)
|
|
bm_parity_combinations = list_of_list_to_bm_list(parity_combinations)
|
|
|
|
needed_parity_bm = create_full_bm(m)
|
|
|
|
parity_bms_template = "int g_%d_%d_%d_hd_code_parity_bms[] = { %s };"
|
|
data_bms_template = "int g_%d_%d_%d_hd_code_data_bms[] = { %s };"
|
|
|
|
k = mpmath.binomial(m, num_bits)
|
|
used_parities = []
|
|
|
|
while k > m:
|
|
if bm_hw(needed_parity_bm) >= num_bits:
|
|
# If HW >= num_bits, find any such that (elm & needed_parity_bm) == elm
|
|
parity_bm = find_first(
|
|
bm_parity_combinations,
|
|
lambda elm: (
|
|
elm & needed_parity_bm) == elm)
|
|
if parity_bm is not None:
|
|
needed_parity_bm ^= parity_bm
|
|
else:
|
|
# If HW < num_bits, find any such that (elm & needed_parity_bm) ==
|
|
# needed_parity_bm
|
|
parity_bm = find_first(
|
|
bm_parity_combinations,
|
|
lambda elm: (
|
|
elm & needed_parity_bm) == needed_parity_bm)
|
|
if parity_bm is not None:
|
|
needed_parity_bm = (
|
|
needed_parity_bm ^ parity_bm) ^ create_full_bm(m)
|
|
|
|
# If we cannot find one, pop the last chosen element and try another
|
|
full_bm = create_full_bm(m)
|
|
if parity_bm is None:
|
|
parity_to_re_add = used_parities.pop()
|
|
# Added at the end, so we are changing the order
|
|
bm_parity_combinations.append(parity_to_re_add)
|
|
needed_parity_bm |= parity_to_re_add
|
|
k += 1
|
|
else:
|
|
used_parities.append(parity_bm)
|
|
k -= 1
|
|
|
|
for parity_bm in used_parities:
|
|
num_data_in_parity = get_num_data_in_parity(bm_parity_combinations)
|
|
parity_eqns = get_parity_eqns(bm_parity_combinations)
|
|
# print "(%d, %d) : %s : %s : %s" % (k, m, bm_parity_combinations,
|
|
# parity_eqns, num_data_in_parity)
|
|
print(parity_bms_template %
|
|
(k, m, num_bits + 1,
|
|
("%s" % parity_eqns).replace("[", "").replace("]", "")))
|
|
print(data_bms_template %
|
|
(k, m, num_bits + 1,
|
|
("%s" % bm_parity_combinations).replace("[", "").replace("]", "")))
|
|
|
|
bm_parity_combinations.append(parity_bm)
|
|
k += 1
|
|
|
|
num_data_in_parity = get_num_data_in_parity(bm_parity_combinations)
|
|
parity_eqns = get_parity_eqns(bm_parity_combinations)
|
|
# print"(%d, %d) : %s : %s" % (k, m, bm_parity_combinations,
|
|
# num_data_in_parity)
|
|
print(parity_bms_template %
|
|
(k, m, num_bits + 1,
|
|
("%s" % parity_eqns).replace("[", "").replace("]", "")))
|
|
print(data_bms_template %
|
|
(k, m, num_bits + 1,
|
|
("%s" % bm_parity_combinations).replace("[", "").replace("]", "")))
|