package org.bouncycastle.pqc.math.linearalgebra;
import java.security.SecureRandom;
import org.bouncycastle.util.Arrays;
This class implements permutations of the set {0,1,...,n-1} for some given n
> 0, i.e., ordered sequences containing each number m (0 <=
m < n)
once and only once.
/**
* This class implements permutations of the set {0,1,...,n-1} for some given n
* > 0, i.e., ordered sequences containing each number <tt>m</tt> (<tt>0 <=
* m < n</tt>)
* once and only once.
*/
public class Permutation
{
perm holds the elements of the permutation vector, i.e. [perm(0),
perm(1), ..., perm(n-1)]
/**
* perm holds the elements of the permutation vector, i.e. <tt>[perm(0),
* perm(1), ..., perm(n-1)]</tt>
*/
private int[] perm;
Create the identity permutation of the given size.
Params: - n – the size of the permutation
/**
* Create the identity permutation of the given size.
*
* @param n the size of the permutation
*/
public Permutation(int n)
{
if (n <= 0)
{
throw new IllegalArgumentException("invalid length");
}
perm = new int[n];
for (int i = n - 1; i >= 0; i--)
{
perm[i] = i;
}
}
Create a permutation using the given permutation vector.
Params: - perm – the permutation vector
/**
* Create a permutation using the given permutation vector.
*
* @param perm the permutation vector
*/
public Permutation(int[] perm)
{
if (!isPermutation(perm))
{
throw new IllegalArgumentException(
"array is not a permutation vector");
}
this.perm = IntUtils.clone(perm);
}
Create a permutation from an encoded permutation.
Params: - enc – the encoded permutation
/**
* Create a permutation from an encoded permutation.
*
* @param enc the encoded permutation
*/
public Permutation(byte[] enc)
{
if (enc.length <= 4)
{
throw new IllegalArgumentException("invalid encoding");
}
int n = LittleEndianConversions.OS2IP(enc, 0);
int size = IntegerFunctions.ceilLog256(n - 1);
if (enc.length != 4 + n * size)
{
throw new IllegalArgumentException("invalid encoding");
}
perm = new int[n];
for (int i = 0; i < n; i++)
{
perm[i] = LittleEndianConversions.OS2IP(enc, 4 + i * size, size);
}
if (!isPermutation(perm))
{
throw new IllegalArgumentException("invalid encoding");
}
}
Create a random permutation of the given size.
Params: - n – the size of the permutation
- sr – the source of randomness
/**
* Create a random permutation of the given size.
*
* @param n the size of the permutation
* @param sr the source of randomness
*/
public Permutation(int n, SecureRandom sr)
{
if (n <= 0)
{
throw new IllegalArgumentException("invalid length");
}
perm = new int[n];
int[] help = new int[n];
for (int i = 0; i < n; i++)
{
help[i] = i;
}
int k = n;
for (int j = 0; j < n; j++)
{
int i = RandUtils.nextInt(sr, k);
k--;
perm[j] = help[i];
help[i] = help[k];
}
}
Encode this permutation as byte array.
Returns: the encoded permutation
/**
* Encode this permutation as byte array.
*
* @return the encoded permutation
*/
public byte[] getEncoded()
{
int n = perm.length;
int size = IntegerFunctions.ceilLog256(n - 1);
byte[] result = new byte[4 + n * size];
LittleEndianConversions.I2OSP(n, result, 0);
for (int i = 0; i < n; i++)
{
LittleEndianConversions.I2OSP(perm[i], result, 4 + i * size, size);
}
return result;
}
Returns: the permutation vector (perm(0),perm(1),...,perm(n-1))
/**
* @return the permutation vector <tt>(perm(0),perm(1),...,perm(n-1))</tt>
*/
public int[] getVector()
{
return IntUtils.clone(perm);
}
Compute the inverse permutation P-1.
Returns: this-1
/**
* Compute the inverse permutation <tt>P<sup>-1</sup></tt>.
*
* @return <tt>this<sup>-1</sup></tt>
*/
public Permutation computeInverse()
{
Permutation result = new Permutation(perm.length);
for (int i = perm.length - 1; i >= 0; i--)
{
result.perm[perm[i]] = i;
}
return result;
}
Compute the product of this permutation and another permutation.
Params: - p – the other permutation
Returns: this * p
/**
* Compute the product of this permutation and another permutation.
*
* @param p the other permutation
* @return <tt>this * p</tt>
*/
public Permutation rightMultiply(Permutation p)
{
if (p.perm.length != perm.length)
{
throw new IllegalArgumentException("length mismatch");
}
Permutation result = new Permutation(perm.length);
for (int i = perm.length - 1; i >= 0; i--)
{
result.perm[i] = perm[p.perm[i]];
}
return result;
}
checks if given object is equal to this permutation.
The method returns false whenever the given object is not permutation.
Params: - other – -
permutation
Returns: true or false
/**
* checks if given object is equal to this permutation.
* <p>
* The method returns false whenever the given object is not permutation.
*
* @param other -
* permutation
* @return true or false
*/
public boolean equals(Object other)
{
if (!(other instanceof Permutation))
{
return false;
}
Permutation otherPerm = (Permutation)other;
return IntUtils.equals(perm, otherPerm.perm);
}
Returns: a human readable form of the permutation
/**
* @return a human readable form of the permutation
*/
public String toString()
{
String result = "[" + perm[0];
for (int i = 1; i < perm.length; i++)
{
result += ", " + perm[i];
}
result += "]";
return result;
}
Returns: the hash code of this permutation
/**
* @return the hash code of this permutation
*/
public int hashCode()
{
return Arrays.hashCode(perm);
}
Check that the given array corresponds to a permutation of the set
{0, 1, ..., n-1}.
Params: - perm – permutation vector
Returns: true if perm represents an n-permutation and false otherwise
/**
* Check that the given array corresponds to a permutation of the set
* <tt>{0, 1, ..., n-1}</tt>.
*
* @param perm permutation vector
* @return true if perm represents an n-permutation and false otherwise
*/
private boolean isPermutation(int[] perm)
{
int n = perm.length;
boolean[] onlyOnce = new boolean[n];
for (int i = 0; i < n; i++)
{
if ((perm[i] < 0) || (perm[i] >= n) || onlyOnce[perm[i]])
{
return false;
}
onlyOnce[perm[i]] = true;
}
return true;
}
}