Created
February 3, 2024 21:37
-
-
Save hacklex/919438bc2c7f1c174dde78c461e67546 to your computer and use it in GitHub Desktop.
Permutation polynomial computation in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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