/** * Copyright (C) 2019 Adrien Hopkins * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package org.unitConverter.unit; import java.util.Objects; import org.unitConverter.dimension.UnitDimension; /** * A unit that is equal to a certain number multiplied by its base. * * @author Adrien Hopkins * @since 2018-12-22 * @since v0.1.0 */ public final class LinearUnit extends AbstractUnit implements OperatableUnit { /** * The value of one of this unit in this unit's base unit * * @since 2018-12-22 * @since v0.1.0 */ private final double conversionFactor; /** * * Creates the {@code LinearUnit}. * * @param base * unit's base * @param conversionFactor * value of one of this unit in its base * @since 2018-12-23 * @since v0.1.0 */ LinearUnit(final BaseUnit base, final double conversionFactor) { super(base); this.conversionFactor = conversionFactor; } /** * Creates the {@code LinearUnit} as a base unit. * * @param dimension * dimension measured by unit * @param system * system unit is part of * @since 2019-01-25 * @since v0.1.0 */ LinearUnit(final UnitDimension dimension, final UnitSystem system, final double conversionFactor) { super(dimension, system); this.conversionFactor = conversionFactor; } @Override public double convertFromBase(final double value) { return value / this.getConversionFactor(); } @Override public double convertToBase(final double value) { return value * this.getConversionFactor(); } /** * Divides this unit by a scalar. * * @param divisor * scalar to divide by * @return quotient * @since 2018-12-23 * @since v0.1.0 */ public LinearUnit dividedBy(final double divisor) { return new LinearUnit(this.getBase(), this.getConversionFactor() / divisor); } /** * Divides this unit by another unit. * * @param other * unit to divide by * @return quotient of two units * @throws NullPointerException * if other is null * @since 2018-12-22 * @since v0.1.0 */ public LinearUnit dividedBy(final LinearUnit other) { Objects.requireNonNull(other, "other must not be null"); final BaseUnit base = this.getBase().dividedBy(other.getBase()); return new LinearUnit(base, this.getConversionFactor() / other.getConversionFactor()); } @Override public boolean equals(final Object obj) { if (!(obj instanceof LinearUnit)) return false; final LinearUnit other = (LinearUnit) obj; return Objects.equals(this.getBase(), other.getBase()) && Objects.equals(this.getConversionFactor(), other.getConversionFactor()); } /** * @return conversionFactor * @since 2018-12-22 * @since v0.1.0 */ public final double getConversionFactor() { return this.conversionFactor; } @Override public int hashCode() { final int prime = 31; int result = 1; result = result * prime + this.getBase().hashCode(); result = result * prime + Double.hashCode(this.getConversionFactor()); return result; } @Override public LinearUnit negated() { return new LinearUnit(this.getBase(), -this.getConversionFactor()); } @Override public OperatableUnit plus(final OperatableUnit addend) { Objects.requireNonNull(addend, "addend must not be null."); // reject addends that cannot be added to this unit if (!this.getSystem().equals(addend.getSystem())) throw new IllegalArgumentException( String.format("Incompatible units for addition or subtraction \"%s\" and \"%s\".", this, addend)); if (!this.getDimension().equals(addend.getDimension())) throw new IllegalArgumentException( String.format("Incompatible units for addition or subtraction \"%s\" and \"%s\".", this, addend)); // add the units if (addend instanceof BaseUnit) // since addend's dimension is equal to this unit's dimension, and there is only one base unit per // system-dimension, addend must be this unit's base. return new LinearUnit(this.getBase(), this.getConversionFactor() + 1); else if (addend instanceof LinearUnit) return new LinearUnit(this.getBase(), this.getConversionFactor() + ((LinearUnit) addend).getConversionFactor()); else return addend.times(this); } @Override public LinearUnit reciprocal() { return this.toExponent(-1); } /** * Multiplies this unit by a scalar. * * @param multiplier * scalar to multiply by * @return product * @since 2018-12-23 * @since v0.1.0 */ public LinearUnit times(final double multiplier) { return new LinearUnit(this.getBase(), this.getConversionFactor() * multiplier); } /** * Multiplies this unit by another unit. * * @param other * unit to multiply by= * @return product of two units * @throws NullPointerException * if other is null * @since 2018-12-22 * @since v0.1.0 */ public LinearUnit times(final LinearUnit other) { Objects.requireNonNull(other, "other must not be null"); final BaseUnit base = this.getBase().times(other.getBase()); return new LinearUnit(base, this.getConversionFactor() * other.getConversionFactor()); } @Override public OperatableUnit times(final OperatableUnit multiplier) { Objects.requireNonNull(multiplier, "multiplier must not be null."); // reject multipliers that cannot be muliplied by this unit if (!this.getSystem().equals(multiplier.getSystem())) throw new IllegalArgumentException(String .format("Incompatible units for multiplication or division \"%s\" and \"%s\".", this, multiplier)); // multiply the units if (multiplier instanceof BaseUnit) { final BaseUnit newBase = this.getBase().times((BaseUnit) multiplier); return new LinearUnit(newBase, this.getConversionFactor()); } else if (multiplier instanceof LinearUnit) { final BaseUnit base = this.getBase().times(multiplier.getBase()); return new LinearUnit(base, this.getConversionFactor() * ((LinearUnit) multiplier).getConversionFactor()); } else return multiplier.times(this); } /** * Returns this unit but to an exponent. * * @param exponent * exponent to exponientate unit to * @return exponientated unit * @since 2019-01-15 * @since v0.1.0 */ @Override public LinearUnit toExponent(final int exponent) { return new LinearUnit(this.getBase().toExponent(exponent), Math.pow(this.conversionFactor, exponent)); } @Override public String toString() { return super.toString() + String.format(" (equal to %s * base)", this.getConversionFactor()); } }