diff options
Diffstat (limited to 'core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java')
-rw-r--r-- | core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java new file mode 100644 index 00000000..8e613e7b --- /dev/null +++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java @@ -0,0 +1,256 @@ +package org.spongycastle.pqc.math.linearalgebra; + + +/** + * This class implements vectors over the finite field + * <tt>GF(2<sup>m</sup>)</tt> for small <tt>m</tt> (i.e., + * <tt>1<m<32</tt>). It extends the abstract class {@link Vector}. + */ +public class GF2mVector + extends Vector +{ + + /** + * the finite field this vector is defined over + */ + private GF2mField field; + + /** + * the element array + */ + private int[] vector; + + /** + * creates the vector over GF(2^m) of given length and with elements from + * array v (beginning at the first bit) + * + * @param field finite field + * @param v array with elements of vector + */ + public GF2mVector(GF2mField field, byte[] v) + { + this.field = new GF2mField(field); + + // decode vector + int d = 8; + int count = 1; + while (field.getDegree() > d) + { + count++; + d += 8; + } + + if ((v.length % count) != 0) + { + throw new IllegalArgumentException( + "Byte array is not an encoded vector over the given finite field."); + } + + length = v.length / count; + vector = new int[length]; + count = 0; + for (int i = 0; i < vector.length; i++) + { + for (int j = 0; j < d; j += 8) + { + vector[i] |= (v[count++] & 0xff) << j; + } + if (!field.isElementOfThisField(vector[i])) + { + throw new IllegalArgumentException( + "Byte array is not an encoded vector over the given finite field."); + } + } + } + + /** + * Create a new vector over <tt>GF(2<sup>m</sup>)</tt> of the given + * length and element array. + * + * @param field the finite field <tt>GF(2<sup>m</sup>)</tt> + * @param vector the element array + */ + public GF2mVector(GF2mField field, int[] vector) + { + this.field = field; + length = vector.length; + for (int i = vector.length - 1; i >= 0; i--) + { + if (!field.isElementOfThisField(vector[i])) + { + throw new ArithmeticException( + "Element array is not specified over the given finite field."); + } + } + this.vector = IntUtils.clone(vector); + } + + /** + * Copy constructor. + * + * @param other another {@link GF2mVector} + */ + public GF2mVector(GF2mVector other) + { + field = new GF2mField(other.field); + length = other.length; + vector = IntUtils.clone(other.vector); + } + + /** + * @return the finite field this vector is defined over + */ + public GF2mField getField() + { + return field; + } + + /** + * @return int[] form of this vector + */ + public int[] getIntArrayForm() + { + return IntUtils.clone(vector); + } + + /** + * @return a byte array encoding of this vector + */ + public byte[] getEncoded() + { + int d = 8; + int count = 1; + while (field.getDegree() > d) + { + count++; + d += 8; + } + + byte[] res = new byte[vector.length * count]; + count = 0; + for (int i = 0; i < vector.length; i++) + { + for (int j = 0; j < d; j += 8) + { + res[count++] = (byte)(vector[i] >>> j); + } + } + + return res; + } + + /** + * @return whether this is the zero vector (i.e., all elements are zero) + */ + public boolean isZero() + { + for (int i = vector.length - 1; i >= 0; i--) + { + if (vector[i] != 0) + { + return false; + } + } + return true; + } + + /** + * Add another vector to this vector. Method is not yet implemented. + * + * @param addend the other vector + * @return <tt>this + addend</tt> + * @throws ArithmeticException if the other vector is not defined over the same field as + * this vector. + * <p> + * TODO: implement this method + */ + public Vector add(Vector addend) + { + throw new RuntimeException("not implemented"); + } + + /** + * Multiply this vector with a permutation. + * + * @param p the permutation + * @return <tt>this*p = p*this</tt> + */ + public Vector multiply(Permutation p) + { + int[] pVec = p.getVector(); + if (length != pVec.length) + { + throw new ArithmeticException( + "permutation size and vector size mismatch"); + } + + int[] result = new int[length]; + for (int i = 0; i < pVec.length; i++) + { + result[i] = vector[pVec[i]]; + } + + return new GF2mVector(field, result); + } + + /** + * Compare this vector with another object. + * + * @param other the other object + * @return the result of the comparison + */ + public boolean equals(Object other) + { + + if (!(other instanceof GF2mVector)) + { + return false; + } + GF2mVector otherVec = (GF2mVector)other; + + if (!field.equals(otherVec.field)) + { + return false; + } + + return IntUtils.equals(vector, otherVec.vector); + } + + /** + * @return the hash code of this vector + */ + public int hashCode() + { + int hash = this.field.hashCode(); + hash = hash * 31 + vector.hashCode(); + return hash; + } + + /** + * @return a human readable form of this vector + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < vector.length; i++) + { + for (int j = 0; j < field.getDegree(); j++) + { + int r = j & 0x1f; + int bitMask = 1 << r; + int coeff = vector[i] & bitMask; + if (coeff != 0) + { + buf.append('1'); + } + else + { + buf.append('0'); + } + } + buf.append(' '); + } + return buf.toString(); + } + +} |