All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphhopper.routing.ev.UnsignedDecimalEncodedValue Maven / Gradle / Ivy

/*
 *  Licensed to GraphHopper GmbH under one or more contributor
 *  license agreements. See the NOTICE file distributed with this work for
 *  additional information regarding copyright ownership.
 *
 *  GraphHopper GmbH licenses this file to you under the Apache License,
 *  Version 2.0 (the "License"); you may not use this file except in
 *  compliance with the License. You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.graphhopper.routing.ev;

import com.graphhopper.storage.IntsRef;

/**
 * This class holds a decimal value and stores it as an unsigned integer value via a conversion factor and a maximum number
 * of bits.
 */
public final class UnsignedDecimalEncodedValue extends UnsignedIntEncodedValue implements DecimalEncodedValue {
    private final double factor;
    private final double defaultValue;
    private final boolean useMaximumAsInfinity;

    public UnsignedDecimalEncodedValue(String name, int bits, double factor, boolean storeTwoDirections) {
        this(name, bits, factor, 0, storeTwoDirections);
    }

    /**
     * @param name               the key to identify this EncodedValue
     * @param bits               the bits that should be reserved for the storage
     * @param factor             the precision factor, i.e. store = (int) Math.round(value / factor)
     * @param defaultValue       the value that should be returned if the stored value is 0.
     * @param storeTwoDirections true if forward and backward direction of the edge should get two independent values.
     */
    public UnsignedDecimalEncodedValue(String name, int bits, double factor, double defaultValue, boolean storeTwoDirections) {
        this(name, bits, factor, defaultValue, storeTwoDirections, false);
    }

    public UnsignedDecimalEncodedValue(String name, int bits, double factor, double defaultValue, boolean storeTwoDirections, boolean useMaximumAsInfinity) {
        super(name, bits, storeTwoDirections);
        this.factor = factor;
        this.defaultValue = defaultValue;
        this.useMaximumAsInfinity = useMaximumAsInfinity;
        if (useMaximumAsInfinity && Double.isInfinite(defaultValue))
            throw new IllegalArgumentException("Default value and maximum value cannot be both infinity");
    }

    private int toInt(double val) {
        return (int) Math.round(val / factor);
    }

    @Override
    public final void setDecimal(boolean reverse, IntsRef ints, double value) {
        if (!isInitialized())
            throw new IllegalStateException("Call init before usage for EncodedValue " + toString());
        if (useMaximumAsInfinity && Double.isInfinite(value)) {
            super.setInt(reverse, ints, maxValue);
            return;
        }
        if (value == defaultValue)
            value = 0;
        else if (value > maxValue * factor)
            throw new IllegalArgumentException(getName() + " value " + value + " too large for encoding. maxValue:" + maxValue * factor);
        else if (value < 0)
            throw new IllegalArgumentException("Negative value for " + getName() + " not allowed! " + value);
        else if (Double.isNaN(value))
            throw new IllegalArgumentException("NaN value for " + getName() + " not allowed!");

        super.setInt(reverse, ints, toInt(value));
    }

    @Override
    public final double getDecimal(boolean reverse, IntsRef ref) {
        int value = getInt(reverse, ref);
        if (useMaximumAsInfinity && value == maxValue)
            return Double.POSITIVE_INFINITY;
        return value == 0 ? defaultValue : value * factor;
    }

    @Override
    public double getMaxDecimal() {
        return maxValue * factor;
    }

    @Override
    public boolean equals(Object o) {
        if (!super.equals(o)) return false;
        UnsignedDecimalEncodedValue that = (UnsignedDecimalEncodedValue) o;
        return Double.compare(that.factor, factor) == 0;
    }

    @Override
    public int getVersion() {
        return 31 * (31 * super.getVersion() + staticHashCode(factor)) + staticHashCode(defaultValue);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy