diff --git a/src/main/java/net/imglib2/type/label/BasePairBitType.java b/src/main/java/net/imglib2/type/label/BasePairBitType.java index b809c19ff3..662a435cc4 100644 --- a/src/main/java/net/imglib2/type/label/BasePairBitType.java +++ b/src/main/java/net/imglib2/type/label/BasePairBitType.java @@ -49,18 +49,63 @@ */ public class BasePairBitType extends AbstractBit64Type< BasePairBitType > implements BasePairType< BasePairBitType > { - public static enum Base { gap, N, A, T, G, C, U; } + // hom many bits a BasePairBitType contains + private static final int NBITS = 3; + + public enum Base + { + gap( ' ' ), + N( 'N' ), + A( 'A' ), + T( 'T' ), + G( 'G' ), + C( 'C' ), + U( 'U' ); + + private final char c; + + Base( final char c ) + { + this.c = c; + } + + public char getChar() + { + return c; + } + + public static Base fromChar( final char c ) + { + switch ( c ) + { + case 'A': + return A; + case 'T': + return T; + case 'G': + return G; + case 'C': + return C; + case 'U': + return U; + case ' ': + return gap; + default: + return N; + } + } + } // this is the constructor if you want it to read from an array public BasePairBitType( final NativeImg< ?, ? extends LongAccess > bitStorage ) { - super( bitStorage, 3 ); + super( bitStorage, NBITS ); } // this is the constructor if you want it to be a variable public BasePairBitType( final Base value ) { - super( value.ordinal() ); + super( value.ordinal(), NBITS ); } // this is the constructor if you want it to be a variable @@ -89,29 +134,13 @@ public void set( final Base base ) @Override public Base get() { - return Base.values()[ (int)getBits() ]; + return Base.values()[ ( int ) getBits() ]; } @Override public int compareTo( final BasePairBitType c ) { - final Base input = get(); - final Base compare = c.get(); - - if ( input == compare ) - { - return 0; - } - switch ( input ) - { - case gap: return -1; - case N: return compare == Base.gap ? 1 : -1; - case A: return compare == Base.gap || compare == Base.N ? 1 : -1; - case T: return compare == Base.G || compare == Base.C || compare == Base.U ? -1 : 1; - case G: return compare == Base.C || compare == Base.U ? -1 : 1; - case C: return compare == Base.U ? -1 : 1; - default: return 1; - } + return get().compareTo( c.get() ); } @Override @@ -132,25 +161,7 @@ public void complement() @Override public byte baseToValue() { - final Base base = get(); - - switch ( base ) - { - case N: - return 1; - case A: - return 2; - case T: - return 3; - case G: - return 4; - case C: - return 5; - case U: - return 6; - default: - return 0; - } + return ( byte ) get().ordinal(); } @Override diff --git a/src/main/java/net/imglib2/type/label/BasePairCharType.java b/src/main/java/net/imglib2/type/label/BasePairCharType.java index ad4d8c9bf8..06bdd49285 100644 --- a/src/main/java/net/imglib2/type/label/BasePairCharType.java +++ b/src/main/java/net/imglib2/type/label/BasePairCharType.java @@ -124,54 +124,13 @@ public void setChar( final char f ) @Override public void set( final Base base ) { - switch ( base ) - { - case A: - setChar( 'A' ); - return; - case T: - setChar( 'T' ); - return; - case G: - setChar( 'G' ); - return; - case C: - setChar( 'C' ); - return; - case U: - setChar( 'U' ); - return; - case gap: - setChar( ' ' ); - return; - default: - setChar( 'N' ); - return; - } + setChar( base.getChar() ); } @Override public Base get() { - final char value = getChar(); - - switch ( value ) - { - case 'A': - return Base.A; - case 'T': - return Base.T; - case 'G': - return Base.G; - case 'C': - return Base.C; - case 'U': - return Base.U; - case ' ': - return Base.gap; - default: - return Base.N; - } + return Base.fromChar( getChar() ); } @Override @@ -183,27 +142,7 @@ public void set( final BasePairCharType c ) @Override public int compareTo( final BasePairCharType c ) { - final char input = getChar(); - final char compare = c.getChar(); - - if ( input == compare ) { return 0; } - switch ( input ) - { - case ' ': - return -1; - case 'N': - return compare == ' ' ? 1 : -1; - case 'A': - return compare == ' ' || compare == 'N' ? 1 : -1; - case 'T': - return compare == 'G' || compare == 'C' || compare == 'U' ? -1 : 1; - case 'G': - return compare == 'C' || compare == 'U' ? -1 : 1; - case 'C': - return compare == 'U' ? -1 : 1; - default: - return 1; - } + return get().compareTo( c.get() ); } @Override @@ -233,25 +172,7 @@ public void complement() @Override public byte baseToValue() { - final char base = getChar(); - - switch ( base ) - { - case 'N': - return 1; - case 'A': - return 2; - case 'T': - return 3; - case 'G': - return 4; - case 'C': - return 5; - case 'U': - return 6; - default: - return 0; - } + return ( byte ) get().ordinal(); } @Override diff --git a/src/main/java/net/imglib2/type/logic/BitType.java b/src/main/java/net/imglib2/type/logic/BitType.java index 12d45cbcde..95b2a08ed4 100644 --- a/src/main/java/net/imglib2/type/logic/BitType.java +++ b/src/main/java/net/imglib2/type/logic/BitType.java @@ -45,6 +45,7 @@ import net.imglib2.type.numeric.IntegerType; import net.imglib2.type.numeric.integer.AbstractIntegerType; import net.imglib2.util.Fraction; +import net.imglib2.util.Util; /** * TODO @@ -289,20 +290,6 @@ public void dec() not(); } - @Override - public int compareTo( final BitType c ) - { - final boolean b1 = get(); - final boolean b2 = c.get(); - - if ( b1 && !b2 ) - return 1; - else if ( !b1 && b2 ) - return -1; - else - return 0; - } - @Override public BitType createVariable() { @@ -371,9 +358,27 @@ public int getBitsPerPixel() return 1; } + @Override + public int compareTo( final BitType other ) + { + return Boolean.compare( get(), other.get() ); + } + @Override public boolean valueEquals( final BitType t ) { return get() == t.get(); } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + return Boolean.hashCode( get() ); + } } diff --git a/src/main/java/net/imglib2/type/logic/BoolType.java b/src/main/java/net/imglib2/type/logic/BoolType.java index 3e9e267e4f..41e577b66b 100644 --- a/src/main/java/net/imglib2/type/logic/BoolType.java +++ b/src/main/java/net/imglib2/type/logic/BoolType.java @@ -37,6 +37,7 @@ import net.imglib2.type.BooleanType; import net.imglib2.type.numeric.integer.AbstractIntegerType; +import net.imglib2.util.Util; /** * A {@link BooleanType} wrapping a single primitive {@code boolean} variable. @@ -80,15 +81,6 @@ public void set( final BoolType c ) value = c.get(); } - @Override - public int compareTo( final BoolType o ) - { - if ( value ) - return o.value ? 0 : 1; - else - return o.value ? -1 : 0; - } - @Override public boolean get() { @@ -193,10 +185,28 @@ public void setBigInteger( final BigInteger b ) { set( b.compareTo(BigInteger.ZERO) > 0 ); } - + + @Override + public int compareTo( final BoolType other ) + { + return Boolean.compare( get(), other.get() ); + } + @Override public boolean valueEquals( BoolType t ) { return get() == t.get(); } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + return Boolean.hashCode( get() ); + } } diff --git a/src/main/java/net/imglib2/type/logic/NativeBoolType.java b/src/main/java/net/imglib2/type/logic/NativeBoolType.java index 72f5f5593f..e06cbb8746 100644 --- a/src/main/java/net/imglib2/type/logic/NativeBoolType.java +++ b/src/main/java/net/imglib2/type/logic/NativeBoolType.java @@ -44,6 +44,7 @@ import net.imglib2.type.NativeTypeFactory; import net.imglib2.type.numeric.integer.AbstractIntegerType; import net.imglib2.util.Fraction; +import net.imglib2.util.Util; /** * {@link NativeType} backed by {@code boolean}. @@ -267,24 +268,22 @@ public boolean valueEquals( final NativeBoolType t ) return get() == t.get(); } + @Override + public boolean equals( Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + @Override public int hashCode() { - // NB: Use the same hash code as java.lang.Boolean#hashCode(). return Boolean.hashCode( get() ); } @Override public int compareTo( final NativeBoolType c ) { - final boolean b1 = get(); - final boolean b2 = c.get(); - - if ( b1 && !b2 ) - return 1; - if ( !b1 && b2 ) - return -1; - return 0; + return Boolean.compare( get(), c.get() ); } @Override @@ -346,5 +345,4 @@ public void setBigInteger( BigInteger b ) { set( b.compareTo( BigInteger.ZERO ) > 0 ); } - } diff --git a/src/main/java/net/imglib2/type/numeric/ARGBType.java b/src/main/java/net/imglib2/type/numeric/ARGBType.java index f566e36c8f..abd391533c 100644 --- a/src/main/java/net/imglib2/type/numeric/ARGBType.java +++ b/src/main/java/net/imglib2/type/numeric/ARGBType.java @@ -250,4 +250,16 @@ public boolean valueEquals( final ARGBType t ) { return get() == t.get(); } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + return Integer.hashCode( get() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/AbstractARGBDoubleType.java b/src/main/java/net/imglib2/type/numeric/AbstractARGBDoubleType.java index c47ff4f6d4..f23d24fd2e 100644 --- a/src/main/java/net/imglib2/type/numeric/AbstractARGBDoubleType.java +++ b/src/main/java/net/imglib2/type/numeric/AbstractARGBDoubleType.java @@ -166,4 +166,25 @@ public boolean valueEquals( T t ) ( getG() == t.getG() ) && ( getB() == t.getB() ); } + + @Override + public boolean equals( final Object obj ) + { + if ( ! getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + T t = ( T ) obj; + return AbstractARGBDoubleType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + // NB: this is the same as Objects.hashCode( getA(), getR(), getG(), getB() ) but faster, no boxing, no memory allocation + int result = 31 + Double.hashCode( getA() ); + result = 31 * result + Double.hashCode( getR() ); + result = 31 * result + Double.hashCode( getG() ); + result = 31 * result + Double.hashCode( getB() ); + return result; + } } diff --git a/src/main/java/net/imglib2/type/numeric/complex/AbstractComplexType.java b/src/main/java/net/imglib2/type/numeric/complex/AbstractComplexType.java index 8a62f295bd..0d92778903 100644 --- a/src/main/java/net/imglib2/type/numeric/complex/AbstractComplexType.java +++ b/src/main/java/net/imglib2/type/numeric/complex/AbstractComplexType.java @@ -35,6 +35,8 @@ package net.imglib2.type.numeric.complex; import net.imglib2.type.numeric.ComplexType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.util.Util; /** * TODO @@ -169,23 +171,28 @@ public void setComplexNumber( final double r, final double i ) } @Override - public boolean equals( final Object o ) + public boolean valueEquals( T other ) { - if ( !getClass().isInstance(o) ) + return DoubleType.equals( getRealDouble(), other.getRealDouble() ) && + DoubleType.equals( getImaginaryDouble(), other.getImaginaryDouble() ); + } + + @Override + public boolean equals( final Object obj ) + { + if ( !getClass().isInstance(obj) ) return false; @SuppressWarnings("unchecked") - final T t = (T) o; - return getRealDouble() == t.getRealDouble() && - getImaginaryDouble() == t .getImaginaryDouble(); + final T t = (T) obj; + return AbstractComplexType.this.valueEquals( t ); } @Override public int hashCode() { - // NB: Compute similar hash code to java.lang.Double#hashCode(). - final long rBits = Double.doubleToLongBits(getRealDouble()); - final long iBits = Double.doubleToLongBits(getImaginaryDouble()); - return (int) (rBits ^ (rBits >>> 32) ^ iBits ^ (iBits >>> 32)); + final int rHash = Double.hashCode( getRealDouble() ); + final int iHash = Double.hashCode( getImaginaryDouble() ); + return Util.combineHash( rHash, iHash ); } @Override diff --git a/src/main/java/net/imglib2/type/numeric/complex/ComplexDoubleType.java b/src/main/java/net/imglib2/type/numeric/complex/ComplexDoubleType.java index ced5299896..ddec75e3e8 100644 --- a/src/main/java/net/imglib2/type/numeric/complex/ComplexDoubleType.java +++ b/src/main/java/net/imglib2/type/numeric/complex/ComplexDoubleType.java @@ -233,11 +233,4 @@ public int getIndex() { return i; } - - @Override - public boolean valueEquals( final ComplexDoubleType t ) - { - return ( getRealDouble() == t.getRealDouble() ) && - ( getImaginaryDouble() == t.getImaginaryDouble() ); - } } diff --git a/src/main/java/net/imglib2/type/numeric/complex/ComplexFloatType.java b/src/main/java/net/imglib2/type/numeric/complex/ComplexFloatType.java index d93c6d2f59..79ec7cd798 100644 --- a/src/main/java/net/imglib2/type/numeric/complex/ComplexFloatType.java +++ b/src/main/java/net/imglib2/type/numeric/complex/ComplexFloatType.java @@ -39,7 +39,9 @@ import net.imglib2.img.basictypeaccess.array.FloatArray; import net.imglib2.type.NativeType; import net.imglib2.type.NativeTypeFactory; +import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.Fraction; +import net.imglib2.util.Util; /** * TODO @@ -291,7 +293,21 @@ public int getIndex() @Override public boolean valueEquals( final ComplexFloatType t ) { - return ( getRealFloat() == t.getRealFloat() ) && - ( getImaginaryFloat() == t.getImaginaryFloat() ); + return FloatType.equals( getRealFloat(), t.getRealFloat() ) && + FloatType.equals( getImaginaryFloat(), t.getImaginaryFloat() ); + } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + final int rHash = Float.hashCode( getRealFloat() ); + final int iHash = Float.hashCode( getImaginaryFloat() ); + return Util.combineHash( rHash, iHash ); } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerBitType.java b/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerBitType.java index c4ccca6ec5..7d3af6251b 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerBitType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerBitType.java @@ -96,35 +96,6 @@ public AbstractIntegerBitType( @Override public void setOne() { setInteger( 1 ); } - @Override - public boolean equals( final Object o ) { - if ( !getClass().isInstance(o) ) - return false; - @SuppressWarnings("unchecked") - final T t = (T) o; - return compareTo(t) == 0; - } - - @Override - public int hashCode() { - // NB: Use the same hash code as java.lang.Long#hashCode(). - final long value = get(); - return (int) (value ^ (value >>> 32)); - } - - @Override - public int compareTo( final T c ) - { - final long a = getIntegerLong(); - final long b = c.getIntegerLong(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public String toString() { return "" + getIntegerLong(); } @@ -201,6 +172,12 @@ public void setImaginary( final double complex ){} @Override public void complexConjugate(){} + @Override + public int compareTo( final T other ) + { + return Long.compare( getIntegerLong(), other.getIntegerLong() ); + } + /** * Default test at long precision. Please override for types longer than 64bit. * @@ -212,4 +189,20 @@ public boolean valueEquals( final T t ) { return get() == t.get(); } + + @Override + public boolean equals( final Object obj ) + { + if ( !getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) obj; + return AbstractIntegerBitType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + return Long.hashCode( get() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerType.java b/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerType.java index 45f3ffd112..d949699a04 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/AbstractIntegerType.java @@ -99,29 +99,36 @@ public void setOne() } @Override - public int hashCode() + public String toString() { - // NB: Use the same hash code as java.lang.Long#hashCode(). - final long value = getIntegerLong(); - return ( int ) ( value ^ ( value >>> 32 ) ); + return Long.toString( getIntegerLong() ); } @Override - public int compareTo( final T c ) + public int compareTo( final T other ) { - final long a = getIntegerLong(); - final long b = c.getIntegerLong(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; + return Long.compare( getIntegerLong(), other.getIntegerLong() ); } @Override - public String toString() + public boolean valueEquals( final T other ) + { + return getIntegerLong() == getIntegerLong(); + } + + @Override + public boolean equals( final Object obj ) + { + if ( !getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) obj; + return AbstractIntegerType.this.valueEquals( t ); + } + + @Override + public int hashCode() { - return "" + getIntegerLong(); + return Long.hashCode( getIntegerLong() ); } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/GenericByteType.java b/src/main/java/net/imglib2/type/numeric/integer/GenericByteType.java index 24bc84853b..2f2617cfd1 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/GenericByteType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/GenericByteType.java @@ -177,26 +177,6 @@ public void sub( final T c ) setByte( ( byte ) ( a - c.getByte() ) ); } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Byte#hashCode(). - return getByte(); - } - - @Override - public int compareTo( final T c ) - { - final byte a = getByte(); - final byte b = c.getByte(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public void set( final T c ) { @@ -277,9 +257,31 @@ public int getBitsPerPixel() return 8; } + @Override + public int compareTo( final T other ) + { + return Byte.compare( getByte(), other.getByte() ); + } + @Override public boolean valueEquals( final T t ) { return getByte() == t.getByte(); } + + @Override + public boolean equals( final Object obj ) + { + if ( !getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) obj; + return GenericByteType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + return Byte.hashCode( getByte() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/GenericIntType.java b/src/main/java/net/imglib2/type/numeric/integer/GenericIntType.java index 61e5be3fa7..0df28c40b6 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/GenericIntType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/GenericIntType.java @@ -177,26 +177,6 @@ public void sub( final T c ) setInt( a - c.getInt() ); } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Integer#hashCode(). - return getInt(); - } - - @Override - public int compareTo( final T c ) - { - final int a = getInt(); - final int b = c.getInt(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public void set( final T c ) { @@ -277,9 +257,31 @@ public int getBitsPerPixel() return 32; } + @Override + public int compareTo( final T other ) + { + return Integer.compare( getInt(), other.getInt() ); + } + @Override public boolean valueEquals( final T t ) { return getInt() == t.getInt(); } + + @Override + public boolean equals( final Object obj ) + { + if ( !getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) obj; + return GenericIntType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + return Integer.hashCode( getInt() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/GenericLongType.java b/src/main/java/net/imglib2/type/numeric/integer/GenericLongType.java index 8badb60227..5ffd7ea7ba 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/GenericLongType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/GenericLongType.java @@ -169,26 +169,6 @@ public void sub( final T c ) setLong( getLong() - c.getLong() ); } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Long#hashCode(). - return ( ( Long ) getLong() ).hashCode(); - } - - @Override - public int compareTo( final T c ) - { - final long a = getLong(); - final long b = c.getLong(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public void set( final T c ) { @@ -270,8 +250,30 @@ public int getBitsPerPixel() } @Override - public boolean valueEquals( final T t ) + public int compareTo( final T other ) + { + return Long.compare( getLong(), other.getLong() ); + } + + @Override + public boolean valueEquals( final T other ) + { + return getLong() == other.getLong(); + } + + @Override + public boolean equals( final Object obj ) + { + if ( !getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) obj; + return GenericLongType.this.valueEquals( t ); + } + + @Override + public int hashCode() { - return getLong() == t.getLong(); + return Long.hashCode( getLong() ); } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/GenericShortType.java b/src/main/java/net/imglib2/type/numeric/integer/GenericShortType.java index 2b9c0e700c..14ef26a5c7 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/GenericShortType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/GenericShortType.java @@ -181,26 +181,6 @@ public void sub( final T c ) setShort( ( short ) ( a - c.getShort() ) ); } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Short#hashCode(). - return getShort(); - } - - @Override - public int compareTo( final T c ) - { - final short a = getShort(); - final short b = c.getShort(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public void set( final T c ) { @@ -281,9 +261,31 @@ public int getBitsPerPixel() return 16; } + @Override + public int compareTo( final T other ) + { + return Short.compare( getShort(), other.getShort() ); + } + @Override public boolean valueEquals( final T t ) { return getShort() == t.getShort(); } + + @Override + public boolean equals( final Object obj ) + { + if ( ! getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) obj; + return GenericShortType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + return Short.hashCode( getShort() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/LongType.java b/src/main/java/net/imglib2/type/numeric/integer/LongType.java index 75c555a3bf..0cc31cac80 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/LongType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/LongType.java @@ -89,7 +89,7 @@ public NativeTypeFactory< LongType, LongAccess > getNativeTypeFactory() public long get() { - return dataAccess.getValue( i ); + return getLong(); } public void set( final long f ) @@ -145,27 +145,6 @@ public double getMinValue() return Long.MIN_VALUE; } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Long#hashCode(). - final long value = get(); - return ( int ) ( value ^ ( value >>> 32 ) ); - } - - @Override - public int compareTo( final LongType c ) - { - final long a = get(); - final long b = c.get(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public LongType createVariable() { diff --git a/src/main/java/net/imglib2/type/numeric/integer/Unsigned128BitType.java b/src/main/java/net/imglib2/type/numeric/integer/Unsigned128BitType.java index 6b80ce61ea..01cddf89ad 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/Unsigned128BitType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/Unsigned128BitType.java @@ -45,6 +45,7 @@ import net.imglib2.type.Type; import net.imglib2.type.numeric.NumericType; import net.imglib2.util.Fraction; +import net.imglib2.util.Util; /** * A {@link Type} with a bit depth of 128. Each value is stored in two adjacent @@ -427,19 +428,15 @@ public void div( final Unsigned128BitType t ) @Override public int compareTo( final Unsigned128BitType t ) { - final long upper1 = dataAccess.getValue( i * 2 + 1 ), - upper2 = t.dataAccess.getValue( t.i * 2 + 1 ); - if ( -1 == UnsignedLongType.compare( upper1, upper2 ) ) - { - return -1; - } - else if ( upper1 == upper2 ) - { - final long lower1 = dataAccess.getValue( i * 2 ), - lower2 = t.dataAccess.getValue( t.i * 2 ); - return UnsignedLongType.compare( lower1, lower2 ); - } - return 1; + final long upper1 = dataAccess.getValue( i * 2 + 1 ); + final long upper2 = t.dataAccess.getValue( t.i * 2 + 1 ); + final int compareUpper = Long.compareUnsigned( upper1, upper2 ); + if ( compareUpper != 0 ) + return compareUpper; + + final long lower1 = dataAccess.getValue( i * 2 ); + final long lower2 = t.dataAccess.getValue( t.i * 2 ); + return Long.compareUnsigned( lower1, lower2 ); } @Override @@ -451,4 +448,19 @@ public boolean valueEquals( final Unsigned128BitType t ) return ( dataAccess.getValue( k ) == t.dataAccess.getValue( kt ) ) && ( dataAccess.getValue( k + 1 ) == t.dataAccess.getValue( kt + 1 ) ); } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + final int k = i * 2; + final int hash1 = Long.hashCode( dataAccess.getValue( k + 1 ) ); + final int hash2 = Long.hashCode( dataAccess.getValue( k ) ); + return Util.combineHash( hash1, hash2 ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/UnsignedByteType.java b/src/main/java/net/imglib2/type/numeric/integer/UnsignedByteType.java index ac66d78501..e870609e6d 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/UnsignedByteType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/UnsignedByteType.java @@ -204,27 +204,6 @@ public double getMinValue() return 0; } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Integer#hashCode(). - return get(); - } - - @Override - public int compareTo( final UnsignedByteType c ) - { - final int a = get(); - final int b = c.get(); - - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public UnsignedByteType createVariable() { @@ -242,4 +221,10 @@ public String toString() { return "" + get(); } + + @Override + public int compareTo( final UnsignedByteType other ) + { + return Integer.compare( get(), other.get() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/UnsignedIntType.java b/src/main/java/net/imglib2/type/numeric/integer/UnsignedIntType.java index 8ac5216771..59962c004b 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/UnsignedIntType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/UnsignedIntType.java @@ -233,28 +233,6 @@ public double getMinValue() return 0; } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Long#hashCode(). - final long value = get(); - return ( int ) ( value ^ ( value >>> 32 ) ); - } - - @Override - public int compareTo( final UnsignedIntType c ) - { - final long a = get(); - final long b = c.get(); - - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public UnsignedIntType createVariable() { @@ -266,4 +244,10 @@ public UnsignedIntType copy() { return new UnsignedIntType( get() ); } + + @Override + public int compareTo( final UnsignedIntType other ) + { + return Long.compare( get(), other.get() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/UnsignedLongType.java b/src/main/java/net/imglib2/type/numeric/integer/UnsignedLongType.java index a3158e6989..e71ffa5a31 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/UnsignedLongType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/UnsignedLongType.java @@ -11,7 +11,7 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, @@ -143,7 +143,7 @@ static public final long divide( final long d1, final long d2 ) if ( d2 < 0 ) { // d2 is larger than the maximum signed long value - if ( -1 == compare( d1, d2 ) ) + if ( Long.compareUnsigned( d1, d2 ) < 0 ) { // d1 is smaller than d2 return 0; @@ -160,7 +160,7 @@ static public final long divide( final long d1, final long d2 ) // Approximate division: exact or one less than the actual value final long quotient = ( ( d1 >>> 1 ) / d2 ) << 1; final long reminder = d1 - quotient * d2; - return quotient + ( -1 == compare( d2, reminder ) ? 0 : 1 ); + return quotient + ( Long.compareUnsigned( d2, reminder ) < 0 ? 0 : 1 ); } // Exact division, given that both d1 and d2 are smaller than @@ -180,14 +180,6 @@ public void sub( final UnsignedLongType c ) set( get() - c.get() ); } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Long#hashCode(). - final long value = get(); - return ( int ) ( value ^ ( value >>> 32 ) ); - } - @Override public void setOne() { @@ -303,18 +295,10 @@ public double getMinValue() return 0; } - @Override - public int compareTo( final UnsignedLongType c ) - { - return compare( get(), c.get() ); - } - /** - * - * @param a - * @param b - * @return -1 if {@code a < b}, 0 if {@code a == b}, 1 if {@code a > b}. + * @deprecated Use {@link Long#compareUnsigned(long, long)} instead. */ + @Deprecated static public final int compare( final long a, final long b ) { if ( a == b ) @@ -356,4 +340,9 @@ public double getRealDouble() return l >= 0 ? l : (MAX_VALUE_PLUS_ONE + l); } + @Override + public int compareTo( final UnsignedLongType other ) + { + return Long.compareUnsigned( get(), other.get() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/UnsignedShortType.java b/src/main/java/net/imglib2/type/numeric/integer/UnsignedShortType.java index c347d0a3c1..7512f7f0a5 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/UnsignedShortType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/UnsignedShortType.java @@ -213,27 +213,6 @@ public double getMinValue() return 0; } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Integer#hashCode(). - return get(); - } - - @Override - public int compareTo( final UnsignedShortType c ) - { - final int a = get(); - final int b = c.get(); - - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public UnsignedShortType createVariable() { @@ -251,4 +230,10 @@ public String toString() { return "" + get(); } + + @Override + public int compareTo( final UnsignedShortType other ) + { + return Integer.compare( get(), other.get() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/integer/UnsignedVariableBitLengthType.java b/src/main/java/net/imglib2/type/numeric/integer/UnsignedVariableBitLengthType.java index 9d1f9740bf..c520997826 100644 --- a/src/main/java/net/imglib2/type/numeric/integer/UnsignedVariableBitLengthType.java +++ b/src/main/java/net/imglib2/type/numeric/integer/UnsignedVariableBitLengthType.java @@ -131,13 +131,6 @@ public void div( final UnsignedVariableBitLengthType t ) setBits( UnsignedLongType.divide( getBits(), t.getBits() ) ); } - /** @see UnsignedLongType#compare(long, long) */ - @Override - public int compareTo( final UnsignedVariableBitLengthType t ) - { - return UnsignedLongType.compare( getBits(), t.getBits() ); - } - @Override public void mul( final float c ) { @@ -347,6 +340,12 @@ public void setComplexNumber( final double r, final double i ) public void complexConjugate() {} + @Override + public int compareTo( final UnsignedVariableBitLengthType t ) + { + return Long.compareUnsigned( getBits(), t.getBits() ); + } + /** * Default test at long precision. Please override for types longer than * 64bit. @@ -359,4 +358,16 @@ public boolean valueEquals( final UnsignedVariableBitLengthType t ) { return getBits() == t.getBits(); } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + return Long.hashCode( getBits() ); + } } diff --git a/src/main/java/net/imglib2/type/numeric/real/AbstractRealType.java b/src/main/java/net/imglib2/type/numeric/real/AbstractRealType.java index be441a35cd..f92b8997bb 100644 --- a/src/main/java/net/imglib2/type/numeric/real/AbstractRealType.java +++ b/src/main/java/net/imglib2/type/numeric/real/AbstractRealType.java @@ -130,34 +130,31 @@ public void setOne() } @Override - public boolean equals( final Object o ) + public int compareTo( final T other ) { - if ( !getClass().isInstance(o) ) - return false; - @SuppressWarnings("unchecked") - final T t = (T) o; - return compareTo(t) == 0; + return Double.compare( getRealDouble(), other.getRealDouble() ); } @Override - public int hashCode() + public boolean valueEquals( T other ) + { + return DoubleType.equals( getRealDouble(), other.getRealDouble() ); + } + + @Override + public boolean equals( final Object obj ) { - // NB: Use the same hash code as java.lang.Double#hashCode(). - final long bits = Double.doubleToLongBits(getRealDouble()); - return (int) (bits ^ (bits >>> 32)); + if ( !getClass().isInstance( obj ) ) + return false; + @SuppressWarnings("unchecked") + final T t = (T) obj; + return AbstractRealType.this.valueEquals( t ); } @Override - public int compareTo( final T c ) + public int hashCode() { - final double a = getRealDouble(); - final double b = c.getRealDouble(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; + return Double.hashCode( getRealDouble() ); } @Override diff --git a/src/main/java/net/imglib2/type/numeric/real/DoubleType.java b/src/main/java/net/imglib2/type/numeric/real/DoubleType.java index fce7423e71..c0ca75b280 100644 --- a/src/main/java/net/imglib2/type/numeric/real/DoubleType.java +++ b/src/main/java/net/imglib2/type/numeric/real/DoubleType.java @@ -215,9 +215,7 @@ public int getBitsPerPixel() return 64; } - @Override - public boolean valueEquals( final DoubleType t ) - { - return get() == t.get(); + public static boolean equals(double a, double b) { + return Double.doubleToLongBits( a ) == Double.doubleToLongBits( b ); } } diff --git a/src/main/java/net/imglib2/type/numeric/real/FloatType.java b/src/main/java/net/imglib2/type/numeric/real/FloatType.java index 6130d4b00d..dfa9d6caeb 100644 --- a/src/main/java/net/imglib2/type/numeric/real/FloatType.java +++ b/src/main/java/net/imglib2/type/numeric/real/FloatType.java @@ -40,6 +40,7 @@ import net.imglib2.type.NativeType; import net.imglib2.type.NativeTypeFactory; import net.imglib2.util.Fraction; +import net.imglib2.util.Util; /** * TODO @@ -191,26 +192,6 @@ public void sub( final FloatType c ) set( get() - c.get() ); } - @Override - public int hashCode() - { - // NB: Use the same hash code as java.lang.Float#hashCode(). - return Float.floatToIntBits( get() ); - } - - @Override - public int compareTo( final FloatType c ) - { - final float a = get(); - final float b = c.get(); - if ( a > b ) - return 1; - else if ( a < b ) - return -1; - else - return 0; - } - @Override public void set( final FloatType c ) { @@ -304,8 +285,31 @@ public int getBitsPerPixel() } @Override - public boolean valueEquals( final FloatType t ) + public int compareTo( final FloatType other ) + { + return Float.compare( get(), other.get() ); + } + + @Override + public boolean valueEquals( final FloatType other ) + { + return FloatType.equals( get(), other.get() ); + } + + @Override + public boolean equals( final Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + + @Override + public int hashCode() + { + return Float.hashCode( get() ); + } + + public static boolean equals( float a, float b ) { - return get() == t.get(); + return Float.floatToIntBits( a ) == Float.floatToIntBits( b ); } } diff --git a/src/main/java/net/imglib2/type/volatiles/AbstractVolatileNumericType.java b/src/main/java/net/imglib2/type/volatiles/AbstractVolatileNumericType.java index 111fcf4c2a..83f2662781 100644 --- a/src/main/java/net/imglib2/type/volatiles/AbstractVolatileNumericType.java +++ b/src/main/java/net/imglib2/type/volatiles/AbstractVolatileNumericType.java @@ -36,6 +36,7 @@ import net.imglib2.Volatile; import net.imglib2.type.numeric.NumericType; +import net.imglib2.util.Util; /** * Abstract base class for {@link VolatileNumericType}s that wrap a @@ -124,6 +125,22 @@ public void mul( final double c ) @Override public boolean valueEquals( T other ) { - return ( isValid() && other.isValid() ) && t.valueEquals( other.t ); + return isValid() == other.isValid() && t.valueEquals( other.t ); + } + + @Override + public boolean equals( final Object obj ) + { + if ( ! getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + T t = ( T ) obj; + return AbstractVolatileNumericType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + return Util.combineHash( Boolean.hashCode( isValid() ), t.hashCode() ); } } diff --git a/src/main/java/net/imglib2/type/volatiles/AbstractVolatileRealType.java b/src/main/java/net/imglib2/type/volatiles/AbstractVolatileRealType.java index 387c0c1de6..73eb1ecd96 100644 --- a/src/main/java/net/imglib2/type/volatiles/AbstractVolatileRealType.java +++ b/src/main/java/net/imglib2/type/volatiles/AbstractVolatileRealType.java @@ -35,6 +35,7 @@ import net.imglib2.Volatile; import net.imglib2.type.numeric.RealType; +import net.imglib2.util.Util; /** * Abstract base class for {@link VolatileRealType}s that wrap {@link RealType}. @@ -146,12 +147,6 @@ public void complexConjugate() t.complexConjugate(); } - @Override - public int compareTo( final T o ) - { - return t.compareTo( o.t ); - } - @Override public void inc() { @@ -247,9 +242,31 @@ public void mul( final double c ) t.mul( c ); } + @Override + public int compareTo( final T o ) + { + return t.compareTo( o.t ); + } + @Override public boolean valueEquals( T other ) { - return ( isValid() && other.isValid() ) && t.valueEquals( other.t ); + return isValid() == other.isValid() && t.valueEquals( other.t ); + } + + @Override + public boolean equals( final Object obj ) + { + if ( ! getClass().isInstance( obj ) ) + return false; + @SuppressWarnings( "unchecked" ) + T t = ( T ) obj; + return AbstractVolatileRealType.this.valueEquals( t ); + } + + @Override + public int hashCode() + { + return Util.combineHash( Boolean.hashCode( isValid() ), t.hashCode() ); } } diff --git a/src/main/java/net/imglib2/util/Util.java b/src/main/java/net/imglib2/util/Util.java index 332143e694..312f731e15 100644 --- a/src/main/java/net/imglib2/util/Util.java +++ b/src/main/java/net/imglib2/util/Util.java @@ -971,11 +971,11 @@ public static < T extends ValueEquals< U >, U > boolean imagesEqual( final Rando * Checks if both images have equal intervals and content. * A predicate must be given to check if two pixels are equal. */ - public static < T, U > boolean imagesEqual( final RandomAccessibleInterval< ? extends T > a, final RandomAccessibleInterval< ? extends U > b, BiPredicate< T, U > pixelEquals ) + public static < T, U > boolean imagesEqual( final RandomAccessibleInterval< ? extends T > a, final RandomAccessibleInterval< ? extends U > b, final BiPredicate< T, U > pixelEquals ) { if ( !Intervals.equals( a, b ) ) return false; - for ( Pair< ? extends T, ? extends U > pair : Views.interval( Views.pair( a, b ), b ) ) + for ( final Pair< ? extends T, ? extends U > pair : Views.interval( Views.pair( a, b ), b ) ) if ( !pixelEquals.test( pair.getA(), pair.getB() ) ) return false; return true; @@ -1010,7 +1010,7 @@ final static public void max( final double[] a, final double[] b ) /** * Returns the content of {@code Iterable} as array of doubles. */ - public static double[] asDoubleArray( Iterable< ? extends RealType< ? > > iterable ) + public static double[] asDoubleArray( final Iterable< ? extends RealType< ? > > iterable ) { return StreamSupport.stream( iterable.spliterator(), false ).mapToDouble( RealType::getRealDouble ).toArray(); } @@ -1019,7 +1019,7 @@ public static double[] asDoubleArray( Iterable< ? extends RealType< ? > > iterab * Returns the pixels of an RandomAccessibleInterval of RealType as array of doubles. * The pixels are sorted in flat iteration order. */ - public static double[] asDoubleArray( RandomAccessibleInterval< ? extends RealType< ? > > rai ) + public static double[] asDoubleArray( final RandomAccessibleInterval< ? extends RealType< ? > > rai ) { return asDoubleArray( Views.flatIterable( rai ) ); } @@ -1028,8 +1028,28 @@ public static double[] asDoubleArray( RandomAccessibleInterval< ? extends RealTy * Returns the pixels of an image of RealType as array of doubles. * The pixels are sorted in flat iteration order. */ - public static double[] asDoubleArray( Img< ? extends RealType< ? > > image ) + public static double[] asDoubleArray( final Img< ? extends RealType< ? > > image ) { return asDoubleArray( ( RandomAccessibleInterval< ? extends RealType< ? > > ) image ); } + + /** + * This method should be used in implementations of {@link ValueEquals}, to + * override {@link Object#equals(Object)}. + * + * @see net.imglib2.type.AbstractNativeType#equals(Object) + */ + public static < T extends ValueEquals< T > > boolean valueEqualsObject( final T a, final Object b ) + { + if ( !a.getClass().isInstance( b ) ) + return false; + @SuppressWarnings( "unchecked" ) + final T t = ( T ) b; + return a.valueEquals( t ); + } + + public static int combineHash( final int hash1, final int hash2 ) + { + return 31 * hash1 + hash2; + } } diff --git a/src/test/java/net/imglib2/type/numeric/NumericTypeTest.java b/src/test/java/net/imglib2/type/numeric/NumericTypeTest.java new file mode 100644 index 0000000000..1e50634231 --- /dev/null +++ b/src/test/java/net/imglib2/type/numeric/NumericTypeTest.java @@ -0,0 +1,364 @@ +/* + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2018 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld, + * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke, + * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner, + * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert, + * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin, + * Jean-Yves Tinevez and Michael Zinsmaier. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ + +package net.imglib2.type.numeric; + +import net.imglib2.type.BooleanType; +import net.imglib2.type.logic.BitType; +import net.imglib2.type.logic.BoolType; +import net.imglib2.type.numeric.complex.ComplexDoubleType; +import net.imglib2.type.numeric.complex.ComplexFloatType; +import net.imglib2.type.numeric.integer.ByteType; +import net.imglib2.type.numeric.integer.IntType; +import net.imglib2.type.numeric.integer.LongType; +import net.imglib2.type.numeric.integer.ShortType; +import net.imglib2.type.numeric.integer.Unsigned128BitType; +import net.imglib2.type.numeric.integer.Unsigned12BitType; +import net.imglib2.type.numeric.integer.Unsigned2BitType; +import net.imglib2.type.numeric.integer.Unsigned4BitType; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.type.numeric.integer.UnsignedIntType; +import net.imglib2.type.numeric.integer.UnsignedLongType; +import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.integer.UnsignedVariableBitLengthType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.type.numeric.real.FloatType; +import net.imglib2.type.volatiles.VolatileARGBType; +import net.imglib2.type.volatiles.VolatileByteType; +import net.imglib2.type.volatiles.VolatileDoubleType; +import net.imglib2.type.volatiles.VolatileFloatType; +import net.imglib2.type.volatiles.VolatileIntType; +import net.imglib2.type.volatiles.VolatileLongType; +import net.imglib2.type.volatiles.VolatileNumericType; +import net.imglib2.type.volatiles.VolatileRealType; +import net.imglib2.type.volatiles.VolatileShortType; +import net.imglib2.type.volatiles.VolatileUnsignedByteType; +import net.imglib2.type.volatiles.VolatileUnsignedIntType; +import net.imglib2.type.volatiles.VolatileUnsignedLongType; +import net.imglib2.type.volatiles.VolatileUnsignedShortType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; + +/** + * Test basic functionality of every NumericType implementation. + *

+ * It's a parameterized test, see Junit4 + * Parameterized Test. The test is executed for every type in the list + * {@link NumericTypeTest#numericTypes}. + * + * @param + */ +@RunWith( Parameterized.class ) +public class NumericTypeTest< T extends NumericType< T > > +{ + private static final List< NumericType< ? > > numericTypes = Arrays.asList( + new ARGBDoubleType(), + new ARGBType(), + new BitType(), + new BoolType(), + new ByteType(), + new ComplexDoubleType(), + new ComplexFloatType(), + new DoubleType(), + new FloatType(), + new IntType(), + new LongType(), + new ShortType(), + new UnsignedByteType(), + new UnsignedIntType(), + new UnsignedLongType(), + new UnsignedShortType(), + new Unsigned128BitType(), + new Unsigned2BitType(), + new Unsigned4BitType(), + new Unsigned12BitType(), + new UnsignedVariableBitLengthType( 7 ), + new VolatileARGBType(), + new VolatileByteType(), + new VolatileDoubleType(), + new VolatileFloatType(), + new VolatileIntType(), + new VolatileLongType(), + new VolatileShortType(), + new VolatileUnsignedByteType(), + new VolatileUnsignedIntType(), + new VolatileUnsignedLongType(), + new VolatileUnsignedShortType(), + new VolatileNumericType<>( new DoubleType() ), + new VolatileRealType<>( new DoubleType() ) + ); + + private final T type; + + // NB: The class is parameterized with pairs of (className, numeric type) + // className is there for nicer error messages when a test fails. + @Parameterized.Parameters( name = "{0}" ) + public static Collection< Object > data() + { + return numericTypes.stream().map( + type -> new Object[] { type.getClass().getSimpleName(), type } + ).collect( Collectors.toList() ); + } + + public NumericTypeTest( final String className, final T type ) + { + this.type = type; + } + + @Test + public void testValueEquals() + { + final boolean result = newOne().valueEquals( newOne() ); + assumeTrue( result ); + } + + @Test + public void testNotValueEquals() + { + final boolean result = newZero().valueEquals( newOne() ); + assumeFalse( result ); + } + + @Test + public void testEquals() + { + final boolean result = newOne().equals( newOne() ); + assertTrue( result ); + } + + @Test + public void testNotEqual() + { + final boolean result = newOne().equals( newZero() ); + assertFalse( result ); + } + + @Test + public void testSet() + { + final T a = newZero(); + final T b = newOne(); + a.set( b ); + assertEquals( b, a ); + } + + @Test + public void testOneMinusOne() + { + final T value = newOne(); + value.sub( newOne() ); + assertEquals( newZero(), value ); + } + + @Test + public void testAdd() + { + if ( isMaxValueLessThanSix() ) + return; + + final T value = newNumber( 3 ); + value.add( newNumber( 2 ) ); + assertEquals( newNumber( 5 ), value ); + } + + @Test + public void testSub() + { + if ( isMaxValueLessThanSix() ) + return; + + final T value = newNumber( 5 ); + value.sub( newNumber( 3 ) ); + assertEquals( newNumber( 2 ), value ); + } + + @Test + public void testMulNumerivType() + { + if ( isMaxValueLessThanSix() ) + return; + final T value = newNumber( 3 ); + value.mul( newNumber( 2 ) ); + assertEquals( newNumber( 6 ), value ); + } + + @Test + public void testMulDouble() + { + if ( isMaxValueLessThanSix() ) + return; + final T value = newNumber( 3 ); + value.mul( 2.0 ); + assertEquals( newNumber( 6 ), value ); + } + + @Test + public void testMulFloat() + { + if ( isMaxValueLessThanSix() ) + return; + + final T value = newNumber( 3 ); + value.mul( 2.0f ); + assertEquals( newNumber( 6 ), value ); + } + + @Test + public void testDiv() + { + if ( isMaxValueLessThanSix() ) + return; + final T value = newNumber( 6 ); + value.div( newNumber( 2 ) ); + assertEquals( newNumber( 3 ), value ); + } + + @Test + public void testHashCodeEquals() + { + final int hashA = newOne().hashCode(); + final int hashB = newOne().hashCode(); + assertEquals( hashA, hashB ); + } + + /* + * NB: This test is here as a sanity check. In principle, there may be hash + * collision between 0 and 1 values. In practice, for the current + * implementations there never is. (If there is ever a good reason to change + * that, this test can be removed.) + */ + @Test + public void testHashCodeChanges() + { + final T variable = newZero(); + final int hashZero = variable.hashCode(); + variable.set( newOne() ); + final int hashOne = variable.hashCode(); + assertNotEquals( hashZero, hashOne ); + } + + @Test + public void testCompareTo() + { + final T t = newZero(); + if ( ( t instanceof Comparable ) && !( t instanceof BooleanType ) ) + testCompareTo( ( Comparable ) newZero(), ( Comparable ) newOne(), ( Comparable ) newOne() ); + } + + private < T extends Comparable< T > > void testCompareTo( final T one, final T two, final T anotherOne ) + { + assertTrue( one.compareTo( two ) < 0 ); + assertTrue( two.compareTo( one ) > 0 ); + assertEquals( 0, two.compareTo( anotherOne ) ); + } + + @Test + public void testCompareMinMax() + { + if ( newZero() instanceof RealType ) + testCompareMinMax( ( RealType ) newOne() ); + } + + private < T extends RealType< T > > void testCompareMinMax( final T one ) + { + // NB: This ensures that comparison for unsigned types is correctly implemented. + final T minValue = minValue( one ); + final T maxValue = maxValue( one ); + assertTrue( minValue.compareTo( maxValue ) < 0 ); + } + + private < T extends RealType< T > > T maxValue( final T one ) + { + if ( one instanceof Unsigned128BitType ) + // NB: Max value for Unsigned128BitType, is not returned with required precision by one.getMaxValue(). + return ( T ) new Unsigned128BitType( 0xffffffffffffffffL, 0xffffffffffffffffL ); + final T maxValue = one.copy(); + maxValue.mul( one.getMaxValue() ); + return maxValue; + } + + private < T extends RealType< T > > T minValue( final T one ) + { + final T minValue = one.copy(); + minValue.mul( one.getMinValue() ); + return minValue; + } + + // -- Helper methods -- + + private T newZero() + { + final T zero = type.createVariable(); + zero.setZero(); + return zero; + } + + private T newOne() + { + final T one = type.createVariable(); + one.setOne(); + return one; + } + + private boolean isMaxValueLessThanSix() + { + return type instanceof BooleanType + || type instanceof Unsigned2BitType; + } + + private T newNumber( final int value ) + { + if ( value < 0 ) + throw new AssertionError(); + final T result = newZero(); + final T one = newOne(); + for ( int i = 0; i < value; i++ ) + result.add( one ); + return result; + } +} diff --git a/src/test/java/net/imglib2/type/numeric/complex/ComplexDoubleTypeTest.java b/src/test/java/net/imglib2/type/numeric/complex/ComplexDoubleTypeTest.java index ae2e764f88..9ca2aaa7ce 100644 --- a/src/test/java/net/imglib2/type/numeric/complex/ComplexDoubleTypeTest.java +++ b/src/test/java/net/imglib2/type/numeric/complex/ComplexDoubleTypeTest.java @@ -76,13 +76,4 @@ public void testEquals() assertTrue( i4.equals( b ) ); } - - /** Tests {@link ComplexDoubleType#hashCode()}. */ - @Test - public void testHashCode() - { - final ComplexDoubleType b = new ComplexDoubleType( 1.234, 5.678 ); - assertEquals( 379318760, b.hashCode() ); - } - } diff --git a/src/test/java/net/imglib2/type/numeric/complex/ComplexFloatTypeTest.java b/src/test/java/net/imglib2/type/numeric/complex/ComplexFloatTypeTest.java index 07c36281e4..20fcc8d89c 100644 --- a/src/test/java/net/imglib2/type/numeric/complex/ComplexFloatTypeTest.java +++ b/src/test/java/net/imglib2/type/numeric/complex/ComplexFloatTypeTest.java @@ -75,14 +75,4 @@ public void testEquals() assertTrue( b.equals( i4 ) ); assertTrue( i4.equals( b ) ); } - - - /** Tests {@link ComplexFloatType#hashCode()}. */ - @Test - public void testHashCode() - { - final ComplexFloatType b = new ComplexFloatType( 1.234f, 5.678f ); - assertEquals( 535103539, b.hashCode() ); - } - } diff --git a/src/test/java/net/imglib2/util/UtilTest.java b/src/test/java/net/imglib2/util/UtilTest.java index f4fb15bd11..45f8b79aba 100644 --- a/src/test/java/net/imglib2/util/UtilTest.java +++ b/src/test/java/net/imglib2/util/UtilTest.java @@ -48,13 +48,14 @@ import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.IntType; import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.type.operators.ValueEquals; import org.junit.Test; import java.util.function.BiPredicate; -import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class UtilTest @@ -187,4 +188,43 @@ public void testAsDoubleArray() double[] result = Util.asDoubleArray( img ); assertArrayEquals( expected, result, 0.0 ); } + + /** + * Tests {@link Util#valueEqualsObject(ValueEquals, Object)}. + *

+ * Class {@link Simple} demonstrates how the method is supposed to be used. + */ + @Test + public void testValueEqualsObject() + { + Simple four = new Simple( 4 ); + assertTrue( four.equals( four ) ); + assertTrue( four.equals( new Simple( 4 ) ) ); + assertFalse( four.equals( new Simple( 5 ) ) ); + assertFalse( four.equals( new Object() ) ); + assertFalse( four.equals( null ) ); + } + + private static class Simple implements ValueEquals< Simple > + { + + private final int value; + + private Simple( int value ) + { + this.value = value; + } + + @Override + public boolean valueEquals( Simple simple ) + { + return this.value == simple.value; + } + + @Override + public boolean equals( Object obj ) + { + return Util.valueEqualsObject( this, obj ); + } + } }