Skip to content

Instantly share code, notes, and snippets.

@hacklex
Created February 3, 2024 21:37
Show Gist options
  • Save hacklex/919438bc2c7f1c174dde78c461e67546 to your computer and use it in GitHub Desktop.
Save hacklex/919438bc2c7f1c174dde78c461e67546 to your computer and use it in GitHub Desktop.
Permutation polynomial computation in C#
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.WriteLine("Permutation: (0 1)");
Console.WriteLine("Permutation polynomial:");
Console.WriteLine(BytePolynomial.FromPermutation(new BitSwapPermutation(0, 1)));
Console.ReadKey();
public struct BitSwapPermutation
{
public int iFrom;
public int iTo;
public BitSwapPermutation(int from, int to)
{
iFrom = from;
iTo = to;
}
public byte Apply(byte input)
{
byte fromBit = (byte)((input & (1 << iFrom)) >> iTo);
byte toBit = (byte)((input & (1 << iTo)) >> iFrom);
byte invertedMaskForBoth = (byte)~((1 << iFrom) | (1 << iTo));
return (byte)((input & invertedMaskForBoth) | fromBit | toBit);
}
public byte this[byte input] => Apply(input);
}
public struct BytePolynomial
{
public BytePolynomial()
{
}
public override string ToString()
{
string superscriptCharacters = "⁰¹²³⁴⁵⁶⁷⁸⁹";
string NumToSuperscript(int num)
{
string result = "";
while (num > 0)
{
result = superscriptCharacters[num % 10] + result;
num /= 10;
}
return result.PadRight(3);
}
string DegOfXIfNotZero(int deg)
{
if (deg == 0) return "";
return $"x{NumToSuperscript(deg)}";
}
string result = "";
for (int i = 0; i < Coefficients.Count; i++)
{
result += $"{Coefficients[i]}{DegOfXIfNotZero(i)}".PadRight(7);
if (i < Coefficients.Count - 1) result += " + ";
}
return result;
}
public bool IsZero()
{
for (int i = 0; i < Coefficients.Count; i++)
{
if (Coefficients[i] != 0) return false;
}
return true;
}
public List<byte> Coefficients { get; set; } = new(256);
public byte Apply(byte x)
{
byte result = 0;
byte xDegree = 1;
for (int i = 0; i < Coefficients.Count; i++)
{
result += (byte)(Coefficients[i] * xDegree);
xDegree *= x;
}
return result;
}
public byte this[byte x] => Apply(x);
public static BytePolynomial operator +(BytePolynomial a, BytePolynomial b)
{
BytePolynomial result = new();
for (int i = 0; i < Math.Max(a.Coefficients.Count, b.Coefficients.Count); i++)
{
byte aCoeff = i < a.Coefficients.Count ? a.Coefficients[i] : (byte)0;
byte bCoeff = i < b.Coefficients.Count ? b.Coefficients[i] : (byte)0;
result.Coefficients.Add((byte)(aCoeff + bCoeff));
}
result.Truncate();
return result;
}
public static BytePolynomial operator *(BytePolynomial a, BytePolynomial b)
{
BytePolynomial result = new();
for (int i = 0; i < a.Coefficients.Count; i++)
{
for (int j = 0; j < b.Coefficients.Count; j++)
{
int newDegree = i + j;
if (newDegree >= result.Coefficients.Count)
{
result.Coefficients.AddRange(Enumerable.Repeat((byte)0, newDegree - result.Coefficients.Count + 1));
}
result.Coefficients[newDegree] += (byte)(a.Coefficients[i] * b.Coefficients[j]);
}
}
result.Truncate();
return result;
}
public static BytePolynomial operator -(BytePolynomial a, BytePolynomial b)
{
BytePolynomial result = new();
for (int i = 0; i < Math.Max(a.Coefficients.Count, b.Coefficients.Count); i++)
{
byte aCoeff = i < a.Coefficients.Count ? a.Coefficients[i] : (byte)0;
byte bCoeff = i < b.Coefficients.Count ? b.Coefficients[i] : (byte)0;
result.Coefficients.Add((byte)(aCoeff - bCoeff));
}
result.Truncate();
return result;
}
public BytePolynomial Deg(int deg)
{
BytePolynomial result = new() { Coefficients = { 1 } };
BytePolynomial a = this;
while (deg > 0)
{
if (deg % 2 == 1)
{
result *= a;
}
a *= a;
deg /= 2;
}
return result;
}
public static BytePolynomial FromPermutation(BitSwapPermutation permutation)
{
BytePolynomial result = new();
for (int i = 0; i < 256; i++)
{
byte a = (byte)i;
var sigma = permutation.Apply(a);
result += new BytePolynomial() { Coefficients = { sigma } } * (One - (X - a).Deg(255));
}
return result;
}
public static BytePolynomial operator -(BytePolynomial x, byte coeff0)
{
BytePolynomial result = new();
result.Coefficients.AddRange(x.Coefficients);
if (result.Coefficients.Count == 0) result.Coefficients.Add(0);
result.Coefficients[0] -= coeff0;
result.Truncate();
return result;
}
public static BytePolynomial X => new BytePolynomial() { Coefficients = { 0, 1 } };
public static BytePolynomial One => new() { Coefficients = { 1 } };
void Truncate()
{
while (Coefficients.Count > 0 && Coefficients[Coefficients.Count - 1] == 0)
{
Coefficients.RemoveAt(Coefficients.Count - 1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment