Class TiledApertureProcessorFactory

java.lang.Object
net.algart.matrices.TiledApertureProcessorFactory

public final class TiledApertureProcessorFactory extends Object

Tiler: generator of tiled aperture matrix processors. The tiler works with some algorithm, represented by ApertureProcessor interface and called one-tile processor: it can be any algorithm, which processes one or several n-dimensional matrices (with identical sets of dimensions) and returns one or several other matrices as a result (with the same sets of dimensions). The only requirement is that the value of every element of the resulting matrices depends only on the elements of the source matrices in a fixed rectangular aperture "around" the same position, as described in ApertureProcessor interface. This class allows to convert the given one-tile processor into another aperture processor, called a tiled processor, created on the base of the original one-tile processor and functionally equivalent to it. (The equivalence can be violated on the bounds of the matrices, where the tiled processor provides several models of continuations — see below the section "Continuation model outside the bounds of the large matrices".) This new processor splits all the matrices into relatively little tiles (rectangular areas, i.e. submatrices), performs the processing of every tile with the one-tile processor and places the results into the corresponding submatrices of the resulting matrices. Such conversion of one algorithm to another is called tiling an algorithm and is performed by tile(ApertureProcessor) method — the main method of this class.

Why to tile aperture processors

The goal of tiling some algorithms is optimization of processing very large matrices, usually located on external storage devices (for example, with help of LargeMemoryModel).

First, very large matrices are usually tiled, but many algorithms process matrices in a simple "streaming" manner, i.e. load elements in the order, corresponding to the order of elements in the built-in AlgART array. This order of downloading is inefficient for tiled matrices. The same algorithms, tiled with help of this class, process large tiled matrices in more efficient order: they download a rectangular block from all source matrices into newly created (relatively little) matrices, process them and store the results into the corresponding submatrices of the destination matrices. For maximal efficiency, the tiler tries to use SimpleMemoryModel for storing and processing every rectangular block (a tile); you can control this with maxTempJavaMemory argument of all instantiation methods getInstance. In addition, the matrices, allocated by the tiled processor (if it creates them), are automatically tiled by Matrix.tile(long...) method (see more details below in the specification of process method in the tiled aperture processors, stage 4.d).

Second, many algorithms (for example, the basic implementation of mathematical morphology from net.algart.matrices.morphology package) are multipass, i.e. process source matrices in many passes though all the matrix. It can be very important for high performance, when all data are located in RAM, especially in a form of Java memory (via SimpleMemoryModel), but it can extremely slow down the calculations, when the source matrices are very large and located on a disk or another storage, because an algorithm downloads all data from external devices again during each pass. Unlike this, a matrix processor, generated by the tiler (by tile(ApertureProcessor) method), is always single-pass: each tile is downloaded and saved only 1 time, and multipass processing is applied to relatively little tile matrices, usually allocated in SimpleMemoryModel.

Third, tiling by this class is the simplest way to optimize an algorithm for multiprocessor or multi-core computers, if the algorithm does not provide multithreading optimization itself: several tiles can be processed simultaneously in parallel threads. See below about multithreading.

Specification of process and other methods in the tiled aperture processors

Here is the precise specification of the behaviour of the ApertureProcessor, tiled by this tiler, i.e. of the result of tile(ApertureProcessor oneTileProcessor). We call the argument of this method the one-tile processor, and the result of this method the tiled processor.

  • The generic type K of indexes of the source and resulting matrices in the tiled processor is the same as in the one-tile processor. (It is obvious from the declaration of tile method.)
     
  • ApertureProcessor.process(Map dest, Map src) method of the tiled processor does the following.
     
    1. It checks, whether the arguments are correct. If they violate one of common requirement, described in "Throws" section in comments to "process" method, a corresponding exception is thrown. In particular, this implementation checks, that all matrices in the dest map are either null or updatable, i.e. their built-in arrays implement UpdatableArray interface — if at least one non-null matrix in the dest map is not updatable, IllegalArgumentException is thrown.
      In addition, the given implementation throws IllegalArgumentException if one of the passed matrices has number of dimensions, other than the number of dimensions of this tiler, returned by its dimCount() method.
      If no source matrices and no non-null resulting matrices were passed to this method, i.e. if src.isEmpty() and either dest.isEmpty(), or all matrices dest.get(key)==null, then process method does nothing and immediately returns. If at least one of dimensions of the passed matrices is 0, then process method also does nothing and immediately returns (there are no elements to process).
       
    2. It calculates the maximal dependence aperture Am: a minimal integer rectangular area (an instance of IRectangularArea), containing all dependence apertures Ai of the one-tile processor (returned by its dependenceAperture(i) method) for all indexes iQ=src.keySet(), and also containing the origin of coordinates. While this calculation, IndexOutOfBoundsException will be thrown, if the number of dimensions for one of results of dependenceAperture(i) calls is less than dimCount(), but if some of them has more than dimCount() dimensions, the extra dimensions of such aperture are just ignored (here and in the further algorithm).
       
    3. It splits all source matrices Mi (src.get(i)) and all resulting matrices M'j (dest.get(j)) into a set of rectangular non-overlapping tiles, i.e. submatrices, the dimensions of which are chosen to be equal to the desired tile dimensions of this tiler (tileDim()) or, maybe, less. (This stage does not suppose any actual calculations: we consider this stage for the sake of simplicity.)
      For every tile, we shall designate f = (f0, f1, ..., fn−1) the n-dimensional starting point of the tile (inclusive) and t = (t0, t1, ..., tn−1) the n-dimensional ending point of the tile (exclusive). (Here "f" is the starting letter of "from" word, "t" is the starting letter of "to" word.) More precisely, this tile consists of all elements of the source and target matrices with such indexes (i0, i1, ..., in−1), that
          fkik < tk, k=0,1,...,n−1.
      Besides this tile (ft), we also consider the extended tile (fete), consisting of all elements of the source and target matrices with such indexes (i0, i1, ..., in−1), that
          fek = fk + Am.min(k)ik < tek = tk + Am.max(k).
      Note that all tiles (ft) lie fully inside the dimensions of the source and target matrices, but it is not always so for extended tiles (fete). Also note that each tile (ft) is a subset of the corresponding extended tile (fete), because the maximal dependence aperture Am always contains the origin of coordinates (as written in the item 2).
       
    4. Then the process method of the tiled processor does the following, for every tile (ft) and the corresponding extended tile (fete):
      1. For each index of a source matrices iQ=src.keySet() and for each index of a resulting non-null matrix jR=dest.keySet(), passed to this method, it allocates new matrices mi and m'j with the same element type as Mi and M'j and with dimensions, equal to the sizes of the extended tile tekfek. For each index j of a null resulting matrix M'j=null, passed to this method, it's assumed m'j=null. The newly created (relatively small) matrices (or null references) mi and m'j are stored in two Map<K, Matrix<?>> objects srcTile (mi) and destTile (m'j), in the same manner as the original dest and src arguments.
        Note that the tiled processor tries to use the created matrices mi and m'j many times for different tiles, because there is no sense to create them again for every tile.
        This algorithm tries to create all matrices in SimpleMemoryModel. But, it the total amount of memory, necessary simultaneously for all these matrices, is greater than maxTempJavaMemory() bytes (this parameter is passed to all instantiation methods getInstance of the tiler), then the memory model from the current context is used instead. Note that the total amount of memory depends not only on the number of arguments and results and the tile dimensions, but also on the desired number of parallel tasks.
        Here is a guarantee that all non-null matrices m'j (stored in destTile) are updatable, i.e. their built-in arrays implement UpdatableArray interface.
      2. For each source matrix Mi, its submatrix, corresponding to the extended tile and extracted with Mi.subMatrix(fe, te, continuationMode) call, is copied into the corresponding small matrix mi (srcTile.get(i)). Here the continuationMode is equal to the continuation mode of this tiler, returned by continuationMode() method.
        At this step, the method may really copy less data from some source matrices (with getting the same results), if the corresponding dependence apertures Ai are less than the maximal aperture Am.
      3. Main part of the algorithm: process method of the one-tile processor is called with the arguments m'j and mioneTileProcessor.process(destTile, srcTile).
        Note that, as a result, all null small matrices m'j (destTile.get(j)) will become not null — it is a requirement, described in comments to "process" method. If some matrix destTile.get(j) is null after calling the one-tile processor, it means an invalid implementation of the one-tile processor: AssertionError is thrown in this case.
      4. If it is the first processed tile, this algorithm scans the whole map destTile. If it contains some matrix m'j, for which the index j is not present in the dest map (!dest.containsKey(j)) or the value dest.get(j)==null, the corresponding resulting matrices M'j is created with the element type, equal to corresponding m'j.elementType(), and dimensions, equal to dimensions of other source and resulting matrices Mi and M'j. Each created matrix M'j is saved back into dest argument: dest.put(jM'j).
        The resulting matrices M'j are created in the memory model from the current context of the tiler: context().getMemoryModel(). Moreover, every newly created matrix is automatically tiled, i.e. replaced with newMatrix.tile(allocationTileDim), where allocationTileDim is the corresponding argument of the getInstance instantiation method — with the only exception, when you explicitly specify null for this argument (in this case the new matrices are not tiled). In most cases, the tiler is used with very large matrices, and automatic tiling the resulting matrices improves performance.
      5. The central part (submatrix) of all matrices m'j, corresponding to the original (non-extended) tile (ft), is copied into the corresponding tile of the resulting matrices M'j, i.e. into their submatrices M'j.subMatrix(f, t).
         
  • ApertureProcessor.dependenceAperture(Object srcMatrixKey) method of the tiled processor just calls the same method of the one-tile processor with the same srcMatrixKey argument and returns its result.
     

Note: there is a guarantee, that each resulting matrix M'j, created by process method of the tiled processor at the stage 4.d is updatable: its built-in array is UpdatableArray and, thus, the matrix can be cast to Matrix<UpdatableArray> with help of Matrix.cast(UpdatableArray.class) call.

Note: process method of the tiled processor can process several tiles simultaneously in parallel threads to optimize calculations on multiprocessor or multi-core computers. It depends on the numberOfTasks argument of the instantiation methods getInstance. If it is 0 (or absent), the desired number of parallel tasks is detected automatically on the base of the ArrayContext argument of the instantiation methods. Many algorithms (one-tile processors) provide multithreading optimization themselves, so there is no sense to use this feature: in this case you may specify numberOfTasks=1.

Continuation model outside the bounds of the large matrices

The behaviour of the aperture processor, tiled by tile(ApertureProcessor oneTileProcessor) method, can little differ from the behaviour of the original one-tile processor near the bounds of the matrices, namely for the resulting elements, for which the dependence aperture Ai=dependenceAperture(i) (at least for one index i of a source matrix) does not fully lie inside the corresponding source matrix Mi.

In such situation the behaviour of the original one-tile processor depends on implementation — for example, many algorithms suppose so-called pseudo-cyclic continuation mode, described in comments to Matrix.ContinuationMode.PSEUDO_CYCLIC constant. But the behaviour of the resulting processor, tiled by tile(ApertureProcessor) method, is strictly defined always and corresponds to the continuation mode, passed as continuationMode argument to an instantiation method getInstance of the tiler and returned by continuationMode() method. You can see it from the specification of the behaviour of process method above, stage 4.b.

If the one-tile processor works according one of continuation models, provided by Matrix.ContinuationMode class, you can guarantee the identical behaviour of the tiled processor by passing the same continuation mode into a tiler instantiation method getInstance; if no, the tiled processor will be impossible to provide identical results.

Note that Matrix.ContinuationMode.NONE continuation mode cannot be used in the tiler: such value of continuationMode argument of instantiation methods getInstance leads to IllegalArgumentException.

Contexts for the one-tile processor

First of all, we note that every tiled processor — a result of tile(ApertureProcessor) method — always implements not only ApertureProcessor, but also ArrayProcessorWithContextSwitching interface. So, you can use its ArrayProcessor.context() and ArrayProcessorWithContextSwitching.context(ArrayContext) methods after corresponding type cast. The current context of the tiled processor (returned by context() method) is initially equal to the current context of the tiler, and you can change it with help of context(ArrayContext) method. This context (if it is not null) is used for determining memory model, which should be used for allocating matrices, for showing execution progress and allowing to stop execution after processing every tile (even if the one-tile processor does not support these features) and for multithreading simultaneous processing several tiles, if numberOfTasks()>1. And it will be initially null, if the current context of the tiler is null — then it will be ignored.

Many algorithms, which can be tiled by this class, also works with some ArrayContext to provide abilities to stop calculations, show progress, determine desired memory model for allocating AlgART arrays, etc. Such algorithms should implement not only ApertureProcessor interface, but also ArrayProcessorWithContextSwitching interface, and should get the current context via their context() method. This requirement if not absolute, but if your algorithm retrieves the context with some other way, then the behaviour of its ArrayContext.updateProgress(ArrayContext.Event) method can be incorrect — your processor, processing one tile, will not "know" that it is only a part of the full task (processing all tiles).

If a one-tile processor, tiled by tile(ApertureProcessor) method, really implements ArrayProcessorWithContextSwitching, then process method of the tiled processor creates special tile context before processing every tile and switches the one-tile processor to this context before calling its process method. In other words, at the stage 4.c the tiled processor calls not
     oneTileProcessor.process(destTile, srcTile),
but
     ((ApertureProcessor<K>)(oneTileProcessor.context(tileContext))).process(destTile, srcTile).
(By the way, it means that you are able not to think about the initial value of the current context in the constructor of your one-tile processor: it will be surely replaced with tileContext before usage of your processor. For example, you may initialize it by null.) Of course, it is supposed that the switching method oneTileProcessor.context(tileContext) returns an object that also implements ApertureProcessor — if it is not so, it means an invalid implementation of that method, and AssertionError or ClassCastException can be thrown in this case.

The tileContext here is never null: you can freely use this fact in your implementation of the one-tile processor. This context is formed automatically as a part of the current context of the tiled processor, returned by its context() method — a part, corresponding to processing only one from a lot of tiles. (As written above, by default the current context of the tiled processor is equal to the current context of the tiler.) Thus, the tiler provides correct behaviour of oneTileProcessor.context().updateProgress(...) inside process method of your one-tile processor. If the current context of the tiled processor is null, tileContext is formed from ArrayContext.DEFAULT.

The tileContext also provides additional information about the position and sizes of the currently processed tile. Namely, it is created with help of ArrayContext.customDataVersion(Object) method in such a way, that its customData() method always returns a correctly filled instance of TiledApertureProcessorFactory.TileInformation class, describing the currently processed tile.

If the current number of tasks, desired for this tiler, is greater than 1, and the tiled processor uses multithreading for parallel processing several tiles, then the tileContext is formed in a more complex way. Namely, in this case it is also a part of the full context with correctly filled customData() (an instance of TiledApertureProcessorFactory.TileInformation), and in addition:

  • ArrayContext.multithreadingVersion(int k, int n) method is called — so, the one-tile processor can determine, in which of several parallel threads it is called (the index k) and what is the total number of parallel threads (the value n≤numberOfTasks() — it can be less than numberOfTasks(), for example, when the total number of tiles is less than it). This is helpful if the implementation of the one-tile processor needs some work memory or another objects, which should be created before all calculations and must be separate for different threads;
  • ArrayContext.singleThreadVersion() method is called — in other words, the tiler tries to suppress multithreading in the one-tile processor, when it uses multithreading itself for parallel processing several tiles;
  • ArrayContext.noProgressVersion() method is called — because a progress bar cannot be updated correctly while parallel processing several tiles (it will be updated after finishing processing this group of tiles).

Restrictions

Every instance of this class can work only with some fixed number n of matrix dimensions, returned by dimCount() method and equal to the length of tileDim array, passed as an argument of the instantiation methods getInstance. It means that process method of an aperture processor, returned by tile(ApertureProcessor) method, can process only n-dimensional matrices with n=dimCount() and throws IllegalArgumentException if some of the passed matrices has another number of dimensions.

The tiler has no restrictions for the types of matrix elements: it can work with any element types, including non-primitive types. But usually the types of matrix elements are primitive.

Note: in improbable cases, when the dimensions of the source and resulting matrices and/or the sizes of the dependence apertures are extremely large (about 263), so that the sum of some matrix dimension and the corresponding size of the aperture (IRectangularArea.width(int)) or the product of all such sums (i.e. the number of elements in a source/resulting matrix, extended by such aperture) is greater than Long.MAX_VALUE, the process method of the tiled processor throws IndexOutOfBoundsException and does nothing. Of course, these are very improbable cases.

Creating instances of this class

To create instances of this class, you should use one of the following methods:

Multithread compatibility

This class is immutable and thread-safe: there are no ways to modify settings of the created instance. The same is true for the tiled processors, created by tile(ApertureProcessor) method.

Author:
Daniel Alievsky
  • Method Details

    • getInstance

      public static TiledApertureProcessorFactory getInstance(ArrayContext context, Matrix.ContinuationMode continuationMode, long maxTempJavaMemory, long[] tileDim)
      Creates new instance of the tiler. Equivalent to the following call of the basic instantiation method:
      getInstance(context, continuationMode, maxTempJavaMemory, tileDim, Matrices.defaultTileDimensions(tileDim.length), 0).
      Parameters:
      context - see the basic getInstance method.
      continuationMode - see the basic getInstance method.
      maxTempJavaMemory - see the basic getInstance method.
      tileDim - see the basic getInstance method.
      Returns:
      new tiler.
      Throws:
      NullPointerException - if continuationMode or tileDim argument is null.
      IllegalArgumentException - if continuationMode==Matrix.ContinuationMode.NONE, or if maxTempJavaMemory<0, or if tileDim.length==0, or if one of elements of tileDim Java array is zero or negative.
    • getInstance

      public static TiledApertureProcessorFactory getInstance(ArrayContext context, Matrix.ContinuationMode continuationMode, long maxTempJavaMemory, long[] tileDim, long[] allocationTileDim)
      Creates new instance of the tiler. Equivalent to the following call of the basic instantiation method:
      getInstance(context, continuationMode, maxTempJavaMemory, tileDim, allocationTileDim, 0).
      Parameters:
      context - see the basic getInstance method.
      continuationMode - see the basic getInstance method.
      maxTempJavaMemory - see the basic getInstance method.
      tileDim - see the basic getInstance method.
      allocationTileDim - see the basic getInstance method.
      Returns:
      new tiler.
      Throws:
      NullPointerException - if continuationMode or tileDim argument is null.
      IllegalArgumentException - if continuationMode==Matrix.ContinuationMode.NONE, or if maxTempJavaMemory<0, or if tileDim.length==0, or if allocationTileDim!=null and allocationTileDim.length!=tileDim.length, or if one of elements of tileDim or (non-null) allocationTileDim Java arrays is zero or negative.
    • getInstance

      public static TiledApertureProcessorFactory getInstance(ArrayContext context, Matrix.ContinuationMode continuationMode, long maxTempJavaMemory, long[] tileDim, int numberOfTasks)
      Creates new instance of the tiler. Equivalent to the following call of the basic instantiation method:
      getInstance(context, continuationMode, maxTempJavaMemory, tileDim, Matrices.defaultTileDimensions(tileDim.length), numberOfTasks).
      Parameters:
      context - see the basic getInstance method.
      continuationMode - see the basic getInstance method.
      maxTempJavaMemory - see the basic getInstance method.
      tileDim - see the basic getInstance method.
      numberOfTasks - see the basic getInstance method.
      Returns:
      new tiler.
      Throws:
      NullPointerException - if continuationMode or tileDim argument is null.
      IllegalArgumentException - if continuationMode==Matrix.ContinuationMode.NONE, or if maxTempJavaMemory<0, or if tileDim.length==0, or if numberOfTasks<0, or if one of elements of tileDim Java array is zero or negative.
    • getInstance

      public static TiledApertureProcessorFactory getInstance(ArrayContext context, Matrix.ContinuationMode continuationMode, long maxTempJavaMemory, long[] tileDim, long[] allocationTileDim, int numberOfTasks)
      Creates new instance of the tiler.

      The passed Java arrays tileDim and allocationTileDim are cloned by this method: no references to them are maintained by the created object.

      Parameters:
      context - the context that will be used by this tiler; may be null, then it will be ignored, and the tiled processor will create all temporary matrices in SimpleMemoryModel.
       
      continuationMode - continuation mode, used by the tiled processor (see also the specification of the process method in the comments to this class, stage 4.b).
       
      maxTempJavaMemory - maximal amount of Java memory, in bytes, allowed for allocating by the process method of the tiled processor (see ibid., stage 4.a). If you are sure that there is enough Java memory for allocating all necessary matrices for numberOfTasks() tiles of all source and resulting matrices (with the given dimensions tileDim), you may specify here Long.MAX_VALUE.
       
      tileDim - the desired dimensions of tiles, into which the source and resulting matrices are split by the tiled processor (see ibid., stage 3). Typical values for most applications are 4096x4096 or 2048x2048 (in 2-dimensional case).
       
      allocationTileDim - if not null, then the resulting matrices M'j, created by the tiled processor (see ibid., stage 4.d), are automatically tiled by the call newMatrix.tile(allocationTileDim). If it is null, the resulting matrices are not tiled.
       
      numberOfTasks - the desired number of tiles, which should be processed simultaneously in parallel threads to optimize calculations on multiprocessor or multi-core computers; may be 0, then it will be detected automatically as Arrays.getThreadPoolFactory(context).recommendedNumberOfTasks(). You may specify numberOfTasks=1 for saving memory, if you know that the one-tile processors, which you are going to tile, provide multithreading optimization themselves.
      Returns:
      new tiler.
      Throws:
      NullPointerException - if continuationMode or tileDim argument is null.
      IllegalArgumentException - if continuationMode==Matrix.ContinuationMode.NONE, or if maxTempJavaMemory<0, or if tileDim.length==0, or if allocationTileDim!=null and allocationTileDim.length!=tileDim.length, or if numberOfTasks<0, or if one of elements of tileDim or (non-null) allocationTileDim Java arrays is zero or negative.
      See Also:
    • context

      public ArrayContext context()
      Returns the current context, used by this tiler. Equal to the first argument, passed to an instantiation method getInstance.

      This context (if it is not null) is used by the tiled processor for determining memory model, which should be used for allocating resulting matrices and, maybe, temporary matrices for every tile (if maxTempJavaMemory() is too small to allocate them in SimpleMemoryModel), for showing execution progress and allowing to stop execution after processing every tile (even if the one-tile processor does not support these features) and for multithreading simultaneous processing several tiles, if numberOfTasks()>1.

      See also the comments to this class, the section "Contexts for the one-tile processor".

      Returns:
      the current context, used by this tiler; may be null.
    • context

      public TiledApertureProcessorFactory context(ArrayContext newContext)
      Switches the context: returns an instance, identical to this one excepting that it uses the specified newContext for all operations.
      Parameters:
      newContext - another context, used by the returned instance; may be null.
      Returns:
      new instance with another context.
    • dimCount

      public int dimCount()
      Returns the number of dimensions of this tiler. Equal to the number of elements of tileDim arrays, passed to an instantiation method getInstance.

      The tiled processor, created by tile(ApertureProcessor) method of this tiler, can process only matrices with this number of dimensions.

      Returns:
      the number of dimensions of matrices, which can be processed by aperture processors, tiled by this tiler; always ≥1.
    • continuationMode

      public Matrix.ContinuationMode continuationMode()
      Returns the continuation mode, used by this tiler. Equal to the corresponding argument, passed to an instantiation method getInstance.

      See comments to the basic getInstance method and the comments to this class for more details.

      Returns:
      the continuation mode of this tiler; cannot be null or Matrix.ContinuationMode.NONE.
    • maxTempJavaMemory

      public long maxTempJavaMemory()
      Returns the maximal amount of Java memory, in bytes, allowed for allocating temporary matrices for storing a tile. Equal to the corresponding argument, passed to an instantiation method getInstance.

      See comments to the basic getInstance method and the comments to this class for more details.

      Returns:
      the maximal amount of Java memory, in bytes, allowed for allocating temporary matrices for storing a tile; always ≥0.
    • tileDim

      public long[] tileDim()
      Returns the desired dimensions of every tile. Equal to tileDim arrays, passed to an instantiation method getInstance.

      The returned array is a clone of the internal dimension array stored in this object. The returned array is never empty (its length cannot be zero). The elements of the returned array are never zero or negative.

      See comments to the basic getInstance method and the comments to this class for more details.

      Returns:
      the desired dimensions of every tile.
    • numberOfTasks

      public int numberOfTasks()
      Returns the number of tiles, which should be processed simultaneously in parallel threads to optimize calculations on multiprocessor or multi-core computers. It is equal to:
      Returns:
      the number of threads, that this class uses for multithreading optimization; always ≥1.
    • tile

      public <K> ApertureProcessor<K> tile(ApertureProcessor<K> oneTileProcessor)
      The main method: builds the tiled aperture processor on the base of the given one-tile processor. See the comments to this class for more details.

      The result of this method always implements ArrayProcessorWithContextSwitching interface. See the comments to this class, the section "Contexts for the one-tile processor".

      Parameters:
      oneTileProcessor - one-tile aperture processor.
      Returns:
      tiled aperture processor.
      Throws:
      NullPointerException - if the argument is null.
    • toString

      public String toString()
      Returns a brief string description of this object.

      The result of this method may depend on implementation and usually contains a short description of this tiler.

      Overrides:
      toString in class Object
      Returns:
      a brief string description of this object.