net.imglib2
imglib2-ij
diff --git a/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java
new file mode 100644
index 000000000..a15ecad19
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java
@@ -0,0 +1,96 @@
+package net.imglib2.algorithm.blocks;
+
+import static net.imglib2.util.Util.safeInt;
+
+import java.util.Arrays;
+
+import net.imglib2.Interval;
+import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
+import net.imglib2.blocks.TempArray;
+import net.imglib2.type.PrimitiveType;
+import net.imglib2.util.Intervals;
+
+/**
+ * Boilerplate for {@link BlockProcessor} to simplify implementations.
+ *
+ * This is intented as a base class for {@code BlockProcessor} that have source
+ * dimensionality fixed at construction. For {@code BlockProcessor} with
+ * adaptable number of dimensions (such as converters), see {@link
+ * AbstractDimensionlessBlockProcessor}.
+ *
+ * {@link BlockProcessor#getSourcePos() getSourcePos()}, {@link
+ * BlockProcessor#getSourceSize() getSourceSize()}, and {@link
+ * BlockProcessor#getSourceInterval() getSourceInterval()} are implemented to
+ * return the {@code protected} fields {@code long[] sourcePos} and {@code
+ * }int[] sourceSize}. The {@code }protected} method {@code }int sourceLength()}
+ * can be used to get the number of elements in the source interval.
+ *
+ * {@link BlockProcessor#getSourceBuffer() getSourceBuffer()} is implemented
+ * according to the {@code sourcePrimitiveType} specified at construction.
+ *
+ * @param
+ * input primitive array type, e.g., float[]
+ * @param
+ * output primitive array type, e.g., float[]
+ */
+public abstract class AbstractBlockProcessor< I, O > implements BlockProcessor< I, O >
+{
+ private final TempArray< I > tempArray;
+
+ protected final long[] sourcePos;
+
+ protected final int[] sourceSize;
+
+ private final BlockProcessorSourceInterval sourceInterval = new BlockProcessorSourceInterval( this );
+
+ protected AbstractBlockProcessor( final PrimitiveType sourcePrimitiveType, final int numSourceDimensions )
+ {
+ tempArray = TempArray.forPrimitiveType( sourcePrimitiveType );
+ sourcePos = new long[ numSourceDimensions ];
+ sourceSize = new int[ numSourceDimensions ];
+ }
+
+ protected AbstractBlockProcessor( final AbstractBlockProcessor< I, O > proc )
+ {
+ tempArray = proc.tempArray.newInstance();
+ final int numSourceDimensions = proc.sourcePos.length;
+ sourcePos = new long[ numSourceDimensions ];
+ sourceSize = new int[ numSourceDimensions ];
+ }
+
+ protected int sourceLength()
+ {
+ return safeInt( Intervals.numElements( sourceSize ) );
+ }
+
+ @Override
+ public void setTargetInterval( final Interval interval )
+ {
+ interval.min( sourcePos );
+ Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
+ }
+
+ @Override
+ public long[] getSourcePos()
+ {
+ return sourcePos;
+ }
+
+ @Override
+ public int[] getSourceSize()
+ {
+ return sourceSize;
+ }
+
+ @Override
+ public Interval getSourceInterval()
+ {
+ return sourceInterval;
+ }
+
+ @Override
+ public I getSourceBuffer()
+ {
+ return tempArray.get( sourceLength() );
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java
new file mode 100644
index 000000000..7d5b7a0f5
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java
@@ -0,0 +1,56 @@
+package net.imglib2.algorithm.blocks;
+
+import java.util.function.Supplier;
+
+import net.imglib2.type.NativeType;
+import net.imglib2.util.CloseableThreadLocal;
+
+/**
+ * Boilerplate for {@link BlockSupplier} to simplify implementations.
+ *
+ * Implements {@link BlockSupplier#threadSafe()} as a wrapper that makes {@link
+ * ThreadLocal} {@link BlockSupplier#independentCopy()} copies.
+ */
+public abstract class AbstractBlockSupplier< T extends NativeType< T > > implements BlockSupplier< T >
+{
+ private Supplier< BlockSupplier< T > > threadSafeSupplier;
+
+ @Override
+ public BlockSupplier< T > threadSafe()
+ {
+ if ( threadSafeSupplier == null )
+ threadSafeSupplier = CloseableThreadLocal.withInitial( this::independentCopy )::get;
+ return new BlockSupplier< T >()
+ {
+ @Override
+ public T getType()
+ {
+ return AbstractBlockSupplier.this.getType();
+ }
+
+ @Override
+ public int numDimensions()
+ {
+ return AbstractBlockSupplier.this.numDimensions();
+ }
+
+ @Override
+ public void copy( final long[] srcPos, final Object dest, final int[] size )
+ {
+ threadSafeSupplier.get().copy( srcPos, dest, size );
+ }
+
+ @Override
+ public BlockSupplier< T > independentCopy()
+ {
+ return AbstractBlockSupplier.this.independentCopy().threadSafe();
+ }
+
+ @Override
+ public BlockSupplier< T > threadSafe()
+ {
+ return this;
+ }
+ };
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java
new file mode 100644
index 000000000..c4657b3f6
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java
@@ -0,0 +1,111 @@
+package net.imglib2.algorithm.blocks;
+
+import static net.imglib2.util.Util.safeInt;
+
+import java.util.Arrays;
+
+import net.imglib2.Interval;
+import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
+import net.imglib2.blocks.TempArray;
+import net.imglib2.type.PrimitiveType;
+import net.imglib2.util.Intervals;
+
+/**
+ * Boilerplate for {@link BlockProcessor} to simplify implementations.
+ *
+ * This is intented as a base class for {@code BlockProcessor} with an adaptable
+ * number of dimensions (such as converters). For {@code BlockProcessor} with a
+ * fixed number of source dimensions, see {@link AbstractBlockProcessor}.
+ *
+ * {@link BlockProcessor#getSourcePos() getSourcePos()}, {@link
+ * BlockProcessor#getSourceSize() getSourceSize()}, and {@link
+ * BlockProcessor#getSourceInterval() getSourceInterval()} are implemented to
+ * return the {@code protected} fields {@code long[] sourcePos} and {@code
+ * }int[] sourceSize}. The {@code }protected} method {@code }int sourceLength()}
+ * can be used to get the number of elements in the source interval.
+ *
+ * {@link BlockProcessor#getSourceBuffer() getSourceBuffer()} is implemented
+ * according to the {@code sourcePrimitiveType} specified at construction.
+ *
+ * @param
+ * input primitive array type, e.g., float[]
+ * @param
+ * output primitive array type, e.g., float[]
+ */
+public abstract class AbstractDimensionlessBlockProcessor< I, O > implements BlockProcessor< I, O >
+{
+ private final TempArray< I > tempArray;
+
+ protected long[] sourcePos;
+
+ protected int[] sourceSize;
+
+ private final BlockProcessorSourceInterval sourceInterval = new BlockProcessorSourceInterval( this );
+
+ protected AbstractDimensionlessBlockProcessor( final PrimitiveType sourcePrimitiveType )
+ {
+ tempArray = TempArray.forPrimitiveType( sourcePrimitiveType );
+ }
+
+ protected AbstractDimensionlessBlockProcessor( final AbstractDimensionlessBlockProcessor< I, O > proc )
+ {
+ tempArray = proc.tempArray.newInstance();
+ }
+
+ @Override
+ public void setTargetInterval( final Interval interval )
+ {
+ updateNumSourceDimsensions( interval.numDimensions() );
+ interval.min( sourcePos );
+ Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
+ }
+
+ /**
+ * Re-allocates {@code sourcePos} and {@code sourceSize} arrays if they do
+ * not already exist and have {@code length==n}.
+ *
+ * @param n
+ * new number of source dimensions
+ *
+ * @return {@code true} if {@code sourcePos} and {@code sourceSize} arrays were re-allocated
+ */
+ protected boolean updateNumSourceDimsensions( final int n )
+ {
+ if ( sourcePos == null || sourcePos.length != n )
+ {
+ sourcePos = new long[ n ];
+ sourceSize = new int[ n ];
+ return true;
+ }
+ return false;
+ }
+
+ protected int sourceLength()
+ {
+ return safeInt( Intervals.numElements( sourceSize ) );
+ }
+
+ @Override
+ public long[] getSourcePos()
+ {
+ return sourcePos;
+ }
+
+ @Override
+ public int[] getSourceSize()
+ {
+ return sourceSize;
+ }
+
+ @Override
+ public Interval getSourceInterval()
+ {
+ return sourceInterval;
+ }
+
+ @Override
+ public I getSourceBuffer()
+ {
+ return tempArray.get( sourceLength() );
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/BlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/BlockProcessor.java
index 93652cfae..1bbb25658 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/BlockProcessor.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/BlockProcessor.java
@@ -33,9 +33,6 @@
*/
package net.imglib2.algorithm.blocks;
-import java.util.Arrays;
-
-import net.imglib2.FinalInterval;
import net.imglib2.Interval;
import net.imglib2.blocks.PrimitiveBlocks;
@@ -59,20 +56,15 @@ public interface BlockProcessor< I, O >
void setTargetInterval( Interval interval );
- default void setTargetInterval( long[] srcPos, int[] size )
+ default void setTargetInterval( long[] pos, int[] size )
{
- final long[] srcMax = new long[ srcPos.length ];
- Arrays.setAll( srcMax, d -> srcPos[ d ] + size[ d ] - 1 );
- setTargetInterval( FinalInterval.wrap( srcPos, srcMax ) );
+ setTargetInterval( new BlockProcessorTargetInterval( pos, size ) );
}
long[] getSourcePos();
int[] getSourceSize();
- // TODO: Its cumbersome to have both getSourcePos()/getSourceSize() *and* getSourceInterval()
- // Only have getSourcePos()/getSourceSize() ?
- // Have a modifiable SourceInterval class exposing getSourcePos()/getSourceSize() ?
Interval getSourceInterval();
/**
diff --git a/src/main/java/net/imglib2/algorithm/blocks/BlockProcessorTargetInterval.java b/src/main/java/net/imglib2/algorithm/blocks/BlockProcessorTargetInterval.java
new file mode 100644
index 000000000..84a7b9f4a
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/BlockProcessorTargetInterval.java
@@ -0,0 +1,45 @@
+package net.imglib2.algorithm.blocks;
+
+import net.imglib2.Interval;
+
+/**
+ * Wraps {@code long[] pos} and {@code int[] size} as a {@code Interval}, for
+ * the default implementation of {@link BlockProcessor#setTargetInterval(long[],
+ * int[])}.
+ */
+class BlockProcessorTargetInterval implements Interval
+{
+ private final long[] min;
+
+ private final int[] size;
+
+ BlockProcessorTargetInterval( long[] min, int[] size )
+ {
+ this.min = min;
+ this.size = size;
+ }
+
+ @Override
+ public long min( final int i )
+ {
+ return min[ i ];
+ }
+
+ @Override
+ public long max( final int i )
+ {
+ return min[ i ] + size[ i ] - 1;
+ }
+
+ @Override
+ public long dimension( final int d )
+ {
+ return size[ d ];
+ }
+
+ @Override
+ public int numDimensions()
+ {
+ return min.length;
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java
index cd2cd621f..3a2e5818b 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -37,15 +37,18 @@
import static net.imglib2.util.Util.safeInt;
import java.util.Arrays;
+import java.util.function.Function;
+import net.imglib2.EuclideanSpace;
import net.imglib2.Interval;
import net.imglib2.RandomAccessible;
import net.imglib2.Typed;
import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.type.NativeType;
+import net.imglib2.util.Cast;
import net.imglib2.util.Util;
-public interface BlockSupplier< T extends NativeType< T > > extends Typed< T >
+public interface BlockSupplier< T extends NativeType< T > > extends Typed< T >, EuclideanSpace
{
/**
* Copy a block from the ({@code T}-typed) source into primitive arrays (of
@@ -111,13 +114,50 @@ default void copy( Interval interval, Object dest )
*/
BlockSupplier< T > independentCopy();
+ /**
+ * Returns a new {@code BlockSupplier} that handles {@link #copy} requests
+ * by splitting into {@code tileSize} portions that are each handled by this
+ * {@code BlockSupplier} and assembled into the final result.
+ *
+ * Example use cases:
+ *
+ * - Compute large outputs (e.g. for writing to N5 or wrapping as {@code
+ * ArrayImg}) with operators that have better performance with small
+ * block sizes.
+ * - Avoid excessively large blocks when chaining downsampling
+ * operators.
+ *
+ *
+ * @param tileSize
+ * (maximum) dimensions of a request to the {@code srcSupplier}.
+ * {@code tileSize} is expanded or truncated to the necessary size. For
+ * example, if {@code tileSize=={64}} and this {@code BlockSupplier} is 3D,
+ * then {@code tileSize} is expanded to {@code {64, 64, 64}}.
+ */
+ default BlockSupplier< T > tile( int... tileSize )
+ {
+ return new TilingBlockSupplier<>( this, tileSize );
+ }
+
/**
* Returns a {@code UnaryBlockOperator} that is equivalent to applying
* {@code this}, and then applying {@code op} to the result.
*/
default < U extends NativeType< U > > BlockSupplier< U > andThen( UnaryBlockOperator< T, U > operator )
{
- return new ConcatenatedBlockSupplier<>( this.independentCopy(), operator.independentCopy() );
+ if ( operator instanceof NoOpUnaryBlockOperator )
+ return Cast.unchecked( this );
+ else
+ return new ConcatenatedBlockSupplier<>( this.independentCopy(), operator.independentCopy() );
+ }
+
+ default < U extends NativeType< U > > BlockSupplier< U > andThen( Function< BlockSupplier< T >, UnaryBlockOperator< T, U > > function )
+ {
+ final UnaryBlockOperator< T, U > op = function.apply( this );
+ if ( op instanceof NoOpUnaryBlockOperator )
+ return Cast.unchecked( this );
+ else
+ return new ConcatenatedBlockSupplier<>( this.independentCopy(), op );
}
/**
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/ClampType.java b/src/main/java/net/imglib2/algorithm/blocks/ClampType.java
similarity index 92%
rename from src/main/java/net/imglib2/algorithm/blocks/convert/ClampType.java
rename to src/main/java/net/imglib2/algorithm/blocks/ClampType.java
index 2957132c8..39eefd2a1 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/ClampType.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/ClampType.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -31,10 +31,10 @@
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
-package net.imglib2.algorithm.blocks.convert;
+package net.imglib2.algorithm.blocks;
/**
- * How to clamp values when converting between {@link net.imglib2.algorithm.blocks.util.OperandType}.
+ * How to clamp values when converting to target type.
*/
public enum ClampType
{
@@ -48,8 +48,13 @@ public enum ClampType
*/
CLAMP,
+ /**
+ * clamp only to lower bound
+ */
+ CLAMP_MIN,
+
/**
* clamp only to upper bound
*/
- CLAMP_MAX;
+ CLAMP_MAX
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/ComputationType.java b/src/main/java/net/imglib2/algorithm/blocks/ComputationType.java
new file mode 100644
index 000000000..f2e8f9918
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/ComputationType.java
@@ -0,0 +1,12 @@
+package net.imglib2.algorithm.blocks;
+
+/**
+ * Specify in which precision should intermediate values be computed. (For
+ * {@code AUTO}, the type that can represent the input/output type without
+ * loss of precision is picked. That is, {@code FLOAT} for u8, i8, u16, i16,
+ * i32, f32, and otherwise {@code DOUBLE} for u32, i64, f64.
+ */
+public enum ComputationType
+{
+ FLOAT, DOUBLE, AUTO
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java
index 735a89898..6b2d26040 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java
@@ -62,13 +62,6 @@ public void setTargetInterval( final Interval interval )
p0.setTargetInterval( p1.getSourceInterval() );
}
- @Override
- public void setTargetInterval( final long[] srcPos, final int[] size )
- {
- p1.setTargetInterval( srcPos, size );
- p0.setTargetInterval( p1.getSourcePos(), p1.getSourceSize() );
- }
-
@Override
public long[] getSourcePos()
{
@@ -96,7 +89,8 @@ public I getSourceBuffer()
@Override
public void compute( final I src, final O dest )
{
- p0.compute( src, p1.getSourceBuffer() );
- p1.compute( p1.getSourceBuffer(), dest );
+ final K temp = p1.getSourceBuffer();
+ p0.compute( src, temp );
+ p1.compute( temp, dest );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java
index ca6545e44..f217b958d 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,13 +33,10 @@
*/
package net.imglib2.algorithm.blocks;
-import java.util.function.Supplier;
-
import net.imglib2.type.NativeType;
import net.imglib2.util.Cast;
-import net.imglib2.util.CloseableThreadLocal;
-class ConcatenatedBlockSupplier< T extends NativeType< T > > implements BlockSupplier< T >
+class ConcatenatedBlockSupplier< T extends NativeType< T > > extends AbstractBlockSupplier< T >
{
private final BlockSupplier< ? > p0;
@@ -47,7 +44,7 @@ class ConcatenatedBlockSupplier< T extends NativeType< T > > implements BlockSup
private final T type;
- private Supplier< BlockSupplier< T > > threadSafeSupplier;
+ private final int numDimensions;
public < S extends NativeType< S > > ConcatenatedBlockSupplier(
final BlockSupplier< S > srcSupplier,
@@ -56,6 +53,16 @@ public < S extends NativeType< S > > ConcatenatedBlockSupplier(
this.p0 = srcSupplier;
this.p1 = operator.blockProcessor();
this.type = operator.getTargetType();
+ if ( operator.numSourceDimensions() > 0 )
+ {
+ if ( srcSupplier.numDimensions() != operator.numSourceDimensions() )
+ throw new IllegalArgumentException( "UnaryBlockOperator cannot be concatenated: number of dimensions mismatch." );
+ this.numDimensions = operator.numTargetDimensions();
+ }
+ else
+ {
+ this.numDimensions = srcSupplier.numDimensions();
+ }
}
private ConcatenatedBlockSupplier( final ConcatenatedBlockSupplier< T > s )
@@ -63,6 +70,7 @@ private ConcatenatedBlockSupplier( final ConcatenatedBlockSupplier< T > s )
p0 = s.p0.independentCopy();
p1 = s.p1.independentCopy();
type = s.type;
+ numDimensions = s.numDimensions;
}
@Override
@@ -71,6 +79,12 @@ public T getType()
return type;
}
+ @Override
+ public int numDimensions()
+ {
+ return numDimensions;
+ }
+
@Override
public void copy( final long[] srcPos, final Object dest, final int[] size )
{
@@ -85,37 +99,4 @@ public BlockSupplier< T > independentCopy()
{
return new ConcatenatedBlockSupplier<>( this );
}
-
- @Override
- public BlockSupplier< T > threadSafe()
- {
- if ( threadSafeSupplier == null )
- threadSafeSupplier = CloseableThreadLocal.withInitial( this::independentCopy )::get;
- return new BlockSupplier< T >()
- {
- @Override
- public T getType()
- {
- return type;
- }
-
- @Override
- public void copy( final long[] srcPos, final Object dest, final int[] size )
- {
- threadSafeSupplier.get().copy( srcPos, dest, size );
- }
-
- @Override
- public BlockSupplier< T > independentCopy()
- {
- return ConcatenatedBlockSupplier.this.independentCopy().threadSafe();
- }
-
- @Override
- public BlockSupplier< T > threadSafe()
- {
- return this;
- }
- };
- }
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java
index aec938fa0..fdba81fcc 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java
@@ -38,16 +38,37 @@
import net.imglib2.util.Cast;
import net.imglib2.util.CloseableThreadLocal;
+/**
+ * Default implementation of {@link UnaryBlockOperator}.
+ *
+ * If you implement a {@code BlockProcessor}, you typically wrap it with a
+ * {@code DefaultUnaryBlockOperator}, specifying the source {@code S} and target
+ * {@code T} ImgLib2 {@code NativeType}s corresponding to primitive array types
+ * {@code I} and {@code O}, and the number of source and target dimension.
+ *
+ * The {@link UnaryBlockOperator} can then be used in {@link
+ * BlockSupplier#andThen(UnaryBlockOperator)} chains in a type- and
+ * simensionality-safe manner.
+ *
+ * @param
+ * source type
+ * @param
+ * target type
+ */
public class DefaultUnaryBlockOperator< S extends NativeType< S >, T extends NativeType< T > > implements UnaryBlockOperator< S, T >
{
private final S sourceType;
private final T targetType;
+ private final int numSourceDimensions;
+ private final int numTargetDimensions;
private final BlockProcessor< ?, ? > blockProcessor;
- public DefaultUnaryBlockOperator( S sourceType, T targetType, BlockProcessor< ?, ? > blockProcessor )
+ public DefaultUnaryBlockOperator( S sourceType, T targetType, int numSourceDimensions, int numTargetDimensions, BlockProcessor< ?, ? > blockProcessor )
{
this.sourceType = sourceType;
this.targetType = targetType;
+ this.numSourceDimensions = numSourceDimensions;
+ this.numTargetDimensions = numTargetDimensions;
this.blockProcessor = blockProcessor;
}
@@ -69,10 +90,22 @@ public T getTargetType()
return targetType;
}
+ @Override
+ public int numSourceDimensions()
+ {
+ return numSourceDimensions;
+ }
+
+ @Override
+ public int numTargetDimensions()
+ {
+ return numTargetDimensions;
+ }
+
@Override
public UnaryBlockOperator< S, T > independentCopy()
{
- return new DefaultUnaryBlockOperator<>( sourceType, targetType, blockProcessor.independentCopy() );
+ return new DefaultUnaryBlockOperator<>( sourceType, targetType, numSourceDimensions, numTargetDimensions, blockProcessor.independentCopy() );
}
private Supplier< UnaryBlockOperator< S, T > > threadSafeSupplier;
@@ -102,6 +135,18 @@ public T getTargetType()
return targetType;
}
+ @Override
+ public int numSourceDimensions()
+ {
+ return numSourceDimensions;
+ }
+
+ @Override
+ public int numTargetDimensions()
+ {
+ return numTargetDimensions;
+ }
+
@Override
public UnaryBlockOperator< S, T > threadSafe()
{
diff --git a/src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java
new file mode 100644
index 000000000..cf6b123ea
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java
@@ -0,0 +1,97 @@
+/*-
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks;
+
+import java.util.function.Supplier;
+
+import net.imglib2.type.NativeType;
+import net.imglib2.util.Cast;
+import net.imglib2.util.CloseableThreadLocal;
+
+/**
+ * Does nothing. This should be eliminated when concatenating through
+ * {@link UnaryBlockOperator#andThen(UnaryBlockOperator)} or {@link BlockSupplier#andThen(UnaryBlockOperator)}.
+ *
+ * @param
+ */
+public class NoOpUnaryBlockOperator< S extends NativeType< S >, T extends NativeType< T > > implements UnaryBlockOperator< S, T >
+{
+ @Override
+ public < I, O > BlockProcessor< I, O > blockProcessor()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public < U extends NativeType< U > > UnaryBlockOperator< S, U > andThen( UnaryBlockOperator< T, U > op )
+ {
+ return Cast.unchecked( op );
+ }
+
+ @Override
+ public S getSourceType()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public T getTargetType()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int numSourceDimensions()
+ {
+ return 0;
+ }
+
+ @Override
+ public int numTargetDimensions()
+ {
+ return 0;
+ }
+
+ @Override
+ public UnaryBlockOperator< S, T > independentCopy()
+ {
+ return this;
+ }
+
+ @Override
+ public UnaryBlockOperator< S, T > threadSafe()
+ {
+ return this;
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/PrimitiveBlocksSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/PrimitiveBlocksSupplier.java
index ab7db848b..ca4696a4a 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/PrimitiveBlocksSupplier.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/PrimitiveBlocksSupplier.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,18 +33,13 @@
*/
package net.imglib2.algorithm.blocks;
-import java.util.function.Supplier;
-
import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.type.NativeType;
-import net.imglib2.util.CloseableThreadLocal;
-class PrimitiveBlocksSupplier< T extends NativeType< T > > implements BlockSupplier< T >
+class PrimitiveBlocksSupplier< T extends NativeType< T > > extends AbstractBlockSupplier< T >
{
private final PrimitiveBlocks< T > blocks;
- private Supplier< BlockSupplier< T > > threadSafeSupplier;
-
PrimitiveBlocksSupplier( final PrimitiveBlocks< T > blocks )
{
this.blocks = blocks;
@@ -56,6 +51,12 @@ public T getType()
return blocks.getType();
}
+ @Override
+ public int numDimensions()
+ {
+ return blocks.numDimensions();
+ }
+
@Override
public void copy( final long[] srcPos, final Object dest, final int[] size )
{
@@ -74,37 +75,4 @@ public BlockSupplier< T > independentCopy()
final PrimitiveBlocks< T > blocksCopy = blocks.independentCopy();
return blocksCopy == blocks ? this : new PrimitiveBlocksSupplier<>( blocksCopy );
}
-
- @Override
- public BlockSupplier< T > threadSafe()
- {
- if ( threadSafeSupplier == null )
- threadSafeSupplier = CloseableThreadLocal.withInitial( this::independentCopy )::get;
- return new BlockSupplier< T >()
- {
- @Override
- public T getType()
- {
- return blocks.getType();
- }
-
- @Override
- public void copy( final long[] srcPos, final Object dest, final int[] size )
- {
- threadSafeSupplier.get().copy( srcPos, dest, size );
- }
-
- @Override
- public BlockSupplier< T > independentCopy()
- {
- return PrimitiveBlocksSupplier.this.independentCopy().threadSafe();
- }
-
- @Override
- public BlockSupplier< T > threadSafe()
- {
- return this;
- }
- };
- }
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/TilingBlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/TilingBlockSupplier.java
new file mode 100644
index 000000000..f9113e562
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/TilingBlockSupplier.java
@@ -0,0 +1,200 @@
+/*-
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks;
+
+import net.imglib2.blocks.SubArrayCopy;
+import net.imglib2.blocks.TempArray;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.PrimitiveType;
+import net.imglib2.util.Cast;
+import net.imglib2.util.Intervals;
+import net.imglib2.util.Util;
+
+/**
+ * {@code TilingBlockSupplier} wraps a source {@code BlockSupplier}, and splits
+ * large {@link BlockSupplier#copy} requests into several smaller {@code copy}
+ * calls on the source {@code BlockSupplier}.
+ *
+ * Each {@code copy} on the source {@code BlockSupplier} requests (at most) an
+ * interval of the {@code tileSize} specified in the constructor. The source
+ * {@code BlockSupplier.copy} writes to a temporary buffer, which is then copied
+ * into the appropriate portion of the {@code dest} buffer.
+ *
+ * {@link BlockSupplier#copy} requests that are smaller or equal to {@code
+ * tileSize} are passed directly to the source {@code BlockSupplier}.
+ *
+ * Example use cases:
+ *
+ * - Computing large outputs (e.g. to write to N5 or wrap as {@code ArrayImg})
+ * with operators that have better performance with smaller block sizes.
+ * - Avoiding excessively large blocks when chaining downsampling
+ * operators.
+ *
+ *
+ * @param
+ * pixel type
+ * @param
+ * corresponding primitive array type
+ */
+class TilingBlockSupplier< T extends NativeType< T >, P > extends AbstractBlockSupplier< T >
+{
+ private final BlockSupplier< T > p0;
+
+ private final int[] innerTileSize;
+ private final int[] borderTileSize;
+ private final int[] numTiles;
+
+ private final TempArray< P > tempArray;
+ private final int innerTileNumElements;
+
+ private final SubArrayCopy.Typed< P, P > subArrayCopy;
+
+ final int[] tile_pos_in_dest;
+ final long[] tile_pos_in_src;
+ final int[] tile_origin;
+ final int[] tile_size;
+
+ /**
+ * Create a {@code BlockSupplier} that handles {@link BlockSupplier#copy}
+ * requests by splitting into {@code tileSize} portions that are each
+ * handled by the given {@code srcSupplier} and assembled into the final
+ * result.
+ *
+ * @param srcSupplier
+ * source {@code BlockSupplier} to wrap.
+ * @param tileSize
+ * (maximum) dimensions of a request to the {@code srcSupplier}.
+ * {@code tileSize} is expanded or truncated to the necessary size.
+ * For example, if {@code tileSize=={64}} when wrapping a 3D {@code
+ * srcSupplier}, {@code tileSize} is expanded to {@code {64, 64,
+ * 64}}.
+ */
+ public TilingBlockSupplier(
+ final BlockSupplier< T > srcSupplier,
+ final int... tileSize )
+ {
+ this.p0 = srcSupplier;
+ final int n = srcSupplier.numDimensions();
+ innerTileSize = Util.expandArray( tileSize, n );
+ innerTileNumElements = Util.safeInt( Intervals.numElements( innerTileSize ) );
+ borderTileSize = new int[ n ];
+ numTiles = new int[ n ];
+
+ final PrimitiveType primitiveType = srcSupplier.getType().getNativeTypeFactory().getPrimitiveType();
+ tempArray = TempArray.forPrimitiveType( primitiveType );
+ subArrayCopy = SubArrayCopy.forPrimitiveType( primitiveType );
+
+ tile_pos_in_dest = new int[ n ];
+ tile_pos_in_src = new long[ n ];
+ tile_origin = new int[ n ];
+ tile_size = new int[ n ];
+ }
+
+ private TilingBlockSupplier( final TilingBlockSupplier< T, P > s )
+ {
+ p0 = s.p0.independentCopy();
+ innerTileSize = s.innerTileSize;
+ innerTileNumElements = s.innerTileNumElements;
+ tempArray = s.tempArray.newInstance();
+ subArrayCopy = s.subArrayCopy;
+
+ final int n = numDimensions();
+ borderTileSize = new int[ n ];
+ numTiles = new int[ n ];
+ tile_pos_in_dest = new int[ n ];
+ tile_pos_in_src = new long[ n ];
+ tile_origin = new int[ n ];
+ tile_size = new int[ n ];
+ }
+
+ @Override
+ public T getType()
+ {
+ return p0.getType();
+ }
+
+ @Override
+ public int numDimensions()
+ {
+ return p0.numDimensions();
+ }
+
+ @Override
+ public void copy( final long[] srcPos, final Object dest, final int[] size )
+ {
+ final int n = numDimensions();
+ boolean singleTile = true;
+ for ( int d = 0; d < n; ++d )
+ {
+ numTiles[ d ] = ( size[ d ] - 1 ) / innerTileSize[ d ] + 1;
+ if ( numTiles[ d ] > 1 )
+ singleTile = false;
+ borderTileSize[ d ] = size[ d ] - ( numTiles[ d ] - 1 ) * innerTileSize[ d ];
+ }
+ if ( singleTile )
+ {
+ p0.copy( srcPos, dest, size );
+ }
+ else
+ {
+ final P tile_buf = tempArray.get( innerTileNumElements );
+ compute_tiles_recursively( n - 1, srcPos, Cast.unchecked( dest ), size, tile_buf );
+ }
+ }
+
+ private void compute_tiles_recursively( final int d, final long[] srcPos, final P dest, final int[] dest_size, final P tile_buf ) {
+ final int numTiles = this.numTiles[ d ];
+ for ( int i = 0; i < numTiles; ++i )
+ {
+ tile_pos_in_dest[ d ] = innerTileSize[ d ] * i;
+ tile_pos_in_src[ d ] = srcPos[ d ] + tile_pos_in_dest[ d ];
+ tile_size[ d ] = ( i == numTiles - 1 ) ? borderTileSize[ d ] : innerTileSize[ d ];
+ if ( d == 0 )
+ {
+ p0.copy( tile_pos_in_src, tile_buf, tile_size );
+ subArrayCopy.copy( tile_buf, tile_size, tile_origin, dest, dest_size, tile_pos_in_dest, tile_size );
+ }
+ else
+ {
+ compute_tiles_recursively( d - 1, srcPos, dest, dest_size, tile_buf );
+ }
+ }
+ }
+
+ @Override
+ public BlockSupplier< T > independentCopy()
+ {
+ return new TilingBlockSupplier<>( this );
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java
index ce2de27a6..0c2f31b91 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java
@@ -33,12 +33,10 @@
*/
package net.imglib2.algorithm.blocks;
-import net.imglib2.algorithm.blocks.convert.ClampType;
+import net.imglib2.algorithm.blocks.convert.Convert;
import net.imglib2.type.NativeType;
import net.imglib2.util.Cast;
-import static net.imglib2.algorithm.blocks.convert.Convert.convert;
-
/**
* Wraps {@code BlockProcessor}, where {@code I} is the primitive array
* type backing ImgLib2 {@code NativeType} {@code S} and {@code O} is the
@@ -77,6 +75,32 @@ public interface UnaryBlockOperator< S extends NativeType< S >, T extends Native
T getTargetType();
+ /**
+ * Number of source dimensions.
+ *
+ * Some operators can be applied to arbitrary dimensions, e.g., converters.
+ * In this case, they should return {@code numSourceDimensions() <= 0}. It
+ * is expected that these operators do not modify the number of dimensions,
+ * that is, when such an operator is applied to a 3D block, the result is
+ * also a 3D block.
+ *
+ * @return the number of source dimensions
+ */
+ int numSourceDimensions();
+
+ /**
+ * Number of target dimensions.
+ *
+ * Some operators can be applied to arbitrary dimensions, e.g., converters.
+ * In this case, they should return {@code numTargetDimensions() <= 0}. It
+ * is expected that these operators do not modify the number of dimensions,
+ * that is, when such an operator is applied to a 3D block, the result is
+ * also a 3D block.
+ *
+ * @return the number of target dimensions
+ */
+ int numTargetDimensions();
+
/**
* Get a thread-safe version of this {@code UnaryBlockOperator}.
* (Implemented as a wrapper that makes {@link ThreadLocal} copies).
@@ -96,9 +120,21 @@ public interface UnaryBlockOperator< S extends NativeType< S >, T extends Native
*/
default < U extends NativeType< U > > UnaryBlockOperator< S, U > andThen( UnaryBlockOperator< T, U > op )
{
+ if ( op instanceof NoOpUnaryBlockOperator )
+ return Cast.unchecked( this );
+
+ final boolean thisHasDimensions = numSourceDimensions() > 0;
+ final boolean opHasDimensions = op.numSourceDimensions() > 0;
+ if ( opHasDimensions && thisHasDimensions && numTargetDimensions() != op.numSourceDimensions() ) {
+ throw new IllegalArgumentException( "UnaryBlockOperator cannot be concatenated: number of dimensions mismatch." );
+ }
+ final int numSourceDimensions = thisHasDimensions ? numSourceDimensions() : op.numSourceDimensions();
+ final int numTargetDimensions = opHasDimensions ? op.numTargetDimensions() : numTargetDimensions();
return new DefaultUnaryBlockOperator<>(
getSourceType(),
op.getTargetType(),
+ numSourceDimensions,
+ numTargetDimensions,
blockProcessor().andThen( op.blockProcessor() ) );
}
@@ -112,7 +148,7 @@ default < U extends NativeType< U > > UnaryBlockOperator< U, T > adaptSourceType
if ( newSourceType.getClass().isInstance( getSourceType() ) )
return Cast.unchecked( this );
else
- return convert( newSourceType, getSourceType(), clamp ).andThen( this );
+ return Convert.createOperator( newSourceType, getSourceType(), clamp ).andThen( this );
}
/**
@@ -125,6 +161,6 @@ default < U extends NativeType< U > > UnaryBlockOperator< S, U > adaptTargetTyp
if ( newTargetType.getClass().isInstance( getTargetType() ) )
return Cast.unchecked( this );
else
- return this.andThen( convert( getTargetType(), newTargetType, clamp ) );
+ return this.andThen( Convert.createOperator( getTargetType(), newTargetType, clamp ) );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java b/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java
index f79b56987..efff1ad31 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java
@@ -33,9 +33,14 @@
*/
package net.imglib2.algorithm.blocks.convert;
+import java.util.Objects;
+import java.util.function.Function;
import java.util.function.Supplier;
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ClampType;
import net.imglib2.algorithm.blocks.DefaultUnaryBlockOperator;
+import net.imglib2.algorithm.blocks.NoOpUnaryBlockOperator;
import net.imglib2.algorithm.blocks.UnaryBlockOperator;
import net.imglib2.converter.Converter;
import net.imglib2.type.NativeType;
@@ -59,15 +64,101 @@
*/
public class Convert
{
+ /**
+ * Create {@link UnaryBlockOperator} to convert blocks from {@code S} to
+ * {@code T}.
+ *
+ * Supported source/target types are {@code ByteType}, {@code
+ * UnsignedByteType}, {@code ShortType}, {@code UnsignedShortType}, {@code
+ * IntType}, {@code UnsignedIntType}, {@code LongType}, {@code
+ * UnsignedLongType}, {@code FloatType}, and {@code DoubleType}.
+ *
+ * Target values are not clamped, so overflow may occur if the source type
+ * has a larger range than the target type.
+ *
+ * The returned factory function creates an operator matching the type
+ * {@code S} of the given input {@code BlockSupplier}.
+ *
+ * @param targetType
+ * an instance of the target type
+ * @param
+ * source type
+ * @param
+ * target type
+ *
+ * @return factory for {@code UnaryBlockOperator} to convert blocks from {@code S} to {@code T}
+ */
+ public static < S extends NativeType< S >, T extends NativeType< T > >
+ Function< BlockSupplier< S >, UnaryBlockOperator< S, T > > convert( final T targetType )
+ {
+ return convert( targetType, ClampType.NONE );
+ }
+
+ /**
+ * Create {@link UnaryBlockOperator} to convert blocks from {@code S} to
+ * {@code T}.
+ *
+ * Supported source/target types are {@code ByteType}, {@code
+ * UnsignedByteType}, {@code ShortType}, {@code UnsignedShortType}, {@code
+ * IntType}, {@code UnsignedIntType}, {@code LongType}, {@code
+ * UnsignedLongType}, {@code FloatType}, and {@code DoubleType}.
+ *
+ * If the target type cannot represent the full range of the source type,
+ * values are clamped according to the specified {@link ClampType}.
+ *
+ * The returned factory function creates an operator matching the type
+ * {@code S} of the given input {@code BlockSupplier}.
+ *
+ * @param targetType
+ * an instance of the target type
+ * @param clamp
+ * ClampType
+ * @param
+ * source type
+ * @param
+ * target type
+ *
+ * @return factory for {@code UnaryBlockOperator} to convert blocks from {@code S} to {@code T}
+ */
+ public static < S extends NativeType< S >, T extends NativeType< T > >
+ Function< BlockSupplier< S >, UnaryBlockOperator< S, T > > convert( final T targetType, final ClampType clamp )
+ {
+ return s -> createOperator( s.getType(), targetType, clamp );
+ }
+
+ /**
+ * Create {@link UnaryBlockOperator} to convert blocks from {@code S} to
+ * {@code T} with the specified {@code Converter}.
+ *
+ * The returned factory function creates an operator matching the type
+ * {@code S} of the given input {@code BlockSupplier}.
+ *
+ * @param targetType
+ * an instance of the target type
+ * @param converterSupplier
+ * creates new converter instances
+ * @param
+ * source type
+ * @param
+ * target type
+ *
+ * @return factory for {@code UnaryBlockOperator} to convert blocks from {@code S} to {@code T}
+ */
+ public static < S extends NativeType< S >, T extends NativeType< T > >
+ Function< BlockSupplier< S >, UnaryBlockOperator< S, T > > convert( final T targetType, Supplier< Converter< ? super S, T > > converterSupplier )
+ {
+ return s -> createOperator( s.getType(), targetType, converterSupplier );
+ }
+
/**
* Create {@link UnaryBlockOperator} to convert blocks between {@code
* sourceType} and {@code targetType}.
* No clamping.
*/
public static < S extends NativeType< S >, T extends NativeType< T > >
- UnaryBlockOperator< S, T > convert( final S sourceType, final T targetType )
+ UnaryBlockOperator< S, T > createOperator( final S sourceType, final T targetType )
{
- return convert( sourceType, targetType, ClampType.NONE );
+ return createOperator( sourceType, targetType, ClampType.NONE );
}
/**
@@ -76,9 +167,14 @@ UnaryBlockOperator< S, T > convert( final S sourceType, final T targetType )
* Clamp target values according to {@code clamp}.
*/
public static < S extends NativeType< S >, T extends NativeType< T > >
- UnaryBlockOperator< S, T > convert( final S sourceType, final T targetType, final ClampType clamp )
+ UnaryBlockOperator< S, T > createOperator( final S sourceType, final T targetType, final ClampType clamp )
{
- return new DefaultUnaryBlockOperator<>( sourceType, targetType, new ConvertBlockProcessor<>( sourceType, targetType, clamp ) );
+ if ( Objects.equals( sourceType.getClass(), targetType.getClass() ) )
+ return new NoOpUnaryBlockOperator<>();
+
+ return new DefaultUnaryBlockOperator<>(
+ sourceType, targetType, 0, 0,
+ new ConvertBlockProcessor<>( sourceType, targetType, clamp ) );
}
/**
@@ -86,8 +182,10 @@ UnaryBlockOperator< S, T > convert( final S sourceType, final T targetType, fina
* sourceType} and {@code targetType} with the specified {@code Converter}.
*/
public static < S extends NativeType< S >, T extends NativeType< T > >
- UnaryBlockOperator< S, T > convert( final S sourceType, final T targetType, Supplier< Converter< ? super S, T > > converterSupplier )
+ UnaryBlockOperator< S, T > createOperator( final S sourceType, final T targetType, Supplier< Converter< ? super S, T > > converterSupplier )
{
- return new DefaultUnaryBlockOperator<>( sourceType, targetType, new ConverterBlockProcessor<>( sourceType, targetType, converterSupplier ) );
+ return new DefaultUnaryBlockOperator<>(
+ sourceType, targetType, 0, 0,
+ new ConverterBlockProcessor<>( sourceType, targetType, converterSupplier ) );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertBlockProcessor.java
index 9c6dc34a1..88f36a03f 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertBlockProcessor.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertBlockProcessor.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,17 +33,11 @@
*/
package net.imglib2.algorithm.blocks.convert;
-import static net.imglib2.util.Util.safeInt;
-
-import java.util.Arrays;
-
-import net.imglib2.Interval;
+import net.imglib2.algorithm.blocks.AbstractDimensionlessBlockProcessor;
import net.imglib2.algorithm.blocks.BlockProcessor;
-import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
+import net.imglib2.algorithm.blocks.ClampType;
import net.imglib2.algorithm.blocks.util.UnaryOperatorType;
-import net.imglib2.blocks.TempArray;
import net.imglib2.type.NativeType;
-import net.imglib2.util.Intervals;
/**
* Convert primitive arrays between standard ImgLib2 {@code Type}s.
@@ -54,40 +48,20 @@
* @param
* output primitive array type, e.g., float[]
*/
-class ConvertBlockProcessor< S extends NativeType< S >, T extends NativeType< T >, I, O > implements BlockProcessor< I, O >
+class ConvertBlockProcessor< I, O > extends AbstractDimensionlessBlockProcessor< I, O >
{
- private final S sourceType;
-
- private final T targetType;
-
- private final TempArray< I > tempArray;
-
private final ConvertLoop< I, O > loop;
- private long[] sourcePos;
-
- private int[] sourceSize;
-
- private int sourceLength;
-
- private final BlockProcessorSourceInterval sourceInterval;
-
- public ConvertBlockProcessor( final S sourceType, final T targetType, final ClampType clamp )
+ public < S extends NativeType< S >, T extends NativeType< T > > ConvertBlockProcessor( final S sourceType, final T targetType, final ClampType clamp )
{
- this.sourceType = sourceType;
- this.targetType = targetType;
- tempArray = TempArray.forPrimitiveType( sourceType.getNativeTypeFactory().getPrimitiveType() );
+ super( sourceType.getNativeTypeFactory().getPrimitiveType() );
loop = ConvertLoops.get( UnaryOperatorType.of( sourceType, targetType ), clamp );
- sourceInterval = new BlockProcessorSourceInterval( this );
}
- private ConvertBlockProcessor( ConvertBlockProcessor< S, T, I, O > convert )
+ private ConvertBlockProcessor( ConvertBlockProcessor< I, O > convert )
{
- sourceType = convert.sourceType;
- targetType = convert.targetType;
- tempArray = convert.tempArray.newInstance();
+ super( convert );
loop = convert.loop;
- sourceInterval = new BlockProcessorSourceInterval( this );
}
@Override
@@ -96,61 +70,9 @@ public BlockProcessor< I, O > independentCopy()
return new ConvertBlockProcessor<>( this );
}
- @Override
- public void setTargetInterval( final Interval interval )
- {
- final int n = interval.numDimensions();
- if ( sourcePos == null || sourcePos.length != n )
- {
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
- }
- interval.min( sourcePos );
- Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
- sourceLength = safeInt( Intervals.numElements( sourceSize ) );
- }
-
- @Override
- public void setTargetInterval( final long[] pos, final int[] size )
- {
- final int n = pos.length;
- if ( sourcePos == null || sourcePos.length != n )
- {
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
- }
- System.arraycopy( pos, 0, sourcePos, 0, n );
- System.arraycopy( size, 0, sourceSize, 0, n );
- sourceLength = safeInt( Intervals.numElements( sourceSize ) );
- }
-
- @Override
- public long[] getSourcePos()
- {
- return sourcePos;
- }
-
- @Override
- public int[] getSourceSize()
- {
- return sourceSize;
- }
-
- @Override
- public Interval getSourceInterval()
- {
- return sourceInterval;
- }
-
- @Override
- public I getSourceBuffer()
- {
- return tempArray.get( sourceLength );
- }
-
@Override
public void compute( final I src, final O dest )
{
- loop.apply( src, dest, sourceLength );
+ loop.apply( src, dest, sourceLength() );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertLoops.java b/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertLoops.java
index 4621195ed..7ab9fbefe 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertLoops.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertLoops.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,45 +33,55 @@
*/
package net.imglib2.algorithm.blocks.convert;
+import net.imglib2.algorithm.blocks.ClampType;
import net.imglib2.algorithm.blocks.util.UnaryOperatorType;
import net.imglib2.util.Cast;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_i8;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i8;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i8_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i8_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_u8;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u8;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u8_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u8_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_i16;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i16;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i16_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i16_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_u16;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u16;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u16_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u16_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_i32;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i32;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i32_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i32_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_u32;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u32;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u32_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_u32_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_i64;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i64;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i64_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_i64_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_f32;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_f32;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_f32_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_f32_clamp_max;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_f64;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_f64;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_f64_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_f64_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_i8;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i8;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i8_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i8_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i8_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_u8;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u8;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u8_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u8_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u8_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_i16;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i16;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i16_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i16_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i16_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_u16;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u16;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u16_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u16_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u16_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_i32;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i32;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i32_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i32_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i32_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_u32;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u32;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u32_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u32_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_u32_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_i64;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i64;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i64_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i64_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_i64_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_f32;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f32;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f32_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f32_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f32_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_f64;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f64;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f64_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f64_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_f64_clamp_max;
/*
* This is autogenerated source code -- DO NOT EDIT. Instead, edit the
@@ -80,280 +90,367 @@
class ConvertLoops
{
- static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type )
- {
- return get( type, ClampType.NONE );
- }
-
- static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type, ClampType clampType )
- {
- switch ( clampType )
- {
- case NONE:
- switch( type )
- {
- case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8.INSTANCE );
- case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8.INSTANCE );
- case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16.INSTANCE );
- case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16.INSTANCE );
- case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32.INSTANCE );
- case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32.INSTANCE );
- case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64.INSTANCE );
- case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32.INSTANCE );
- case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64.INSTANCE );
- case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8.INSTANCE );
- case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8.INSTANCE );
- case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16.INSTANCE );
- case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16.INSTANCE );
- case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32.INSTANCE );
- case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32.INSTANCE );
- case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64.INSTANCE );
- case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32.INSTANCE );
- case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64.INSTANCE );
- case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8.INSTANCE );
- case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8.INSTANCE );
- case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16.INSTANCE );
- case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16.INSTANCE );
- case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32.INSTANCE );
- case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32.INSTANCE );
- case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64.INSTANCE );
- case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32.INSTANCE );
- case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64.INSTANCE );
- case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8.INSTANCE );
- case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8.INSTANCE );
- case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16.INSTANCE );
- case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16.INSTANCE );
- case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32.INSTANCE );
- case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32.INSTANCE );
- case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64.INSTANCE );
- case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32.INSTANCE );
- case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64.INSTANCE );
- case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8.INSTANCE );
- case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8.INSTANCE );
- case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16.INSTANCE );
- case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16.INSTANCE );
- case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32.INSTANCE );
- case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32.INSTANCE );
- case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64.INSTANCE );
- case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32.INSTANCE );
- case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64.INSTANCE );
- case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8.INSTANCE );
- case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8.INSTANCE );
- case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16.INSTANCE );
- case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16.INSTANCE );
- case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32.INSTANCE );
- case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32.INSTANCE );
- case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64.INSTANCE );
- case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32.INSTANCE );
- case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64.INSTANCE );
- case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8.INSTANCE );
- case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8.INSTANCE );
- case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16.INSTANCE );
- case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16.INSTANCE );
- case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32.INSTANCE );
- case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32.INSTANCE );
- case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64.INSTANCE );
- case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32.INSTANCE );
- case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64.INSTANCE );
- case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8.INSTANCE );
- case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8.INSTANCE );
- case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16.INSTANCE );
- case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16.INSTANCE );
- case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32.INSTANCE );
- case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32.INSTANCE );
- case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64.INSTANCE );
- case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32.INSTANCE );
- case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64.INSTANCE );
- case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8.INSTANCE );
- case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8.INSTANCE );
- case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16.INSTANCE );
- case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16.INSTANCE );
- case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32.INSTANCE );
- case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32.INSTANCE );
- case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64.INSTANCE );
- case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32.INSTANCE );
- case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64.INSTANCE );
- default:
- throw new IllegalArgumentException();
- }
- case CLAMP:
- switch( type )
- {
- case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8_clamp.INSTANCE );
- case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8_clamp.INSTANCE );
- case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16_clamp.INSTANCE );
- case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16_clamp.INSTANCE );
- case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32_clamp.INSTANCE );
- case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32_clamp.INSTANCE );
- case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64_clamp.INSTANCE );
- case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32_clamp.INSTANCE );
- case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64_clamp.INSTANCE );
- case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8_clamp.INSTANCE );
- case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8_clamp.INSTANCE );
- case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16_clamp.INSTANCE );
- case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16_clamp.INSTANCE );
- case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32_clamp.INSTANCE );
- case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32_clamp.INSTANCE );
- case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64_clamp.INSTANCE );
- case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32_clamp.INSTANCE );
- case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64_clamp.INSTANCE );
- case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8_clamp.INSTANCE );
- case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8_clamp.INSTANCE );
- case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16_clamp.INSTANCE );
- case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16_clamp.INSTANCE );
- case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32_clamp.INSTANCE );
- case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32_clamp.INSTANCE );
- case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64_clamp.INSTANCE );
- case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32_clamp.INSTANCE );
- case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64_clamp.INSTANCE );
- case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8_clamp.INSTANCE );
- case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8_clamp.INSTANCE );
- case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16_clamp.INSTANCE );
- case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16_clamp.INSTANCE );
- case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32_clamp.INSTANCE );
- case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32_clamp.INSTANCE );
- case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64_clamp.INSTANCE );
- case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32_clamp.INSTANCE );
- case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64_clamp.INSTANCE );
- case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8_clamp.INSTANCE );
- case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8_clamp.INSTANCE );
- case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16_clamp.INSTANCE );
- case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16_clamp.INSTANCE );
- case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32_clamp.INSTANCE );
- case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32_clamp.INSTANCE );
- case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64_clamp.INSTANCE );
- case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32_clamp.INSTANCE );
- case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64_clamp.INSTANCE );
- case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8_clamp.INSTANCE );
- case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8_clamp.INSTANCE );
- case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16_clamp.INSTANCE );
- case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16_clamp.INSTANCE );
- case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32_clamp.INSTANCE );
- case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32_clamp.INSTANCE );
- case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64_clamp.INSTANCE );
- case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32_clamp.INSTANCE );
- case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64_clamp.INSTANCE );
- case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8_clamp.INSTANCE );
- case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8_clamp.INSTANCE );
- case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16_clamp.INSTANCE );
- case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16_clamp.INSTANCE );
- case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32_clamp.INSTANCE );
- case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32_clamp.INSTANCE );
- case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64_clamp.INSTANCE );
- case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32_clamp.INSTANCE );
- case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64_clamp.INSTANCE );
- case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8_clamp.INSTANCE );
- case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8_clamp.INSTANCE );
- case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16_clamp.INSTANCE );
- case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16_clamp.INSTANCE );
- case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32_clamp.INSTANCE );
- case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32_clamp.INSTANCE );
- case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64_clamp.INSTANCE );
- case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32_clamp.INSTANCE );
- case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64_clamp.INSTANCE );
- case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8_clamp.INSTANCE );
- case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8_clamp.INSTANCE );
- case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16_clamp.INSTANCE );
- case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16_clamp.INSTANCE );
- case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32_clamp.INSTANCE );
- case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32_clamp.INSTANCE );
- case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64_clamp.INSTANCE );
- case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32_clamp.INSTANCE );
- case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64_clamp.INSTANCE );
- default:
- throw new IllegalArgumentException();
- }
- case CLAMP_MAX:
- switch( type )
- {
- case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8_clamp_max.INSTANCE );
- case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8_clamp_max.INSTANCE );
- case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16_clamp_max.INSTANCE );
- case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16_clamp_max.INSTANCE );
- case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32_clamp_max.INSTANCE );
- case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32_clamp_max.INSTANCE );
- case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64_clamp_max.INSTANCE );
- case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32_clamp_max.INSTANCE );
- case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64_clamp_max.INSTANCE );
- case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8_clamp_max.INSTANCE );
- case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8_clamp_max.INSTANCE );
- case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16_clamp_max.INSTANCE );
- case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16_clamp_max.INSTANCE );
- case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32_clamp_max.INSTANCE );
- case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32_clamp_max.INSTANCE );
- case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64_clamp_max.INSTANCE );
- case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32_clamp_max.INSTANCE );
- case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64_clamp_max.INSTANCE );
- case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8_clamp_max.INSTANCE );
- case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8_clamp_max.INSTANCE );
- case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16_clamp_max.INSTANCE );
- case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16_clamp_max.INSTANCE );
- case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32_clamp_max.INSTANCE );
- case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32_clamp_max.INSTANCE );
- case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64_clamp_max.INSTANCE );
- case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32_clamp_max.INSTANCE );
- case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64_clamp_max.INSTANCE );
- case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8_clamp_max.INSTANCE );
- case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8_clamp_max.INSTANCE );
- case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16_clamp_max.INSTANCE );
- case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16_clamp_max.INSTANCE );
- case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32_clamp_max.INSTANCE );
- case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32_clamp_max.INSTANCE );
- case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64_clamp_max.INSTANCE );
- case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32_clamp_max.INSTANCE );
- case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64_clamp_max.INSTANCE );
- case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8_clamp_max.INSTANCE );
- case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8_clamp_max.INSTANCE );
- case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16_clamp_max.INSTANCE );
- case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16_clamp_max.INSTANCE );
- case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32_clamp_max.INSTANCE );
- case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32_clamp_max.INSTANCE );
- case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64_clamp_max.INSTANCE );
- case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32_clamp_max.INSTANCE );
- case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64_clamp_max.INSTANCE );
- case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8_clamp_max.INSTANCE );
- case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8_clamp_max.INSTANCE );
- case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16_clamp_max.INSTANCE );
- case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16_clamp_max.INSTANCE );
- case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32_clamp_max.INSTANCE );
- case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32_clamp_max.INSTANCE );
- case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64_clamp_max.INSTANCE );
- case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32_clamp_max.INSTANCE );
- case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64_clamp_max.INSTANCE );
- case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8_clamp_max.INSTANCE );
- case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8_clamp_max.INSTANCE );
- case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16_clamp_max.INSTANCE );
- case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16_clamp_max.INSTANCE );
- case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32_clamp_max.INSTANCE );
- case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32_clamp_max.INSTANCE );
- case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64_clamp_max.INSTANCE );
- case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32_clamp_max.INSTANCE );
- case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64_clamp_max.INSTANCE );
- case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8_clamp_max.INSTANCE );
- case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8_clamp_max.INSTANCE );
- case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16_clamp_max.INSTANCE );
- case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16_clamp_max.INSTANCE );
- case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32_clamp_max.INSTANCE );
- case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32_clamp_max.INSTANCE );
- case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64_clamp_max.INSTANCE );
- case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32_clamp_max.INSTANCE );
- case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64_clamp_max.INSTANCE );
- case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8_clamp_max.INSTANCE );
- case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8_clamp_max.INSTANCE );
- case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16_clamp_max.INSTANCE );
- case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16_clamp_max.INSTANCE );
- case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32_clamp_max.INSTANCE );
- case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32_clamp_max.INSTANCE );
- case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64_clamp_max.INSTANCE );
- case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32_clamp_max.INSTANCE );
- case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64_clamp_max.INSTANCE );
- default:
- throw new IllegalArgumentException();
- }
- default:
- throw new IllegalArgumentException();
- }
- }
+ static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type )
+ {
+ return get( type, ClampType.NONE );
+ }
+
+ static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type, ClampType clampType )
+ {
+ switch ( clampType )
+ {
+ case NONE:
+ switch( type )
+ {
+ case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8.INSTANCE );
+ case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8.INSTANCE );
+ case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16.INSTANCE );
+ case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16.INSTANCE );
+ case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32.INSTANCE );
+ case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32.INSTANCE );
+ case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64.INSTANCE );
+ case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32.INSTANCE );
+ case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64.INSTANCE );
+ case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8.INSTANCE );
+ case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8.INSTANCE );
+ case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16.INSTANCE );
+ case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16.INSTANCE );
+ case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32.INSTANCE );
+ case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32.INSTANCE );
+ case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64.INSTANCE );
+ case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32.INSTANCE );
+ case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64.INSTANCE );
+ case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8.INSTANCE );
+ case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8.INSTANCE );
+ case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16.INSTANCE );
+ case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16.INSTANCE );
+ case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32.INSTANCE );
+ case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32.INSTANCE );
+ case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64.INSTANCE );
+ case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32.INSTANCE );
+ case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64.INSTANCE );
+ case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8.INSTANCE );
+ case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8.INSTANCE );
+ case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16.INSTANCE );
+ case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16.INSTANCE );
+ case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32.INSTANCE );
+ case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32.INSTANCE );
+ case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64.INSTANCE );
+ case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32.INSTANCE );
+ case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64.INSTANCE );
+ case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8.INSTANCE );
+ case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8.INSTANCE );
+ case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16.INSTANCE );
+ case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16.INSTANCE );
+ case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32.INSTANCE );
+ case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32.INSTANCE );
+ case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64.INSTANCE );
+ case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32.INSTANCE );
+ case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64.INSTANCE );
+ case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8.INSTANCE );
+ case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8.INSTANCE );
+ case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16.INSTANCE );
+ case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16.INSTANCE );
+ case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32.INSTANCE );
+ case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32.INSTANCE );
+ case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64.INSTANCE );
+ case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32.INSTANCE );
+ case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64.INSTANCE );
+ case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8.INSTANCE );
+ case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8.INSTANCE );
+ case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16.INSTANCE );
+ case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16.INSTANCE );
+ case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32.INSTANCE );
+ case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32.INSTANCE );
+ case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64.INSTANCE );
+ case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32.INSTANCE );
+ case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64.INSTANCE );
+ case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8.INSTANCE );
+ case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8.INSTANCE );
+ case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16.INSTANCE );
+ case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16.INSTANCE );
+ case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32.INSTANCE );
+ case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32.INSTANCE );
+ case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64.INSTANCE );
+ case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32.INSTANCE );
+ case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64.INSTANCE );
+ case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8.INSTANCE );
+ case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8.INSTANCE );
+ case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16.INSTANCE );
+ case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16.INSTANCE );
+ case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32.INSTANCE );
+ case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32.INSTANCE );
+ case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64.INSTANCE );
+ case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32.INSTANCE );
+ case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64.INSTANCE );
+ default:
+ throw new IllegalArgumentException();
+ }
+ case CLAMP:
+ switch( type )
+ {
+ case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8_clamp.INSTANCE );
+ case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8_clamp.INSTANCE );
+ case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16_clamp.INSTANCE );
+ case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16_clamp.INSTANCE );
+ case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32_clamp.INSTANCE );
+ case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32_clamp.INSTANCE );
+ case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64_clamp.INSTANCE );
+ case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32_clamp.INSTANCE );
+ case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64_clamp.INSTANCE );
+ case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8_clamp.INSTANCE );
+ case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8_clamp.INSTANCE );
+ case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16_clamp.INSTANCE );
+ case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16_clamp.INSTANCE );
+ case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32_clamp.INSTANCE );
+ case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32_clamp.INSTANCE );
+ case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64_clamp.INSTANCE );
+ case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32_clamp.INSTANCE );
+ case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64_clamp.INSTANCE );
+ case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8_clamp.INSTANCE );
+ case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8_clamp.INSTANCE );
+ case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16_clamp.INSTANCE );
+ case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16_clamp.INSTANCE );
+ case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32_clamp.INSTANCE );
+ case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32_clamp.INSTANCE );
+ case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64_clamp.INSTANCE );
+ case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32_clamp.INSTANCE );
+ case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64_clamp.INSTANCE );
+ case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8_clamp.INSTANCE );
+ case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8_clamp.INSTANCE );
+ case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16_clamp.INSTANCE );
+ case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16_clamp.INSTANCE );
+ case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32_clamp.INSTANCE );
+ case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32_clamp.INSTANCE );
+ case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64_clamp.INSTANCE );
+ case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32_clamp.INSTANCE );
+ case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64_clamp.INSTANCE );
+ case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8_clamp.INSTANCE );
+ case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8_clamp.INSTANCE );
+ case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16_clamp.INSTANCE );
+ case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16_clamp.INSTANCE );
+ case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32_clamp.INSTANCE );
+ case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32_clamp.INSTANCE );
+ case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64_clamp.INSTANCE );
+ case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32_clamp.INSTANCE );
+ case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64_clamp.INSTANCE );
+ case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8_clamp.INSTANCE );
+ case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8_clamp.INSTANCE );
+ case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16_clamp.INSTANCE );
+ case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16_clamp.INSTANCE );
+ case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32_clamp.INSTANCE );
+ case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32_clamp.INSTANCE );
+ case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64_clamp.INSTANCE );
+ case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32_clamp.INSTANCE );
+ case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64_clamp.INSTANCE );
+ case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8_clamp.INSTANCE );
+ case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8_clamp.INSTANCE );
+ case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16_clamp.INSTANCE );
+ case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16_clamp.INSTANCE );
+ case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32_clamp.INSTANCE );
+ case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32_clamp.INSTANCE );
+ case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64_clamp.INSTANCE );
+ case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32_clamp.INSTANCE );
+ case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64_clamp.INSTANCE );
+ case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8_clamp.INSTANCE );
+ case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8_clamp.INSTANCE );
+ case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16_clamp.INSTANCE );
+ case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16_clamp.INSTANCE );
+ case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32_clamp.INSTANCE );
+ case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32_clamp.INSTANCE );
+ case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64_clamp.INSTANCE );
+ case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32_clamp.INSTANCE );
+ case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64_clamp.INSTANCE );
+ case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8_clamp.INSTANCE );
+ case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8_clamp.INSTANCE );
+ case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16_clamp.INSTANCE );
+ case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16_clamp.INSTANCE );
+ case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32_clamp.INSTANCE );
+ case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32_clamp.INSTANCE );
+ case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64_clamp.INSTANCE );
+ case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32_clamp.INSTANCE );
+ case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64_clamp.INSTANCE );
+ default:
+ throw new IllegalArgumentException();
+ }
+ case CLAMP_MIN:
+ switch( type )
+ {
+ case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8_clamp_min.INSTANCE );
+ case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8_clamp_min.INSTANCE );
+ case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16_clamp_min.INSTANCE );
+ case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16_clamp_min.INSTANCE );
+ case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32_clamp_min.INSTANCE );
+ case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32_clamp_min.INSTANCE );
+ case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64_clamp_min.INSTANCE );
+ case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32_clamp_min.INSTANCE );
+ case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64_clamp_min.INSTANCE );
+ case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8_clamp_min.INSTANCE );
+ case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8_clamp_min.INSTANCE );
+ case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16_clamp_min.INSTANCE );
+ case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16_clamp_min.INSTANCE );
+ case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32_clamp_min.INSTANCE );
+ case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32_clamp_min.INSTANCE );
+ case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64_clamp_min.INSTANCE );
+ case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32_clamp_min.INSTANCE );
+ case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64_clamp_min.INSTANCE );
+ case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8_clamp_min.INSTANCE );
+ case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8_clamp_min.INSTANCE );
+ case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16_clamp_min.INSTANCE );
+ case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16_clamp_min.INSTANCE );
+ case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32_clamp_min.INSTANCE );
+ case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32_clamp_min.INSTANCE );
+ case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64_clamp_min.INSTANCE );
+ case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32_clamp_min.INSTANCE );
+ case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64_clamp_min.INSTANCE );
+ case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8_clamp_min.INSTANCE );
+ case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8_clamp_min.INSTANCE );
+ case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16_clamp_min.INSTANCE );
+ case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16_clamp_min.INSTANCE );
+ case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32_clamp_min.INSTANCE );
+ case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32_clamp_min.INSTANCE );
+ case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64_clamp_min.INSTANCE );
+ case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32_clamp_min.INSTANCE );
+ case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64_clamp_min.INSTANCE );
+ case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8_clamp_min.INSTANCE );
+ case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8_clamp_min.INSTANCE );
+ case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16_clamp_min.INSTANCE );
+ case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16_clamp_min.INSTANCE );
+ case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32_clamp_min.INSTANCE );
+ case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32_clamp_min.INSTANCE );
+ case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64_clamp_min.INSTANCE );
+ case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32_clamp_min.INSTANCE );
+ case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64_clamp_min.INSTANCE );
+ case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8_clamp_min.INSTANCE );
+ case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8_clamp_min.INSTANCE );
+ case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16_clamp_min.INSTANCE );
+ case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16_clamp_min.INSTANCE );
+ case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32_clamp_min.INSTANCE );
+ case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32_clamp_min.INSTANCE );
+ case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64_clamp_min.INSTANCE );
+ case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32_clamp_min.INSTANCE );
+ case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64_clamp_min.INSTANCE );
+ case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8_clamp_min.INSTANCE );
+ case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8_clamp_min.INSTANCE );
+ case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16_clamp_min.INSTANCE );
+ case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16_clamp_min.INSTANCE );
+ case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32_clamp_min.INSTANCE );
+ case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32_clamp_min.INSTANCE );
+ case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64_clamp_min.INSTANCE );
+ case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32_clamp_min.INSTANCE );
+ case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64_clamp_min.INSTANCE );
+ case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8_clamp_min.INSTANCE );
+ case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8_clamp_min.INSTANCE );
+ case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16_clamp_min.INSTANCE );
+ case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16_clamp_min.INSTANCE );
+ case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32_clamp_min.INSTANCE );
+ case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32_clamp_min.INSTANCE );
+ case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64_clamp_min.INSTANCE );
+ case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32_clamp_min.INSTANCE );
+ case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64_clamp_min.INSTANCE );
+ case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8_clamp_min.INSTANCE );
+ case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8_clamp_min.INSTANCE );
+ case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16_clamp_min.INSTANCE );
+ case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16_clamp_min.INSTANCE );
+ case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32_clamp_min.INSTANCE );
+ case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32_clamp_min.INSTANCE );
+ case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64_clamp_min.INSTANCE );
+ case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32_clamp_min.INSTANCE );
+ case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64_clamp_min.INSTANCE );
+ default:
+ throw new IllegalArgumentException();
+ }
+ case CLAMP_MAX:
+ switch( type )
+ {
+ case I8_TO_I8: return Cast.unchecked( Convert_i8_to_i8_clamp_max.INSTANCE );
+ case I8_TO_U8: return Cast.unchecked( Convert_i8_to_u8_clamp_max.INSTANCE );
+ case I8_TO_I16: return Cast.unchecked( Convert_i8_to_i16_clamp_max.INSTANCE );
+ case I8_TO_U16: return Cast.unchecked( Convert_i8_to_u16_clamp_max.INSTANCE );
+ case I8_TO_I32: return Cast.unchecked( Convert_i8_to_i32_clamp_max.INSTANCE );
+ case I8_TO_U32: return Cast.unchecked( Convert_i8_to_u32_clamp_max.INSTANCE );
+ case I8_TO_I64: return Cast.unchecked( Convert_i8_to_i64_clamp_max.INSTANCE );
+ case I8_TO_F32: return Cast.unchecked( Convert_i8_to_f32_clamp_max.INSTANCE );
+ case I8_TO_F64: return Cast.unchecked( Convert_i8_to_f64_clamp_max.INSTANCE );
+ case U8_TO_I8: return Cast.unchecked( Convert_u8_to_i8_clamp_max.INSTANCE );
+ case U8_TO_U8: return Cast.unchecked( Convert_u8_to_u8_clamp_max.INSTANCE );
+ case U8_TO_I16: return Cast.unchecked( Convert_u8_to_i16_clamp_max.INSTANCE );
+ case U8_TO_U16: return Cast.unchecked( Convert_u8_to_u16_clamp_max.INSTANCE );
+ case U8_TO_I32: return Cast.unchecked( Convert_u8_to_i32_clamp_max.INSTANCE );
+ case U8_TO_U32: return Cast.unchecked( Convert_u8_to_u32_clamp_max.INSTANCE );
+ case U8_TO_I64: return Cast.unchecked( Convert_u8_to_i64_clamp_max.INSTANCE );
+ case U8_TO_F32: return Cast.unchecked( Convert_u8_to_f32_clamp_max.INSTANCE );
+ case U8_TO_F64: return Cast.unchecked( Convert_u8_to_f64_clamp_max.INSTANCE );
+ case I16_TO_I8: return Cast.unchecked( Convert_i16_to_i8_clamp_max.INSTANCE );
+ case I16_TO_U8: return Cast.unchecked( Convert_i16_to_u8_clamp_max.INSTANCE );
+ case I16_TO_I16: return Cast.unchecked( Convert_i16_to_i16_clamp_max.INSTANCE );
+ case I16_TO_U16: return Cast.unchecked( Convert_i16_to_u16_clamp_max.INSTANCE );
+ case I16_TO_I32: return Cast.unchecked( Convert_i16_to_i32_clamp_max.INSTANCE );
+ case I16_TO_U32: return Cast.unchecked( Convert_i16_to_u32_clamp_max.INSTANCE );
+ case I16_TO_I64: return Cast.unchecked( Convert_i16_to_i64_clamp_max.INSTANCE );
+ case I16_TO_F32: return Cast.unchecked( Convert_i16_to_f32_clamp_max.INSTANCE );
+ case I16_TO_F64: return Cast.unchecked( Convert_i16_to_f64_clamp_max.INSTANCE );
+ case U16_TO_I8: return Cast.unchecked( Convert_u16_to_i8_clamp_max.INSTANCE );
+ case U16_TO_U8: return Cast.unchecked( Convert_u16_to_u8_clamp_max.INSTANCE );
+ case U16_TO_I16: return Cast.unchecked( Convert_u16_to_i16_clamp_max.INSTANCE );
+ case U16_TO_U16: return Cast.unchecked( Convert_u16_to_u16_clamp_max.INSTANCE );
+ case U16_TO_I32: return Cast.unchecked( Convert_u16_to_i32_clamp_max.INSTANCE );
+ case U16_TO_U32: return Cast.unchecked( Convert_u16_to_u32_clamp_max.INSTANCE );
+ case U16_TO_I64: return Cast.unchecked( Convert_u16_to_i64_clamp_max.INSTANCE );
+ case U16_TO_F32: return Cast.unchecked( Convert_u16_to_f32_clamp_max.INSTANCE );
+ case U16_TO_F64: return Cast.unchecked( Convert_u16_to_f64_clamp_max.INSTANCE );
+ case I32_TO_I8: return Cast.unchecked( Convert_i32_to_i8_clamp_max.INSTANCE );
+ case I32_TO_U8: return Cast.unchecked( Convert_i32_to_u8_clamp_max.INSTANCE );
+ case I32_TO_I16: return Cast.unchecked( Convert_i32_to_i16_clamp_max.INSTANCE );
+ case I32_TO_U16: return Cast.unchecked( Convert_i32_to_u16_clamp_max.INSTANCE );
+ case I32_TO_I32: return Cast.unchecked( Convert_i32_to_i32_clamp_max.INSTANCE );
+ case I32_TO_U32: return Cast.unchecked( Convert_i32_to_u32_clamp_max.INSTANCE );
+ case I32_TO_I64: return Cast.unchecked( Convert_i32_to_i64_clamp_max.INSTANCE );
+ case I32_TO_F32: return Cast.unchecked( Convert_i32_to_f32_clamp_max.INSTANCE );
+ case I32_TO_F64: return Cast.unchecked( Convert_i32_to_f64_clamp_max.INSTANCE );
+ case U32_TO_I8: return Cast.unchecked( Convert_u32_to_i8_clamp_max.INSTANCE );
+ case U32_TO_U8: return Cast.unchecked( Convert_u32_to_u8_clamp_max.INSTANCE );
+ case U32_TO_I16: return Cast.unchecked( Convert_u32_to_i16_clamp_max.INSTANCE );
+ case U32_TO_U16: return Cast.unchecked( Convert_u32_to_u16_clamp_max.INSTANCE );
+ case U32_TO_I32: return Cast.unchecked( Convert_u32_to_i32_clamp_max.INSTANCE );
+ case U32_TO_U32: return Cast.unchecked( Convert_u32_to_u32_clamp_max.INSTANCE );
+ case U32_TO_I64: return Cast.unchecked( Convert_u32_to_i64_clamp_max.INSTANCE );
+ case U32_TO_F32: return Cast.unchecked( Convert_u32_to_f32_clamp_max.INSTANCE );
+ case U32_TO_F64: return Cast.unchecked( Convert_u32_to_f64_clamp_max.INSTANCE );
+ case I64_TO_I8: return Cast.unchecked( Convert_i64_to_i8_clamp_max.INSTANCE );
+ case I64_TO_U8: return Cast.unchecked( Convert_i64_to_u8_clamp_max.INSTANCE );
+ case I64_TO_I16: return Cast.unchecked( Convert_i64_to_i16_clamp_max.INSTANCE );
+ case I64_TO_U16: return Cast.unchecked( Convert_i64_to_u16_clamp_max.INSTANCE );
+ case I64_TO_I32: return Cast.unchecked( Convert_i64_to_i32_clamp_max.INSTANCE );
+ case I64_TO_U32: return Cast.unchecked( Convert_i64_to_u32_clamp_max.INSTANCE );
+ case I64_TO_I64: return Cast.unchecked( Convert_i64_to_i64_clamp_max.INSTANCE );
+ case I64_TO_F32: return Cast.unchecked( Convert_i64_to_f32_clamp_max.INSTANCE );
+ case I64_TO_F64: return Cast.unchecked( Convert_i64_to_f64_clamp_max.INSTANCE );
+ case F32_TO_I8: return Cast.unchecked( Convert_f32_to_i8_clamp_max.INSTANCE );
+ case F32_TO_U8: return Cast.unchecked( Convert_f32_to_u8_clamp_max.INSTANCE );
+ case F32_TO_I16: return Cast.unchecked( Convert_f32_to_i16_clamp_max.INSTANCE );
+ case F32_TO_U16: return Cast.unchecked( Convert_f32_to_u16_clamp_max.INSTANCE );
+ case F32_TO_I32: return Cast.unchecked( Convert_f32_to_i32_clamp_max.INSTANCE );
+ case F32_TO_U32: return Cast.unchecked( Convert_f32_to_u32_clamp_max.INSTANCE );
+ case F32_TO_I64: return Cast.unchecked( Convert_f32_to_i64_clamp_max.INSTANCE );
+ case F32_TO_F32: return Cast.unchecked( Convert_f32_to_f32_clamp_max.INSTANCE );
+ case F32_TO_F64: return Cast.unchecked( Convert_f32_to_f64_clamp_max.INSTANCE );
+ case F64_TO_I8: return Cast.unchecked( Convert_f64_to_i8_clamp_max.INSTANCE );
+ case F64_TO_U8: return Cast.unchecked( Convert_f64_to_u8_clamp_max.INSTANCE );
+ case F64_TO_I16: return Cast.unchecked( Convert_f64_to_i16_clamp_max.INSTANCE );
+ case F64_TO_U16: return Cast.unchecked( Convert_f64_to_u16_clamp_max.INSTANCE );
+ case F64_TO_I32: return Cast.unchecked( Convert_f64_to_i32_clamp_max.INSTANCE );
+ case F64_TO_U32: return Cast.unchecked( Convert_f64_to_u32_clamp_max.INSTANCE );
+ case F64_TO_I64: return Cast.unchecked( Convert_f64_to_i64_clamp_max.INSTANCE );
+ case F64_TO_F32: return Cast.unchecked( Convert_f64_to_f32_clamp_max.INSTANCE );
+ case F64_TO_F64: return Cast.unchecked( Convert_f64_to_f64_clamp_max.INSTANCE );
+ default:
+ throw new IllegalArgumentException();
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
static class Convert_i8_to_i8 implements ConvertLoop< byte[], byte[] >
@@ -380,6 +477,18 @@ public void apply( final byte[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i8_to_i8_clamp_min implements ConvertLoop< byte[], byte[] >
+ {
+ static final Convert_i8_to_i8_clamp_min INSTANCE = new Convert_i8_to_i8_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_i8_clamp_max implements ConvertLoop< byte[], byte[] >
{
static final Convert_i8_to_i8_clamp_max INSTANCE = new Convert_i8_to_i8_clamp_max();
@@ -416,6 +525,18 @@ public void apply( final byte[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i8_to_u8_clamp_min implements ConvertLoop< byte[], byte[] >
+ {
+ static final Convert_i8_to_u8_clamp_min INSTANCE = new Convert_i8_to_u8_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_u8_clamp_max implements ConvertLoop< byte[], byte[] >
{
static final Convert_i8_to_u8_clamp_max INSTANCE = new Convert_i8_to_u8_clamp_max();
@@ -452,6 +573,18 @@ public void apply( final byte[] src, final short[] dest, final int length )
}
}
+ static class Convert_i8_to_i16_clamp_min implements ConvertLoop< byte[], short[] >
+ {
+ static final Convert_i8_to_i16_clamp_min INSTANCE = new Convert_i8_to_i16_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_i16_clamp_max implements ConvertLoop< byte[], short[] >
{
static final Convert_i8_to_i16_clamp_max INSTANCE = new Convert_i8_to_i16_clamp_max();
@@ -488,6 +621,18 @@ public void apply( final byte[] src, final short[] dest, final int length )
}
}
+ static class Convert_i8_to_u16_clamp_min implements ConvertLoop< byte[], short[] >
+ {
+ static final Convert_i8_to_u16_clamp_min INSTANCE = new Convert_i8_to_u16_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_u16_clamp_max implements ConvertLoop< byte[], short[] >
{
static final Convert_i8_to_u16_clamp_max INSTANCE = new Convert_i8_to_u16_clamp_max();
@@ -524,6 +669,18 @@ public void apply( final byte[] src, final int[] dest, final int length )
}
}
+ static class Convert_i8_to_i32_clamp_min implements ConvertLoop< byte[], int[] >
+ {
+ static final Convert_i8_to_i32_clamp_min INSTANCE = new Convert_i8_to_i32_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_i32_clamp_max implements ConvertLoop< byte[], int[] >
{
static final Convert_i8_to_i32_clamp_max INSTANCE = new Convert_i8_to_i32_clamp_max();
@@ -560,6 +717,18 @@ public void apply( final byte[] src, final int[] dest, final int length )
}
}
+ static class Convert_i8_to_u32_clamp_min implements ConvertLoop< byte[], int[] >
+ {
+ static final Convert_i8_to_u32_clamp_min INSTANCE = new Convert_i8_to_u32_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_u32_clamp_max implements ConvertLoop< byte[], int[] >
{
static final Convert_i8_to_u32_clamp_max INSTANCE = new Convert_i8_to_u32_clamp_max();
@@ -596,6 +765,18 @@ public void apply( final byte[] src, final long[] dest, final int length )
}
}
+ static class Convert_i8_to_i64_clamp_min implements ConvertLoop< byte[], long[] >
+ {
+ static final Convert_i8_to_i64_clamp_min INSTANCE = new Convert_i8_to_i64_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_i64_clamp_max implements ConvertLoop< byte[], long[] >
{
static final Convert_i8_to_i64_clamp_max INSTANCE = new Convert_i8_to_i64_clamp_max();
@@ -632,6 +813,18 @@ public void apply( final byte[] src, final float[] dest, final int length )
}
}
+ static class Convert_i8_to_f32_clamp_min implements ConvertLoop< byte[], float[] >
+ {
+ static final Convert_i8_to_f32_clamp_min INSTANCE = new Convert_i8_to_f32_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_f32_clamp_max implements ConvertLoop< byte[], float[] >
{
static final Convert_i8_to_f32_clamp_max INSTANCE = new Convert_i8_to_f32_clamp_max();
@@ -668,6 +861,18 @@ public void apply( final byte[] src, final double[] dest, final int length )
}
}
+ static class Convert_i8_to_f64_clamp_min implements ConvertLoop< byte[], double[] >
+ {
+ static final Convert_i8_to_f64_clamp_min INSTANCE = new Convert_i8_to_f64_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_i8( src[ i ] ) );
+ }
+ }
+
static class Convert_i8_to_f64_clamp_max implements ConvertLoop< byte[], double[] >
{
static final Convert_i8_to_f64_clamp_max INSTANCE = new Convert_i8_to_f64_clamp_max();
@@ -704,6 +909,18 @@ public void apply( final byte[] src, final byte[] dest, final int length )
}
}
+ static class Convert_u8_to_i8_clamp_min implements ConvertLoop< byte[], byte[] >
+ {
+ static final Convert_u8_to_i8_clamp_min INSTANCE = new Convert_u8_to_i8_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_i8_clamp_max implements ConvertLoop< byte[], byte[] >
{
static final Convert_u8_to_i8_clamp_max INSTANCE = new Convert_u8_to_i8_clamp_max();
@@ -740,6 +957,18 @@ public void apply( final byte[] src, final byte[] dest, final int length )
}
}
+ static class Convert_u8_to_u8_clamp_min implements ConvertLoop< byte[], byte[] >
+ {
+ static final Convert_u8_to_u8_clamp_min INSTANCE = new Convert_u8_to_u8_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_u8_clamp_max implements ConvertLoop< byte[], byte[] >
{
static final Convert_u8_to_u8_clamp_max INSTANCE = new Convert_u8_to_u8_clamp_max();
@@ -776,6 +1005,18 @@ public void apply( final byte[] src, final short[] dest, final int length )
}
}
+ static class Convert_u8_to_i16_clamp_min implements ConvertLoop< byte[], short[] >
+ {
+ static final Convert_u8_to_i16_clamp_min INSTANCE = new Convert_u8_to_i16_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_i16_clamp_max implements ConvertLoop< byte[], short[] >
{
static final Convert_u8_to_i16_clamp_max INSTANCE = new Convert_u8_to_i16_clamp_max();
@@ -812,6 +1053,18 @@ public void apply( final byte[] src, final short[] dest, final int length )
}
}
+ static class Convert_u8_to_u16_clamp_min implements ConvertLoop< byte[], short[] >
+ {
+ static final Convert_u8_to_u16_clamp_min INSTANCE = new Convert_u8_to_u16_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_u16_clamp_max implements ConvertLoop< byte[], short[] >
{
static final Convert_u8_to_u16_clamp_max INSTANCE = new Convert_u8_to_u16_clamp_max();
@@ -848,6 +1101,18 @@ public void apply( final byte[] src, final int[] dest, final int length )
}
}
+ static class Convert_u8_to_i32_clamp_min implements ConvertLoop< byte[], int[] >
+ {
+ static final Convert_u8_to_i32_clamp_min INSTANCE = new Convert_u8_to_i32_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_i32_clamp_max implements ConvertLoop< byte[], int[] >
{
static final Convert_u8_to_i32_clamp_max INSTANCE = new Convert_u8_to_i32_clamp_max();
@@ -884,6 +1149,18 @@ public void apply( final byte[] src, final int[] dest, final int length )
}
}
+ static class Convert_u8_to_u32_clamp_min implements ConvertLoop< byte[], int[] >
+ {
+ static final Convert_u8_to_u32_clamp_min INSTANCE = new Convert_u8_to_u32_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_u32_clamp_max implements ConvertLoop< byte[], int[] >
{
static final Convert_u8_to_u32_clamp_max INSTANCE = new Convert_u8_to_u32_clamp_max();
@@ -920,6 +1197,18 @@ public void apply( final byte[] src, final long[] dest, final int length )
}
}
+ static class Convert_u8_to_i64_clamp_min implements ConvertLoop< byte[], long[] >
+ {
+ static final Convert_u8_to_i64_clamp_min INSTANCE = new Convert_u8_to_i64_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_i64_clamp_max implements ConvertLoop< byte[], long[] >
{
static final Convert_u8_to_i64_clamp_max INSTANCE = new Convert_u8_to_i64_clamp_max();
@@ -956,6 +1245,18 @@ public void apply( final byte[] src, final float[] dest, final int length )
}
}
+ static class Convert_u8_to_f32_clamp_min implements ConvertLoop< byte[], float[] >
+ {
+ static final Convert_u8_to_f32_clamp_min INSTANCE = new Convert_u8_to_f32_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_f32_clamp_max implements ConvertLoop< byte[], float[] >
{
static final Convert_u8_to_f32_clamp_max INSTANCE = new Convert_u8_to_f32_clamp_max();
@@ -992,6 +1293,18 @@ public void apply( final byte[] src, final double[] dest, final int length )
}
}
+ static class Convert_u8_to_f64_clamp_min implements ConvertLoop< byte[], double[] >
+ {
+ static final Convert_u8_to_f64_clamp_min INSTANCE = new Convert_u8_to_f64_clamp_min();
+
+ @Override
+ public void apply( final byte[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_u8( src[ i ] ) );
+ }
+ }
+
static class Convert_u8_to_f64_clamp_max implements ConvertLoop< byte[], double[] >
{
static final Convert_u8_to_f64_clamp_max INSTANCE = new Convert_u8_to_f64_clamp_max();
@@ -1028,6 +1341,18 @@ public void apply( final short[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i16_to_i8_clamp_min implements ConvertLoop< short[], byte[] >
+ {
+ static final Convert_i16_to_i8_clamp_min INSTANCE = new Convert_i16_to_i8_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_i8_clamp_max implements ConvertLoop< short[], byte[] >
{
static final Convert_i16_to_i8_clamp_max INSTANCE = new Convert_i16_to_i8_clamp_max();
@@ -1064,6 +1389,18 @@ public void apply( final short[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i16_to_u8_clamp_min implements ConvertLoop< short[], byte[] >
+ {
+ static final Convert_i16_to_u8_clamp_min INSTANCE = new Convert_i16_to_u8_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_u8_clamp_max implements ConvertLoop< short[], byte[] >
{
static final Convert_i16_to_u8_clamp_max INSTANCE = new Convert_i16_to_u8_clamp_max();
@@ -1100,6 +1437,18 @@ public void apply( final short[] src, final short[] dest, final int length )
}
}
+ static class Convert_i16_to_i16_clamp_min implements ConvertLoop< short[], short[] >
+ {
+ static final Convert_i16_to_i16_clamp_min INSTANCE = new Convert_i16_to_i16_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_i16_clamp_max implements ConvertLoop< short[], short[] >
{
static final Convert_i16_to_i16_clamp_max INSTANCE = new Convert_i16_to_i16_clamp_max();
@@ -1136,6 +1485,18 @@ public void apply( final short[] src, final short[] dest, final int length )
}
}
+ static class Convert_i16_to_u16_clamp_min implements ConvertLoop< short[], short[] >
+ {
+ static final Convert_i16_to_u16_clamp_min INSTANCE = new Convert_i16_to_u16_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_u16_clamp_max implements ConvertLoop< short[], short[] >
{
static final Convert_i16_to_u16_clamp_max INSTANCE = new Convert_i16_to_u16_clamp_max();
@@ -1172,6 +1533,18 @@ public void apply( final short[] src, final int[] dest, final int length )
}
}
+ static class Convert_i16_to_i32_clamp_min implements ConvertLoop< short[], int[] >
+ {
+ static final Convert_i16_to_i32_clamp_min INSTANCE = new Convert_i16_to_i32_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_i32_clamp_max implements ConvertLoop< short[], int[] >
{
static final Convert_i16_to_i32_clamp_max INSTANCE = new Convert_i16_to_i32_clamp_max();
@@ -1208,6 +1581,18 @@ public void apply( final short[] src, final int[] dest, final int length )
}
}
+ static class Convert_i16_to_u32_clamp_min implements ConvertLoop< short[], int[] >
+ {
+ static final Convert_i16_to_u32_clamp_min INSTANCE = new Convert_i16_to_u32_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_u32_clamp_max implements ConvertLoop< short[], int[] >
{
static final Convert_i16_to_u32_clamp_max INSTANCE = new Convert_i16_to_u32_clamp_max();
@@ -1244,6 +1629,18 @@ public void apply( final short[] src, final long[] dest, final int length )
}
}
+ static class Convert_i16_to_i64_clamp_min implements ConvertLoop< short[], long[] >
+ {
+ static final Convert_i16_to_i64_clamp_min INSTANCE = new Convert_i16_to_i64_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_i64_clamp_max implements ConvertLoop< short[], long[] >
{
static final Convert_i16_to_i64_clamp_max INSTANCE = new Convert_i16_to_i64_clamp_max();
@@ -1280,6 +1677,18 @@ public void apply( final short[] src, final float[] dest, final int length )
}
}
+ static class Convert_i16_to_f32_clamp_min implements ConvertLoop< short[], float[] >
+ {
+ static final Convert_i16_to_f32_clamp_min INSTANCE = new Convert_i16_to_f32_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_f32_clamp_max implements ConvertLoop< short[], float[] >
{
static final Convert_i16_to_f32_clamp_max INSTANCE = new Convert_i16_to_f32_clamp_max();
@@ -1316,6 +1725,18 @@ public void apply( final short[] src, final double[] dest, final int length )
}
}
+ static class Convert_i16_to_f64_clamp_min implements ConvertLoop< short[], double[] >
+ {
+ static final Convert_i16_to_f64_clamp_min INSTANCE = new Convert_i16_to_f64_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_i16( src[ i ] ) );
+ }
+ }
+
static class Convert_i16_to_f64_clamp_max implements ConvertLoop< short[], double[] >
{
static final Convert_i16_to_f64_clamp_max INSTANCE = new Convert_i16_to_f64_clamp_max();
@@ -1352,6 +1773,18 @@ public void apply( final short[] src, final byte[] dest, final int length )
}
}
+ static class Convert_u16_to_i8_clamp_min implements ConvertLoop< short[], byte[] >
+ {
+ static final Convert_u16_to_i8_clamp_min INSTANCE = new Convert_u16_to_i8_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_i8_clamp_max implements ConvertLoop< short[], byte[] >
{
static final Convert_u16_to_i8_clamp_max INSTANCE = new Convert_u16_to_i8_clamp_max();
@@ -1388,9 +1821,21 @@ public void apply( final short[] src, final byte[] dest, final int length )
}
}
- static class Convert_u16_to_u8_clamp_max implements ConvertLoop< short[], byte[] >
+ static class Convert_u16_to_u8_clamp_min implements ConvertLoop< short[], byte[] >
{
- static final Convert_u16_to_u8_clamp_max INSTANCE = new Convert_u16_to_u8_clamp_max();
+ static final Convert_u16_to_u8_clamp_min INSTANCE = new Convert_u16_to_u8_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
+ static class Convert_u16_to_u8_clamp_max implements ConvertLoop< short[], byte[] >
+ {
+ static final Convert_u16_to_u8_clamp_max INSTANCE = new Convert_u16_to_u8_clamp_max();
@Override
public void apply( final short[] src, final byte[] dest, final int length )
@@ -1424,6 +1869,18 @@ public void apply( final short[] src, final short[] dest, final int length )
}
}
+ static class Convert_u16_to_i16_clamp_min implements ConvertLoop< short[], short[] >
+ {
+ static final Convert_u16_to_i16_clamp_min INSTANCE = new Convert_u16_to_i16_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_i16_clamp_max implements ConvertLoop< short[], short[] >
{
static final Convert_u16_to_i16_clamp_max INSTANCE = new Convert_u16_to_i16_clamp_max();
@@ -1460,6 +1917,18 @@ public void apply( final short[] src, final short[] dest, final int length )
}
}
+ static class Convert_u16_to_u16_clamp_min implements ConvertLoop< short[], short[] >
+ {
+ static final Convert_u16_to_u16_clamp_min INSTANCE = new Convert_u16_to_u16_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_u16_clamp_max implements ConvertLoop< short[], short[] >
{
static final Convert_u16_to_u16_clamp_max INSTANCE = new Convert_u16_to_u16_clamp_max();
@@ -1496,6 +1965,18 @@ public void apply( final short[] src, final int[] dest, final int length )
}
}
+ static class Convert_u16_to_i32_clamp_min implements ConvertLoop< short[], int[] >
+ {
+ static final Convert_u16_to_i32_clamp_min INSTANCE = new Convert_u16_to_i32_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_i32_clamp_max implements ConvertLoop< short[], int[] >
{
static final Convert_u16_to_i32_clamp_max INSTANCE = new Convert_u16_to_i32_clamp_max();
@@ -1532,6 +2013,18 @@ public void apply( final short[] src, final int[] dest, final int length )
}
}
+ static class Convert_u16_to_u32_clamp_min implements ConvertLoop< short[], int[] >
+ {
+ static final Convert_u16_to_u32_clamp_min INSTANCE = new Convert_u16_to_u32_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_u32_clamp_max implements ConvertLoop< short[], int[] >
{
static final Convert_u16_to_u32_clamp_max INSTANCE = new Convert_u16_to_u32_clamp_max();
@@ -1568,6 +2061,18 @@ public void apply( final short[] src, final long[] dest, final int length )
}
}
+ static class Convert_u16_to_i64_clamp_min implements ConvertLoop< short[], long[] >
+ {
+ static final Convert_u16_to_i64_clamp_min INSTANCE = new Convert_u16_to_i64_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_i64_clamp_max implements ConvertLoop< short[], long[] >
{
static final Convert_u16_to_i64_clamp_max INSTANCE = new Convert_u16_to_i64_clamp_max();
@@ -1604,6 +2109,18 @@ public void apply( final short[] src, final float[] dest, final int length )
}
}
+ static class Convert_u16_to_f32_clamp_min implements ConvertLoop< short[], float[] >
+ {
+ static final Convert_u16_to_f32_clamp_min INSTANCE = new Convert_u16_to_f32_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_f32_clamp_max implements ConvertLoop< short[], float[] >
{
static final Convert_u16_to_f32_clamp_max INSTANCE = new Convert_u16_to_f32_clamp_max();
@@ -1640,6 +2157,18 @@ public void apply( final short[] src, final double[] dest, final int length )
}
}
+ static class Convert_u16_to_f64_clamp_min implements ConvertLoop< short[], double[] >
+ {
+ static final Convert_u16_to_f64_clamp_min INSTANCE = new Convert_u16_to_f64_clamp_min();
+
+ @Override
+ public void apply( final short[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_u16( src[ i ] ) );
+ }
+ }
+
static class Convert_u16_to_f64_clamp_max implements ConvertLoop< short[], double[] >
{
static final Convert_u16_to_f64_clamp_max INSTANCE = new Convert_u16_to_f64_clamp_max();
@@ -1676,6 +2205,18 @@ public void apply( final int[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i32_to_i8_clamp_min implements ConvertLoop< int[], byte[] >
+ {
+ static final Convert_i32_to_i8_clamp_min INSTANCE = new Convert_i32_to_i8_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_i8_clamp_max implements ConvertLoop< int[], byte[] >
{
static final Convert_i32_to_i8_clamp_max INSTANCE = new Convert_i32_to_i8_clamp_max();
@@ -1712,6 +2253,18 @@ public void apply( final int[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i32_to_u8_clamp_min implements ConvertLoop< int[], byte[] >
+ {
+ static final Convert_i32_to_u8_clamp_min INSTANCE = new Convert_i32_to_u8_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_u8_clamp_max implements ConvertLoop< int[], byte[] >
{
static final Convert_i32_to_u8_clamp_max INSTANCE = new Convert_i32_to_u8_clamp_max();
@@ -1748,6 +2301,18 @@ public void apply( final int[] src, final short[] dest, final int length )
}
}
+ static class Convert_i32_to_i16_clamp_min implements ConvertLoop< int[], short[] >
+ {
+ static final Convert_i32_to_i16_clamp_min INSTANCE = new Convert_i32_to_i16_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_i16_clamp_max implements ConvertLoop< int[], short[] >
{
static final Convert_i32_to_i16_clamp_max INSTANCE = new Convert_i32_to_i16_clamp_max();
@@ -1784,6 +2349,18 @@ public void apply( final int[] src, final short[] dest, final int length )
}
}
+ static class Convert_i32_to_u16_clamp_min implements ConvertLoop< int[], short[] >
+ {
+ static final Convert_i32_to_u16_clamp_min INSTANCE = new Convert_i32_to_u16_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_u16_clamp_max implements ConvertLoop< int[], short[] >
{
static final Convert_i32_to_u16_clamp_max INSTANCE = new Convert_i32_to_u16_clamp_max();
@@ -1820,6 +2397,18 @@ public void apply( final int[] src, final int[] dest, final int length )
}
}
+ static class Convert_i32_to_i32_clamp_min implements ConvertLoop< int[], int[] >
+ {
+ static final Convert_i32_to_i32_clamp_min INSTANCE = new Convert_i32_to_i32_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_i32_clamp_max implements ConvertLoop< int[], int[] >
{
static final Convert_i32_to_i32_clamp_max INSTANCE = new Convert_i32_to_i32_clamp_max();
@@ -1856,6 +2445,18 @@ public void apply( final int[] src, final int[] dest, final int length )
}
}
+ static class Convert_i32_to_u32_clamp_min implements ConvertLoop< int[], int[] >
+ {
+ static final Convert_i32_to_u32_clamp_min INSTANCE = new Convert_i32_to_u32_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_u32_clamp_max implements ConvertLoop< int[], int[] >
{
static final Convert_i32_to_u32_clamp_max INSTANCE = new Convert_i32_to_u32_clamp_max();
@@ -1892,6 +2493,18 @@ public void apply( final int[] src, final long[] dest, final int length )
}
}
+ static class Convert_i32_to_i64_clamp_min implements ConvertLoop< int[], long[] >
+ {
+ static final Convert_i32_to_i64_clamp_min INSTANCE = new Convert_i32_to_i64_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_i64_clamp_max implements ConvertLoop< int[], long[] >
{
static final Convert_i32_to_i64_clamp_max INSTANCE = new Convert_i32_to_i64_clamp_max();
@@ -1928,6 +2541,18 @@ public void apply( final int[] src, final float[] dest, final int length )
}
}
+ static class Convert_i32_to_f32_clamp_min implements ConvertLoop< int[], float[] >
+ {
+ static final Convert_i32_to_f32_clamp_min INSTANCE = new Convert_i32_to_f32_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_f32_clamp_max implements ConvertLoop< int[], float[] >
{
static final Convert_i32_to_f32_clamp_max INSTANCE = new Convert_i32_to_f32_clamp_max();
@@ -1964,6 +2589,18 @@ public void apply( final int[] src, final double[] dest, final int length )
}
}
+ static class Convert_i32_to_f64_clamp_min implements ConvertLoop< int[], double[] >
+ {
+ static final Convert_i32_to_f64_clamp_min INSTANCE = new Convert_i32_to_f64_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_i32( src[ i ] ) );
+ }
+ }
+
static class Convert_i32_to_f64_clamp_max implements ConvertLoop< int[], double[] >
{
static final Convert_i32_to_f64_clamp_max INSTANCE = new Convert_i32_to_f64_clamp_max();
@@ -2000,6 +2637,18 @@ public void apply( final int[] src, final byte[] dest, final int length )
}
}
+ static class Convert_u32_to_i8_clamp_min implements ConvertLoop< int[], byte[] >
+ {
+ static final Convert_u32_to_i8_clamp_min INSTANCE = new Convert_u32_to_i8_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_i8_clamp_max implements ConvertLoop< int[], byte[] >
{
static final Convert_u32_to_i8_clamp_max INSTANCE = new Convert_u32_to_i8_clamp_max();
@@ -2036,6 +2685,18 @@ public void apply( final int[] src, final byte[] dest, final int length )
}
}
+ static class Convert_u32_to_u8_clamp_min implements ConvertLoop< int[], byte[] >
+ {
+ static final Convert_u32_to_u8_clamp_min INSTANCE = new Convert_u32_to_u8_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_u8_clamp_max implements ConvertLoop< int[], byte[] >
{
static final Convert_u32_to_u8_clamp_max INSTANCE = new Convert_u32_to_u8_clamp_max();
@@ -2072,6 +2733,18 @@ public void apply( final int[] src, final short[] dest, final int length )
}
}
+ static class Convert_u32_to_i16_clamp_min implements ConvertLoop< int[], short[] >
+ {
+ static final Convert_u32_to_i16_clamp_min INSTANCE = new Convert_u32_to_i16_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_i16_clamp_max implements ConvertLoop< int[], short[] >
{
static final Convert_u32_to_i16_clamp_max INSTANCE = new Convert_u32_to_i16_clamp_max();
@@ -2108,6 +2781,18 @@ public void apply( final int[] src, final short[] dest, final int length )
}
}
+ static class Convert_u32_to_u16_clamp_min implements ConvertLoop< int[], short[] >
+ {
+ static final Convert_u32_to_u16_clamp_min INSTANCE = new Convert_u32_to_u16_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_u16_clamp_max implements ConvertLoop< int[], short[] >
{
static final Convert_u32_to_u16_clamp_max INSTANCE = new Convert_u32_to_u16_clamp_max();
@@ -2144,6 +2829,18 @@ public void apply( final int[] src, final int[] dest, final int length )
}
}
+ static class Convert_u32_to_i32_clamp_min implements ConvertLoop< int[], int[] >
+ {
+ static final Convert_u32_to_i32_clamp_min INSTANCE = new Convert_u32_to_i32_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_i32_clamp_max implements ConvertLoop< int[], int[] >
{
static final Convert_u32_to_i32_clamp_max INSTANCE = new Convert_u32_to_i32_clamp_max();
@@ -2180,6 +2877,18 @@ public void apply( final int[] src, final int[] dest, final int length )
}
}
+ static class Convert_u32_to_u32_clamp_min implements ConvertLoop< int[], int[] >
+ {
+ static final Convert_u32_to_u32_clamp_min INSTANCE = new Convert_u32_to_u32_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_u32_clamp_max implements ConvertLoop< int[], int[] >
{
static final Convert_u32_to_u32_clamp_max INSTANCE = new Convert_u32_to_u32_clamp_max();
@@ -2216,6 +2925,18 @@ public void apply( final int[] src, final long[] dest, final int length )
}
}
+ static class Convert_u32_to_i64_clamp_min implements ConvertLoop< int[], long[] >
+ {
+ static final Convert_u32_to_i64_clamp_min INSTANCE = new Convert_u32_to_i64_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_i64_clamp_max implements ConvertLoop< int[], long[] >
{
static final Convert_u32_to_i64_clamp_max INSTANCE = new Convert_u32_to_i64_clamp_max();
@@ -2252,6 +2973,18 @@ public void apply( final int[] src, final float[] dest, final int length )
}
}
+ static class Convert_u32_to_f32_clamp_min implements ConvertLoop< int[], float[] >
+ {
+ static final Convert_u32_to_f32_clamp_min INSTANCE = new Convert_u32_to_f32_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_f32_clamp_max implements ConvertLoop< int[], float[] >
{
static final Convert_u32_to_f32_clamp_max INSTANCE = new Convert_u32_to_f32_clamp_max();
@@ -2288,6 +3021,18 @@ public void apply( final int[] src, final double[] dest, final int length )
}
}
+ static class Convert_u32_to_f64_clamp_min implements ConvertLoop< int[], double[] >
+ {
+ static final Convert_u32_to_f64_clamp_min INSTANCE = new Convert_u32_to_f64_clamp_min();
+
+ @Override
+ public void apply( final int[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_u32( src[ i ] ) );
+ }
+ }
+
static class Convert_u32_to_f64_clamp_max implements ConvertLoop< int[], double[] >
{
static final Convert_u32_to_f64_clamp_max INSTANCE = new Convert_u32_to_f64_clamp_max();
@@ -2324,6 +3069,18 @@ public void apply( final long[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i64_to_i8_clamp_min implements ConvertLoop< long[], byte[] >
+ {
+ static final Convert_i64_to_i8_clamp_min INSTANCE = new Convert_i64_to_i8_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_i8_clamp_max implements ConvertLoop< long[], byte[] >
{
static final Convert_i64_to_i8_clamp_max INSTANCE = new Convert_i64_to_i8_clamp_max();
@@ -2360,6 +3117,18 @@ public void apply( final long[] src, final byte[] dest, final int length )
}
}
+ static class Convert_i64_to_u8_clamp_min implements ConvertLoop< long[], byte[] >
+ {
+ static final Convert_i64_to_u8_clamp_min INSTANCE = new Convert_i64_to_u8_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_u8_clamp_max implements ConvertLoop< long[], byte[] >
{
static final Convert_i64_to_u8_clamp_max INSTANCE = new Convert_i64_to_u8_clamp_max();
@@ -2396,6 +3165,18 @@ public void apply( final long[] src, final short[] dest, final int length )
}
}
+ static class Convert_i64_to_i16_clamp_min implements ConvertLoop< long[], short[] >
+ {
+ static final Convert_i64_to_i16_clamp_min INSTANCE = new Convert_i64_to_i16_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_i16_clamp_max implements ConvertLoop< long[], short[] >
{
static final Convert_i64_to_i16_clamp_max INSTANCE = new Convert_i64_to_i16_clamp_max();
@@ -2432,6 +3213,18 @@ public void apply( final long[] src, final short[] dest, final int length )
}
}
+ static class Convert_i64_to_u16_clamp_min implements ConvertLoop< long[], short[] >
+ {
+ static final Convert_i64_to_u16_clamp_min INSTANCE = new Convert_i64_to_u16_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_u16_clamp_max implements ConvertLoop< long[], short[] >
{
static final Convert_i64_to_u16_clamp_max INSTANCE = new Convert_i64_to_u16_clamp_max();
@@ -2468,6 +3261,18 @@ public void apply( final long[] src, final int[] dest, final int length )
}
}
+ static class Convert_i64_to_i32_clamp_min implements ConvertLoop< long[], int[] >
+ {
+ static final Convert_i64_to_i32_clamp_min INSTANCE = new Convert_i64_to_i32_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_i32_clamp_max implements ConvertLoop< long[], int[] >
{
static final Convert_i64_to_i32_clamp_max INSTANCE = new Convert_i64_to_i32_clamp_max();
@@ -2504,6 +3309,18 @@ public void apply( final long[] src, final int[] dest, final int length )
}
}
+ static class Convert_i64_to_u32_clamp_min implements ConvertLoop< long[], int[] >
+ {
+ static final Convert_i64_to_u32_clamp_min INSTANCE = new Convert_i64_to_u32_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_u32_clamp_max implements ConvertLoop< long[], int[] >
{
static final Convert_i64_to_u32_clamp_max INSTANCE = new Convert_i64_to_u32_clamp_max();
@@ -2540,6 +3357,18 @@ public void apply( final long[] src, final long[] dest, final int length )
}
}
+ static class Convert_i64_to_i64_clamp_min implements ConvertLoop< long[], long[] >
+ {
+ static final Convert_i64_to_i64_clamp_min INSTANCE = new Convert_i64_to_i64_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_i64_clamp_max implements ConvertLoop< long[], long[] >
{
static final Convert_i64_to_i64_clamp_max INSTANCE = new Convert_i64_to_i64_clamp_max();
@@ -2576,6 +3405,18 @@ public void apply( final long[] src, final float[] dest, final int length )
}
}
+ static class Convert_i64_to_f32_clamp_min implements ConvertLoop< long[], float[] >
+ {
+ static final Convert_i64_to_f32_clamp_min INSTANCE = new Convert_i64_to_f32_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_f32_clamp_max implements ConvertLoop< long[], float[] >
{
static final Convert_i64_to_f32_clamp_max INSTANCE = new Convert_i64_to_f32_clamp_max();
@@ -2612,6 +3453,18 @@ public void apply( final long[] src, final double[] dest, final int length )
}
}
+ static class Convert_i64_to_f64_clamp_min implements ConvertLoop< long[], double[] >
+ {
+ static final Convert_i64_to_f64_clamp_min INSTANCE = new Convert_i64_to_f64_clamp_min();
+
+ @Override
+ public void apply( final long[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_i64( src[ i ] ) );
+ }
+ }
+
static class Convert_i64_to_f64_clamp_max implements ConvertLoop< long[], double[] >
{
static final Convert_i64_to_f64_clamp_max INSTANCE = new Convert_i64_to_f64_clamp_max();
@@ -2648,6 +3501,18 @@ public void apply( final float[] src, final byte[] dest, final int length )
}
}
+ static class Convert_f32_to_i8_clamp_min implements ConvertLoop< float[], byte[] >
+ {
+ static final Convert_f32_to_i8_clamp_min INSTANCE = new Convert_f32_to_i8_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_i8_clamp_max implements ConvertLoop< float[], byte[] >
{
static final Convert_f32_to_i8_clamp_max INSTANCE = new Convert_f32_to_i8_clamp_max();
@@ -2684,6 +3549,18 @@ public void apply( final float[] src, final byte[] dest, final int length )
}
}
+ static class Convert_f32_to_u8_clamp_min implements ConvertLoop< float[], byte[] >
+ {
+ static final Convert_f32_to_u8_clamp_min INSTANCE = new Convert_f32_to_u8_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_u8_clamp_max implements ConvertLoop< float[], byte[] >
{
static final Convert_f32_to_u8_clamp_max INSTANCE = new Convert_f32_to_u8_clamp_max();
@@ -2720,6 +3597,18 @@ public void apply( final float[] src, final short[] dest, final int length )
}
}
+ static class Convert_f32_to_i16_clamp_min implements ConvertLoop< float[], short[] >
+ {
+ static final Convert_f32_to_i16_clamp_min INSTANCE = new Convert_f32_to_i16_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_i16_clamp_max implements ConvertLoop< float[], short[] >
{
static final Convert_f32_to_i16_clamp_max INSTANCE = new Convert_f32_to_i16_clamp_max();
@@ -2756,6 +3645,18 @@ public void apply( final float[] src, final short[] dest, final int length )
}
}
+ static class Convert_f32_to_u16_clamp_min implements ConvertLoop< float[], short[] >
+ {
+ static final Convert_f32_to_u16_clamp_min INSTANCE = new Convert_f32_to_u16_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_u16_clamp_max implements ConvertLoop< float[], short[] >
{
static final Convert_f32_to_u16_clamp_max INSTANCE = new Convert_f32_to_u16_clamp_max();
@@ -2792,6 +3693,18 @@ public void apply( final float[] src, final int[] dest, final int length )
}
}
+ static class Convert_f32_to_i32_clamp_min implements ConvertLoop< float[], int[] >
+ {
+ static final Convert_f32_to_i32_clamp_min INSTANCE = new Convert_f32_to_i32_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_i32_clamp_max implements ConvertLoop< float[], int[] >
{
static final Convert_f32_to_i32_clamp_max INSTANCE = new Convert_f32_to_i32_clamp_max();
@@ -2828,6 +3741,18 @@ public void apply( final float[] src, final int[] dest, final int length )
}
}
+ static class Convert_f32_to_u32_clamp_min implements ConvertLoop< float[], int[] >
+ {
+ static final Convert_f32_to_u32_clamp_min INSTANCE = new Convert_f32_to_u32_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_u32_clamp_max implements ConvertLoop< float[], int[] >
{
static final Convert_f32_to_u32_clamp_max INSTANCE = new Convert_f32_to_u32_clamp_max();
@@ -2864,6 +3789,18 @@ public void apply( final float[] src, final long[] dest, final int length )
}
}
+ static class Convert_f32_to_i64_clamp_min implements ConvertLoop< float[], long[] >
+ {
+ static final Convert_f32_to_i64_clamp_min INSTANCE = new Convert_f32_to_i64_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_i64_clamp_max implements ConvertLoop< float[], long[] >
{
static final Convert_f32_to_i64_clamp_max INSTANCE = new Convert_f32_to_i64_clamp_max();
@@ -2900,6 +3837,18 @@ public void apply( final float[] src, final float[] dest, final int length )
}
}
+ static class Convert_f32_to_f32_clamp_min implements ConvertLoop< float[], float[] >
+ {
+ static final Convert_f32_to_f32_clamp_min INSTANCE = new Convert_f32_to_f32_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_f32_clamp_max implements ConvertLoop< float[], float[] >
{
static final Convert_f32_to_f32_clamp_max INSTANCE = new Convert_f32_to_f32_clamp_max();
@@ -2936,6 +3885,18 @@ public void apply( final float[] src, final double[] dest, final int length )
}
}
+ static class Convert_f32_to_f64_clamp_min implements ConvertLoop< float[], double[] >
+ {
+ static final Convert_f32_to_f64_clamp_min INSTANCE = new Convert_f32_to_f64_clamp_min();
+
+ @Override
+ public void apply( final float[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_f32( src[ i ] ) );
+ }
+ }
+
static class Convert_f32_to_f64_clamp_max implements ConvertLoop< float[], double[] >
{
static final Convert_f32_to_f64_clamp_max INSTANCE = new Convert_f32_to_f64_clamp_max();
@@ -2972,6 +3933,18 @@ public void apply( final double[] src, final byte[] dest, final int length )
}
}
+ static class Convert_f64_to_i8_clamp_min implements ConvertLoop< double[], byte[] >
+ {
+ static final Convert_f64_to_i8_clamp_min INSTANCE = new Convert_f64_to_i8_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i8_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_i8_clamp_max implements ConvertLoop< double[], byte[] >
{
static final Convert_f64_to_i8_clamp_max INSTANCE = new Convert_f64_to_i8_clamp_max();
@@ -3008,6 +3981,18 @@ public void apply( final double[] src, final byte[] dest, final int length )
}
}
+ static class Convert_f64_to_u8_clamp_min implements ConvertLoop< double[], byte[] >
+ {
+ static final Convert_f64_to_u8_clamp_min INSTANCE = new Convert_f64_to_u8_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final byte[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u8_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_u8_clamp_max implements ConvertLoop< double[], byte[] >
{
static final Convert_f64_to_u8_clamp_max INSTANCE = new Convert_f64_to_u8_clamp_max();
@@ -3044,6 +4029,18 @@ public void apply( final double[] src, final short[] dest, final int length )
}
}
+ static class Convert_f64_to_i16_clamp_min implements ConvertLoop< double[], short[] >
+ {
+ static final Convert_f64_to_i16_clamp_min INSTANCE = new Convert_f64_to_i16_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i16_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_i16_clamp_max implements ConvertLoop< double[], short[] >
{
static final Convert_f64_to_i16_clamp_max INSTANCE = new Convert_f64_to_i16_clamp_max();
@@ -3080,6 +4077,18 @@ public void apply( final double[] src, final short[] dest, final int length )
}
}
+ static class Convert_f64_to_u16_clamp_min implements ConvertLoop< double[], short[] >
+ {
+ static final Convert_f64_to_u16_clamp_min INSTANCE = new Convert_f64_to_u16_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final short[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u16_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_u16_clamp_max implements ConvertLoop< double[], short[] >
{
static final Convert_f64_to_u16_clamp_max INSTANCE = new Convert_f64_to_u16_clamp_max();
@@ -3116,6 +4125,18 @@ public void apply( final double[] src, final int[] dest, final int length )
}
}
+ static class Convert_f64_to_i32_clamp_min implements ConvertLoop< double[], int[] >
+ {
+ static final Convert_f64_to_i32_clamp_min INSTANCE = new Convert_f64_to_i32_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i32_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_i32_clamp_max implements ConvertLoop< double[], int[] >
{
static final Convert_f64_to_i32_clamp_max INSTANCE = new Convert_f64_to_i32_clamp_max();
@@ -3152,6 +4173,18 @@ public void apply( final double[] src, final int[] dest, final int length )
}
}
+ static class Convert_f64_to_u32_clamp_min implements ConvertLoop< double[], int[] >
+ {
+ static final Convert_f64_to_u32_clamp_min INSTANCE = new Convert_f64_to_u32_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final int[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_u32_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_u32_clamp_max implements ConvertLoop< double[], int[] >
{
static final Convert_f64_to_u32_clamp_max INSTANCE = new Convert_f64_to_u32_clamp_max();
@@ -3188,6 +4221,18 @@ public void apply( final double[] src, final long[] dest, final int length )
}
}
+ static class Convert_f64_to_i64_clamp_min implements ConvertLoop< double[], long[] >
+ {
+ static final Convert_f64_to_i64_clamp_min INSTANCE = new Convert_f64_to_i64_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final long[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_i64_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_i64_clamp_max implements ConvertLoop< double[], long[] >
{
static final Convert_f64_to_i64_clamp_max INSTANCE = new Convert_f64_to_i64_clamp_max();
@@ -3224,6 +4269,18 @@ public void apply( final double[] src, final float[] dest, final int length )
}
}
+ static class Convert_f64_to_f32_clamp_min implements ConvertLoop< double[], float[] >
+ {
+ static final Convert_f64_to_f32_clamp_min INSTANCE = new Convert_f64_to_f32_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final float[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f32_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_f32_clamp_max implements ConvertLoop< double[], float[] >
{
static final Convert_f64_to_f32_clamp_max INSTANCE = new Convert_f64_to_f32_clamp_max();
@@ -3260,6 +4317,18 @@ public void apply( final double[] src, final double[] dest, final int length )
}
}
+ static class Convert_f64_to_f64_clamp_min implements ConvertLoop< double[], double[] >
+ {
+ static final Convert_f64_to_f64_clamp_min INSTANCE = new Convert_f64_to_f64_clamp_min();
+
+ @Override
+ public void apply( final double[] src, final double[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_f64_clamp_min( from_f64( src[ i ] ) );
+ }
+ }
+
static class Convert_f64_to_f64_clamp_max implements ConvertLoop< double[], double[] >
{
static final Convert_f64_to_f64_clamp_max INSTANCE = new Convert_f64_to_f64_clamp_max();
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertScalars.java b/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertScalars.java
deleted file mode 100644
index 03ed085e5..000000000
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/ConvertScalars.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * #%L
- * ImgLib2: a general-purpose, multidimensional image processing library.
- * %%
- * Copyright (C) 2009 - 2024 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.algorithm.blocks.convert;
-
-/*
- * This is autogenerated source code -- DO NOT EDIT. Instead, edit the
- * corresponding template in templates/ and rerun bin/generate.groovy.
- */
-
-class ConvertScalars
-{
- /*
- * Methods to convert each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64)
- * to the corresponding primitive type used for computation.
- *
- * i8, u8, i16, u16, i32 are all converted to int, because java
- * computes in int for byte, short, and int operands.
- *
- * u32, i64 are converted to long, because that is the primitive type that
- * can represent all values of the pixel type.
- *
- * f32 is converted to float
- *
- * f64 is converted to double
- */
- static int from_i8( byte value ) { return value; }
- static int from_u8( byte value ) { return value & 0xff; }
- static int from_i16( short value ) { return value; }
- static int from_u16( short value ) { return value & 0xffff; }
- static int from_i32( int value ) { return value; }
- static long from_u32( int value ) { return value & 0xffffffffL; }
- static long from_i64( long value ) { return value; }
- static float from_f32( float value ) { return value; }
- static double from_f64( double value ) { return value; }
-
- /*
- * Methods to convert int values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
- *
- * The basic to_u8() etc methods don't do any bounds-checking or clamping.
- * They only cast the argument to the output type.
- *
- * The to_u8_clamp() etc methods clamp the argument to the range of the
- * output type.
- *
- * The to_u8_clamp_max() etc methods clamp only to the upper bound output
- * range. This is useful for computations that could possibly overflow but
- * can never underflow (like summing unsigned values).
- */
- static byte to_i8( int value ) { return ( byte ) value; }
- static byte to_i8_clamp_max( int value ) { return to_i8( Math.min( 0x7f, value ) ); }
- static byte to_i8_clamp( int value ) { return to_i8( Math.min( 0x7f, Math.max( -0x80, value ) ) ); }
- static byte to_u8( int value ) { return ( byte ) value; }
- static byte to_u8_clamp_max( int value ) { return to_u8( Math.min( 0xff, value ) ); }
- static byte to_u8_clamp( int value ) { return to_u8( Math.min( 0xff, Math.max( 0, value ) ) ); }
- static short to_i16( int value ) { return ( short ) value; }
- static short to_i16_clamp_max( int value ) { return to_i16( Math.min( 0x7fff, value ) ); }
- static short to_i16_clamp( int value ) { return to_i16( Math.min( 0x7fff, Math.max( -0x8000, value ) ) ); }
- static short to_u16( int value ) { return ( short ) value; }
- static short to_u16_clamp_max( int value ) { return to_u16( Math.min( 0xffff, value ) ); }
- static short to_u16_clamp( int value ) { return to_u16( Math.min( 0xffff, Math.max( 0, value ) ) ); }
- static int to_i32( int value ) { return value; }
- static int to_i32_clamp_max( int value ) { return to_i32( value ); }
- static int to_i32_clamp( int value ) { return to_i32( value ); }
- static int to_u32( int value ) { return value; }
- static int to_u32_clamp_max( int value ) { return to_u32( Math.min( 0xffff_ffffL, value ) ); }
- static int to_u32_clamp( int value ) { return to_u32( Math.min( 0xffff_ffffL, Math.max( 0L, value ) ) ); }
- static long to_i64( int value ) { return value; }
- static long to_i64_clamp_max( int value ) { return to_i64( value ); }
- static long to_i64_clamp( int value ) { return to_i64( value ); }
- static float to_f32( int value ) { return value; }
- static float to_f32_clamp_max( int value ) { return to_f32( value ); }
- static float to_f32_clamp( int value ) { return to_f32( value ); }
- static double to_f64( int value ) { return value; }
- static double to_f64_clamp_max( int value ) { return to_f64( value ); }
- static double to_f64_clamp( int value ) { return to_f64( value ); }
-
- /*
- * Methods to convert long values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
- *
- * The basic to_u8() etc methods don't do any bounds-checking or clamping.
- * They only cast the argument to the output type.
- *
- * The to_u8_clamp() etc methods clamp the argument to the range of the
- * output type.
- *
- * The to_u8_clamp_max() etc methods clamp only to the upper bound output
- * range. This is useful for computations that could possibly overflow but
- * can never underflow (like summing unsigned values).
- */
- static byte to_i8( long value ) { return ( byte ) value; }
- static byte to_i8_clamp_max( long value ) { return to_i8( Math.min( 0x7f, value ) ); }
- static byte to_i8_clamp( long value ) { return to_i8( Math.min( 0x7f, Math.max( -0x80, value ) ) ); }
- static byte to_u8( long value ) { return ( byte ) value; }
- static byte to_u8_clamp_max( long value ) { return to_u8( Math.min( 0xff, value ) ); }
- static byte to_u8_clamp( long value ) { return to_u8( Math.min( 0xff, Math.max( 0, value ) ) ); }
- static short to_i16( long value ) { return ( short ) value; }
- static short to_i16_clamp_max( long value ) { return to_i16( Math.min( 0x7fff, value ) ); }
- static short to_i16_clamp( long value ) { return to_i16( Math.min( 0x7fff, Math.max( -0x8000, value ) ) ); }
- static short to_u16( long value ) { return ( short ) value; }
- static short to_u16_clamp_max( long value ) { return to_u16( Math.min( 0xffff, value ) ); }
- static short to_u16_clamp( long value ) { return to_u16( Math.min( 0xffff, Math.max( 0, value ) ) ); }
- static int to_i32( long value ) { return ( int ) value; }
- static int to_i32_clamp_max( long value ) { return to_i32( Math.min( 0x7fff_ffff, value ) ); }
- static int to_i32_clamp( long value ) { return to_i32( Math.min( 0x7fff_ffff, Math.max( -0x8000_0000, value ) ) ); }
- static int to_u32( long value ) { return ( int ) value; }
- static int to_u32_clamp_max( long value ) { return to_u32( Math.min( 0xffff_ffffL, value ) ); }
- static int to_u32_clamp( long value ) { return to_u32( Math.min( 0xffff_ffffL, Math.max( 0L, value ) ) ); }
- static long to_i64( long value ) { return value; }
- static long to_i64_clamp_max( long value ) { return to_i64( value ); }
- static long to_i64_clamp( long value ) { return to_i64( value ); }
- static float to_f32( long value ) { return ( float ) value; }
- static float to_f32_clamp_max( long value ) { return to_f32( value ); }
- static float to_f32_clamp( long value ) { return to_f32( value ); }
- static double to_f64( long value ) { return value; }
- static double to_f64_clamp_max( long value ) { return to_f64( value ); }
- static double to_f64_clamp( long value ) { return to_f64( value ); }
-
- /*
- * Methods to convert float values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
- *
- * The basic to_u8() etc methods don't do any bounds-checking or clamping.
- * They round the argument and then cast to the output type.
- *
- * The to_u8_clamp() etc methods additionally clamp the argument to the
- * range of the output type.
- *
- * The to_u8_clamp_max() etc methods additionally clamp only to the upper
- * bound output range. This is useful for computations that could possibly
- * overflow but can never underflow (like summing unsigned values).
- */
- static byte to_i8( float value ) { return to_i8( Math.round( value ) ); }
- static byte to_i8_clamp_max( float value ) { return to_i8_clamp_max( Math.round( value ) ); }
- static byte to_i8_clamp( float value ) { return to_i8_clamp( Math.round( value ) ); }
- static byte to_u8( float value ) { return to_u8( Math.round( value ) ); }
- static byte to_u8_clamp_max( float value ) { return to_u8_clamp_max( Math.round( value ) ); }
- static byte to_u8_clamp( float value ) { return to_u8_clamp( Math.round( value ) ); }
- static short to_i16( float value ) { return to_i16( Math.round( value ) ); }
- static short to_i16_clamp_max( float value ) { return to_i16_clamp_max( Math.round( value ) ); }
- static short to_i16_clamp( float value ) { return to_i16_clamp( Math.round( value ) ); }
- static short to_u16( float value ) { return to_u16( Math.round( value ) ); }
- static short to_u16_clamp_max( float value ) { return to_u16_clamp_max( Math.round( value ) ); }
- static short to_u16_clamp( float value ) { return to_u16_clamp( Math.round( value ) ); }
- static int to_i32( float value ) { return to_i32( Math.round( value ) ); }
- static int to_i32_clamp_max( float value ) { return to_i32_clamp_max( Math.round( value ) ); }
- static int to_i32_clamp( float value ) { return to_i32_clamp( Math.round( value ) ); }
- static int to_u32( float value ) { return to_u32( Math.round( ( double ) value ) ); }
- static int to_u32_clamp_max( float value ) { return to_u32_clamp_max( Math.round( ( double ) value ) ); }
- static int to_u32_clamp( float value ) { return to_u32_clamp( Math.round( ( double ) value ) ); }
- static long to_i64( float value ) { return to_i64( Math.round( ( double ) value ) ); }
- static long to_i64_clamp_max( float value ) { return to_i64_clamp_max( Math.round( ( double ) value ) ); }
- static long to_i64_clamp( float value ) { return to_i64_clamp( Math.round( ( double ) value ) ); }
- static float to_f32( float value ) { return value; }
- static float to_f32_clamp_max( float value ) { return to_f32( value ); }
- static float to_f32_clamp( float value ) { return to_f32( value ); }
- static double to_f64( float value ) { return value; }
- static double to_f64_clamp_max( float value ) { return to_f64( value ); }
- static double to_f64_clamp( float value ) { return to_f64( value ); }
-
- /*
- * Methods to convert double values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
- *
- * The basic to_u8() etc methods don't do any bounds-checking or clamping.
- * They round the argument and then cast to the output type.
- *
- * The to_u8_clamp() etc methods additionally clamp the argument to the
- * range of the output type.
- *
- * The to_u8_clamp_max() etc methods additionally clamp only to the upper
- * bound output range. This is useful for computations that could possibly
- * overflow but can never underflow (like summing unsigned values).
- */
- static byte to_i8( double value ) { return to_i8( Math.round( value ) ); }
- static byte to_i8_clamp_max( double value ) { return to_i8_clamp_max( Math.round( value ) ); }
- static byte to_i8_clamp( double value ) { return to_i8_clamp( Math.round( value ) ); }
- static byte to_u8( double value ) { return to_u8( Math.round( value ) ); }
- static byte to_u8_clamp_max( double value ) { return to_u8_clamp_max( Math.round( value ) ); }
- static byte to_u8_clamp( double value ) { return to_u8_clamp( Math.round( value ) ); }
- static short to_i16( double value ) { return to_i16( Math.round( value ) ); }
- static short to_i16_clamp_max( double value ) { return to_i16_clamp_max( Math.round( value ) ); }
- static short to_i16_clamp( double value ) { return to_i16_clamp( Math.round( value ) ); }
- static short to_u16( double value ) { return to_u16( Math.round( value ) ); }
- static short to_u16_clamp_max( double value ) { return to_u16_clamp_max( Math.round( value ) ); }
- static short to_u16_clamp( double value ) { return to_u16_clamp( Math.round( value ) ); }
- static int to_i32( double value ) { return to_i32( Math.round( value ) ); }
- static int to_i32_clamp_max( double value ) { return to_i32_clamp_max( Math.round( value ) ); }
- static int to_i32_clamp( double value ) { return to_i32_clamp( Math.round( value ) ); }
- static int to_u32( double value ) { return to_u32( Math.round( value ) ); }
- static int to_u32_clamp_max( double value ) { return to_u32_clamp_max( Math.round( value ) ); }
- static int to_u32_clamp( double value ) { return to_u32_clamp( Math.round( value ) ); }
- static long to_i64( double value ) { return to_i64( Math.round( value ) ); }
- static long to_i64_clamp_max( double value ) { return to_i64_clamp_max( Math.round( value ) ); }
- static long to_i64_clamp( double value ) { return to_i64_clamp( Math.round( value ) ); }
- static float to_f32( double value ) { return ( float ) value; }
- static float to_f32_clamp_max( double value ) { return to_f32( value ); }
- static float to_f32_clamp( double value ) { return to_f32( value ); }
- static double to_f64( double value ) { return value; }
- static double to_f64_clamp_max( double value ) { return to_f64( value ); }
- static double to_f64_clamp( double value ) { return to_f64( value ); }
-}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/ConverterBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/convert/ConverterBlockProcessor.java
index a3c751d92..dc7f68a3a 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/ConverterBlockProcessor.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/convert/ConverterBlockProcessor.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,17 +33,12 @@
*/
package net.imglib2.algorithm.blocks.convert;
-import static net.imglib2.util.Util.safeInt;
-
-import java.util.Arrays;
import java.util.function.Supplier;
import net.imglib2.Cursor;
-import net.imglib2.Interval;
import net.imglib2.RandomAccess;
+import net.imglib2.algorithm.blocks.AbstractDimensionlessBlockProcessor;
import net.imglib2.algorithm.blocks.BlockProcessor;
-import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
-import net.imglib2.blocks.TempArray;
import net.imglib2.converter.Converter;
import net.imglib2.img.AbstractImg;
import net.imglib2.img.Img;
@@ -52,7 +47,6 @@
import net.imglib2.type.NativeType;
import net.imglib2.type.NativeTypeFactory;
import net.imglib2.util.Cast;
-import net.imglib2.util.Intervals;
/**
* Convert primitive arrays between ImgLib2 {@code NativeType}s using a {@link }Converter}.
@@ -66,7 +60,7 @@
* @param
* output primitive array type, e.g., float[]. Must correspond to T.
*/
-class ConverterBlockProcessor< S extends NativeType< S >, T extends NativeType< T >, I, O > implements BlockProcessor< I, O >
+class ConverterBlockProcessor< S extends NativeType< S >, T extends NativeType< T >, I, O > extends AbstractDimensionlessBlockProcessor< I, O >
{
private final S sourceType;
@@ -74,16 +68,6 @@ class ConverterBlockProcessor< S extends NativeType< S >, T extends NativeType<
private final Supplier< Converter< ? super S, T > > converterSupplier;
- private final TempArray< I > tempArray;
-
- private long[] sourcePos;
-
- private int[] sourceSize;
-
- private int sourceLength;
-
- private final BlockProcessorSourceInterval sourceInterval;
-
private final Converter< ? super S, T > converter;
private final Wrapper< S > wrapSource;
@@ -92,12 +76,11 @@ class ConverterBlockProcessor< S extends NativeType< S >, T extends NativeType<
public ConverterBlockProcessor( final S sourceType, final T targetType, final Supplier< Converter< ? super S, T > > converterSupplier )
{
+ super( sourceType.getNativeTypeFactory().getPrimitiveType() );
this.sourceType = sourceType;
this.targetType = targetType;
this.converterSupplier = converterSupplier;
- tempArray = TempArray.forPrimitiveType( sourceType.getNativeTypeFactory().getPrimitiveType() );
- sourceInterval = new BlockProcessorSourceInterval( this );
converter = converterSupplier.get();
wrapSource = Wrapper.of( sourceType );
wrapTarget = Wrapper.of( targetType );
@@ -105,12 +88,11 @@ public ConverterBlockProcessor( final S sourceType, final T targetType, final Su
private ConverterBlockProcessor( ConverterBlockProcessor< S, T, I, O > convert )
{
+ super( convert );
sourceType = convert.sourceType;
targetType = convert.targetType;
converterSupplier = convert.converterSupplier;
- tempArray = convert.tempArray.newInstance();
- sourceInterval = new BlockProcessorSourceInterval( this );
converter = converterSupplier.get();
wrapSource = Wrapper.of( sourceType );
wrapTarget = Wrapper.of( targetType );
@@ -122,64 +104,13 @@ public BlockProcessor< I, O > independentCopy()
return new ConverterBlockProcessor<>( this );
}
- @Override
- public void setTargetInterval( final Interval interval )
- {
- final int n = interval.numDimensions();
- if ( sourcePos == null || sourcePos.length != n )
- {
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
- }
- interval.min( sourcePos );
- Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
- sourceLength = safeInt( Intervals.numElements( sourceSize ) );
- }
-
- @Override
- public void setTargetInterval( final long[] pos, final int[] size )
- {
- final int n = pos.length;
- if ( sourcePos == null || sourcePos.length != n )
- {
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
- }
- System.arraycopy( pos, 0, sourcePos, 0, n );
- System.arraycopy( size, 0, sourceSize, 0, n );
- sourceLength = safeInt( Intervals.numElements( sourceSize ) );
- }
-
- @Override
- public long[] getSourcePos()
- {
- return sourcePos;
- }
-
- @Override
- public int[] getSourceSize()
- {
- return sourceSize;
- }
-
- @Override
- public Interval getSourceInterval()
- {
- return sourceInterval;
- }
-
- @Override
- public I getSourceBuffer()
- {
- return tempArray.get( sourceLength );
- }
-
@Override
public void compute( final I src, final O dest )
{
final S in = wrapSource.wrap( src );
final T out = wrapTarget.wrap( dest );
- for ( int i = 0; i < sourceLength; i++ )
+ final int len = sourceLength();
+ for ( int i = 0; i < len; i++ )
{
in.index().set( i );
out.index().set( i );
diff --git a/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsample.java b/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsample.java
index 558126c35..ffa7aa936 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsample.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsample.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -38,21 +38,17 @@
import java.util.Arrays;
import net.imglib2.Interval;
-import net.imglib2.algorithm.blocks.BlockProcessor;
-import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
+import net.imglib2.algorithm.blocks.AbstractBlockProcessor;
import net.imglib2.blocks.TempArray;
import net.imglib2.type.PrimitiveType;
import net.imglib2.util.Intervals;
-import net.imglib2.util.Util;
-abstract class AbstractDownsample< T extends AbstractDownsample< T, P >, P > implements BlockProcessor< P, P >
+abstract class AbstractDownsample< T extends AbstractDownsample< T, P >, P > extends AbstractBlockProcessor< P, P >
{
PrimitiveType primitiveType;
final int n;
final int[] destSize;
- final long[] sourcePos;
- final int[] sourceSize;
final boolean[] downsampleInDim;
final int[] downsampleDims;
@@ -64,15 +60,13 @@ abstract class AbstractDownsample< T extends AbstractDownsample< T, P >, P > imp
private final TempArray< P >[] tempArrays;
final int[] tempArraySizes;
- private final BlockProcessorSourceInterval sourceInterval;
-
AbstractDownsample( final boolean[] downsampleInDim, final PrimitiveType primitiveType )
{
- n = downsampleInDim.length;
+ super( primitiveType, downsampleInDim.length );
this.primitiveType = primitiveType;
+
+ n = downsampleInDim.length;
destSize = new int[ n ];
- sourceSize = new int[ n ];
- sourcePos = new long[ n ];
this.downsampleInDim = downsampleInDim;
downsampleDims = downsampleDimIndices( downsampleInDim );
@@ -80,8 +74,6 @@ abstract class AbstractDownsample< T extends AbstractDownsample< T, P >, P > imp
tempArrays = createTempArrays( steps, primitiveType );
tempArraySizes = new int[ steps ];
-
- sourceInterval = new BlockProcessorSourceInterval( this );
}
private static int[] downsampleDimIndices( final boolean[] downsampleInDim )
@@ -114,6 +106,8 @@ private static < P > TempArray< P >[] createTempArrays( final int steps, final P
AbstractDownsample( T downsample )
{
+ super( downsample );
+
// re-use
primitiveType = downsample.primitiveType;
n = downsample.n;
@@ -123,13 +117,10 @@ private static < P > TempArray< P >[] createTempArrays( final int steps, final P
// init empty
destSize = new int[ n ];
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
tempArraySizes = new int[ steps ];
// init new instance
tempArrays = createTempArrays( steps, primitiveType );
- sourceInterval = new BlockProcessorSourceInterval( this );
}
@Override
@@ -166,45 +157,6 @@ protected void recomputeTempArraySizes()
}
}
- @Override
- public void setTargetInterval( final long[] pos, final int[] size )
- {
- boolean destSizeChanged = false;
- for ( int d = 0; d < n; ++d )
- {
- sourcePos[ d ] = downsampleInDim[ d ] ? pos[ d ] * 2 - 1 : pos[ d ];
-
- final int tdim = safeInt( size[ d ] );
- if ( tdim != destSize[ d ] )
- {
- destSize[ d ] = tdim;
- sourceSize[ d ] = downsampleInDim[ d ] ? tdim * 2 + 1 : tdim;
- destSizeChanged = true;
- }
- }
-
- if ( destSizeChanged )
- recomputeTempArraySizes();
- }
-
- @Override
- public int[] getSourceSize()
- {
- return sourceSize;
- }
-
- @Override
- public long[] getSourcePos()
- {
- return sourcePos;
- }
-
- @Override
- public Interval getSourceInterval()
- {
- return sourceInterval;
- }
-
// optional. also other arrays can be passed to compute()
@Override
public P getSourceBuffer()
diff --git a/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleAvgBlock.java b/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleAvgBlock.java
new file mode 100644
index 000000000..93b58ab78
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleAvgBlock.java
@@ -0,0 +1,97 @@
+/*-
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks.downsample;
+
+import static net.imglib2.util.Util.safeInt;
+
+import java.util.Arrays;
+
+import net.imglib2.Interval;
+import net.imglib2.algorithm.blocks.BlockProcessor;
+import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
+import net.imglib2.blocks.TempArray;
+import net.imglib2.type.PrimitiveType;
+import net.imglib2.util.Intervals;
+
+abstract class AbstractDownsampleAvgBlock< T extends AbstractDownsampleAvgBlock< T, P >, P > extends AbstractDownsample< T, P >
+{
+ final int[] downsamplingFactors;
+
+ AbstractDownsampleAvgBlock( final int[] downsamplingFactors, final PrimitiveType primitiveType )
+ {
+ super( downsampleInDim( downsamplingFactors ), primitiveType );
+ this.downsamplingFactors = downsamplingFactors;
+ }
+
+ private static boolean[] downsampleInDim( final int[] downsamplingFactors )
+ {
+ final int n = downsamplingFactors.length;
+ final boolean[] downsampleInDim = new boolean[ n ];
+ for ( int d = 0; d < n; d++ )
+ {
+ if ( downsamplingFactors[ d ] < 1 )
+ throw new IllegalArgumentException();
+ downsampleInDim[ d ] = ( downsamplingFactors[ d ] > 1 );
+ }
+ return downsampleInDim;
+ }
+
+ AbstractDownsampleAvgBlock( T downsample )
+ {
+ super( downsample );
+ downsamplingFactors = downsample.downsamplingFactors;
+ }
+
+ @Override
+ public void setTargetInterval( final Interval interval )
+ {
+ boolean destSizeChanged = false;
+ for ( int d = 0; d < n; ++d )
+ {
+ final long tpos = interval.min( d );
+ sourcePos[ d ] = tpos * downsamplingFactors[ d ];
+
+ final int tdim = safeInt( interval.dimension( d ) );
+ if ( tdim != destSize[ d ] )
+ {
+ destSize[ d ] = tdim;
+ sourceSize[ d ] = tdim * downsamplingFactors[ d ];
+ destSizeChanged = true;
+ }
+ }
+
+ if ( destSizeChanged )
+ recomputeTempArraySizes();
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleHalfPixel.java b/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleHalfPixel.java
index d7372e266..2a5daec58 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleHalfPixel.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/downsample/AbstractDownsampleHalfPixel.java
@@ -71,25 +71,4 @@ public void setTargetInterval( final Interval interval )
if ( destSizeChanged )
recomputeTempArraySizes();
}
-
- @Override
- public void setTargetInterval( final long[] pos, final int[] size )
- {
- boolean destSizeChanged = false;
- for ( int d = 0; d < n; ++d )
- {
- sourcePos[ d ] = downsampleInDim[ d ] ? pos[ d ] * 2 : pos[ d ];
-
- final int tdim = safeInt( size[ d ] );
- if ( tdim != destSize[ d ] )
- {
- destSize[ d ] = tdim;
- sourceSize[ d ] = downsampleInDim[ d ] ? tdim * 2 : tdim;
- destSizeChanged = true;
- }
- }
-
- if ( destSizeChanged )
- recomputeTempArraySizes();
- }
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/downsample/Downsample.java b/src/main/java/net/imglib2/algorithm/blocks/downsample/Downsample.java
index 888f9eae5..3cb5d93ed 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/downsample/Downsample.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/downsample/Downsample.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -34,7 +34,13 @@
package net.imglib2.algorithm.blocks.downsample;
import java.util.Arrays;
-import net.imglib2.algorithm.blocks.convert.ClampType;
+import java.util.function.Function;
+
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ClampType;
+import net.imglib2.algorithm.blocks.ComputationType;
+import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.AvgBlockDouble;
+import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.AvgBlockFloat;
import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.CenterDouble;
import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.CenterFloat;
import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.HalfPixelDouble;
@@ -45,15 +51,86 @@
import net.imglib2.type.PrimitiveType;
import net.imglib2.type.numeric.real.DoubleType;
import net.imglib2.type.numeric.real.FloatType;
+import net.imglib2.util.Util;
import static net.imglib2.type.PrimitiveType.FLOAT;
/**
- * Downsampling by factor 2.
- * Coordinates of downsampled pixel: either centered, or shifted by half a pixel.
+ * Downsampling by factor 2 in selected dimensions.
+ *
+ * Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
+ * {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
+ * IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * For {@code T} other than {@code DoubleType} or {@code FloatType}, the input
+ * will be converted to float/double for computation and the result converted
+ * back to {@code T}. To avoid unnecessary conversions, if you want the result
+ * as {@code FloatType} then you should explicitly convert to {@code FloatType}
+ * before applying the downsampling operator.
+ * This code:
+ *
{@code
+ * RandomAccessible< UnsignedByteType > input;
+ * BlockSupplier< FloatType > downsampled = BlockSupplier.of( input )
+ * .andThen( Convert.convert( new FloatType() ) )
+ * .andThen( Downsample.downsample( Offset.HALF_PIXEL ) );
+ * }
+ * avoids loss of precision and is more efficient than
+ * {@code
+ * RandomAccessible< UnsignedByteType > input;
+ * BlockSupplier< FloatType > downsampled = BlockSupplier.of( input )
+ * .andThen( Downsample.downsample( Offset.HALF_PIXEL ) )
+ * .andThen( Convert.convert( new FloatType() ) );
+ * }
+ *
+ * The {@link #downsample(ComputationType, Offset)} methods return factory
+ * functions that create {@code UnaryBlockOperator} to match the type and
+ * dimensionality of a given input {@code BlockSupplier}. For example, the
+ * following code creates 2D downsampling operator for 2D {@code input}, a 3D
+ * operator for 3D {@code input}, etc.
+ * {@code
+ * RandomAccessible< UnsignedByteType > input;
+ * BlockSupplier< UnsignedByteType > downsampled = BlockSupplier.of( input )
+ * .andThen( Downsample.downsample( Offset.HALF_PIXEL ) );
+ * }
+ *
+ * An {@link Offset} specifies whether downsampled pixels are placed on corners or centers of input pixels:
+ *
+ * - {@link Offset#HALF_PIXEL} means that each downsampled pixel is computed
+ * as the average of 2 neighboring pixels (respectively 4 pixels for 2D, 8
+ * voxels for 3D, etc.) Downsampled pixels are shifted by half a pixel.
+ *
+ * - {@link Offset#CENTERED} means that each downsampled pixel is computed as
+ * the weighted average (with weights {@code {.25, .5, .25}}) of 3 neighboring
+ * pixels (respectively 9 pixels for 2D, 27 voxels for 3D, etc.). Downsampled
+ * pixels are centered on input pixels.
+ *
+ *
+ *
+ * The {@link #downsample(ComputationType, int[])} methods support downsampling
+ * with arbitrary integer factor by averaging blocks of pixels. (With {@code
+ * factors={2,2,2,...}}, this is equivalent to downsampling with {@link
+ * Offset#HALF_PIXEL}).
*/
public class Downsample
{
+ /**
+ * Returns recommended size of the downsampled image, given an input image
+ * of size {@code imgDimensions}. In each dimension the recommended size is
+ * input size / 2, rounding up (e.g., a 5 pixel input image should be
+ * downsampled to a 3 pixel image).
+ *
+ * @param imgDimensions
+ * dimensions of the input image
+ *
+ * @return the recommended size of the downsampled image
+ */
+ public static long[] getDownsampledDimensions( final long[] imgDimensions )
+ {
+ final long[] destSize = new long[ imgDimensions.length ];
+ Arrays.setAll( destSize, d -> ( imgDimensions[ d ] + 1 ) / 2 );
+ return destSize;
+ }
+
/**
* Returns recommended size of the downsampled image, given an input image
* of size {@code imgDimensions}. In each dimension (that should be
@@ -61,30 +138,52 @@ public class Downsample
* a 5 pixel input image should be downsampled to a 3 pixel image).
*
* @param imgDimensions
- * dimensions of the input image
+ * dimensions of the input image
* @param downsampleInDim
- * for each dimension (same length as imgDimensions}: {@code true} if the input image should be down
- * @return
+ * for each dimension {@code d}: if {@code downsampleInDim[d]==true} then
+ * the input image should be downsampled in dimension {@code d}.
+ * {@code downsampleInDim} is expanded or truncated to the necessary size.
+ * For example, if {@code downsampleInDim=={true,true,false}} and the
+ * operator is applied to a 2D image, {@code downsampleInDim} is truncated
+ * to {@code {true, true}}. If the operator is applied to a 5D image, {@code
+ * downsampleInDim} is expanded to {@code {true, true, false, false, false}}
+ *
+ * @return the recommended size of the downsampled image
*/
public static long[] getDownsampledDimensions( final long[] imgDimensions, final boolean[] downsampleInDim )
{
- final int n = imgDimensions.length;
- if ( downsampleInDim.length != n )
- throw new IllegalArgumentException();
- final long[] destSize = new long[ n ];
- Arrays.setAll( destSize, d -> downsampleInDim[ d ] ? ( imgDimensions[ d ] + 1 ) / 2 : imgDimensions[ d ] );
+ final boolean[] dDimsX = Util.expandArray( downsampleInDim, imgDimensions.length );
+ final long[] destSize = new long[ imgDimensions.length ];
+ Arrays.setAll( destSize, d -> dDimsX[ d ] ? ( imgDimensions[ d ] + 1 ) / 2 : imgDimensions[ d ] );
return destSize;
}
/**
- * Specify in which precision should intermediate values be computed. (For
- * {@code AUTO}, the type that can represent the input/output type without
- * loss of precision is picked. That is, {@code FLOAT} for u8, i8, u16, i16,
- * i32, f32, and otherwise {@code DOUBLE} for u32, i64, f64.
+ * Returns recommended size of the downsampled image, given an input image
+ * of size {@code imgDimensions}. In each dimension, the recommended size is
+ * input {@code imgDimension} / {@code downsamplingFactor}, rounding up
+ * (e.g., a 5 pixel input image downsampled with factor 2, should yield a 3
+ * pixel image).
+ *
+ * @param imgDimensions
+ * dimensions of the input image
+ * @param downsamplingFactors
+ * in each dimension {@code d}, {@code downsamplingFactors[d]}
+ * pixels in the input image should be averaged to one output pixel.
+ * {@code downsamplingFactors} is expanded or truncated to the
+ * necessary size. For example, if {@code downsamplingFactors=={2,2,1}} and
+ * the operator is applied to a 2D image, {@code downsamplingFactors} is
+ * truncated to {@code {2, 2}}. If the operator is applied to a 5D image,
+ * {@code downsamplingFactors} is expanded to {@code {2, 2, 1, 1, 1}}
+ *
+ * @return the recommended size of the downsampled image
*/
- public enum ComputationType
+ public static long[] getDownsampledDimensions( final long[] imgDimensions, final int[] downsamplingFactors )
{
- FLOAT, DOUBLE, AUTO
+ final int[] dFactorsX = Util.expandArray( downsamplingFactors, imgDimensions.length );
+ final long[] destSize = new long[ imgDimensions.length ];
+ Arrays.setAll( destSize, d -> ( imgDimensions[ d ] + dFactorsX[ d ] - 1 ) / dFactorsX[ d ] );
+ return destSize;
}
/**
@@ -96,80 +195,260 @@ public enum Offset
* Downsampled pixel centers fall on input pixel centers.
* Each downsampled pixel is computed as the weighted average (with
* weights {@code {.25, .5, .25}}) of 3 neighboring pixels (respectively
- * 9 pixels for 2D, 27 voxels for 3D, etc).
+ * 9 pixels for 2D, 27 voxels for 3D, etc.)
*/
CENTERED,
/**
* Downsampled pixels are shifted by half a pixel.
* Each downsampled pixel is computed as the average of 2 neighboring
- * pixels (respectively 4 pixels for 2D, 8 voxels for 3D, etc).
+ * pixels (respectively 4 pixels for 2D, 8 voxels for 3D, etc.)
*/
HALF_PIXEL
}
/**
- * Create a {@code UnaryBlockOperator} to downsample (by factor 2) blocks of
- * the standard ImgLib2 {@code RealType}. The {@code downsampleInDim}
- * argument spwecifies in which dimensions the input should be downsampled.
+ * Downsample (by factor 2, in all dimensions) blocks of the standard
+ * ImgLib2 {@code RealType}s.
+ *
+ * Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
+ * {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
+ * IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * Precision for intermediate values is chosen as to represent the
+ * input/output type without loss of precision. That is, {@code FLOAT} for
+ * u8, i8, u16, i16, i32, f32, and otherwise {@code DOUBLE} for u32, i64,
+ * f64.
+ *
+ * Downsampled pixels are computed as the average of 2 neighboring pixels
+ * (respectively 4 pixels for 2D, 8 voxels for 3D, etc.) This means
+ * downsampled pixels are shifted by half a pixel.
+ *
+ * The returned factory function creates an operator matching the
+ * type and dimensionality of a given input {@code BlockSupplier}.
+ *
+ * @param
+ * the input/output type
+ *
+ * @return factory for {@code UnaryBlockOperator} to downsample blocks of type {@code T}
+ */
+ public static < T extends NativeType< T > >
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > downsample()
+ {
+ return downsample( Offset.HALF_PIXEL );
+ }
+
+ /**
+ * Downsample (by factor 2, in all dimensions) blocks of the standard
+ * ImgLib2 {@code RealType}s.
*
* Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
* {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
* IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * Precision for intermediate values is chosen as to represent the
+ * input/output type without loss of precision. That is, {@code FLOAT} for
+ * u8, i8, u16, i16, i32, f32, and otherwise {@code DOUBLE} for u32, i64,
+ * f64.
+ *
+ * The returned factory function creates an operator matching the
+ * type and dimensionality of a given input {@code BlockSupplier}.
+ *
+ * @param offset
+ * Specifies where downsampled pixels should be placed.
+ * {@code HALF_PIXEL} means that each downsampled pixel is computed
+ * as the average of 2 neighboring pixels (respectively 4 pixels for
+ * 2D, 8 voxels for 3D, etc.), and downsampled pixels are shifted by
+ * half a pixel.
+ * {@code CENTERED} means that each downsampled pixel is computed as
+ * the weighted average (with weights {@code {.25, .5, .25}}) of 3
+ * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
+ * etc.) Downsampled pixels are centered on input pixels.
+ * @param
+ * the input/output type
+ *
+ * @return factory for {@code UnaryBlockOperator} to downsample blocks of type {@code T}
+ */
+ public static < T extends NativeType< T > >
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > downsample( final Offset offset )
+ {
+ return downsample( ComputationType.AUTO, offset );
+ }
+
+ /**
+ * Downsample (by factor 2, in all dimensions) blocks of the standard
+ * ImgLib2 {@code RealType}s.
+ *
+ * Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
+ * {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
+ * IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * The returned factory function creates an operator matching the
+ * type and dimensionality of a given input {@code BlockSupplier}.
*
- * @param type
- * instance of the input type
* @param computationType
* specifies in which precision intermediate values should be
- * computed. For {@code AUTO}, the type that can represent the
- * input/output type without loss of precision is picked. That is,
- * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
- * DOUBLE} for u32, i64, f64.
+ * computed. For {@code AUTO}, the type that can represent the
+ * input/output type without loss of precision is picked. That is,
+ * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
+ * DOUBLE} for u32, i64, f64.
* @param offset
* Specifies where downsampled pixels should be placed.
* {@code HALF_PIXEL} means that each downsampled pixel is computed
- * as the average of 2 neighboring pixels (respectively 4 pixels for
- * 2D, 8 voxels for 3D, etc), and downsampled pixels are shifted by
- * half a pixel.
- * {@code CENTERED} means that each downsampled pixel is computed as
- * the weighted average (with weights {@code {.25, .5, .25}}) of 3
- * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
- * etc). Downsampled pixels are centered on input pixels.
+ * as the average of 2 neighboring pixels (respectively 4 pixels for
+ * 2D, 8 voxels for 3D, etc.), and downsampled pixels are shifted by
+ * half a pixel.
+ * {@code CENTERED} means that each downsampled pixel is computed as
+ * the weighted average (with weights {@code {.25, .5, .25}}) of 3
+ * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
+ * etc.) Downsampled pixels are centered on input pixels.
+ * @param
+ * the input/output type
+ *
+ * @return factory for {@code UnaryBlockOperator} to downsample blocks of type {@code T}
+ */
+ public static < T extends NativeType< T > >
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > downsample( final ComputationType computationType, final Offset offset )
+ {
+ return s -> {
+ final T type = s.getType();
+ final int n = s.numDimensions();
+ return createOperator( type, computationType, offset, n );
+ };
+ }
+
+ /**
+ * Downsample (by factor 2) blocks of the standard ImgLib2 {@code
+ * RealType}s. The {@code downsampleInDim} argument specifies in which
+ * dimensions the input should be downsampled.
+ *
+ * Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
+ * {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
+ * IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * The returned factory function creates an operator matching the
+ * type and dimensionality of a given input {@code BlockSupplier}.
+ *
+ * @param computationType
+ * specifies in which precision intermediate values should be
+ * computed. For {@code AUTO}, the type that can represent the
+ * input/output type without loss of precision is picked. That is,
+ * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
+ * DOUBLE} for u32, i64, f64.
+ * @param offset
+ * Specifies where downsampled pixels should be placed.
+ * {@code HALF_PIXEL} means that each downsampled pixel is computed
+ * as the average of 2 neighboring pixels (respectively 4 pixels for
+ * 2D, 8 voxels for 3D, etc.), and downsampled pixels are shifted by
+ * half a pixel.
+ * {@code CENTERED} means that each downsampled pixel is computed as
+ * the weighted average (with weights {@code {.25, .5, .25}}) of 3
+ * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
+ * etc.) Downsampled pixels are centered on input pixels.
* @param downsampleInDim
- * for each dimension {@code d}: if {@code downsampleInDim[d]==true} if
- * the input image should be downsampled in dimension {@code d}.
+ * for each dimension {@code d}: if {@code downsampleInDim[d]==true} then
+ * the input image should be downsampled in dimension {@code d}.
+ * {@code downsampleInDim} is expanded or truncated to the necessary size.
+ * For example, if {@code downsampleInDim=={true,true,false}} and the
+ * operator is applied to a 2D image, {@code downsampleInDim} is truncated
+ * to {@code {true, true}}. If the operator is applied to a 5D image, {@code
+ * downsampleInDim} is expanded to {@code {true, true, false, false, false}}
* @param
* the input/output type
*
- * @return {@code UnaryBlockOperator} to downsample blocks of type {@code T}
+ * @return factory for {@code UnaryBlockOperator} to downsample blocks of type {@code T}
*/
public static < T extends NativeType< T > >
- UnaryBlockOperator< T, T > downsample( final T type, final ComputationType computationType, final Offset offset, final boolean[] downsampleInDim )
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > downsample( final ComputationType computationType, final Offset offset, final boolean[] downsampleInDim )
{
- final boolean processAsFloat;
- switch ( computationType )
- {
- case FLOAT:
- processAsFloat = true;
- break;
- case DOUBLE:
- processAsFloat = false;
- break;
- default:
- case AUTO:
- final PrimitiveType pt = type.getNativeTypeFactory().getPrimitiveType();
- processAsFloat = pt.equals( FLOAT ) || pt.getByteCount() < FLOAT.getByteCount();
- break;
- }
- final UnaryBlockOperator< ?, ? > op = processAsFloat
- ? downsampleFloat( offset, downsampleInDim )
- : downsampleDouble( offset, downsampleInDim );
- return op.adaptSourceType( type, ClampType.NONE ).adaptTargetType( type, ClampType.NONE );
+ return s -> {
+ final T type = s.getType();
+ final int n = s.numDimensions();
+ final boolean[] expandedDownsampleInDim = Util.expandArray( downsampleInDim, n );
+ return createOperator( type, computationType, offset, expandedDownsampleInDim );
+ };
}
/**
- * Create a {@code UnaryBlockOperator} to downsample (by factor 2, in all
- * dimensions) blocks of the standard ImgLib2 {@code RealType}.
+ * Downsample (by the given {@code downsamplingFactors}) blocks of the
+ * standard ImgLib2 {@code RealType}s.
+ *
+ * Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
+ * {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
+ * IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * Precision for intermediate values is chosen as to represent the
+ * input/output type without loss of precision. That is, {@code FLOAT} for
+ * u8, i8, u16, i16, i32, f32, and otherwise {@code DOUBLE} for u32, i64,
+ * f64.
+ *
+ * The returned factory function creates an operator matching the
+ * type and dimensionality of a given input {@code BlockSupplier}.
+ *
+ * @param downsamplingFactors
+ * in each dimension {@code d}, {@code downsamplingFactors[d]}
+ * pixels in the input image should be averaged to one output pixel.
+ * {@code downsamplingFactors} is expanded or truncated to the
+ * necessary size. For example, if {@code downsamplingFactors=={2,2,1}} and
+ * the operator is applied to a 2D image, {@code downsamplingFactors} is
+ * truncated to {@code {2, 2}}. If the operator is applied to a 5D image,
+ * {@code downsamplingFactors} is expanded to {@code {2, 2, 1, 1, 1}}
+ * @param
+ * the input/output type
+ *
+ * @return factory for {@code UnaryBlockOperator} to downsample blocks of type {@code T}
+ */
+ public static < T extends NativeType< T > >
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > downsample( final int[] downsamplingFactors )
+ {
+ return downsample( ComputationType.AUTO, downsamplingFactors );
+ }
+
+ /**
+ * Downsample (by the given {@code downsamplingFactors}) blocks of the
+ * standard ImgLib2 {@code RealType}s.
+ *
+ * Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
+ * {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
+ * IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
+ *
+ * The returned factory function creates an operator matching the
+ * type and dimensionality of a given input {@code BlockSupplier}.
+ *
+ * @param computationType
+ * specifies in which precision intermediate values should be
+ * computed. For {@code AUTO}, the type that can represent the
+ * input/output type without loss of precision is picked. That is,
+ * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
+ * DOUBLE} for u32, i64, f64.
+ * @param downsamplingFactors
+ * in each dimension {@code d}, {@code downsamplingFactors[d]}
+ * pixels in the input image should be averaged to one output pixel.
+ * {@code downsamplingFactors} is expanded or truncated to the
+ * necessary size. For example, if {@code downsamplingFactors=={2,2,1}} and
+ * the operator is applied to a 2D image, {@code downsamplingFactors} is
+ * truncated to {@code {2, 2}}. If the operator is applied to a 5D image,
+ * {@code downsamplingFactors} is expanded to {@code {2, 2, 1, 1, 1}}
+ * @param
+ * the input/output type
+ *
+ * @return factory for {@code UnaryBlockOperator} to downsample blocks of type {@code T}
+ */
+ public static < T extends NativeType< T > >
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > downsample( final ComputationType computationType, final int[] downsamplingFactors )
+ {
+ return s -> {
+ final T type = s.getType();
+ final int n = s.numDimensions();
+ final int[] expandedDownsamplingFactors = Util.expandArray( downsamplingFactors, n );
+ return createOperator( type, computationType, expandedDownsamplingFactors );
+ };
+ }
+
+ /**
+ * Create a {@code UnaryBlockOperator} to downsample (by factor 2) blocks of
+ * the standard ImgLib2 {@code RealType}. The {@code downsampleInDim}
+ * argument specifies in which dimensions the input should be downsampled.
*
* Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
* {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
@@ -179,33 +458,70 @@ UnaryBlockOperator< T, T > downsample( final T type, final ComputationType compu
* instance of the input type
* @param computationType
* specifies in which precision intermediate values should be
- * computed. For {@code AUTO}, the type that can represent the
- * input/output type without loss of precision is picked. That is,
- * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
- * DOUBLE} for u32, i64, f64.
+ * computed. For {@code AUTO}, the type that can represent the
+ * input/output type without loss of precision is picked. That is,
+ * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
+ * DOUBLE} for u32, i64, f64.
* @param offset
* Specifies where downsampled pixels should be placed.
* {@code HALF_PIXEL} means that each downsampled pixel is computed
- * as the average of 2 neighboring pixels (respectively 4 pixels for
- * 2D, 8 voxels for 3D, etc), and downsampled pixels are shifted by
- * half a pixel.
- * {@code CENTERED} means that each downsampled pixel is computed as
- * the weighted average (with weights {@code {.25, .5, .25}}) of 3
- * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
- * etc). Downsampled pixels are centered on input pixels.
- * @param numDimensions
- * number of dimensions in input/output image.
+ * as the average of 2 neighboring pixels (respectively 4 pixels for
+ * 2D, 8 voxels for 3D, etc.), and downsampled pixels are shifted by
+ * half a pixel.
+ * {@code CENTERED} means that each downsampled pixel is computed as
+ * the weighted average (with weights {@code {.25, .5, .25}}) of 3
+ * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
+ * etc.) Downsampled pixels are centered on input pixels.
+ * @param downsampleInDim
+ * for each dimension {@code d}: if {@code downsampleInDim[d]==true} then
+ * the input image should be downsampled in dimension {@code d}.
* @param
* the input/output type
*
* @return {@code UnaryBlockOperator} to downsample blocks of type {@code T}
*/
public static < T extends NativeType< T > >
- UnaryBlockOperator< T, T > downsample( final T type, final ComputationType computationType, final Offset offset, final int numDimensions )
+ UnaryBlockOperator< T, T > createOperator( final T type, final ComputationType computationType, final Offset offset, final boolean[] downsampleInDim )
{
- final boolean[] downsampleInDim = new boolean[ numDimensions ];
- Arrays.fill( downsampleInDim, true );
- return downsample( type, computationType, offset, downsampleInDim );
+ final UnaryBlockOperator< ?, ? > op = processAsFloat( computationType, type )
+ ? downsampleFloat( offset, downsampleInDim )
+ : downsampleDouble( offset, downsampleInDim );
+ return op.adaptSourceType( type, ClampType.NONE ).adaptTargetType( type, ClampType.NONE );
+ }
+
+ private static < T extends NativeType< T > > boolean processAsFloat( final ComputationType computationType, final T type )
+ {
+ switch ( computationType )
+ {
+ case FLOAT:
+ return true;
+ case DOUBLE:
+ return true;
+ case AUTO:
+ default:
+ final PrimitiveType pt = type.getNativeTypeFactory().getPrimitiveType();
+ return pt.equals( FLOAT ) || pt.getByteCount() < FLOAT.getByteCount();
+ }
+ }
+
+ private static UnaryBlockOperator< FloatType, FloatType > downsampleFloat( final Offset offset, final boolean[] downsampleInDim )
+ {
+ final FloatType type = new FloatType();
+ final int n = downsampleInDim.length;
+ return new DefaultUnaryBlockOperator<>( type, type, n, n,
+ offset == Offset.HALF_PIXEL
+ ? new HalfPixelFloat( downsampleInDim )
+ : new CenterFloat( downsampleInDim ) );
+ }
+
+ private static UnaryBlockOperator< DoubleType, DoubleType > downsampleDouble( final Offset offset, final boolean[] downsampleInDim )
+ {
+ final DoubleType type = new DoubleType();
+ final int n = downsampleInDim.length;
+ return new DefaultUnaryBlockOperator<>( type, type, n, n,
+ offset == Offset.HALF_PIXEL
+ ? new HalfPixelDouble( downsampleInDim )
+ : new CenterDouble( downsampleInDim ) );
}
/**
@@ -215,86 +531,85 @@ UnaryBlockOperator< T, T > downsample( final T type, final ComputationType compu
* Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
* {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
* IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
- *
- * Precision for intermediate values is chosen as to represent the
- * input/output type without loss of precision is picked. That is, {@code
- * FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code DOUBLE} for
- * u32, i64, f64.
*
* @param type
* instance of the input type
+ * @param computationType
+ * specifies in which precision intermediate values should be
+ * computed. For {@code AUTO}, the type that can represent the
+ * input/output type without loss of precision is picked. That is,
+ * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
+ * DOUBLE} for u32, i64, f64.
* @param offset
* Specifies where downsampled pixels should be placed.
* {@code HALF_PIXEL} means that each downsampled pixel is computed
- * as the average of 2 neighboring pixels (respectively 4 pixels for
- * 2D, 8 voxels for 3D, etc), and downsampled pixels are shifted by
- * half a pixel.
- * {@code CENTERED} means that each downsampled pixel is computed as
- * the weighted average (with weights {@code {.25, .5, .25}}) of 3
- * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
- * etc). Downsampled pixels are centered on input pixels.
+ * as the average of 2 neighboring pixels (respectively 4 pixels for
+ * 2D, 8 voxels for 3D, etc.), and downsampled pixels are shifted by
+ * half a pixel.
+ * {@code CENTERED} means that each downsampled pixel is computed as
+ * the weighted average (with weights {@code {.25, .5, .25}}) of 3
+ * neighboring pixels (respectively 9 pixels for 2D, 27 voxels for 3D,
+ * etc.) Downsampled pixels are centered on input pixels.
* @param numDimensions
- * number of dimensions in input/output image.
+ * number of dimensions in input/output image.
* @param
* the input/output type
*
* @return {@code UnaryBlockOperator} to downsample blocks of type {@code T}
*/
public static < T extends NativeType< T > >
- UnaryBlockOperator< T, T > downsample( final T type, final Offset offset, final int numDimensions )
+ UnaryBlockOperator< T, T > createOperator( final T type, final ComputationType computationType, final Offset offset, final int numDimensions )
{
- return downsample( type, ComputationType.AUTO, offset, numDimensions );
+ final boolean[] downsampleInDim = new boolean[ numDimensions ];
+ Arrays.fill( downsampleInDim, true );
+ return createOperator( type, computationType, offset, downsampleInDim );
}
/**
- * Create a {@code UnaryBlockOperator} to downsample (by factor 2, in all
- * dimensions) blocks of the standard ImgLib2 {@code RealType}.
+ * Create a {@code UnaryBlockOperator} to downsample (by the given {@code
+ * downsamplingFactors}) blocks of the standard ImgLib2 {@code RealType}.
*
* Supported types are {@code UnsignedByteType}, {@code UnsignedShortType},
* {@code UnsignedIntType}, {@code ByteType}, {@code ShortType}, {@code
* IntType}, {@code LongType}, {@code FloatType}, {@code DoubleType}).
- *
- * Precision for intermediate values is chosen as to represent the
- * input/output type without loss of precision is picked. That is, {@code
- * FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code DOUBLE} for
- * u32, i64, f64.
- *
- * Downsampled pixels are computed as the average of 2 neighboring pixels
- * (respectively 4 pixels for 2D, 8 voxels for 3D, etc). This means
- * downsampled pixels are shifted by half a pixel.
*
* @param type
* instance of the input type
- * @param numDimensions
- * number of dimensions in input/output image.
+ * @param computationType
+ * specifies in which precision intermediate values should be
+ * computed. For {@code AUTO}, the type that can represent the
+ * input/output type without loss of precision is picked. That is,
+ * {@code FLOAT} for u8, i8, u16, i16, i32, f32, and otherwise {@code
+ * DOUBLE} for u32, i64, f64.
+ * @param downsamplingFactors
+ * in each dimension {@code d}, {@code downsamplingFactors[d]}
+ * pixels in the input image should be averaged to one output pixel.
* @param
* the input/output type
*
* @return {@code UnaryBlockOperator} to downsample blocks of type {@code T}
*/
public static < T extends NativeType< T > >
- UnaryBlockOperator< T, T > downsample( final T type, final int numDimensions )
+ UnaryBlockOperator< T, T > createOperator( final T type, final ComputationType computationType, final int[] downsamplingFactors )
{
- return downsample( type, ComputationType.AUTO, Offset.HALF_PIXEL, numDimensions );
+ final UnaryBlockOperator< ?, ? > op = processAsFloat( computationType, type )
+ ? downsampleFloat( downsamplingFactors )
+ : downsampleDouble( downsamplingFactors );
+ return op.adaptSourceType( type, ClampType.NONE ).adaptTargetType( type, ClampType.NONE );
}
-
-
- private static UnaryBlockOperator< FloatType, FloatType > downsampleFloat( Offset offset, final boolean[] downsampleInDim )
+ private static UnaryBlockOperator< FloatType, FloatType > downsampleFloat( final int[] downsamplingFactors )
{
final FloatType type = new FloatType();
- return new DefaultUnaryBlockOperator<>( type, type,
- offset == Offset.HALF_PIXEL
- ? new HalfPixelFloat( downsampleInDim )
- : new CenterFloat( downsampleInDim ) );
+ final int n = downsamplingFactors.length;
+ return new DefaultUnaryBlockOperator<>( type, type, n, n, new AvgBlockFloat( downsamplingFactors ) );
}
- private static UnaryBlockOperator< DoubleType, DoubleType > downsampleDouble( Offset offset, final boolean[] downsampleInDim )
+ private static UnaryBlockOperator< DoubleType, DoubleType > downsampleDouble( final int[] downsamplingFactors )
{
final DoubleType type = new DoubleType();
- return new DefaultUnaryBlockOperator<>( type, type,
- offset == Offset.HALF_PIXEL
- ? new HalfPixelDouble( downsampleInDim )
- : new CenterDouble( downsampleInDim ) );
+ final int n = downsamplingFactors.length;
+ return new DefaultUnaryBlockOperator<>( type, type, n, n, new AvgBlockDouble( downsamplingFactors ) );
}
+
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/downsample/DownsampleBlockProcessors.java b/src/main/java/net/imglib2/algorithm/blocks/downsample/DownsampleBlockProcessors.java
index b811a66eb..e1084db28 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/downsample/DownsampleBlockProcessors.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/downsample/DownsampleBlockProcessors.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -140,6 +140,58 @@ void downsample( final double[] source, final int[] destSize, final double[] des
}
}
+ static class AvgBlockFloat extends AbstractDownsampleAvgBlock< AvgBlockFloat, float[] >
+ {
+ public AvgBlockFloat( final int[] downsamplingFactors )
+ {
+ super( downsamplingFactors, FLOAT );
+ }
+
+ private AvgBlockFloat( AvgBlockFloat downsample )
+ {
+ super( downsample );
+ }
+
+ @Override
+ public BlockProcessor< float[], float[] > independentCopy()
+ {
+ return new AvgBlockFloat( this );
+ }
+
+ @Override
+ void downsample( final float[] source, final int[] destSize, final float[] dest, final int dim )
+ {
+ final int factor = this.downsamplingFactors[ dim ];
+ downsample_avgblock_float( source, destSize, dest, dim, factor );
+ }
+ }
+
+ static class AvgBlockDouble extends AbstractDownsampleAvgBlock< AvgBlockDouble, double[] >
+ {
+ public AvgBlockDouble( final int[] downsamplingFactors )
+ {
+ super( downsamplingFactors, DOUBLE );
+ }
+
+ private AvgBlockDouble( AvgBlockDouble downsample )
+ {
+ super( downsample );
+ }
+
+ @Override
+ public BlockProcessor< double[], double[] > independentCopy()
+ {
+ return new AvgBlockDouble( this );
+ }
+
+ @Override
+ void downsample( final double[] source, final int[] destSize, final double[] dest, final int dim )
+ {
+ final int factor = this.downsamplingFactors[ dim ];
+ downsample_avgblock_double( source, destSize, dest, dim, factor );
+ }
+ }
+
private static void downsample_float( final float[] source, final int[] destSize, final float[] dest, final int dim )
{
if ( dim == 0 )
@@ -268,7 +320,7 @@ private static void downsampleX_halfpixel_float( final float[] source, final int
source[ 2 * x + 1 ] );
}
- static void downsampleN_halfpixel_float( final float[] source, final int[] destSize, final float[] dest, final int dim )
+ private static void downsampleN_halfpixel_float( final float[] source, final int[] destSize, final float[] dest, final int dim )
{
int len0 = mulDims( destSize, 0, dim );
int len1 = mulDims( destSize, dim, destSize.length );
@@ -306,7 +358,7 @@ private static void downsampleX_halfpixel_double( final double[] source, final i
source[ 2 * x + 1 ] );
}
- static void downsampleN_halfpixel_double( final double[] source, final int[] destSize, final double[] dest, final int dim )
+ private static void downsampleN_halfpixel_double( final double[] source, final int[] destSize, final double[] dest, final int dim )
{
int len0 = mulDims( destSize, 0, dim );
int len1 = mulDims( destSize, dim, destSize.length );
@@ -327,6 +379,148 @@ private static double avg_double( final double a, final double b )
return 0.5 * ( a + b );
}
+ private static void downsample_avgblock_float( final float[] source, final int[] destSize, final float[] dest, final int dim, final int factor )
+ {
+ if ( factor == 2 )
+ downsample_halfpixel_float( source, destSize, dest, dim );
+ else if ( dim == 0 )
+ downsampleX_avgblock_float( source, destSize, dest, factor );
+ else
+ downsampleN_avgblock_float( source, destSize, dest, dim, factor );
+ }
+
+ private static final int bw_float = 128;
+
+ private static void downsampleX_avgblock_float(
+ final float[] source, final int[] destSize, final float[] dest,
+ final int factor )
+ {
+ final float scale = ( float ) ( 1.0 / factor );
+ final int len = mulDims( destSize, 0, destSize.length );
+
+ final int nBlocks = ( len - 1 ) / bw_float + 1;
+ final int trailing = len - ( nBlocks - 1 ) * bw_float;
+ for ( int b = 0; b < nBlocks; ++b )
+ {
+ final int tob = b * bw_float;
+ final int bwb = ( b == nBlocks - 1 ) ? trailing : bw_float;
+
+ final int sob = factor * tob;
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] = source[ sob + factor * x ];
+ for ( int i = 1; i < factor; ++i )
+ {
+ final int sobi = sob + i;
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] += source[ sobi + factor * x ];
+ }
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] *= scale;
+ }
+ }
+
+ private static void downsampleN_avgblock_float(
+ final float[] source, final int[] destSize, final float[] dest,
+ final int dim, final int factor )
+ {
+ final float scale = ( float ) ( 1.0 / factor );
+ int len0 = mulDims( destSize, 0, dim );
+ int len1 = mulDims( destSize, dim, destSize.length );
+
+ final int nBlocks = ( len0 - 1 ) / bw_float + 1;
+ final int trailing = len0 - ( nBlocks - 1 ) * bw_float;
+ for ( int y = 0; y < len1; ++y )
+ {
+ final int destOffset = y * len0;
+ for ( int b = 0; b < nBlocks; ++b )
+ {
+ final int tob = b * bw_float + destOffset;
+ final int bwb = ( b == nBlocks - 1 ) ? trailing : bw_float;
+ final int sob = factor * destOffset + b * bw_float;
+ System.arraycopy( source, sob, dest, tob, bwb );
+ for ( int i = 1; i < factor; ++i )
+ {
+ final int sobi = sob + i * len0;
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] += source[ sobi + x ];
+ }
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] *= scale;
+ }
+ }
+ }
+
+ private static void downsample_avgblock_double( final double[] source, final int[] destSize, final double[] dest, final int dim, final int factor )
+ {
+ if ( factor == 2 )
+ downsample_halfpixel_double( source, destSize, dest, dim );
+ else if ( dim == 0 )
+ downsampleX_avgblock_double( source, destSize, dest, factor );
+ else
+ downsampleN_avgblock_double( source, destSize, dest, dim, factor );
+ }
+
+ private static final int bw_double = 64;
+
+ private static void downsampleX_avgblock_double(
+ final double[] source, final int[] destSize, final double[] dest,
+ final int factor )
+ {
+ final double scale = ( double ) ( 1.0 / factor );
+ final int len = mulDims( destSize, 0, destSize.length );
+
+ final int nBlocks = ( len - 1 ) / bw_double + 1;
+ final int trailing = len - ( nBlocks - 1 ) * bw_double;
+ for ( int b = 0; b < nBlocks; ++b )
+ {
+ final int tob = b * bw_double;
+ final int bwb = ( b == nBlocks - 1 ) ? trailing : bw_double;
+
+ final int sob = factor * tob;
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] = source[ sob + factor * x ];
+ for ( int i = 1; i < factor; ++i )
+ {
+ final int sobi = sob + i;
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] += source[ sobi + factor * x ];
+ }
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] *= scale;
+ }
+ }
+
+ private static void downsampleN_avgblock_double(
+ final double[] source, final int[] destSize, final double[] dest,
+ final int dim, final int factor )
+ {
+ final double scale = ( double ) ( 1.0 / factor );
+ int len0 = mulDims( destSize, 0, dim );
+ int len1 = mulDims( destSize, dim, destSize.length );
+
+ final int nBlocks = ( len0 - 1 ) / bw_double + 1;
+ final int trailing = len0 - ( nBlocks - 1 ) * bw_double;
+ for ( int y = 0; y < len1; ++y )
+ {
+ final int destOffset = y * len0;
+ for ( int b = 0; b < nBlocks; ++b )
+ {
+ final int tob = b * bw_double + destOffset;
+ final int bwb = ( b == nBlocks - 1 ) ? trailing : bw_double;
+ final int sob = factor * destOffset + b * bw_double;
+ System.arraycopy( source, sob, dest, tob, bwb );
+ for ( int i = 1; i < factor; ++i )
+ {
+ final int sobi = sob + i * len0;
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] += source[ sobi + x ];
+ }
+ for ( int x = 0; x < bwb; ++x )
+ dest[ tob + x ] *= scale;
+ }
+ }
+ }
+
private static int mulDims( int[] dims, int from, int to )
{
int product = 1;
diff --git a/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java
index bae9c6718..e61cd6592 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -40,6 +40,7 @@
import net.imglib2.Interval;
import net.imglib2.RealInterval;
+import net.imglib2.algorithm.blocks.AbstractBlockProcessor;
import net.imglib2.algorithm.blocks.BlockProcessor;
import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
import net.imglib2.blocks.TempArray;
@@ -56,7 +57,7 @@
* @param
* input/output primitive array type (i.e., float[] or double[])
*/
-abstract class AbstractTransformProcessor< T extends AbstractTransformProcessor< T, P >, P > implements BlockProcessor< P, P >
+abstract class AbstractTransformProcessor< T extends AbstractTransformProcessor< T, P >, P > extends AbstractBlockProcessor< P, P >
{
PrimitiveType primitiveType;
@@ -68,48 +69,28 @@ abstract class AbstractTransformProcessor< T extends AbstractTransformProcessor<
final int[] destSize;
- final long[] sourcePos;
-
- final int[] sourceSize;
-
- private int sourceLength;
-
- private final BlockProcessorSourceInterval sourceInterval;
-
- private final TempArray< P > tempArray;
-
- Supplier< T > threadSafeSupplier;
-
AbstractTransformProcessor( final int n, final Transform.Interpolation interpolation, final PrimitiveType primitiveType )
{
+ super( primitiveType, n );
this.primitiveType = primitiveType;
this.interpolation = interpolation;
this.n = n;
destPos = new long[ n ];
destSize = new int[ n ];
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
- sourceInterval = new BlockProcessorSourceInterval( this );
- tempArray = TempArray.forPrimitiveType( primitiveType );
}
AbstractTransformProcessor( T transform )
{
+ super( transform );
+
// re-use
primitiveType = transform.primitiveType;
interpolation = transform.interpolation;
n = transform.n;
- threadSafeSupplier = transform.threadSafeSupplier;
// init empty
destPos = new long[ n ];
destSize = new int[ n ];
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
-
- // init new instance
- sourceInterval = new BlockProcessorSourceInterval( this );
- tempArray = TempArray.forPrimitiveType( primitiveType );
}
abstract RealInterval estimateBounds( Interval interval );
@@ -132,30 +113,5 @@ public void setTargetInterval( final Interval interval )
Arrays.setAll( sourceSize, d -> ( int ) ( ( long ) Math.floor( bounds.realMax( d ) + 0.5 ) - sourcePos[ d ] ) + 2 );
break;
}
- sourceLength = safeInt( Intervals.numElements( sourceSize ) );
- }
-
- @Override
- public long[] getSourcePos()
- {
- return sourcePos;
- }
-
- @Override
- public int[] getSourceSize()
- {
- return sourceSize;
- }
-
- @Override
- public Interval getSourceInterval()
- {
- return sourceInterval;
- }
-
- @Override
- public P getSourceBuffer()
- {
- return tempArray.get( sourceLength );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/transform/Transform.java b/src/main/java/net/imglib2/algorithm/blocks/transform/Transform.java
index 0722835c4..3e9e9f5b2 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/transform/Transform.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/transform/Transform.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,9 +33,11 @@
*/
package net.imglib2.algorithm.blocks.transform;
+import net.imglib2.algorithm.blocks.BlockSupplier;
import net.imglib2.algorithm.blocks.DefaultUnaryBlockOperator;
import net.imglib2.algorithm.blocks.UnaryBlockOperator;
-import net.imglib2.algorithm.blocks.convert.ClampType;
+import net.imglib2.algorithm.blocks.ClampType;
+import net.imglib2.algorithm.blocks.ComputationType;
import net.imglib2.realtransform.AffineGet;
import net.imglib2.realtransform.AffineTransform2D;
import net.imglib2.realtransform.AffineTransform3D;
@@ -46,21 +48,13 @@
import static net.imglib2.type.PrimitiveType.FLOAT;
+import java.util.function.Function;
+
/**
* Affine transform in 2D/3D with n-linear or nearest-neighbor interpolation.
*/
public class Transform
{
- /**
- * Specify in which precision should intermediate values be computed. (For
- * {@code AUTO}, the type that can represent the input/output type without
- * loss of precision is picked. That is, {@code FLOAT} for u8, i8, u16, i16,
- * i32, f32, and otherwise {@code DOUBLE} for u32, i64, f64.
- */
- public enum ComputationType
- {
- FLOAT, DOUBLE, AUTO
- }
public enum Interpolation
{
@@ -69,13 +63,14 @@ public enum Interpolation
}
/**
- * Create a {@code UnaryBlockOperator} to interpolate and affine-transform
- * blocks of the standard ImgLib2 {@code RealType}s.
+ * Interpolate and affine-transform blocks of the standard ImgLib2 {@code
+ * RealType}s.
*
* Only 2D and 3D are supported currently!
+ *
+ * The returned factory function creates an operator matching the type a
+ * given input {@code BlockSupplier}.
*
- * @param type
- * instance of the input type
* @param transformFromSource
* a 2D or 3D affine transform
* @param interpolation
@@ -83,12 +78,43 @@ public enum Interpolation
* @param
* the input/output type
*
- * @return {@code UnaryBlockOperator} to affine-transform blocks of type {@code T}
+ * @return factory for {@code UnaryBlockOperator} to affine-transform blocks of type {@code T}
+ */
+ public static < T extends NativeType< T > >
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > affine( final AffineGet transformFromSource, Interpolation interpolation )
+ {
+ return affine( transformFromSource, interpolation, ComputationType.AUTO );
+ }
+
+ /**
+ * Interpolate and affine-transform blocks of the standard ImgLib2 {@code
+ * RealType}s.
+ *
+ * Only 2D and 3D are supported currently!
+ *
+ * The returned factory function creates an operator matching the type a
+ * given input {@code BlockSupplier}.
+ *
+ * @param transformFromSource
+ * a 2D or 3D affine transform
+ * @param interpolation
+ * which interpolation method to use
+ * @param computationType
+ * For n-linear interpolation, this specifies in which precision
+ * intermediate values should be computed. For {@code AUTO}, the type
+ * that can represent the input/output type without loss of precision
+ * is picked. That is, {@code FLOAT} for u8, i8, u16, i16, i32, f32,
+ * and otherwise {@code DOUBLE} for u32, i64, f64. For nearest-neighbor
+ * interpolation, {@code computationType} is not used.
+ * @param
+ * the input/output type
+ *
+ * @return factory for {@code UnaryBlockOperator} to affine-transform blocks of type {@code T}
*/
public static < T extends NativeType< T > >
- UnaryBlockOperator< T, T > affine( final T type, final AffineGet transformFromSource, Interpolation interpolation )
+ Function< BlockSupplier< T >, UnaryBlockOperator< T, T > > affine( final AffineGet transformFromSource, Interpolation interpolation, final ComputationType computationType )
{
- return affine( type, transformFromSource, interpolation, ComputationType.AUTO );
+ return s -> createAffineOperator( s.getType(), transformFromSource, interpolation, computationType, ClampType.CLAMP );
}
/**
@@ -116,7 +142,7 @@ UnaryBlockOperator< T, T > affine( final T type, final AffineGet transformFromSo
* @return {@code UnaryBlockOperator} to affine-transform blocks of type {@code T}
*/
public static < T extends NativeType< T > >
- UnaryBlockOperator< T, T > affine( final T type, final AffineGet transformFromSource, Interpolation interpolation, final ComputationType computationType )
+ UnaryBlockOperator< T, T > createAffineOperator( final T type, final AffineGet transformFromSource, Interpolation interpolation, final ComputationType computationType, final ClampType clampType )
{
final int n = transformFromSource.numDimensions();
if ( n < 2 || n > 3 ) {
@@ -145,7 +171,7 @@ UnaryBlockOperator< T, T > affine( final T type, final AffineGet transformFromSo
final UnaryBlockOperator< ?, ? > op = processAsFloat
? _affine( transformToSource, interpolation, new FloatType() )
: _affine( transformToSource, interpolation, new DoubleType() );
- return op.adaptSourceType( type, ClampType.NONE ).adaptTargetType( type, ClampType.CLAMP );
+ return op.adaptSourceType( type, ClampType.NONE ).adaptTargetType( type, clampType );
}
else // if ( interpolation == Interpolation.NEARESTNEIGHBOR )
{
@@ -155,8 +181,9 @@ UnaryBlockOperator< T, T > affine( final T type, final AffineGet transformFromSo
private static < T extends NativeType< T > > UnaryBlockOperator< T, T > _affine( final AffineGet transform, final Interpolation interpolation, final T type )
{
- return new DefaultUnaryBlockOperator<>( type, type,
- transform.numDimensions() == 2
+ final int n = transform.numDimensions();
+ return new DefaultUnaryBlockOperator<>( type, type, n, n,
+ n == 2
? new Affine2DProcessor<>( ( AffineTransform2D ) transform, interpolation, type.getNativeTypeFactory().getPrimitiveType() )
: new Affine3DProcessor<>( ( AffineTransform3D ) transform, interpolation, type.getNativeTypeFactory().getPrimitiveType() ) );
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine2D.java b/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine2D.java
index 2009e8c31..6ee36f49e 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine2D.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine2D.java
@@ -36,6 +36,11 @@
import net.imglib2.type.PrimitiveType;
import net.imglib2.util.Cast;
+/*
+ * This is autogenerated source code -- DO NOT EDIT. Instead, edit the
+ * corresponding template in templates/ and rerun bin/generate.groovy.
+ */
+
/**
* Compute a destination X line for 2D.
diff --git a/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine3D.java b/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine3D.java
index 25a5d0885..dafd7ba7d 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine3D.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/transform/TransformLine3D.java
@@ -36,6 +36,11 @@
import net.imglib2.type.PrimitiveType;
import net.imglib2.util.Cast;
+/*
+ * This is autogenerated source code -- DO NOT EDIT. Instead, edit the
+ * corresponding template in templates/ and rerun bin/generate.groovy.
+ */
+
/**
* Compute a destination X line for 2D.
diff --git a/src/main/java/net/imglib2/algorithm/blocks/util/ConvertScalars.java b/src/main/java/net/imglib2/algorithm/blocks/util/ConvertScalars.java
new file mode 100644
index 000000000..4d90bc9aa
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/util/ConvertScalars.java
@@ -0,0 +1,276 @@
+/*
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks.util;
+
+/*
+ * This is autogenerated source code -- DO NOT EDIT. Instead, edit the
+ * corresponding template in templates/ and rerun bin/generate.groovy.
+ */
+
+public class ConvertScalars
+{
+ /*
+ * Methods to convert each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64)
+ * to the corresponding primitive type used for computation.
+ *
+ * i8, u8, i16, u16, i32 are all converted to int, because java
+ * computes in int for byte, short, and int operands.
+ *
+ * u32, i64 are converted to long, because that is the primitive type that
+ * can represent all values of the pixel type.
+ *
+ * f32 is converted to float
+ *
+ * f64 is converted to double
+ */
+ public static int from_i8( byte value ) { return value; }
+ public static int from_u8( byte value ) { return value & 0xff; }
+ public static int from_i16( short value ) { return value; }
+ public static int from_u16( short value ) { return value & 0xffff; }
+ public static int from_i32( int value ) { return value; }
+ public static long from_u32( int value ) { return value & 0xffffffffL; }
+ public static long from_i64( long value ) { return value; }
+ public static float from_f32( float value ) { return value; }
+ public static double from_f64( double value ) { return value; }
+
+ /*
+ * Methods to convert int values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
+ *
+ * The basic to_u8() etc methods don't do any bounds-checking or clamping.
+ * They only cast the argument to the output type.
+ *
+ * The to_u8_clamp() etc methods clamp the argument to the range of the
+ * output type.
+ *
+ * The to_u8_clamp_max() etc methods clamp only to the upper bound output
+ * range. This is useful for computations that could possibly overflow but
+ * can never underflow (like summing unsigned values).
+ *
+ * The to_u8_clamp_min() etc methods clamp only to the lower bound output
+ * range. This is useful for computations that could possibly underflow but
+ * can never overflow (like subtracting unsigned values).
+ */
+ public static byte to_i8( int value ) { return ( byte ) value; }
+ public static byte to_i8_clamp_max( int value ) { return to_i8( Math.min( 0x7f, value ) ); }
+ public static byte to_i8_clamp_min( int value ) { return to_i8( Math.max( -0x80, value ) ); }
+ public static byte to_i8_clamp( int value ) { return to_i8( Math.min( 0x7f, Math.max( -0x80, value ) ) ); }
+ public static byte to_u8( int value ) { return ( byte ) value; }
+ public static byte to_u8_clamp_max( int value ) { return to_u8( Math.min( 0xff, value ) ); }
+ public static byte to_u8_clamp_min( int value ) { return to_u8( Math.max( 0, value ) ); }
+ public static byte to_u8_clamp( int value ) { return to_u8( Math.min( 0xff, Math.max( 0, value ) ) ); }
+ public static short to_i16( int value ) { return ( short ) value; }
+ public static short to_i16_clamp_max( int value ) { return to_i16( Math.min( 0x7fff, value ) ); }
+ public static short to_i16_clamp_min( int value ) { return to_i16( Math.max( -0x8000, value ) ); }
+ public static short to_i16_clamp( int value ) { return to_i16( Math.min( 0x7fff, Math.max( -0x8000, value ) ) ); }
+ public static short to_u16( int value ) { return ( short ) value; }
+ public static short to_u16_clamp_max( int value ) { return to_u16( Math.min( 0xffff, value ) ); }
+ public static short to_u16_clamp_min( int value ) { return to_u16( Math.max( 0, value ) ); }
+ public static short to_u16_clamp( int value ) { return to_u16( Math.min( 0xffff, Math.max( 0, value ) ) ); }
+ public static int to_i32( int value ) { return value; }
+ public static int to_i32_clamp_max( int value ) { return to_i32( value ); }
+ public static int to_i32_clamp_min( int value ) { return to_i32( value ); }
+ public static int to_i32_clamp( int value ) { return to_i32( value ); }
+ public static int to_u32( int value ) { return value; }
+ public static int to_u32_clamp_max( int value ) { return to_u32( Math.min( 0xffff_ffffL, value ) ); }
+ public static int to_u32_clamp_min( int value ) { return to_u32( Math.max( 0L, value ) ); }
+ public static int to_u32_clamp( int value ) { return to_u32( Math.min( 0xffff_ffffL, Math.max( 0L, value ) ) ); }
+ public static long to_i64( int value ) { return value; }
+ public static long to_i64_clamp_max( int value ) { return to_i64( value ); }
+ public static long to_i64_clamp_min( int value ) { return to_i64( value ); }
+ public static long to_i64_clamp( int value ) { return to_i64( value ); }
+ public static float to_f32( int value ) { return value; }
+ public static float to_f32_clamp_max( int value ) { return to_f32( value ); }
+ public static float to_f32_clamp_min( int value ) { return to_f32( value ); }
+ public static float to_f32_clamp( int value ) { return to_f32( value ); }
+ public static double to_f64( int value ) { return value; }
+ public static double to_f64_clamp_max( int value ) { return to_f64( value ); }
+ public static double to_f64_clamp_min( int value ) { return to_f64( value ); }
+ public static double to_f64_clamp( int value ) { return to_f64( value ); }
+
+ /*
+ * Methods to convert long values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
+ *
+ * The basic to_u8() etc methods don't do any bounds-checking or clamping.
+ * They only cast the argument to the output type.
+ *
+ * The to_u8_clamp() etc methods clamp the argument to the range of the
+ * output type.
+ *
+ * The to_u8_clamp_max() etc methods clamp only to the upper bound output
+ * range. This is useful for computations that could possibly overflow but
+ * can never underflow (like summing unsigned values).
+ *
+ * The to_u8_clamp_min() etc methods clamp only to the lower bound output
+ * range. This is useful for computations that could possibly underflow but
+ * can never overflow (like subtracting unsigned values).
+ */
+ public static byte to_i8( long value ) { return ( byte ) value; }
+ public static byte to_i8_clamp_max( long value ) { return to_i8( Math.min( 0x7f, value ) ); }
+ public static byte to_i8_clamp_min( long value ) { return to_i8( Math.max( -0x80, value ) ); }
+ public static byte to_i8_clamp( long value ) { return to_i8( Math.min( 0x7f, Math.max( -0x80, value ) ) ); }
+ public static byte to_u8( long value ) { return ( byte ) value; }
+ public static byte to_u8_clamp_max( long value ) { return to_u8( Math.min( 0xff, value ) ); }
+ public static byte to_u8_clamp_min( long value ) { return to_u8( Math.max( 0, value ) ); }
+ public static byte to_u8_clamp( long value ) { return to_u8( Math.min( 0xff, Math.max( 0, value ) ) ); }
+ public static short to_i16( long value ) { return ( short ) value; }
+ public static short to_i16_clamp_max( long value ) { return to_i16( Math.min( 0x7fff, value ) ); }
+ public static short to_i16_clamp_min( long value ) { return to_i16( Math.max( -0x8000, value ) ); }
+ public static short to_i16_clamp( long value ) { return to_i16( Math.min( 0x7fff, Math.max( -0x8000, value ) ) ); }
+ public static short to_u16( long value ) { return ( short ) value; }
+ public static short to_u16_clamp_max( long value ) { return to_u16( Math.min( 0xffff, value ) ); }
+ public static short to_u16_clamp_min( long value ) { return to_u16( Math.max( 0, value ) ); }
+ public static short to_u16_clamp( long value ) { return to_u16( Math.min( 0xffff, Math.max( 0, value ) ) ); }
+ public static int to_i32( long value ) { return ( int ) value; }
+ public static int to_i32_clamp_max( long value ) { return to_i32( Math.min( 0x7fff_ffff, value ) ); }
+ public static int to_i32_clamp_min( long value ) { return to_i32( Math.max( -0x8000_0000, value ) ); }
+ public static int to_i32_clamp( long value ) { return to_i32( Math.min( 0x7fff_ffff, Math.max( -0x8000_0000, value ) ) ); }
+ public static int to_u32( long value ) { return ( int ) value; }
+ public static int to_u32_clamp_max( long value ) { return to_u32( Math.min( 0xffff_ffffL, value ) ); }
+ public static int to_u32_clamp_min( long value ) { return to_u32( Math.max( 0L, value ) ); }
+ public static int to_u32_clamp( long value ) { return to_u32( Math.min( 0xffff_ffffL, Math.max( 0L, value ) ) ); }
+ public static long to_i64( long value ) { return value; }
+ public static long to_i64_clamp_max( long value ) { return to_i64( value ); }
+ public static long to_i64_clamp_min( long value ) { return to_i64( value ); }
+ public static long to_i64_clamp( long value ) { return to_i64( value ); }
+ public static float to_f32( long value ) { return ( float ) value; }
+ public static float to_f32_clamp_max( long value ) { return to_f32( value ); }
+ public static float to_f32_clamp_min( long value ) { return to_f32( value ); }
+ public static float to_f32_clamp( long value ) { return to_f32( value ); }
+ public static double to_f64( long value ) { return value; }
+ public static double to_f64_clamp_max( long value ) { return to_f64( value ); }
+ public static double to_f64_clamp_min( long value ) { return to_f64( value ); }
+ public static double to_f64_clamp( long value ) { return to_f64( value ); }
+
+ /*
+ * Methods to convert float values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
+ *
+ * The basic to_u8() etc methods don't do any bounds-checking or clamping.
+ * They round the argument and then cast to the output type.
+ *
+ * The to_u8_clamp_max() etc methods clamp only to the upper bound output
+ * range. This is useful for computations that could possibly overflow but
+ * can never underflow (like summing unsigned values).
+ *
+ * The to_u8_clamp_min() etc methods clamp only to the lower bound output
+ * range. This is useful for computations that could possibly underflow but
+ * can never overflow (like subtracting unsigned values).
+ */
+ public static byte to_i8( float value ) { return to_i8( Math.round( value ) ); }
+ public static byte to_i8_clamp_max( float value ) { return to_i8_clamp_max( Math.round( value ) ); }
+ public static byte to_i8_clamp_min( float value ) { return to_i8_clamp_min( Math.round( value ) ); }
+ public static byte to_i8_clamp( float value ) { return to_i8_clamp( Math.round( value ) ); }
+ public static byte to_u8( float value ) { return to_u8( Math.round( value ) ); }
+ public static byte to_u8_clamp_max( float value ) { return to_u8_clamp_max( Math.round( value ) ); }
+ public static byte to_u8_clamp_min( float value ) { return to_u8_clamp_min( Math.round( value ) ); }
+ public static byte to_u8_clamp( float value ) { return to_u8_clamp( Math.round( value ) ); }
+ public static short to_i16( float value ) { return to_i16( Math.round( value ) ); }
+ public static short to_i16_clamp_max( float value ) { return to_i16_clamp_max( Math.round( value ) ); }
+ public static short to_i16_clamp_min( float value ) { return to_i16_clamp_min( Math.round( value ) ); }
+ public static short to_i16_clamp( float value ) { return to_i16_clamp( Math.round( value ) ); }
+ public static short to_u16( float value ) { return to_u16( Math.round( value ) ); }
+ public static short to_u16_clamp_max( float value ) { return to_u16_clamp_max( Math.round( value ) ); }
+ public static short to_u16_clamp_min( float value ) { return to_u16_clamp_min( Math.round( value ) ); }
+ public static short to_u16_clamp( float value ) { return to_u16_clamp( Math.round( value ) ); }
+ public static int to_i32( float value ) { return to_i32( Math.round( value ) ); }
+ public static int to_i32_clamp_max( float value ) { return to_i32_clamp_max( Math.round( value ) ); }
+ public static int to_i32_clamp_min( float value ) { return to_i32_clamp_min( Math.round( value ) ); }
+ public static int to_i32_clamp( float value ) { return to_i32_clamp( Math.round( value ) ); }
+ public static int to_u32( float value ) { return to_u32( Math.round( ( double ) value ) ); }
+ public static int to_u32_clamp_max( float value ) { return to_u32_clamp_max( Math.round( ( double ) value ) ); }
+ public static int to_u32_clamp_min( float value ) { return to_u32_clamp_min( Math.round( ( double ) value ) ); }
+ public static int to_u32_clamp( float value ) { return to_u32_clamp( Math.round( ( double ) value ) ); }
+ public static long to_i64( float value ) { return to_i64( Math.round( ( double ) value ) ); }
+ public static long to_i64_clamp_max( float value ) { return to_i64_clamp_max( Math.round( ( double ) value ) ); }
+ public static long to_i64_clamp_min( float value ) { return to_i64_clamp_min( Math.round( ( double ) value ) ); }
+ public static long to_i64_clamp( float value ) { return to_i64_clamp( Math.round( ( double ) value ) ); }
+ public static float to_f32( float value ) { return value; }
+ public static float to_f32_clamp_max( float value ) { return to_f32( value ); }
+ public static float to_f32_clamp_min( float value ) { return to_f32( value ); }
+ public static float to_f32_clamp( float value ) { return to_f32( value ); }
+ public static double to_f64( float value ) { return value; }
+ public static double to_f64_clamp_max( float value ) { return to_f64( value ); }
+ public static double to_f64_clamp_min( float value ) { return to_f64( value ); }
+ public static double to_f64_clamp( float value ) { return to_f64( value ); }
+
+ /*
+ * Methods to convert double values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
+ *
+ * The basic to_u8() etc methods don't do any bounds-checking or clamping.
+ * They round the argument and then cast to the output type.
+ *
+ * The to_u8_clamp_max() etc methods clamp only to the upper bound output
+ * range. This is useful for computations that could possibly overflow but
+ * can never underflow (like summing unsigned values).
+ *
+ * The to_u8_clamp_min() etc methods clamp only to the lower bound output
+ * range. This is useful for computations that could possibly underflow but
+ * can never overflow (like subtracting unsigned values).
+ */
+ public static byte to_i8( double value ) { return to_i8( Math.round( value ) ); }
+ public static byte to_i8_clamp_max( double value ) { return to_i8_clamp_max( Math.round( value ) ); }
+ public static byte to_i8_clamp_min( double value ) { return to_i8_clamp_min( Math.round( value ) ); }
+ public static byte to_i8_clamp( double value ) { return to_i8_clamp( Math.round( value ) ); }
+ public static byte to_u8( double value ) { return to_u8( Math.round( value ) ); }
+ public static byte to_u8_clamp_max( double value ) { return to_u8_clamp_max( Math.round( value ) ); }
+ public static byte to_u8_clamp_min( double value ) { return to_u8_clamp_min( Math.round( value ) ); }
+ public static byte to_u8_clamp( double value ) { return to_u8_clamp( Math.round( value ) ); }
+ public static short to_i16( double value ) { return to_i16( Math.round( value ) ); }
+ public static short to_i16_clamp_max( double value ) { return to_i16_clamp_max( Math.round( value ) ); }
+ public static short to_i16_clamp_min( double value ) { return to_i16_clamp_min( Math.round( value ) ); }
+ public static short to_i16_clamp( double value ) { return to_i16_clamp( Math.round( value ) ); }
+ public static short to_u16( double value ) { return to_u16( Math.round( value ) ); }
+ public static short to_u16_clamp_max( double value ) { return to_u16_clamp_max( Math.round( value ) ); }
+ public static short to_u16_clamp_min( double value ) { return to_u16_clamp_min( Math.round( value ) ); }
+ public static short to_u16_clamp( double value ) { return to_u16_clamp( Math.round( value ) ); }
+ public static int to_i32( double value ) { return to_i32( Math.round( value ) ); }
+ public static int to_i32_clamp_max( double value ) { return to_i32_clamp_max( Math.round( value ) ); }
+ public static int to_i32_clamp_min( double value ) { return to_i32_clamp_min( Math.round( value ) ); }
+ public static int to_i32_clamp( double value ) { return to_i32_clamp( Math.round( value ) ); }
+ public static int to_u32( double value ) { return to_u32( Math.round( value ) ); }
+ public static int to_u32_clamp_max( double value ) { return to_u32_clamp_max( Math.round( value ) ); }
+ public static int to_u32_clamp_min( double value ) { return to_u32_clamp_min( Math.round( value ) ); }
+ public static int to_u32_clamp( double value ) { return to_u32_clamp( Math.round( value ) ); }
+ public static long to_i64( double value ) { return to_i64( Math.round( value ) ); }
+ public static long to_i64_clamp_max( double value ) { return to_i64_clamp_max( Math.round( value ) ); }
+ public static long to_i64_clamp_min( double value ) { return to_i64_clamp_min( Math.round( value ) ); }
+ public static long to_i64_clamp( double value ) { return to_i64_clamp( Math.round( value ) ); }
+ public static float to_f32( double value ) { return ( float ) value; }
+ public static float to_f32_clamp_max( double value ) { return to_f32( value ); }
+ public static float to_f32_clamp_min( double value ) { return to_f32( value ); }
+ public static float to_f32_clamp( double value ) { return to_f32( value ); }
+ public static double to_f64( double value ) { return value; }
+ public static double to_f64_clamp_max( double value ) { return to_f64( value ); }
+ public static double to_f64_clamp_min( double value ) { return to_f64( value ); }
+ public static double to_f64_clamp( double value ) { return to_f64( value ); }
+}
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleARGBPlayground.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleARGBPlayground.java
new file mode 100644
index 000000000..24acd8634
--- /dev/null
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleARGBPlayground.java
@@ -0,0 +1,100 @@
+/*-
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks.downsample;
+
+import java.util.Arrays;
+
+import bdv.cache.SharedQueue;
+import bdv.util.Bdv;
+import bdv.util.BdvFunctions;
+import bdv.util.BdvSource;
+import bdv.util.volatiles.VolatileViews;
+import bdv.viewer.DisplayMode;
+import ij.IJ;
+import ij.ImagePlus;
+import net.imglib2.algorithm.blocks.BlockAlgoUtils;
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
+import net.imglib2.img.Img;
+import net.imglib2.img.display.imagej.ImageJFunctions;
+import net.imglib2.type.NativeType;
+import net.imglib2.type.numeric.ARGBType;
+import net.imglib2.type.numeric.integer.UnsignedByteType;
+import net.imglib2.view.Views;
+
+public class DownsampleARGBPlayground
+{
+ public static void main( String[] args )
+ {
+ System.setProperty("apple.laf.useScreenMenuBar", "true");
+
+ final String fn = "/Users/pietzsch/workspace/data/first-instar-brain.tif";
+ final ImagePlus imp = IJ.openImage( fn );
+ final Img< ARGBType > img = ImageJFunctions.wrapRGBA( imp );
+
+ final BdvSource bdv = BdvFunctions.show(
+ img,
+ "img",
+ Bdv.options() );
+ bdv.setDisplayRange( 0, 255 );
+
+ final boolean[] downsampleInDim = { true, true, true };
+ final long[] downsampledDimensions = Downsample.getDownsampledDimensions( img.dimensionsAsLongArray(), downsampleInDim );
+ final int[] cellDimensions = { 64, 64, 64 };
+
+ final double[] calib = new double[ 3 ];
+ Arrays.setAll(calib, d -> downsampleInDim[ d ] ? 2 : 1 );
+
+ BlockSupplier< ARGBType > blocks = BlockSupplier
+ .of( Views.extendMirrorDouble( img ) )
+ .andThen( Downsample.downsample( Offset.HALF_PIXEL ) )
+ .tile( 16 );
+
+ final Img< ARGBType > downsampled = BlockAlgoUtils.cellImg(
+ blocks,
+ downsampledDimensions,
+ cellDimensions );
+
+ final BdvSource out = BdvFunctions.show(
+ VolatileViews.wrapAsVolatile( downsampled, new SharedQueue( 32, 1 ) ),
+ "downsampled half-pixel",
+ Bdv.options()
+ .addTo( bdv )
+ .sourceTransform( calib )
+ );
+ out.setDisplayRange( 0, 255 );
+
+
+ }
+}
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleAvgBdvPlayground.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleAvgBdvPlayground.java
new file mode 100644
index 000000000..2b516b9b7
--- /dev/null
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleAvgBdvPlayground.java
@@ -0,0 +1,100 @@
+/*-
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks.downsample;
+
+import java.util.Arrays;
+
+import bdv.cache.SharedQueue;
+import bdv.util.Bdv;
+import bdv.util.BdvFunctions;
+import bdv.util.BdvSource;
+import bdv.util.volatiles.VolatileViews;
+import bdv.viewer.DisplayMode;
+import ij.IJ;
+import ij.ImagePlus;
+import net.imglib2.algorithm.blocks.BlockAlgoUtils;
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ComputationType;
+import net.imglib2.img.Img;
+import net.imglib2.img.display.imagej.ImageJFunctions;
+import net.imglib2.type.numeric.ARGBType;
+import net.imglib2.type.numeric.integer.UnsignedByteType;
+import net.imglib2.view.Views;
+
+public class DownsampleAvgBdvPlayground
+{
+ public static void main( String[] args )
+ {
+ System.setProperty("apple.laf.useScreenMenuBar", "true");
+
+ final String fn = "/Users/pietzsch/workspace/data/e002_stack_fused-8bit.tif";
+ final ImagePlus imp = IJ.openImage( fn );
+ final Img< UnsignedByteType > img = ImageJFunctions.wrapByte( imp );
+
+ final BdvSource bdv = BdvFunctions.show(
+ img,
+ "img",
+ Bdv.options() );
+ bdv.setColor( new ARGBType( 0xffffff ) );
+ bdv.setDisplayRange( 0, 255 );
+ bdv.getBdvHandle().getViewerPanel().setDisplayMode( DisplayMode.SINGLE );
+
+ final int[] downsamplingFactors = { 3, 3, 2 };
+ final long[] downsampledDimensions = Downsample.getDownsampledDimensions( img.dimensionsAsLongArray(), downsamplingFactors );
+ final int[] cellDimensions = { 64, 64, 64 };
+
+ final double[] calib = new double[ 3 ];
+ Arrays.setAll(calib, d -> downsamplingFactors[ d ] );
+
+ BlockSupplier< UnsignedByteType > blocks = BlockSupplier
+ .of( Views.extendMirrorDouble( img ) )
+ .andThen( Downsample.downsample( ComputationType.FLOAT, downsamplingFactors ) )
+ .tile( 16 );
+
+ final Img< UnsignedByteType > downsampled = BlockAlgoUtils.cellImg(
+ blocks,
+ downsampledDimensions,
+ cellDimensions );
+
+ final BdvSource out = BdvFunctions.show(
+ VolatileViews.wrapAsVolatile( downsampled, new SharedQueue( 32, 1 ) ),
+ "downsampled avg-block",
+ Bdv.options()
+ .addTo( bdv )
+ .sourceTransform( calib )
+ );
+ out.setDisplayRange( 0, 255 );
+ out.setColor( new ARGBType( 0x00ff00 ) );
+ }
+}
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvBenchmark.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvBenchmark.java
index f18ee2e4c..c776e8e5e 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvBenchmark.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvBenchmark.java
@@ -44,10 +44,10 @@
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
-import net.imglib2.algorithm.blocks.downsample.Downsample.ComputationType;
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ComputationType;
import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
import net.imglib2.algorithm.blocks.BlockAlgoUtils;
-import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.cache.img.CellLoader;
import net.imglib2.cache.img.ReadOnlyCachedCellImgFactory;
@@ -130,17 +130,10 @@ public void benchmarkBdv()
@Benchmark
public void benchmarkDownsampleDouble()
{
- final PrimitiveBlocks< UnsignedByteType > blocks = PrimitiveBlocks.of( Views.extendBorder( raw ) );
-
-// final CellLoader< DoubleType> loader = cellLoader( blocks, net.imglib2.algorithm.blocks.downsample.Downsample.downsample( new DoubleType(), ComputationType.AUTO, Offset.CENTERED, downsampleInDim ) );
-// final CachedCellImg< DoubleType, ? > downsampleDouble = new ReadOnlyCachedCellImgFactory().create(
-// downsampledDimensions,
-// new DoubleType(),
-// loader,
-// ReadOnlyCachedCellImgOptions.options().cellDimensions( cellDimensions).cacheType( BOUNDED ).maxCacheSize( 1 ) );
- final CachedCellImg< UnsignedByteType, ? > downsampleDouble = BlockAlgoUtils.cellImg(
- blocks, Downsample.downsample( new UnsignedByteType(), ComputationType.DOUBLE, Offset.HALF_PIXEL, downsampleInDim ), new UnsignedByteType(), downsampledDimensions, cellDimensions );
-
+ final BlockSupplier< UnsignedByteType > blocks = BlockSupplier
+ .of( Views.extendBorder( raw ) )
+ .andThen( Downsample.downsample( ComputationType.DOUBLE, Offset.HALF_PIXEL, downsampleInDim ) );
+ final CachedCellImg< UnsignedByteType, ? > downsampleDouble = BlockAlgoUtils.cellImg( blocks, downsampledDimensions, cellDimensions );
touchAllCellsSingleThreaded( downsampleDouble );
downsampleDouble.getCache().invalidateAll();
}
@@ -148,17 +141,10 @@ public void benchmarkDownsampleDouble()
@Benchmark
public void benchmarkDownsampleFloat()
{
- final PrimitiveBlocks< UnsignedByteType > blocksFloat = PrimitiveBlocks.of( Views.extendBorder( raw ) );
-
-// final CellLoader< FloatType> loader = cellLoader( blocksFloat, net.imglib2.algorithm.blocks.downsample.Downsample.downsample( new FloatType(), ComputationType.AUTO, Offset.CENTERED, downsampleInDim ) );
-// final CachedCellImg< FloatType, ? > downsampleFloat = new ReadOnlyCachedCellImgFactory().create(
-// downsampledDimensions,
-// new FloatType(),
-// loader,
-// ReadOnlyCachedCellImgOptions.options().cellDimensions( cellDimensions).cacheType( BOUNDED ).maxCacheSize( 1 ) );
- final CachedCellImg< UnsignedByteType, ? > downsampleFloat = BlockAlgoUtils.cellImg(
- blocksFloat, Downsample.downsample( new UnsignedByteType(), ComputationType.FLOAT, Offset.HALF_PIXEL, downsampleInDim ), new UnsignedByteType(), downsampledDimensions, cellDimensions );
-
+ final BlockSupplier< UnsignedByteType > blocks = BlockSupplier
+ .of( Views.extendBorder( raw ) )
+ .andThen( Downsample.downsample( ComputationType.FLOAT, Offset.HALF_PIXEL, downsampleInDim ) );
+ final CachedCellImg< UnsignedByteType, ? > downsampleFloat = BlockAlgoUtils.cellImg( blocks, downsampledDimensions, cellDimensions );
touchAllCellsSingleThreaded( downsampleFloat );
downsampleFloat.getCache().invalidateAll();
}
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground.java
index b71586f27..b4bb038f5 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground.java
@@ -43,10 +43,10 @@
import ij.ImagePlus;
import java.util.Arrays;
import net.imglib2.RandomAccess;
-import net.imglib2.algorithm.blocks.downsample.Downsample.ComputationType;
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ComputationType;
import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
import net.imglib2.algorithm.blocks.BlockAlgoUtils;
-import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.cache.img.CellLoader;
import net.imglib2.cache.img.ReadOnlyCachedCellImgFactory;
@@ -58,8 +58,6 @@
import net.imglib2.view.ExtendedRandomAccessibleInterval;
import net.imglib2.view.Views;
-import static net.imglib2.algorithm.blocks.downsample.Downsample.downsample;
-
public class DownsampleBdvPlayground
{
public static void main( String[] args )
@@ -83,7 +81,6 @@ public static void main( String[] args )
final int[] cellDimensions = { 64, 64, 64 };
final ExtendedRandomAccessibleInterval< UnsignedByteType, Img< UnsignedByteType > > extended = Views.extendBorder( img );
- final PrimitiveBlocks< UnsignedByteType > blocks = PrimitiveBlocks.of( extended );
final UnsignedByteType type = new UnsignedByteType();
final double[] calib = new double[ 3 ];
@@ -121,13 +118,10 @@ public static void main( String[] args )
out.setColor( new ARGBType( 0xff0000 ) );
-
- final CachedCellImg< UnsignedByteType, ? > downsampled2 = BlockAlgoUtils.cellImg(
- blocks,
- downsample( type, ComputationType.AUTO, Offset.HALF_PIXEL, downsampleInDim ),
- type,
- downsampledDimensions,
- cellDimensions );
+ final BlockSupplier< UnsignedByteType > blocks = BlockSupplier
+ .of( extended )
+ .andThen( Downsample.downsample( ComputationType.AUTO, Offset.HALF_PIXEL, downsampleInDim ) );
+ final CachedCellImg< UnsignedByteType, ? > downsampled2 = BlockAlgoUtils.cellImg( blocks, downsampledDimensions, cellDimensions );
final BdvSource out2 = BdvFunctions.show(
VolatileViews.wrapAsVolatile( downsampled2 ),
"downsampled half-pixel",
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground2.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground2.java
index ef2ecdd1c..73eb1fa2f 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground2.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBdvPlayground2.java
@@ -11,13 +11,13 @@
* %%
* 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
@@ -45,10 +45,7 @@
import ij.ImagePlus;
import net.imglib2.algorithm.blocks.BlockAlgoUtils;
import net.imglib2.algorithm.blocks.BlockSupplier;
-import net.imglib2.algorithm.blocks.UnaryBlockOperator;
-import net.imglib2.algorithm.blocks.convert.Convert;
import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
-import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.img.Img;
import net.imglib2.img.display.imagej.ImageJFunctions;
import net.imglib2.type.numeric.ARGBType;
@@ -80,12 +77,10 @@ public static void main( String[] args )
final double[] calib = new double[ 3 ];
Arrays.setAll(calib, d -> downsampleInDim[ d ] ? 2 : 1 );
- final BlockSupplier< UnsignedByteType > blocks = BlockSupplier
+ BlockSupplier< UnsignedByteType > blocks = BlockSupplier
.of( Views.extendMirrorDouble( img ) )
- .andThen( Downsample.downsample(
- img.getType(),
- Offset.HALF_PIXEL,
- img.numDimensions() ) );
+ .andThen( Downsample.downsample( Offset.HALF_PIXEL ) )
+ .tile( 16 );
final Img< UnsignedByteType > downsampled = BlockAlgoUtils.cellImg(
blocks,
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java
new file mode 100644
index 000000000..05e147dee
--- /dev/null
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java
@@ -0,0 +1,154 @@
+/*-
+ * #%L
+ * ImgLib2: a general-purpose, multidimensional image processing library.
+ * %%
+ * Copyright (C) 2009 - 2024 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.algorithm.blocks.downsample;
+
+import java.util.Arrays;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import net.imglib2.FinalInterval;
+import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.AvgBlockFloat;
+import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.HalfPixelFloat;
+import net.imglib2.util.Intervals;
+import net.imglib2.util.Util;
+
+@State( Scope.Benchmark )
+@Warmup( iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS )
+@Measurement( iterations = 20, time = 100, timeUnit = TimeUnit.MILLISECONDS )
+@BenchmarkMode( Mode.AverageTime )
+@OutputTimeUnit( TimeUnit.MILLISECONDS )
+@Fork( 1 )
+public class DownsampleBenchmarkFull2
+{
+ int[] imgSize;
+
+ int[] outputSize;
+ int[] inputSize;
+ float[] inputF;
+ float[] outputF;
+ HalfPixelFloat halfPixelFloat;
+ AvgBlockFloat avgBlockFloat;
+
+// @Param( { "X", "Y", "Z", "XYZ" } )
+ @Param( { "XYZ" } )
+// @Param( { "Z" } )
+ public String scenario;
+
+// @Param( { "128", "256", "512" } )
+ @Param( { "128" } )
+ public int size;
+
+
+ @Setup(Level.Trial)
+ public void setUp() {
+ final Random random = new Random( 1 );
+
+ final int n = 3;
+ inputSize = new int[ n ];
+ outputSize = new int[ n ];
+
+ boolean[] downsampleInDim = null;
+ switch ( scenario )
+ {
+ case "X":
+ downsampleInDim = new boolean[] { true, false, false };
+ break;
+ case "Y":
+ downsampleInDim = new boolean[] { false, true, false };
+ break;
+ case "Z":
+ downsampleInDim = new boolean[] { false, false, true };
+ break;
+ case "XYZ":
+ downsampleInDim = new boolean[] { true, true, true };
+ break;
+ }
+ int[] downsamplingFactors = new int[ downsampleInDim.length ];
+ for ( int d = 0; d < downsamplingFactors.length; d++ )
+ downsamplingFactors[ d ] = downsampleInDim[ d ] ? 2 : 1;
+
+ imgSize = new int[] { size, size, size };
+
+ final long[] destSize = Downsample.getDownsampledDimensions( Util.int2long( imgSize ), downsampleInDim );
+ System.out.println( "destSize = " + Arrays.toString( destSize ) );
+ Arrays.setAll( outputSize, d -> ( int ) destSize[ d ] );
+
+ halfPixelFloat = new HalfPixelFloat( downsampleInDim );
+ halfPixelFloat.setTargetInterval( new FinalInterval( Util.int2long( outputSize ) ) );
+
+ System.arraycopy( halfPixelFloat.getSourceSize(), 0, inputSize, 0, inputSize.length );
+ inputF = new float[ ( int ) Intervals.numElements( inputSize ) ];
+ for ( int i = 0; i < inputF.length; i++ )
+ inputF[ i ] = random.nextFloat();
+ outputF = new float[ ( int ) Intervals.numElements( outputSize ) ];
+
+ avgBlockFloat = new AvgBlockFloat( downsamplingFactors );
+ avgBlockFloat.setTargetInterval( new FinalInterval( Util.int2long( outputSize ) ) );
+ }
+
+// @Benchmark
+ public void benchmarkHalfPixelFloat()
+ {
+ halfPixelFloat.compute( inputF, outputF );
+ }
+
+ @Benchmark
+ public void benchmarkAvgBlockFloat()
+ {
+ avgBlockFloat.compute( inputF, outputF );
+ }
+
+ public static void main( String... args ) throws RunnerException
+ {
+ Options options = new OptionsBuilder().include( DownsampleBenchmarkFull2.class.getSimpleName() + "\\." ).build();
+ new Runner( options ).run();
+ }
+}
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleDoublePlayground.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleDoublePlayground.java
index f894b9b48..94060cb6c 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleDoublePlayground.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleDoublePlayground.java
@@ -43,10 +43,8 @@
import java.util.Arrays;
import net.imglib2.algorithm.blocks.BlockSupplier;
-import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.CenterDouble;
-import net.imglib2.algorithm.blocks.downsample.DownsampleBlockProcessors.HalfPixelDouble;
import net.imglib2.algorithm.blocks.BlockAlgoUtils;
-import net.imglib2.blocks.PrimitiveBlocks;
+import net.imglib2.algorithm.blocks.ComputationType;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.converter.Converters;
import net.imglib2.converter.RealDoubleConverter;
@@ -83,10 +81,8 @@ public static void main( String[] args )
final int[] cellDimensions = { 64, 64, 64 };
final CachedCellImg< DoubleType, ? > downsampled = BlockAlgoUtils.cellImg(
blocks.andThen( Downsample.downsample(
- new DoubleType(),
- Downsample.ComputationType.DOUBLE,
- Downsample.Offset.CENTERED,
- 3 )
+ ComputationType.DOUBLE,
+ Downsample.Offset.CENTERED )
),
downsampledDimensions, cellDimensions );
@@ -103,10 +99,8 @@ public static void main( String[] args )
final CachedCellImg< DoubleType, ? > downsampled2 = BlockAlgoUtils.cellImg(
blocks.andThen( Downsample.downsample(
- new DoubleType(),
- Downsample.ComputationType.DOUBLE,
- Downsample.Offset.HALF_PIXEL,
- 3 )
+ ComputationType.DOUBLE,
+ Downsample.Offset.HALF_PIXEL )
),
downsampledDimensions, cellDimensions );
final BdvSource out2 = BdvFunctions.show(
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleMemProfile.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleMemProfile.java
index 2334596bf..b577503db 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleMemProfile.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleMemProfile.java
@@ -36,13 +36,14 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+
import net.imglib2.Cursor;
import net.imglib2.IterableInterval;
import net.imglib2.RandomAccessibleInterval;
-import net.imglib2.algorithm.blocks.downsample.Downsample.ComputationType;
-import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
import net.imglib2.algorithm.blocks.BlockAlgoUtils;
-import net.imglib2.blocks.PrimitiveBlocks;
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ComputationType;
+import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.img.array.ArrayImgs;
import net.imglib2.img.cell.AbstractCellImg;
@@ -76,16 +77,12 @@ public DownsampleMemProfile()
public void benchmarkDownsampleFloat()
{
- final PrimitiveBlocks< UnsignedByteType > blocksFloat = PrimitiveBlocks.of( Views.extendBorder( raw ) );
+ final BlockSupplier< UnsignedByteType > blocksFloat = BlockSupplier
+ .of( Views.extendBorder( raw ) )
+ .andThen( Downsample.downsample(ComputationType.FLOAT, Offset.CENTERED, downsampleInDim ) );
-// final CellLoader< FloatType> loader = cellLoader( blocksFloat, net.imglib2.algorithm.blocks.downsample.Downsample.downsample( new FloatType(), ComputationType.AUTO, Offset.CENTERED, downsampleInDim ) );
-// final CachedCellImg< FloatType, ? > downsampleFloat = new ReadOnlyCachedCellImgFactory().create(
-// downsampledDimensions,
-// new FloatType(),
-// loader,
-// ReadOnlyCachedCellImgOptions.options().cellDimensions( cellDimensions).cacheType( BOUNDED ).maxCacheSize( 1 ) );
final CachedCellImg< UnsignedByteType, ? > downsampleFloat = BlockAlgoUtils.cellImg(
- blocksFloat, Downsample.downsample( new UnsignedByteType(), ComputationType.FLOAT, Offset.CENTERED, downsampleInDim ), new UnsignedByteType(), downsampledDimensions, cellDimensions );
+ blocksFloat, downsampledDimensions, cellDimensions );
// touchAllCellsSingleThreaded( downsampleFloat );
touchAllCells( downsampleFloat );
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleUnsignedBytePlayground.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleUnsignedBytePlayground.java
index faee7e4ea..1b6a9fab4 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleUnsignedBytePlayground.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleUnsignedBytePlayground.java
@@ -41,10 +41,11 @@
import ij.IJ;
import ij.ImagePlus;
import java.util.Arrays;
-import net.imglib2.algorithm.blocks.downsample.Downsample.ComputationType;
+
+import net.imglib2.algorithm.blocks.BlockSupplier;
+import net.imglib2.algorithm.blocks.ComputationType;
import net.imglib2.algorithm.blocks.downsample.Downsample.Offset;
import net.imglib2.algorithm.blocks.BlockAlgoUtils;
-import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.img.Img;
import net.imglib2.img.display.imagej.ImageJFunctions;
@@ -52,8 +53,6 @@
import net.imglib2.type.numeric.integer.UnsignedByteType;
import net.imglib2.view.Views;
-import static net.imglib2.algorithm.blocks.downsample.Downsample.downsample;
-
public class DownsampleUnsignedBytePlayground
{
public static void main( String[] args )
@@ -76,13 +75,10 @@ public static void main( String[] args )
final long[] downsampledDimensions = Downsample.getDownsampledDimensions( img.dimensionsAsLongArray(), downsampleInDim );
final int[] cellDimensions = { 64, 64, 64 };
- final PrimitiveBlocks< UnsignedByteType > blocks = PrimitiveBlocks.of( Views.extendBorder( img ) );
- final UnsignedByteType type = new UnsignedByteType();
+ final BlockSupplier< UnsignedByteType > blocks = BlockSupplier.of( Views.extendBorder( img ) );
final CachedCellImg< UnsignedByteType, ? > downsampled = BlockAlgoUtils.cellImg(
- blocks,
- downsample( type, ComputationType.AUTO, Offset.CENTERED, downsampleInDim ),
- type,
+ blocks.andThen( Downsample.downsample( ComputationType.AUTO, Offset.CENTERED, downsampleInDim ) ),
downsampledDimensions,
cellDimensions );
@@ -98,9 +94,7 @@ public static void main( String[] args )
out.setColor( new ARGBType( 0xff0000 ) );
final CachedCellImg< UnsignedByteType, ? > downsampled2 = BlockAlgoUtils.cellImg(
- blocks,
- downsample( type, ComputationType.AUTO, Offset.HALF_PIXEL, downsampleInDim ),
- type,
+ blocks.andThen( Downsample.downsample( ComputationType.AUTO, Offset.HALF_PIXEL, downsampleInDim ) ),
downsampledDimensions,
cellDimensions );
final BdvSource out2 = BdvFunctions.show(
diff --git a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java
index 2f102050b..ae0ab159b 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java
@@ -43,6 +43,8 @@
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.RealRandomAccessible;
import net.imglib2.algorithm.blocks.BlockProcessor;
+import net.imglib2.algorithm.blocks.ClampType;
+import net.imglib2.algorithm.blocks.ComputationType;
import net.imglib2.algorithm.blocks.transform.Transform.Interpolation;
import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.converter.Converters;
@@ -151,15 +153,18 @@ public void blocksnaiveSetup()
Views.extendZero( img ),
new RealFloatConverter<>(),
new FloatType() ) );
- processor = Transform.affine( new FloatType(), affine, Interpolation.NLINEAR ).blockProcessor();
+ final FloatType type2 = new FloatType();
+ processor = Transform.createAffineOperator( type2, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP ).blockProcessor();
blocksDouble = PrimitiveBlocks.of(
Converters.convert(
Views.extendZero( img ),
new RealDoubleConverter<>(),
new DoubleType() ) );
- processorDouble = Transform.affine( new DoubleType(), affine, Interpolation.NLINEAR ).blockProcessor();
+ final DoubleType type1 = new DoubleType();
+ processorDouble = Transform.createAffineOperator( type1, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP ).blockProcessor();
blocksUnsignedByte = PrimitiveBlocks.of( Views.extendZero( img ) );
- processorUnsignedByte = Transform.affine( new UnsignedByteType(), affine, Interpolation.NLINEAR ).blockProcessor();
+ final UnsignedByteType type = new UnsignedByteType();
+ processorUnsignedByte = Transform.createAffineOperator( type, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP ).blockProcessor();
blocksFloat();
blocksDouble();
blocksUnsignedByte();
diff --git a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java
index 8f78f45dc..b85b9d534 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java
@@ -40,13 +40,11 @@
import ij.ImagePlus;
import java.util.Arrays;
import net.imglib2.Cursor;
-import net.imglib2.FinalInterval;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.RealRandomAccessible;
-import net.imglib2.algorithm.blocks.BlockProcessor;
+import net.imglib2.algorithm.blocks.BlockSupplier;
import net.imglib2.algorithm.blocks.transform.Transform.Interpolation;
-import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.img.Img;
import net.imglib2.img.array.ArrayImg;
import net.imglib2.img.array.ArrayImgFactory;
@@ -105,19 +103,13 @@ public static void main( String[] args )
final int[] size = { 64, 64, 64 };
final RandomAccessibleInterval< UnsignedByteType > copy = copy( transformed, new UnsignedByteType(), min, size );
-
- final PrimitiveBlocks< UnsignedByteType > blocks = PrimitiveBlocks.of( Views.extendZero( img ) );
- BlockProcessor< byte[], byte[] > processor = Transform.affine( new UnsignedByteType(), affine, Interpolation.NLINEAR ).blockProcessor();
- long[] max = new long[ size.length ];
- Arrays.setAll( max, d -> min[ d ] + size[ d ] - 1 );
- processor.setTargetInterval( FinalInterval.wrap( min, max ) );
- blocks.copy( processor.getSourcePos(), processor.getSourceBuffer(), processor.getSourceSize() );
+ final BlockSupplier< UnsignedByteType > blocks = BlockSupplier
+ .of( Views.extendZero( img ) )
+ .andThen( Transform.affine( affine, Interpolation.NLINEAR ) );
final byte[] dest = new byte[ ( int ) Intervals.numElements( size ) ];
- processor.compute( processor.getSourceBuffer(), dest );
+ blocks.copy( min, dest, size );
final RandomAccessibleInterval< UnsignedByteType > destImg = ArrayImgs.unsignedBytes( dest, size[ 0 ], size[ 1 ], size[ 2 ] );
-
-
// ----------------------------------------------
final BdvSource bdv2 = BdvFunctions.show(
diff --git a/templates/main/java/net/imglib2/algorithm/blocks/ConvertLoops.vm b/templates/main/java/net/imglib2/algorithm/blocks/ConvertLoops.vm
index 4d673e277..51e764c57 100644
--- a/templates/main/java/net/imglib2/algorithm/blocks/ConvertLoops.vm
+++ b/templates/main/java/net/imglib2/algorithm/blocks/ConvertLoops.vm
@@ -11,13 +11,13 @@
* %%
* 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
@@ -33,15 +33,17 @@
*/
package net.imglib2.algorithm.blocks.convert;
+import net.imglib2.algorithm.blocks.ClampType;
import net.imglib2.algorithm.blocks.util.UnaryOperatorType;
import net.imglib2.util.Cast;
#parse( "PixelTypes.vm" )
#foreach( $t1 in $types )
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.from_${t1};
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_${t1};
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_${t1}_clamp;
-import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_${t1}_clamp_max;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.from_${t1};
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_${t1};
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_${t1}_clamp;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_${t1}_clamp_min;
+import static net.imglib2.algorithm.blocks.util.ConvertScalars.to_${t1}_clamp_max;
#end
/*
@@ -51,52 +53,63 @@ import static net.imglib2.algorithm.blocks.convert.ConvertScalars.to_${t1}_clamp
class ConvertLoops
{
- static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type )
- {
- return get( type, ClampType.NONE );
- }
+ static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type )
+ {
+ return get( type, ClampType.NONE );
+ }
- static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type, ClampType clampType )
- {
- switch ( clampType )
- {
- case NONE:
- switch( type )
- {
+ static < I, O > ConvertLoop< I, O > get( UnaryOperatorType type, ClampType clampType )
+ {
+ switch ( clampType )
+ {
+ case NONE:
+ switch( type )
+ {
+#foreach( $t1 in $types )
+#foreach( $t2 in $types )
+ case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}.INSTANCE );
+#end
+#end
+ default:
+ throw new IllegalArgumentException();
+ }
+ case CLAMP:
+ switch( type )
+ {
#foreach( $t1 in $types )
#foreach( $t2 in $types )
- case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}.INSTANCE );
+ case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}_clamp.INSTANCE );
#end
#end
- default:
- throw new IllegalArgumentException();
- }
- case CLAMP:
- switch( type )
- {
+ default:
+ throw new IllegalArgumentException();
+ }
+ case CLAMP_MIN:
+ switch( type )
+ {
#foreach( $t1 in $types )
#foreach( $t2 in $types )
- case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}_clamp.INSTANCE );
+ case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}_clamp_min.INSTANCE );
#end
#end
- default:
- throw new IllegalArgumentException();
- }
- case CLAMP_MAX:
- switch( type )
- {
+ default:
+ throw new IllegalArgumentException();
+ }
+ case CLAMP_MAX:
+ switch( type )
+ {
#foreach( $t1 in $types )
#foreach( $t2 in $types )
- case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}_clamp_max.INSTANCE );
+ case ${t1.toUpperCase()}_TO_${t2.toUpperCase()}: return Cast.unchecked( Convert_${t1}_to_${t2}_clamp_max.INSTANCE );
#end
#end
- default:
- throw new IllegalArgumentException();
- }
- default:
- throw new IllegalArgumentException();
- }
- }
+ default:
+ throw new IllegalArgumentException();
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
#foreach( $t1 in $types )
#set( $sp1 = $storage_primitive[$t1] )
@@ -127,6 +140,18 @@ class ConvertLoops
}
}
+ static class Convert_${t1}_to_${t2}_clamp_min implements ConvertLoop< ${sp1}[], ${sp2}[] >
+ {
+ static final Convert_${t1}_to_${t2}_clamp_min INSTANCE = new Convert_${t1}_to_${t2}_clamp_min();
+
+ @Override
+ public void apply( final ${sp1}[] src, final ${sp2}[] dest, final int length )
+ {
+ for ( int i = 0; i < length; ++i )
+ dest[ i ] = to_${t2}_clamp_min( from_$t1( src[ i ] ) );
+ }
+ }
+
static class Convert_${t1}_to_${t2}_clamp_max implements ConvertLoop< ${sp1}[], ${sp2}[] >
{
static final Convert_${t1}_to_${t2}_clamp_max INSTANCE = new Convert_${t1}_to_${t2}_clamp_max();
diff --git a/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.list b/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.list
index efdb9f9ee..db0f9dfab 100644
--- a/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.list
+++ b/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.list
@@ -1 +1 @@
-[convert/ConvertScalars.java]
+[util/ConvertScalars.java]
diff --git a/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.vm b/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.vm
index 75bce27ee..bfca43ef3 100644
--- a/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.vm
+++ b/templates/main/java/net/imglib2/algorithm/blocks/ConvertScalars.vm
@@ -11,13 +11,13 @@
* %%
* 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
@@ -31,7 +31,7 @@
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
-package net.imglib2.algorithm.blocks.convert;
+package net.imglib2.algorithm.blocks.util;
/*
* This is autogenerated source code -- DO NOT EDIT. Instead, edit the
@@ -39,64 +39,70 @@ package net.imglib2.algorithm.blocks.convert;
*/
#parse( "PixelTypes.vm" )
-class ConvertScalars
+public class ConvertScalars
{
##
## from_i8(), etc., with corresponding compute_primitive as result type
##
- /*
- * Methods to convert each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64)
- * to the corresponding primitive type used for computation.
- *
- * i8, u8, i16, u16, i32 are all converted to int, because java
- * computes in int for byte, short, and int operands.
- *
- * u32, i64 are converted to long, because that is the primitive type that
- * can represent all values of the pixel type.
- *
- * f32 is converted to float
- *
- * f64 is converted to double
- */
+ /*
+ * Methods to convert each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64)
+ * to the corresponding primitive type used for computation.
+ *
+ * i8, u8, i16, u16, i32 are all converted to int, because java
+ * computes in int for byte, short, and int operands.
+ *
+ * u32, i64 are converted to long, because that is the primitive type that
+ * can represent all values of the pixel type.
+ *
+ * f32 is converted to float
+ *
+ * f64 is converted to double
+ */
#foreach( $t in $types )
#set( $cp = $compute_primitive[$t] )
#set( $sp = $storage_primitive[$t] )
#set( $m = $mask[$t] )
- static $cp from_$t( $sp value ) { return value#if( $m ) & $m#end; }
+ public static $cp from_$t( $sp value ) { return value#if( $m ) & $m#end; }
#end
##
## to_i8(), etc., for int/long
##
#foreach( $cp in ["int", "long"] )
- /*
- * Methods to convert ${cp} values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
- *
- * The basic to_u8() etc methods don't do any bounds-checking or clamping.
- * They only cast the argument to the output type.
- *
- * The to_u8_clamp() etc methods clamp the argument to the range of the
- * output type.
- *
- * The to_u8_clamp_max() etc methods clamp only to the upper bound output
- * range. This is useful for computations that could possibly overflow but
- * can never underflow (like summing unsigned values).
- */
+ /*
+ * Methods to convert ${cp} values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
+ *
+ * The basic to_u8() etc methods don't do any bounds-checking or clamping.
+ * They only cast the argument to the output type.
+ *
+ * The to_u8_clamp() etc methods clamp the argument to the range of the
+ * output type.
+ *
+ * The to_u8_clamp_max() etc methods clamp only to the upper bound output
+ * range. This is useful for computations that could possibly overflow but
+ * can never underflow (like summing unsigned values).
+ *
+ * The to_u8_clamp_min() etc methods clamp only to the lower bound output
+ * range. This is useful for computations that could possibly underflow but
+ * can never overflow (like subtracting unsigned values).
+ */
#foreach( $t in $types )
#set( $sp = $storage_primitive[$t] )
#set( $max = $max_value[$t] )
#set( $min = $min_value[$t] )
#if( $nbits[$sp] >= $nbits[$cp] )
- static $sp to_${t}( $cp value ) { return value; }
+ public static $sp to_${t}( $cp value ) { return value; }
#else
- static $sp to_${t}( $cp value ) { return ( $sp ) value; }
+ public static $sp to_${t}( $cp value ) { return ( $sp ) value; }
#end
#if( $max && !( $cp=="int" && $t=="i32" ) )
- static $sp to_${t}_clamp_max( $cp value ) { return to_${t}( Math.min( $max, value ) ); }
- static $sp to_${t}_clamp( $cp value ) { return to_${t}( Math.min( $max, Math.max( $min, value ) ) ); }
+ public static $sp to_${t}_clamp_max( $cp value ) { return to_${t}( Math.min( $max, value ) ); }
+ public static $sp to_${t}_clamp_min( $cp value ) { return to_${t}( Math.max( $min, value ) ); }
+ public static $sp to_${t}_clamp( $cp value ) { return to_${t}( Math.min( $max, Math.max( $min, value ) ) ); }
#else
- static $sp to_${t}_clamp_max( $cp value ) { return to_${t}( value ); }
- static $sp to_${t}_clamp( $cp value ) { return to_${t}( value ); }
+ public static $sp to_${t}_clamp_max( $cp value ) { return to_${t}( value ); }
+ public static $sp to_${t}_clamp_min( $cp value ) { return to_${t}( value ); }
+ public static $sp to_${t}_clamp( $cp value ) { return to_${t}( value ); }
#end
#end
#end
@@ -106,35 +112,39 @@ class ConvertScalars
##
#foreach( $cp in ["float", "double"] )
- /*
- * Methods to convert ${cp} values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
- *
- * The basic to_u8() etc methods don't do any bounds-checking or clamping.
- * They round the argument and then cast to the output type.
- *
- * The to_u8_clamp() etc methods additionally clamp the argument to the
- * range of the output type.
- *
- * The to_u8_clamp_max() etc methods additionally clamp only to the upper
- * bound output range. This is useful for computations that could possibly
- * overflow but can never underflow (like summing unsigned values).
- */
+ /*
+ * Methods to convert ${cp} values to each pixel type (i8, u8, i16, u16, i32, u32, i64, f32, f64).
+ *
+ * The basic to_u8() etc methods don't do any bounds-checking or clamping.
+ * They round the argument and then cast to the output type.
+ *
+ * The to_u8_clamp_max() etc methods clamp only to the upper bound output
+ * range. This is useful for computations that could possibly overflow but
+ * can never underflow (like summing unsigned values).
+ *
+ * The to_u8_clamp_min() etc methods clamp only to the lower bound output
+ * range. This is useful for computations that could possibly underflow but
+ * can never overflow (like subtracting unsigned values).
+ */
#foreach( $t in $types )
#set( $sp = $storage_primitive[$t] )
#set( $no_rounding = ["f32", "f64"] )
#set( $double_rounding = ["u32", "i64"] )
#if( $cp.equals("float") && $double_rounding.contains($t) )
- static $sp to_${t}( $cp value ) { return to_${t}( Math.round( ( double ) value ) ); }
- static $sp to_${t}_clamp_max( $cp value ) { return to_${t}_clamp_max( Math.round( ( double ) value ) ); }
- static $sp to_${t}_clamp( $cp value ) { return to_${t}_clamp( Math.round( ( double ) value ) ); }
+ public static $sp to_${t}( $cp value ) { return to_${t}( Math.round( ( double ) value ) ); }
+ public static $sp to_${t}_clamp_max( $cp value ) { return to_${t}_clamp_max( Math.round( ( double ) value ) ); }
+ public static $sp to_${t}_clamp_min( $cp value ) { return to_${t}_clamp_min( Math.round( ( double ) value ) ); }
+ public static $sp to_${t}_clamp( $cp value ) { return to_${t}_clamp( Math.round( ( double ) value ) ); }
#elseif( $no_rounding.contains($t) )
- static $sp to_${t}( $cp value ) { return #if( $nbits[$sp] < $nbits[$cp] )( $sp ) #end value; }
- static $sp to_${t}_clamp_max( $cp value ) { return to_${t}( value ); }
- static $sp to_${t}_clamp( $cp value ) { return to_${t}( value ); }
+ public static $sp to_${t}( $cp value ) { return #if( $nbits[$sp] < $nbits[$cp] )( $sp ) #end value; }
+ public static $sp to_${t}_clamp_max( $cp value ) { return to_${t}( value ); }
+ public static $sp to_${t}_clamp_min( $cp value ) { return to_${t}( value ); }
+ public static $sp to_${t}_clamp( $cp value ) { return to_${t}( value ); }
#else
- static $sp to_${t}( $cp value ) { return to_${t}( Math.round( value ) ); }
- static $sp to_${t}_clamp_max( $cp value ) { return to_${t}_clamp_max( Math.round( value ) ); }
- static $sp to_${t}_clamp( $cp value ) { return to_${t}_clamp( Math.round( value ) ); }
+ public static $sp to_${t}( $cp value ) { return to_${t}( Math.round( value ) ); }
+ public static $sp to_${t}_clamp_max( $cp value ) { return to_${t}_clamp_max( Math.round( value ) ); }
+ public static $sp to_${t}_clamp_min( $cp value ) { return to_${t}_clamp_min( Math.round( value ) ); }
+ public static $sp to_${t}_clamp( $cp value ) { return to_${t}_clamp( Math.round( value ) ); }
#end
#end
#end
diff --git a/templates/main/java/net/imglib2/algorithm/blocks/TransformLine2D.vm b/templates/main/java/net/imglib2/algorithm/blocks/TransformLine2D.vm
index 52ff467f0..6deb84af1 100644
--- a/templates/main/java/net/imglib2/algorithm/blocks/TransformLine2D.vm
+++ b/templates/main/java/net/imglib2/algorithm/blocks/TransformLine2D.vm
@@ -36,6 +36,11 @@ package net.imglib2.algorithm.blocks.transform;
import net.imglib2.type.PrimitiveType;
import net.imglib2.util.Cast;
+/*
+ * This is autogenerated source code -- DO NOT EDIT. Instead, edit the
+ * corresponding template in templates/ and rerun bin/generate.groovy.
+ */
+
#parse( "PixelTypes.vm" )
/**
diff --git a/templates/main/java/net/imglib2/algorithm/blocks/TransformLine3D.vm b/templates/main/java/net/imglib2/algorithm/blocks/TransformLine3D.vm
index ba13977e8..455b5ec1f 100644
--- a/templates/main/java/net/imglib2/algorithm/blocks/TransformLine3D.vm
+++ b/templates/main/java/net/imglib2/algorithm/blocks/TransformLine3D.vm
@@ -36,6 +36,11 @@ package net.imglib2.algorithm.blocks.transform;
import net.imglib2.type.PrimitiveType;
import net.imglib2.util.Cast;
+/*
+ * This is autogenerated source code -- DO NOT EDIT. Instead, edit the
+ * corresponding template in templates/ and rerun bin/generate.groovy.
+ */
+
#parse( "PixelTypes.vm" )
/**