{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "054915e4", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%HTML\n", "" ] }, { "cell_type": "code", "execution_count": 11, "id": "62243eff", "metadata": { "jupyter": { "source_hidden": true } }, "outputs": [ { "data": { "text/plain": [ "[0, 0, 0, 0, 1, 1, 0, 1]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def id2bit(ls: list):\n", " \"\"\"\n", " Converts a list of indices into a binary representation (bit vector).\n", "\n", " Given a list of indices (ls), this function returns a list of bits where\n", " the bit positions corresponding to the indices in the list are set to 1,\n", " and all other positions are set to 0. The resulting list is reversed.\n", "\n", " Args:\n", " ls (list): A list of indices to be converted to bits.\n", "\n", " Returns:\n", " list: A list of bits representing the binary values.\n", " \"\"\"\n", " if len(ls) == 0:\n", " return [0, 0, 0, 0, 0, 0, 0, 0] # Return a default 8-bit array\n", " aa = [0 for _ in range(max(ls) + 1)]\n", " for i in ls:\n", " aa[i] = 1\n", " return aa[::-1]\n", "\n", "\n", "def bit2id(ls: list, log=False):\n", " \"\"\"\n", " Converts a binary list (bit vector) back to a list of indices.\n", "\n", " Given a list of bits (ls), this function returns the indices of the bits\n", " that are set to 1. The binary list is reversed during the conversion.\n", "\n", " Args:\n", " ls (list): A list of bits representing a binary value.\n", " log (bool, optional): Whether to log intermediate steps (default is False).\n", "\n", " Returns:\n", " list: A list of indices where the bits are set to 1.\n", " \"\"\"\n", " ls = ls[::-1]\n", " aa = []\n", "\n", " for i in range(len(ls)):\n", " if ls[i] == 1:\n", " aa.append(i)\n", " return aa[::-1]\n", "\n", "\n", "def bit2mul(a, b, log=False):\n", " \"\"\"\n", " Multiplies two binary numbers represented as lists of bits.\n", "\n", " This function multiplies two binary numbers by performing a bitwise\n", " multiplication and addition over Galois Field (GF(2)).\n", "\n", " Args:\n", " a (list): A list of bits representing the first binary number.\n", " b (list): A list of bits representing the second binary number.\n", " log (bool, optional): Whether to log intermediate steps (default is False).\n", "\n", " Returns:\n", " list: The resulting binary number (list of bits).\n", " \"\"\"\n", " ai = bit2id(a)\n", " bi = bit2id(b)\n", " a, b = a[::-1], b[::-1]\n", "\n", " if ai == []:\n", " return a\n", " elif bi == []:\n", " return b\n", "\n", " addn = [[ai[i] + bi[j] for j in range(len(bi))][::-1] for i in range(len(ai))][::-1]\n", " addn = [id2bit(i) for i in addn]\n", "\n", " maxsiz = max([len(i) for i in addn])\n", " for i in range(len(addn)):\n", " if len(addn[i]) < maxsiz:\n", " addn[i] = [0 for _ in range(maxsiz - len(addn[i]))] + addn[i]\n", "\n", " smm = []\n", " for i in range(maxsiz):\n", " t = 0\n", " for j in addn:\n", " t += j[i]\n", " smm.append(t % 2)\n", "\n", " return smm\n", "\n", "\n", "def bit2add(a, b):\n", " \"\"\"\n", " Adds two binary numbers represented as lists of bits (bitwise addition).\n", "\n", " This function adds two binary numbers by performing a bitwise addition over GF(2).\n", "\n", " Args:\n", " a (list): A list of bits representing the first binary number.\n", " b (list): A list of bits representing the second binary number.\n", "\n", " Returns:\n", " list: The resulting binary number after addition (list of bits).\n", " \"\"\"\n", " a, b = list(a), list(b)\n", " a, b = a[::-1], b[::-1]\n", " maxsiz = max(len(a), len(b))\n", "\n", " if len(a) < maxsiz:\n", " a = a + [0 for _ in range(maxsiz - len(a))]\n", " if len(b) < maxsiz:\n", " b = b + [0 for _ in range(maxsiz - len(b))]\n", "\n", " smm = []\n", " for i in range(maxsiz):\n", " smm.append((a[i] + b[i]) % 2)\n", "\n", " return smm[::-1]\n", "\n", "\n", "def bit2str(bit: list):\n", " \"\"\"\n", " Converts a list of bits into a string.\n", "\n", " This function converts a list of binary bits (0s and 1s) into a string of characters.\n", "\n", " Args:\n", " bit (list): A list of bits (0s and 1s).\n", "\n", " Returns:\n", " str: The string representation of the binary bits.\n", " \"\"\"\n", " s = \"\"\n", " for i in bit:\n", " s += str(i)\n", " return s\n", "\n", "\n", "def str2bit(s: str):\n", " \"\"\"\n", " Converts a string of '0's and '1's into a list of bits.\n", "\n", " This function converts a string containing '0's and '1's into a list of integer bits.\n", "\n", " Args:\n", " s (str): A string containing '0's and '1's.\n", "\n", " Returns:\n", " list: A list of bits (integers).\n", "\n", " Raises:\n", " ValueError: If the string contains characters other than '0' and '1'.\n", " \"\"\"\n", " if set(s).issubset(set(\"01\")):\n", " bit = [int(i) for i in s]\n", " return bit\n", " else:\n", " print(\"bit string should contain 1s and 0s\")\n", "\n", "\n", "def modgf(dsr: list, dnt=[1, 0, 0, 0, 1, 1, 0, 1, 1]):\n", " \"\"\"\n", " Performs polynomial division over Galois Field (GF(2)).\n", "\n", " This function divides the binary polynomial `dsr` by the binary polynomial `dnt`\n", " and returns the quotient and remainder.\n", "\n", " Args:\n", " dsr (list): The dividend as a list of bits (binary polynomial).\n", " dnt (list, optional): The divisor as a list of bits (default is a predefined irreducible polynomial).\n", "\n", " Returns:\n", " tuple: The remainder and quotient as lists of bits.\n", " \"\"\"\n", " dsr = bit2id(dsr)\n", " dnt = bit2id(dnt)\n", " qtnt = []\n", "\n", " while len(dnt) != 0 and len(dsr) != 0 and (max(dnt) - max(dsr) >= 0):\n", " ml = max(dnt) - max(dsr)\n", " qtnt.append(ml)\n", " plus = id2bit(dnt)\n", " minus = id2bit([ml + i for i in dsr])\n", " rem = bit2add(plus, minus)\n", " dnt = bit2id(rem)\n", "\n", " return id2bit(dnt), id2bit(qtnt)\n", "\n", "\n", "def ext_eucld(a, b, log=False):\n", " \"\"\"\n", " Extended Euclidean algorithm for binary polynomials.\n", "\n", " This function computes the extended Euclidean algorithm for binary polynomials `a` and `b`,\n", " returning the coefficients of the linear combination of `a` and `b` that equals the greatest common divisor (GCD).\n", "\n", " Args:\n", " a (list): A list of bits representing the first binary polynomial.\n", " b (list): A list of bits representing the second binary polynomial.\n", " log (bool, optional): Whether to log intermediate steps (default is False).\n", "\n", " Returns:\n", " list: The coefficients of the linear combination of `a` and `b` (as lists of bits).\n", " \"\"\"\n", " ai, bi = bit2id(a), bit2id(b)\n", " if len(ai) != 0 and len(bi) != 0:\n", " if max(max(ai), max(bi)) == max(bi):\n", " a, b = b, a\n", " elif len(ai) == 0 and len(bi) != 0:\n", " a, b = b, a\n", "\n", " def eucld(a, b, log=False):\n", " a, b = a[::-1], b[::-1]\n", "\n", " if set(b) == set([0]) or (b[0] == 1 and (set(b[1:]) == set([0]))):\n", " return []\n", "\n", " ls = []\n", "\n", " while not (b[0] == 1 and (set(b[1:]) == set([0]))):\n", " r, idx = modgf(b[::-1], dnt=a[::-1])\n", " r, idx = r[::-1], idx[::-1]\n", "\n", " if set(r) == set([0]):\n", " return ls\n", "\n", " ls.append(idx[::-1])\n", " a = b\n", " b = r\n", " return ls\n", "\n", " row = [\n", " [[0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0]],\n", " [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1]],\n", " ]\n", "\n", " ls = eucld(a, b)\n", " for i in ls:\n", " r10, r11 = row[-1][0], row[-1][1]\n", " r20, r21 = row[-2][0], row[-2][1]\n", " r0 = bit2add(r20, bit2mul(r10, i))\n", " r1 = bit2add(r21, bit2mul(r11, i))\n", " rowl = [r0, r1]\n", " row.append(rowl)\n", "\n", " return row[-1]\n", "\n", "\n", "def Gfinv(bit, irrpoly=[1, 0, 0, 0, 1, 1, 0, 1, 1]):\n", " \"\"\"\n", " Computes the multiplicative inverse of a binary polynomial over GF(2).\n", "\n", " This function uses the extended Euclidean algorithm to compute the inverse of a binary polynomial `bit`\n", " with respect to a predefined irreducible polynomial `irrpoly`.\n", "\n", " Args:\n", " bit (list): A list of bits representing the binary polynomial to be inverted.\n", " irrpoly (list, optional): The irreducible polynomial used for the field (default is a predefined polynomial).\n", "\n", " Returns:\n", " list: The multiplicative inverse of the polynomial `bit` (list of bits).\n", " \"\"\"\n", " if set(bit) == set(\"0\"):\n", " return \"--\"\n", "\n", " ans = ext_eucld(irrpoly, bit)\n", " ans = ans[-1][-len(bit) :]\n", " return ans\n", "\n", "\n", "# Example call\n", "Gfinv([0, 0, 0, 0, 0, 1, 0, 0], irrpoly=[0, 0, 0, 1, 0, 0, 1, 1])" ] }, { "cell_type": "code", "execution_count": 4, "id": "0c2b9aab", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 0, 0, 0, 1, 1, 0, 1]\n" ] } ], "source": [ "def id2bit(ls: list):\n", " if len(ls) == 0:\n", " return [0, 0, 0, 0, 0, 0, 0, 0] # Return a default 8-bit array\n", " aa = [0 for _ in range(max(ls) + 1)]\n", " for i in ls:\n", " aa[i] = 1\n", " return aa[::-1]\n", "\n", "def bit2id(ls: list, log=False):\n", " ls = ls[::-1]\n", " aa = []\n", " for i in range(len(ls)):\n", " if ls[i] == 1:\n", " aa.append(i)\n", " return aa[::-1]\n", "\n", "def bit2mul(a, b, log=False):\n", " ai = bit2id(a)\n", " bi = bit2id(b)\n", " a, b = a[::-1], b[::-1]\n", " \n", " if ai == []:\n", " return a\n", " elif bi == []:\n", " return b\n", " \n", " addn = [[ai[i] + bi[j] for j in range(len(bi))][::-1] for i in range(len(ai))][::-1]\n", " addn = [id2bit(i) for i in addn]\n", " \n", " maxsiz = max([len(i) for i in addn])\n", " for i in range(len(addn)):\n", " if len(addn[i]) < maxsiz:\n", " addn[i] = [0 for _ in range(maxsiz - len(addn[i]))] + addn[i]\n", " \n", " smm = []\n", " for i in range(maxsiz):\n", " t = 0\n", " for j in addn:\n", " t += j[i]\n", " smm.append(t % 2)\n", " \n", " return smm\n", "\n", "def bit2add(a, b):\n", " a, b = list(a), list(b)\n", " a, b = a[::-1], b[::-1]\n", " maxsiz = max(len(a), len(b))\n", " \n", " if len(a) < maxsiz:\n", " a = a + [0 for _ in range(maxsiz - len(a))]\n", " if len(b) < maxsiz:\n", " b = b + [0 for _ in range(maxsiz - len(b))]\n", " \n", " smm = []\n", " for i in range(maxsiz):\n", " smm.append((a[i] + b[i]) % 2)\n", " \n", " return smm[::-1]\n", "\n", "def bit2str(bit: list):\n", " s = \"\"\n", " for i in bit:\n", " s += str(i)\n", " return s\n", "\n", "def str2bit(s: str):\n", " if set(s).issubset(set('01')):\n", " bit = [int(i) for i in s]\n", " return bit\n", " else:\n", " print(\"bit string should contain 1s and 0s\")\n", "\n", "def modgf(dsr: list, dnt=None):\n", " if dnt is None:\n", " dnt = [1, 0, 0, 0, 1, 1, 0, 1, 1]\n", " \n", " dsr = bit2id(dsr)\n", " dnt = bit2id(dnt)\n", " qtnt = []\n", " \n", " while len(dnt) != 0 and len(dsr) != 0 and (max(dnt) - max(dsr) >= 0):\n", " ml = max(dnt) - max(dsr)\n", " qtnt.append(ml)\n", " plus = id2bit(dnt)\n", " minus = id2bit([ml + i for i in dsr])\n", " rem = bit2add(plus, minus)\n", " dnt = bit2id(rem)\n", " \n", " return id2bit(dnt), id2bit(qtnt)\n", "\n", "def ext_eucld(a, b, log=False):\n", " ai, bi = bit2id(a), bit2id(b)\n", " if len(ai) != 0 and len(bi) != 0:\n", " if max(max(ai), max(bi)) == max(bi):\n", " a, b = b, a\n", " elif len(ai) == 0 and len(bi) != 0:\n", " a, b = b, a\n", " \n", " def eucld(a, b, log=False):\n", " a, b = a[::-1], b[::-1]\n", " \n", " if set(b) == set([0]) or (b[0] == 1 and set(b[1:]) == set([0])):\n", " return []\n", " \n", " ls = []\n", " \n", " while not (b[0] == 1 and set(b[1:]) == set([0])):\n", " r, idx = modgf(b[::-1], dnt=a[::-1])\n", " r, idx = r[::-1], idx[::-1]\n", " \n", " if set(r) == set([0]):\n", " return ls\n", " \n", " ls.append(idx[::-1])\n", " a = b\n", " b = r\n", " return ls\n", " \n", " row = [[[0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0]],\n", " [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1]]]\n", " \n", " ls = eucld(a, b)\n", " for i in ls:\n", " r10, r11 = row[-1][0], row[-1][1]\n", " r20, r21 = row[-2][0], row[-2][1]\n", " r0 = bit2add(r20, bit2mul(r10, i))\n", " r1 = bit2add(r21, bit2mul(r11, i))\n", " rowl = [r0, r1]\n", " row.append(rowl)\n", " \n", " return row[-1]\n", "\n", "def Gfinv(bit, irrpoly=None):\n", " if irrpoly is None:\n", " irrpoly = [1, 0, 0, 0, 1, 1, 0, 1, 1]\n", " \n", " if set(bit) == set([0]):\n", " return '--'\n", " \n", " ans = ext_eucld(irrpoly, bit)\n", " ans = ans[-1][-len(bit):]\n", " return ans\n", "\n", "# Example call\n", "print(Gfinv([0, 0, 0, 0, 0, 1, 0, 0], irrpoly=[0, 0, 0, 1, 0, 0, 1, 1]))\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "edb53805", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 0, 0, 0, 1, 1, 0, 1]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def genmapping(n: int, irrpoly):\n", " \"\"\"\n", " Generates the elements of GF(2^n) and their corresponding multiplicative inverses\n", " based on the provided irreducible polynomial.\n", "\n", " Parameters:\n", " n (int): The size of the Galois Field (GF(2^n)). Determines the number of elements\n", " in the field, which is 2^n.\n", " irrpoly (list): A list of bits representing the irreducible polynomial used\n", " for the finite field operations (e.g., [1, 0, 0, 1] for x^3 + 1).\n", "\n", " Returns:\n", " tuple: A tuple containing:\n", " - gf (list): A list of binary strings of length `n`, representing all elements\n", " of GF(2^n). The binary strings are padded with leading zeros.\n", " - invmap (dict): A dictionary mapping the index of each element in `gf` to the\n", " index of its multiplicative inverse, using the irreducible\n", " polynomial for the field.\n", "\n", " Example:\n", " gf, invmap = genmapping(3, [1, 0, 0, 1])\n", " # gf will contain the elements ['000', '001', '010', '011', '100', '101', '110', '111']\n", " # invmap will contain a mapping of the inverses for each non-zero element.\n", " \"\"\"\n", " gf = [str(bin(i))[2:] for i in range(2**n)]\n", "\n", " # Ensure each element has length n (pad with leading zeros if necessary)\n", " for i in range(len(gf)):\n", " if len(gf[i]) < n:\n", " gf[i] = \"0\" * (n - len(gf[i])) + gf[i]\n", "\n", " # Create mappings: index -> element (key2ele) and element -> index (ele2key)\n", " key2ele = dict(enumerate(gf))\n", " ele2key = dict([i[::-1] for i in list(enumerate(gf))])\n", "\n", " # Generate the inverse map for all non-zero elements\n", " invmap = dict()\n", " for i in gf:\n", " if set(i) != set(\"0\"): # Skip zero element\n", " inv = bit2str(Gfinv(str2bit(i), irrpoly=irrpoly)) # Find the inverse of i\n", <<<<<<< HEAD " invmap[ele2key[i]] = ele2key[inv] # Map the inverse using element-to-key mapping\n", " \n", " return gf, invmap\n", "# Example call\n", "Gfinv([0, 0, 0, 0, 0, 1, 0, 0], irrpoly=[0, 0, 0, 1, 0, 0, 1, 1])\n" ======= " invmap[ele2key[i]] = ele2key[\n", " inv\n", " ] # Map the inverse using element-to-key mapping\n", "\n", " return gf, invmap" >>>>>>> ffbe3bbd8623bff453d16b942b7cf035c20d808c ] }, { "cell_type": "code", "execution_count": 6, "id": "d4ca99d5", "metadata": {}, "outputs": [], "source": [ "gf5, invmap = genmapping(n=5, irrpoly=id2bit([5, 2, 0]))" ] }, { "cell_type": "code", "execution_count": 7, "id": "44e4797e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "set(invmap.values()) == set(invmap.keys())" ] }, { "cell_type": "code", "execution_count": 8, "id": "b08bd2b6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1: 1,\n", " 2: 18,\n", " 3: 28,\n", " 4: 9,\n", " 5: 23,\n", " 6: 14,\n", " 7: 12,\n", " 8: 22,\n", " 9: 4,\n", " 10: 25,\n", " 11: 16,\n", " 12: 7,\n", " 13: 15,\n", " 14: 6,\n", " 15: 13,\n", " 16: 11,\n", " 17: 24,\n", " 18: 2,\n", " 19: 29,\n", " 20: 30,\n", " 21: 26,\n", " 22: 8,\n", " 23: 5,\n", " 24: 17,\n", " 25: 10,\n", " 26: 21,\n", " 27: 31,\n", " 28: 3,\n", " 29: 19,\n", " 30: 20,\n", " 31: 27}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "invmap" ] }, { "cell_type": "code", "execution_count": null, "id": "90374ee9", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 9, "id": "06a7f472", "metadata": {}, "outputs": [], "source": [ "gf28 = [str(bin(i))[2:] for i in range(256)]\n", "for i in range(len(gf28)):\n", " if len(gf28[i]) < 8:\n", " gf28[i] = \"0\" * (8 - len(gf28[i])) + gf28[i]\n", "\n", "key2ele = dict(enumerate(gf28))\n", "ele2key = dict([i[::-1] for i in list(enumerate(gf28))])\n", "invmap = dict()\n", "for i in gf28:\n", " if set(i) != set(\"0\"):\n", " inv = bit2str(Gfinv(str2bit(i)))\n", " invmap[ele2key[i]] = ele2key[inv]" ] }, { "cell_type": "code", "execution_count": 10, "id": "5fcfedd5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "set(invmap.values()) == set(invmap.keys())" ] }, { "cell_type": "code", "execution_count": null, "id": "4059dff6", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "06b3e5d5", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "37dd903a", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }