Skip to content

Commit 37ea55d

Browse files
committed
ImgMath: faster IF statements by reInit'ing If as IfBoolean
when the first argument is a Compare (Equal, NotEqual, LessThan, GreaterThan). Performance of IF improves from ~4X to 2X-3X relative to low-level math with Cursor.
1 parent 8ba51f7 commit 37ea55d

File tree

6 files changed

+108
-15
lines changed

6 files changed

+108
-15
lines changed

src/main/java/net/imglib2/algorithm/math/Equal.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ private Equal( final RealType< ? > scrap, final IFunction f1, final IFunction f2
1919
}
2020

2121
@SuppressWarnings({ "rawtypes", "unchecked" })
22+
@Override
2223
public final boolean compare( final RealType t1, final RealType t2 )
2324
{
2425
return 0 == t1.compareTo( t2 );
2526
}
2627

2728
@Override
28-
public Equal reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
29+
public Equal reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
2930
{
3031
return new Equal( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
3132
}

src/main/java/net/imglib2/algorithm/math/If.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,28 @@
44

55
import net.imglib2.Localizable;
66
import net.imglib2.algorithm.math.abstractions.ATrinaryFunction;
7+
import net.imglib2.algorithm.math.abstractions.Compare;
78
import net.imglib2.algorithm.math.abstractions.IFunction;
89
import net.imglib2.converter.Converter;
910
import net.imglib2.type.numeric.RealType;
1011

11-
public final class If extends ATrinaryFunction
12+
public class If extends ATrinaryFunction
1213
{
1314
public If( final Object o1, final Object o2, final Object o3 )
1415
{
1516
super( o1, o2, o3 );
1617
}
1718

18-
private If( final RealType< ? > scrap, final IFunction f1, final IFunction f2, final IFunction f3 )
19+
protected If( final RealType< ? > scrap, final IFunction f1, final IFunction f2, final IFunction f3 )
1920
{
2021
super ( scrap, f1, f2, f3 );
2122
}
2223

2324
@Override
24-
public final void eval( final RealType<?> output )
25+
public void eval( final RealType< ? > output )
2526
{
2627
this.a.eval( this.scrap );
27-
if ( 0.0f != this.scrap.getRealFloat() )
28+
if ( 0 != this.scrap.getRealFloat() )
2829
{
2930
// Then
3031
this.b.eval( output );
@@ -36,10 +37,10 @@ public final void eval( final RealType<?> output )
3637
}
3738

3839
@Override
39-
public final void eval( final RealType<?> output, final Localizable loc )
40+
public void eval( final RealType< ? > output, final Localizable loc )
4041
{
4142
this.a.eval( this.scrap, loc );
42-
if ( 0.0f != this.scrap.getRealFloat() )
43+
if ( 0 != this.scrap.getRealFloat() )
4344
{
4445
// Then
4546
this.b.eval( output, loc );
@@ -51,8 +52,14 @@ public final void eval( final RealType<?> output, final Localizable loc )
5152
}
5253

5354
@Override
54-
public If reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter )
55+
public If reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
5556
{
57+
// Optimization: reInit as IfBoolean if the first argument is a Compare.
58+
// Avoids having to set the output to 1 (true) or 0 (false),
59+
// and then having to read it out and compare it to zero to make a boolean,
60+
// instead returning a boolean directly.
61+
if ( this.a instanceof Compare )
62+
return new IfBoolean( tmp.copy(), ( Compare ) this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ), this.c.reInit( tmp, bindings, converter ) );
5663
return new If( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ), this.c.reInit( tmp, bindings, converter ) );
5764
}
5865
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package net.imglib2.algorithm.math;
2+
3+
import java.util.Map;
4+
5+
import net.imglib2.Localizable;
6+
import net.imglib2.algorithm.math.abstractions.Compare;
7+
import net.imglib2.algorithm.math.abstractions.IBooleanFunction;
8+
import net.imglib2.algorithm.math.abstractions.IFunction;
9+
import net.imglib2.converter.Converter;
10+
import net.imglib2.type.numeric.RealType;
11+
12+
public class IfBoolean extends If
13+
{
14+
/**
15+
* Same as this.a, to avoid casting.
16+
*/
17+
final IBooleanFunction abool;
18+
19+
protected IfBoolean( final RealType< ? > scrap, final Compare f1, final IFunction f2, final IFunction f3 )
20+
{
21+
super ( scrap, f1, f2, f3 );
22+
this.abool = f1; // same as this.a
23+
}
24+
25+
@Override
26+
public final void eval( final RealType< ? > output )
27+
{
28+
if ( this.abool.evalBoolean( this.scrap ) )
29+
{
30+
// Then
31+
this.b.eval( output );
32+
} else
33+
{
34+
// Else
35+
this.c.eval( output );
36+
}
37+
}
38+
39+
@Override
40+
public final void eval( final RealType< ? > output, final Localizable loc )
41+
{
42+
if ( this.abool.evalBoolean( output, loc ) )
43+
{
44+
// Then
45+
this.b.eval( output, loc );
46+
} else
47+
{
48+
// Else
49+
this.c.eval( output, loc );
50+
}
51+
}
52+
53+
@Override
54+
public IfBoolean reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter )
55+
{
56+
return new IfBoolean( tmp.copy(), ( Compare ) this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ), this.c.reInit( tmp, bindings, converter ) );
57+
}
58+
}

src/main/java/net/imglib2/algorithm/math/NotEqual.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public final boolean compare( final RealType t1, final RealType t2 )
2525
}
2626

2727
@Override
28-
public NotEqual reInit( final RealType<?> tmp, final Map<String, RealType<?>> bindings, final Converter<RealType<?>, RealType<?>> converter ) {
28+
public NotEqual reInit( final RealType< ? > tmp, final Map< String, RealType< ? > > bindings, final Converter< RealType< ? >, RealType< ? > > converter ) {
2929
return new NotEqual( tmp.copy(), this.a.reInit( tmp, bindings, converter ), this.b.reInit( tmp, bindings, converter ) );
3030
}
3131
}

src/main/java/net/imglib2/algorithm/math/abstractions/Compare.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import net.imglib2.Localizable;
44
import net.imglib2.type.numeric.RealType;
55

6-
abstract public class Compare extends ABinaryFunction
6+
abstract public class Compare extends ABinaryFunction implements IBooleanFunction
77
{
88
public Compare( final Object o1, final Object o2) {
99
super( o1, o2 );
@@ -14,11 +14,11 @@ protected Compare( final RealType< ? > scrap, final IFunction f1, final IFunctio
1414
super( scrap, f1, f2 );
1515
}
1616

17-
abstract protected boolean compare( final RealType<?> t1, final RealType<?> t2 );
17+
abstract protected boolean compare( final RealType< ? > t1, final RealType< ? > t2 );
1818

19-
@SuppressWarnings("rawtypes")
2019
@Override
21-
public void eval( final RealType output ) {
20+
public final void eval( final RealType< ? > output )
21+
{
2222
this.a.eval( this.scrap );
2323
this.b.eval( output );
2424
if ( this.compare( this.scrap, output ) )
@@ -27,14 +27,30 @@ public void eval( final RealType output ) {
2727
output.setZero();
2828
}
2929

30-
@SuppressWarnings("rawtypes")
3130
@Override
32-
public void eval( final RealType output, final Localizable loc) {
31+
public final void eval( final RealType< ? > output, final Localizable loc)
32+
{
3333
this.a.eval( this.scrap, loc );
3434
this.b.eval( output, loc );
3535
if ( this.compare( this.scrap, output ) )
3636
output.setOne();
3737
else
3838
output.setZero();
3939
}
40+
41+
@Override
42+
public final boolean evalBoolean( final RealType< ? > output )
43+
{
44+
this.a.eval( this.scrap );
45+
this.b.eval( output );
46+
return this.compare( this.scrap, output );
47+
}
48+
49+
@Override
50+
public final boolean evalBoolean( final RealType< ? > output, final Localizable loc )
51+
{
52+
this.a.eval( this.scrap, loc );
53+
this.b.eval( output, loc );
54+
return this.compare( this.scrap, output );
55+
}
4056
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package net.imglib2.algorithm.math.abstractions;
2+
3+
import net.imglib2.Localizable;
4+
import net.imglib2.type.numeric.RealType;
5+
6+
public interface IBooleanFunction
7+
{
8+
public boolean evalBoolean( final RealType< ? > output );
9+
10+
public boolean evalBoolean( final RealType< ? > output, final Localizable loc );
11+
}

0 commit comments

Comments
 (0)