Package net.algart.math.patterns

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

/*
* 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 net.algart.math.IRange;
import net.algart.math.Range;

import java.util.Set;

class BasicWeightedPattern extends AbstractWeightedPattern implements WeightedPattern {
    private final IPoint weightCoordMin;
    private final IPoint weightCoordMax;
    private final long[] wcMin, wcMax; // little optimization for weight() method
    private final double[] weights;
    private final double outsideWeight;
    private volatile Range weightRange = null;

    BasicWeightedPattern(
        Pattern parent,
        IPoint weightCoordMin,
        IPoint weightCoordMax,
        double[] weights,
        double outsideWeight,
        boolean cloneWeights)
    {
        super(parent);
        int n = dimCount();
        if (n != weightCoordMin.coordCount())
            throw new IllegalArgumentException("Dimensions count mismatch: \"coordMin\" is "
                + weightCoordMin.coordCount() + "-dimensional, the pattern is " + n + "-dimensional");
        if (n != weightCoordMax.coordCount())
            throw new IllegalArgumentException("Dimensions count mismatch: \"coordMax\" is "
                + weightCoordMax.coordCount() + "-dimensional, the pattern is " + n + "-dimensional");
        this.weightCoordMin = weightCoordMin;
        this.weightCoordMax = weightCoordMax;
        this.wcMin = weightCoordMin.coordinates();
        this.wcMax = weightCoordMax.coordinates();
        final IRange[] ranges = new IRange[n];
        long count = 1;
        for (int k = 0; k < n; k++) {
            IRange range = IRange.valueOf(weightCoordMin.coord(k), weightCoordMax.coord(k));
            ranges[k] = range;
            if (range.size() >= Integer.MAX_VALUE || (count *= range.size()) >= Integer.MAX_VALUE)
                throw new IllegalArgumentException("Too large desired weight matrix: more than 2^31-1 elements");
        }
        assert count >= 1;
        if (weights.length != count)
            throw new IllegalArgumentException("The length of weights array " + weights.length
                + " does not match to the product " + count + " of dimensions of the desired weight matrix");
        this.weights = cloneWeights ? weights.clone() : weights;
        for (double w : this.weights) {
            if (Double.isNaN(w))
                throw new IllegalArgumentException("Cannot create " + getClass().getName()
                    + ": NaN weight is not allowed");
        }
        if (Double.isNaN(outsideWeight))
            throw new IllegalArgumentException("Cannot create " + getClass().getName()
                + ": NaN outside weight is not allowed");
        this.outsideWeight = outsideWeight;
    }

    @Override
    public WeightedPattern shift(IPoint shift) {
        return new BasicWeightedPattern(parent.shift(shift.toPoint()),
            weightCoordMin.add(shift), weightCoordMax.add(shift), weights, outsideWeight, false);
    }

    @Override
    public WeightedPattern scale(double... multipliers) {
        if (multipliers == null)
            throw new NullPointerException("Null multipliers argument");
        if (multipliers.length != dimCount())
            throw new IllegalArgumentException("Illegal number of multipliers: "
                + multipliers.length + " instead of " + dimCount());
        int n = dimCount();
        Pattern newPattern = parent.scale(multipliers);
        IPoint newMin = weightCoordMin.roundedScale(multipliers);
        IPoint newMax = weightCoordMin.roundedScale(multipliers);
        long count = 1;
        for (int k = 0; k < n; k++) {
            IRange range = IRange.valueOf(newMin.coord(k), newMax.coord(k));
            if (range.size() >= Integer.MAX_VALUE || (count *= range.size()) >= Integer.MAX_VALUE)
                throw new IllegalArgumentException("Too large desired weight matrix after resizing: "
                    + "more than 2^31-1 elements");
        }
        double[] newWeights = new double[(int) count]; // zero-filled
        double newOutsideWeight = outsideWeight * newPattern.largePointCount() / this.largePointCount();
        BasicWeightedPattern result = new BasicWeightedPattern(newPattern,
            newMin, newMax, newWeights, newOutsideWeight, false);
        if (Math.abs(multipliers[0]) < 1.0) { //TODO!!
            Set<IPoint> points = roundedPoints();
            for (IPoint point : points) {
                IPoint newPoint = point.roundedScale(multipliers);
                int newIndex = result.weightIndex(newPoint);
                if (newIndex != -1) {
                    newWeights[newIndex] += weight(point);
                }
            }
        } else {
            double multInv = 1.0 / multipliers[0]; //TODO!!
            int[] duplicationCounts = new int[weights.length]; // zero-filled
            Set<IPoint> newPoints = result.roundedPoints();
            for (IPoint newPoint : newPoints) {
                IPoint point = newPoint.multiply(multInv);
                int index = weightIndex(point);
                if (index != -1) {
                    duplicationCounts[index]++;
                }
            }
            for (IPoint newPoint : newPoints) {
                int newIndex = result.weightIndex(newPoint);
                if (newIndex != -1) {
                    IPoint point = newPoint.multiply(multInv);
                    int index = weightIndex(point);
                    if (index != -1) {
                        newWeights[newIndex] = weights[index] / duplicationCounts[index];
                    } else {
                        newWeights[newIndex] = newOutsideWeight;
                    }
                }
            }
        }
        return result;
    }

    @Override
    public double weight(IPoint point) {
        int index = weightIndex(point);
        if (index == -1) {
            return outsideWeight;
        }
        return weights[index];
    }

    @Override
    public Range weightRange() {
        if (weightRange != null) {
            return weightRange;
        }
        double min, max;
        if (weightCoordMin.equals(parent.coordMin().toRoundedPoint())
            && weightCoordMax.equals(parent.coordMax().toRoundedPoint()))
        {
            min = weights[0];
            max = weights[0];
            for (int k = 1; k < weights.length; k++) {
                if (weights[k] < min) {
                    min = weights[k];
                }
                if (weights[k] > max) {
                    max = weights[k];
                }
            }
        } else {
            min = Double.POSITIVE_INFINITY;
            max = Double.NEGATIVE_INFINITY;
            for (IPoint point : roundedPoints()) {
                double w = weight(point);
                if (w < min) {
                    min = w;
                }
                if (w > max) {
                    max = w;
                }
            }
        }
        return weightRange = Range.valueOf(min, max);
    }

    int weightIndex(IPoint point) {
        int n = dimCount();
        long index = point.coord(n - 1);
        if (index < wcMin[n - 1] || index > wcMax[n - 1]) {
            return -1;
        }
        index -= wcMin[n - 1];
        for (int k = n - 2; k >= 0; k--) {
            long coord = point.coord(k);
            if (coord < wcMin[k] || coord > wcMax[k]) {
                return -1;
            }
            coord -= wcMin[k];
            long dim = wcMax[k] - wcMin[k] + 1;
            index = index * dim + coord;
        }
        assert index <= Integer.MAX_VALUE;
        return (int) index;
    }
}
TOP

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

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.