Package net.algart.math.patterns

Source Code of net.algart.math.patterns.TinyBitMatrix

/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2014 Daniel Alievsky, AlgART Laboratory (http://algart.net)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.algart.math.patterns;

import net.algart.math.IPoint;

import java.util.HashSet;
import java.util.Set;

/**
* <p>A simple multidimensional bit matrix. Used for optimization of some methods processing patterns.
* All dimensions of this matrix must be not greater than Integer.MAX_VALUE.</p>
*
* <p>AlgART Laboratory 2007&ndash;2014</p>
*
* @author Daniel Alievsky
* @version 1.2
* @since JDK 1.5
*/
class TinyBitMatrix {
    private final long[] array;
    private final int[] dimensions;
    private final long length;

    private TinyBitMatrix(long[] array, int[] dimensions) {
        this.length = checkDimensions(dimensions);
        long packedLength = TinyBitArrays.packedLength(this.length);
        if (packedLength > Integer.MAX_VALUE)
            throw new IllegalArgumentException("Too large bit array: >=2^37 elements");
        if (packedLength > array.length)
            throw new IllegalArgumentException("Too large bit array: longer than the passed long[] array");
        this.dimensions = dimensions.clone();
        this.array = array;
    }

    TinyBitMatrix(int[] dimensions) {
        this.length = checkDimensions(dimensions);
        long packedLength = TinyBitArrays.packedLength(this.length);
        if (packedLength > Integer.MAX_VALUE)
            throw new IllegalArgumentException("Too large bit array: >=2^37 elements");
        this.dimensions = dimensions.clone();
        this.array = new long[(int) packedLength];
    }

    public long[] array() {
        return this.array;
    }

    public int[] dimensions() {
        return this.dimensions.clone();
    }

    public int dimCount() {
        return this.dimensions.length;
    }

    public int dim(int n) {
        return n < this.dimensions.length ? this.dimensions[n] : 1;
    }

    /*Repeat(INCLUDE_FROM_FILE, ../../arrays/AbstractMatrix.java, dimEquals)
      @Override\s+(public) ==> $1 ;;
      \(Matrix\b.*?\s(\w+)\) ==> (TinyBitMatrix $1)
       !! Auto-generated: NOT EDIT !! */
    public boolean dimEquals(TinyBitMatrix m) {
        if (m == null)
            throw new NullPointerException("Null matrix");
        int dimCount = dimCount();
        if (m.dimCount() != dimCount) {
            return false;
        }
        for (int k = 0; k < dimCount; k++) {
            if (m.dim(k) != dim(k)) {
                return false;
            }
        }
        return true;
    }
    /*Repeat.IncludeEnd*/

    /*Repeat(INCLUDE_FROM_FILE, ../../arrays/AbstractMatrix.java, pseudoCyclicIndex)
      @Override\s+(public) ==> $1 ;;
      size\(\) ==> this.length
       !! Auto-generated: NOT EDIT !! */
    public long pseudoCyclicIndex(long... coordinates) {
        int n = coordinates.length;
        if (n == 0)
            throw new IllegalArgumentException("Empty coordinates array");
        // 4D example:
        // index = (u*nz*ny*nx + z*ny*nz + y*nx + x) % N =
        //       = (u'*nz*ny*nx + z'*ny*nz + y'*nx + x') % N =
        //       = ((((u'*nz + z')*ny + y')*nx + x') % N
        // (N = nu*nz*ny*nx), where
        //       u' = u % nu
        //       z' = z % (nu*nz)
        //       y' = y % (nu*nz*ny)
        //       x' = x % (nu*nz*ny*nx)
        //
        --n;
        if (this.length == 0) {
            // we must check it here, in other case the further assertions can be false:
            // production of some dimensions in an empty matrix can be greater than Long.MAX_VALUE
            return 0;
        }
        long limit = dim(n);
        long result = coordinates[n] % limit;
        if (result < 0) {
            result += limit;
        }
        while (n > 0) {
            --n;
            long dim = dim(n);
            if (dim == 0) {
                return 0;
            }
            limit *= dim;
            long coord = coordinates[n] % limit;
            if (coord < 0) {
                coord += limit;
            }
            result *= dim;
            assert result >= 0 : "cyclic index becomes " + result + ", n=" + n + " in " + this; // overflow impossible
            result += coord;
            if (result < 0 || result >= limit) { // "< 0" means overflow
                result -= limit;
                assert result >= 0 : "cyclic index becomes " + result + ", n=" + n + " in " + this;
            }
        }
        return result;
    }
    /*Repeat.IncludeEnd*/

    public TinyBitMatrix reDim(int[] newDimensions) {
        return new TinyBitMatrix(array, newDimensions);
    }

    public void putPattern(Pattern pattern) {
        if (pattern.dimCount() != dimCount())
            throw new IllegalArgumentException("Number of dimensions of the pattern and the bit matrix mismatch");
        for (IPoint ip : pattern.roundedPoints()) {
            TinyBitArrays.setBit(array, pseudoCyclicIndex(ip.coordinates()), true);
        }
    }

    public UniformGridPattern getIntegerPattern() {
        Set<IPoint> points = new HashSet<IPoint>();
        addPoints(points, new long[dimCount()], new boolean[dim(0)], 0, null);
        return Patterns.newIntegerPattern(points);
    }

    public UniformGridPattern getPattern(IPoint shift) {
        Set<IPoint> points = new HashSet<IPoint>();
        addPoints(points, new long[dimCount()], new boolean[dim(0)], 0, shift);
        return new BasicDirectPointSetUniformGridPattern(shift.coordCount(), points);
    }

    public void simpleDilation(TinyBitMatrix src, Pattern pattern) {
        if (src == null)
            throw new NullPointerException("Null src bit matrix");
        if (!dimEquals(src))
            throw new IllegalArgumentException("Bit matrix dimensions mismatch");
        if (pattern.dimCount() != dimCount())
            throw new IllegalArgumentException("Number of dimensions mismatch of the pattern and the bit matrix");
        Set<IPoint> points = pattern.roundedPoints();
        boolean first = true;
        for (IPoint ip : points) {
            long shift = pseudoCyclicIndex(ip.coordinates());
            if (first) {
                TinyBitArrays.copyBits(array, shift, src.array, 0, length - shift);
                TinyBitArrays.copyBits(array, 0, src.array, length - shift, shift);
            } else {
                TinyBitArrays.orBits(array, shift, src.array, 0, length - shift);
                TinyBitArrays.orBits(array, 0, src.array, length - shift, shift);
            }
            first = false;
        }
    }

    public long cardinality() {
        return TinyBitArrays.cardinality(array, 0, length);
    }

    private void addPoints(
        Set<IPoint> points,
        long[] coordinates, boolean[] temp, int lastCoordinatesCount, IPoint shift)
    {
        int currentCoordIndex = coordinates.length - 1 - lastCoordinatesCount;
        if (currentCoordIndex == 0) {
            coordinates[0] = 0;
            int n = dim(0);
            TinyBitArrays.unpackBits(temp, 0, array, pseudoCyclicIndex(coordinates), n);
            for (int i = 0; i < n; i++) {
                if (temp[i]) {
                    coordinates[0] = i;
                    IPoint p = IPoint.valueOf(coordinates);
                    if (shift != null) {
                        p = p.add(shift);
                    }
                    points.add(p);
                }
            }
        } else {
            for (int i = 0, n = dim(currentCoordIndex); i < n; i++) {
                coordinates[currentCoordIndex] = i;
                addPoints(points, coordinates, temp, lastCoordinatesCount + 1, shift);
            }
        }
    }

    private static long checkDimensions(int[] dim) throws IllegalArgumentException {
        if (dim == null)
            throw new NullPointerException("Null dimensions Java array");
        if (dim.length == 0)
            throw new IllegalArgumentException("Empty dimensions Java array");
        for (int n = 0; n < dim.length; n++) {
            if (dim[n] < 0)
                throw new IllegalArgumentException("Negative matrix dimension #" + n + ": " + dim[n]);
        }
        long[] lDim = new long[dim.length];
        for (int k = 0; k < dim.length; k++)
            lDim[k] = dim[k];
        long len = Patterns.longMul(lDim);
        if (len == Long.MIN_VALUE)
            throw new TooManyPointsInPatternError("Illegal dimensions: dim[0] * dim[1] * ... > Long.MAX_VALUE");
        return len;
    }
}
TOP

Related Classes of net.algart.math.patterns.TinyBitMatrix

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.