Skip to content

Commit

Permalink
Added more static factory methods for functions
Browse files Browse the repository at this point in the history
- Added support for double width AND and XOR functions.

- Added negation function.

- Added unit tests for double width AND and XOR, as well NEG.

- Moved some methods to FunctionUtils to cut down on code replication

- Resolves #12

- Resolves #13
  • Loading branch information
geekbeast committed Feb 7, 2014
1 parent 3da0290 commit e420861
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ public static SimplePolynomialFunction XOR( int xorLength ) {
return new PolynomialFunctionGF2( xorLength , xorLength , monomials, contributions );
}

public static SimplePolynomialFunction BINARY_XOR( int xorLength ) {
int inputLength = xorLength << 1;
Monomial[] monomials = new Monomial[ inputLength ];
BitVector[] contributions = new BitVector[ inputLength ];

for( int i = 0 ; i < xorLength ; ++i ) {
int offsetIndex = i + xorLength;
monomials[ i ] = Monomial.linearMonomial( inputLength , i);
monomials[ offsetIndex ] = Monomial.linearMonomial( inputLength , offsetIndex );
BitVector contribution = new BitVector( xorLength );
contribution.set( i );
contributions[ i ] = contribution;
//TODO: In theory everything else makes a copy so we could cheat here and save memory.
contributions[ offsetIndex ] = contribution.copy();
}

return new PolynomialFunctionGF2( inputLength , xorLength , monomials, contributions );
}

public static SimplePolynomialFunction AND( int andLength ) {
int inputLength = andLength >>> 1;
Monomial[] monomials = new Monomial[ inputLength ];
Expand All @@ -48,6 +67,24 @@ public static SimplePolynomialFunction AND( int andLength ) {
return new PolynomialFunctionGF2( andLength , andLength , monomials, contributions );
}

public static SimplePolynomialFunction BINARY_AND( int andLength ) {
int inputLength = andLength << 1;
Monomial[] monomials = new Monomial[ andLength ];
BitVector[] contributions = new BitVector[ andLength ];

for( int i = 0 ; i < andLength ; ++i ) {
int offsetIndex = i + andLength;
monomials[ i ] = Monomial
.linearMonomial( inputLength , i)
.inplaceProd( Monomial.linearMonomial( inputLength , offsetIndex ) );
BitVector contribution = new BitVector( andLength );
contribution.set( i );
contributions[ i ] = contribution;
}

return new PolynomialFunctionGF2( inputLength , andLength , monomials, contributions );
}

public static SimplePolynomialFunction LSH( int inputLength , int shiftLength ) {
Monomial[] monomials = new Monomial[ inputLength - shiftLength ];
BitVector[] contributions = new BitVector[ inputLength - shiftLength ];
Expand All @@ -61,6 +98,22 @@ public static SimplePolynomialFunction LSH( int inputLength , int shiftLength )
return new PolynomialFunctionGF2( inputLength, inputLength , monomials , contributions );
}

public static SimplePolynomialFunction NEG( int inputLength ) {
Monomial[] monomials = new Monomial[ inputLength + 1];
BitVector[] contributions = new BitVector[ inputLength + 1];
for( int i = 0 ; i < ( monomials.length - 1) ; ++i ) {
monomials[ i ] = Monomial.linearMonomial( inputLength , i );
BitVector contribution = new BitVector( inputLength );
contribution.set( i );
contributions[ i ] = contribution;
}

monomials[ inputLength ] = new Monomial( inputLength );
contributions[ inputLength ] = new BitVector( inputLength );
contributions[ inputLength ].not();
return new PolynomialFunctionGF2( inputLength, inputLength , monomials , contributions );
}

public static SimplePolynomialFunction RSH( int inputLength , int shiftLength ) {
Monomial[] monomials = new Monomial[ inputLength - shiftLength ];
BitVector[] contributions = new BitVector[ inputLength - shiftLength ];
Expand Down Expand Up @@ -89,6 +142,13 @@ public static PolynomialFunction ADDER( int length , SimplePolynomialFunction xo

/*
* Actually building out the algebraic representation of an adder is prohibitively expensive.
* Initialization:
* carry = x&y;
* current = x + y
*
* next_carry = ( current & carry ) << 1
* current ^= carry
* carry = next_carry
*/
PolynomialFunction currentCarry = CompoundPolynomialFunctionGF2.fromFunctions( and , lsh );
PolynomialFunction applyCarry = new PolynomialFunctionJoiner( xor , xor , currentCarry );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kryptnostic.multivariate.FunctionUtils;
import com.kryptnostic.multivariate.PolynomialFunctionGF2;
import com.kryptnostic.multivariate.gf2.Monomial;
import com.kryptnostic.multivariate.gf2.SimplePolynomialFunction;
Expand Down Expand Up @@ -228,14 +229,7 @@ public SimplePolynomialFunction multiply( SimplePolynomialFunction f ) {
return PolynomialFunctionGF2.fromMonomialContributionMap(
f.getInputLength() ,
rows() ,
PolynomialFunctionGF2.mapViewFromMonomialsAndContributions(newMonomials, newContributions) );
// PolynomialFunctionGF2 result = new PolynomialFunctionGF2(
// f.getInputLength(),
// this.rows(),
// newMonomials,
// newContributions );
//
// return result;
FunctionUtils.mapViewFromMonomialsAndContributions(newMonomials, newContributions) );
}

public static EnhancedBitMatrix identity( int size ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ public static BitVector concatenate( BitVector lhs, BitVector rhs ) {
return concatenated;
}

/**
* Provides a mutable map view over an array of {@code Monomial}s and corresponding {@code BitVector} contributions.
*
* @param monomials The monomials to use as the map key
* @param contributions The contributions paired with each monomial.
* @return a {@code HashMap<Monomial,BitVector} with each monomial paired to its contribution.
*/
public static Map<Monomial, BitVector> mapViewFromMonomialsAndContributions( Monomial[] monomials, BitVector[] contributions ) {
Map<Monomial, BitVector> result = Maps.newHashMapWithExpectedSize( monomials.length );
for( int i = 0 ; i < monomials.length ; ++i ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,6 @@ public SimplePolynomialFunction xor( SimplePolynomialFunction rhs ) {
contribution.xor( rhsContributions[ i ] );
}

// removeNilContributions( monomialContributionsMap );
// Monomial[] newMonomials = new Monomial[ monomialContributionsMap.size() ];
// BitVector[] newContributions = new BitVector[ monomialContributionsMap.size() ];
// int index = 0;
// for( Entry<Monomial,BitVector> entry : monomialContributionsMap.entrySet() ) {
// BitVector contribution = entry.getValue();
//// if( contribution.cardinality() > 0 ) {
// newMonomials[ index ] = entry.getKey();
// newContributions[ index ] = contribution;
// ++index;
//// }
// }

return PolynomialFunctionGF2.fromMonomialContributionMap( inputLength , outputLength , monomialContributionsMap );
}

Expand Down Expand Up @@ -353,20 +340,6 @@ public static Map<Monomial, BitVector> mapCopyFromMonomialsAndContributions( Mon
return result;
}

/**
* Provides a mutable map view over an array of {@code Monomial}s and corresponding {@code BitVector} contributions.
*
* @param monomials The monomials to use as the map key
* @param contributions The contributions paired with each monomial.
* @return a {@code HashMap<Monomial,BitVector} with each monomial paired to its contribution.
*/
public static Map<Monomial, BitVector> mapViewFromMonomialsAndContributions( Monomial[] monomials, BitVector[] contributions ) {
Map<Monomial, BitVector> result = Maps.newHashMapWithExpectedSize( monomials.length );
for( int i = 0 ; i < monomials.length ; ++i ) {
result.put( monomials[ i ].clone() , contributions[ i ].copy() );
}
return result;
}

public static void removeNilContributions( Map<Monomial,BitVector> monomialContributionMap ) {
Set<Monomial> forRemoval = Sets.newHashSet();
Expand Down Expand Up @@ -469,15 +442,15 @@ public static PolynomialFunctionGF2 prepareForRhsOfBinaryOp( PolynomialFunctionG
return new PolynomialFunctionGF2( monomials[0].size() , contributions.length , monomials, contributions );
}

public static PolynomialFunctionGF2 concatenate( SimplePolynomialFunction lhs , SimplePolynomialFunction rhs ) {
public static SimplePolynomialFunction concatenate( SimplePolynomialFunction lhs , SimplePolynomialFunction rhs ) {
Preconditions.checkArgument( lhs.getInputLength() == rhs.getInputLength() , "Functions being composed must have compatible monomial lengths" );
int lhsOutputLength = lhs.getOutputLength();
int rhsOutputLength = rhs.getOutputLength();
int combinedOutputLength = lhsOutputLength + rhsOutputLength;
Map<Monomial, BitVector> lhsMap =
PolynomialFunctionGF2.mapViewFromMonomialsAndContributions( lhs.getMonomials() , lhs.getContributions() );
FunctionUtils.mapViewFromMonomialsAndContributions( lhs.getMonomials() , lhs.getContributions() );
Map<Monomial, BitVector> rhsMap =
PolynomialFunctionGF2.mapViewFromMonomialsAndContributions( rhs.getMonomials() , rhs.getContributions() );
FunctionUtils.mapViewFromMonomialsAndContributions( rhs.getMonomials() , rhs.getContributions() );
Map<Monomial, BitVector> monomialContributionMap = Maps.newHashMap();

Set<Monomial> monomials = Sets.union( lhsMap.keySet() , rhsMap.keySet() );
Expand Down Expand Up @@ -510,7 +483,6 @@ public static PolynomialFunctionGF2 concatenate( SimplePolynomialFunction lhs ,
}

public static SimplePolynomialFunction concatenateInputsAndOutputs( SimplePolynomialFunction lhs , SimplePolynomialFunction rhs ) {
// Preconditions.checkArgument( lhs.getInputLength() == rhs.getInputLength() , "Functions being composed must have compatible monomial lengths" );
int lhsInputLength = lhs.getInputLength();
int rhsInputLength = rhs.getInputLength();
int lhsOutputLength = lhs.getOutputLength();
Expand Down Expand Up @@ -549,7 +521,7 @@ public static SimplePolynomialFunction concatenateInputsAndOutputs( SimplePolyno
}


public static PolynomialFunctionGF2 fromMonomialContributionMap( int inputLength , int outputLength , Map<Monomial,BitVector> monomialContributionsMap) {
public static SimplePolynomialFunction fromMonomialContributionMap( int inputLength , int outputLength , Map<Monomial,BitVector> monomialContributionsMap) {
removeNilContributions(monomialContributionsMap);
Monomial[] newMonomials = new Monomial[ monomialContributionsMap.size() ];
BitVector[] newContributions = new BitVector[ monomialContributionsMap.size() ];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,27 @@ public void testXor() {
Assert.assertArrayEquals( expected , result.elements() );
}

@Test
public void testBinaryXor() {
SimplePolynomialFunction xor = PolynomialFunctions.BINARY_XOR( 128 );
Assert.assertEquals( 256 , xor.getInputLength() );
Assert.assertEquals( 128 , xor.getContributions()[0].size() );

long[] values = new long[ 4 ];

for( int i = 0 ; i < values.length ; ++i ){
values[ i ] = r.nextLong();
}

long[] expected = new long[] {
values[0]^values[2] ,
values[1]^values[3] };

BitVector result = xor.apply( new BitVector( values , 256 ) );
Assert.assertEquals( 128 , result.size() );
Assert.assertArrayEquals( expected , result.elements() );
}

@Test
public void testAnd() {
SimplePolynomialFunction and = PolynomialFunctions.AND( 256 );
Expand All @@ -63,6 +84,37 @@ public void testAnd() {
Assert.assertArrayEquals( expected , result.elements() );
}

@Test
public void testBinaryAnd() {
SimplePolynomialFunction and = PolynomialFunctions.BINARY_AND( 128 );
Assert.assertEquals( 256 , and.getInputLength() );
Assert.assertEquals( 128 , and.getContributions()[0].size() );

long[] values = new long[ 4 ];

for( int i = 0 ; i < values.length ; ++i ){
values[ i ] = r.nextLong();
}

long[] expected = new long[] {
values[0]&values[2] ,
values[1]&values[3] };

BitVector result = and.apply( new BitVector( values , 256 ) );
Assert.assertEquals( 128 , result.size() );
Assert.assertArrayEquals( expected , result.elements() );
}

@Test
public void testNEG() {
SimplePolynomialFunction neg = PolynomialFunctions.NEG( 128 );
BitVector v = BitUtils.randomVector( 128 );
BitVector result = neg.apply( v );
BitVector expected = v.copy();
expected.not();
Assert.assertEquals( expected , result );
}

@Test
public void testLSH() {
SimplePolynomialFunction lsh = PolynomialFunctions.LSH( 128 , 23 );
Expand Down

0 comments on commit e420861

Please sign in to comment.