From 54ab9c05234b09547e2a01b1eab812420c6a3dda Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Thu, 17 Oct 2019 14:25:17 -0400
Subject: Implemented the new Units system
Fahrenheit has temporarily been removed; it will be back.
---
src/org/unitConverter/unit/LinearUnit.java | 166 ++++++++++++++---------------
1 file changed, 80 insertions(+), 86 deletions(-)
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 1b1ac97..c397250 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -18,73 +18,78 @@ package org.unitConverter.unit;
import java.util.Objects;
-import org.unitConverter.dimension.UnitDimension;
import org.unitConverter.math.DecimalComparison;
+import org.unitConverter.math.ObjectProduct;
/**
- * A unit that is equal to a certain number multiplied by its base.
- *
- * {@code LinearUnit} does not have any public constructors or static factories. In order to obtain a {@code LinearUnit}
- * instance, multiply its base by the conversion factor. Example:
- *
- *
- * LinearUnit foot = METRE.times(0.3048);
- *
- *
- * (where {@code METRE} is a {@code BaseUnit} instance)
- *
+ * A unit that can be expressed as a product of its base and a number. For example, kilometres, inches and pounds.
*
* @author Adrien Hopkins
- * @since 2018-12-22
- * @since v0.1.0
+ * @since 2019-10-16
*/
-public class LinearUnit extends AbstractUnit {
+public final class LinearUnit extends Unit {
/**
- * The value of one of this unit in this unit's base unit
+ * Gets a {@code LinearUnit} from a unit and a value. For example, converts '59 °F' to a linear unit with the value
+ * of '288.15 K'
*
- * @since 2018-12-22
- * @since v0.1.0
+ * @param unit
+ * unit to convert
+ * @param value
+ * value to convert
+ * @return value expressed as a {@code LinearUnit}
+ * @since 2019-10-16
*/
- private final double conversionFactor;
+ public static LinearUnit fromUnitValue(final Unit unit, final double value) {
+ return new LinearUnit(unit.getBase(), unit.convertToBase(value));
+ }
/**
+ * Gets a {@code LinearUnit} from a unit base and a conversion factor. In other words, gets the product of
+ * {@code unitBase} and {@code conversionFactor}, expressed as a {@code LinearUnit}.
*
- * Creates the {@code LinearUnit}.
- *
- * @param base
- * unit's base
+ * @param unitBase
+ * unit base to multiply by
* @param conversionFactor
- * value of one of this unit in its base
- * @since 2018-12-23
- * @since v0.1.0
+ * number to multiply base by
+ * @return product of base and conversion factor
+ * @since 2019-10-16
*/
- LinearUnit(final BaseUnit base, final double conversionFactor) {
- super(base);
- this.conversionFactor = conversionFactor;
+ public static LinearUnit valueOf(final ObjectProduct unitBase, final double conversionFactor) {
+ return new LinearUnit(unitBase, conversionFactor);
}
/**
- * Creates the {@code LinearUnit} as a base unit.
+ * The value of this unit as represented in its base form. Mathematically,
*
- * @param dimension
- * dimension measured by unit
- * @param system
- * system unit is part of
- * @since 2019-01-25
- * @since v0.1.0
+ *
+ * this = conversionFactor * getBase()
+ *
+ *
+ * @since 2019-10-16
+ */
+ private final double conversionFactor;
+
+ /**
+ * Creates the {@code LinearUnit}.
+ *
+ * @param unitBase
+ * base of linear unit
+ * @param conversionFactor
+ * conversion factor between base and unit
+ * @since 2019-10-16
*/
- LinearUnit(final UnitDimension dimension, final UnitSystem system, final double conversionFactor) {
- super(dimension, system);
+ private LinearUnit(final ObjectProduct unitBase, final double conversionFactor) {
+ super(unitBase);
this.conversionFactor = conversionFactor;
}
@Override
- public double convertFromBase(final double value) {
+ protected double convertFromBase(final double value) {
return value / this.getConversionFactor();
}
@Override
- public double convertToBase(final double value) {
+ protected double convertToBase(final double value) {
return value * this.getConversionFactor();
}
@@ -98,21 +103,15 @@ public class LinearUnit extends AbstractUnit {
* @since v0.1.0
*/
public LinearUnit dividedBy(final double divisor) {
- return new LinearUnit(this.getBase(), this.getConversionFactor() / divisor);
+ return valueOf(this.getBase(), this.getConversionFactor() / divisor);
}
/**
* Returns the quotient of this unit and another.
- *
- * Two units can be divided if they are part of the same unit system. If {@code divisor} does not meet this
- * condition, an {@code IllegalArgumentException} should be thrown.
- *
*
* @param divisor
* unit to divide by
* @return quotient of two units
- * @throws IllegalArgumentException
- * if {@code divisor} is not compatible for division as described above
* @throws NullPointerException
* if {@code divisor} is null
* @since 2018-12-22
@@ -121,14 +120,9 @@ public class LinearUnit extends AbstractUnit {
public LinearUnit dividedBy(final LinearUnit divisor) {
Objects.requireNonNull(divisor, "other must not be null");
- // check that these units can be multiplied
- if (!this.getSystem().equals(divisor.getSystem()))
- throw new IllegalArgumentException(
- String.format("Incompatible units for division \"%s\" and \"%s\".", this, divisor));
-
// divide the units
- final BaseUnit base = this.getBase().dividedBy(divisor.getBase());
- return new LinearUnit(base, this.getConversionFactor() / divisor.getConversionFactor());
+ final ObjectProduct base = this.getBase().dividedBy(divisor.getBase());
+ return valueOf(base, this.getConversionFactor() / divisor.getConversionFactor());
}
@Override
@@ -136,28 +130,38 @@ public class LinearUnit extends AbstractUnit {
if (!(obj instanceof LinearUnit))
return false;
final LinearUnit other = (LinearUnit) obj;
- return Objects.equals(this.getSystem(), other.getSystem())
- && Objects.equals(this.getDimension(), other.getDimension())
+ return Objects.equals(this.getBase(), other.getBase())
&& DecimalComparison.equals(this.getConversionFactor(), other.getConversionFactor());
}
/**
- * @return conversion factor between this unit and its base
- * @since 2018-12-22
- * @since v0.1.0
+ * @return conversion factor
+ * @since 2019-10-16
*/
- public final double getConversionFactor() {
+ public double getConversionFactor() {
return this.conversionFactor;
}
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = result * prime + this.getSystem().hashCode();
- result = result * prime + this.getDimension().hashCode();
- result = result * prime + Double.hashCode(this.getConversionFactor());
- return result;
+ return 31 * this.getBase().hashCode() + DecimalComparison.hash(this.getConversionFactor());
+ }
+
+ /**
+ * @return whether this unit is equivalent to a {@code BaseUnit} (i.e. there is a {@code BaseUnit b} where
+ * {@code b.asLinearUnit().equals(this)} returns {@code true}.)
+ * @since 2019-10-16
+ */
+ public boolean isBase() {
+ return this.isCoherent() && this.getBase().isSingleObject();
+ }
+
+ /**
+ * @return whether this unit is coherent (i.e. has conversion factor 1)
+ * @since 2019-10-16
+ */
+ public boolean isCoherent() {
+ return this.getConversionFactor() == 1;
}
/**
@@ -186,7 +190,7 @@ public class LinearUnit extends AbstractUnit {
String.format("Incompatible units for subtraction \"%s\" and \"%s\".", this, subtrahendend));
// add the units
- return new LinearUnit(this.getBase(), this.getConversionFactor() - subtrahendend.getConversionFactor());
+ return valueOf(this.getBase(), this.getConversionFactor() - subtrahendend.getConversionFactor());
}
/**
@@ -215,7 +219,7 @@ public class LinearUnit extends AbstractUnit {
String.format("Incompatible units for addition \"%s\" and \"%s\".", this, addend));
// add the units
- return new LinearUnit(this.getBase(), this.getConversionFactor() + addend.getConversionFactor());
+ return valueOf(this.getBase(), this.getConversionFactor() + addend.getConversionFactor());
}
/**
@@ -228,21 +232,15 @@ public class LinearUnit extends AbstractUnit {
* @since v0.1.0
*/
public LinearUnit times(final double multiplier) {
- return new LinearUnit(this.getBase(), this.getConversionFactor() * multiplier);
+ return valueOf(this.getBase(), this.getConversionFactor() * multiplier);
}
/**
* Returns the product of this unit and another.
- *
- * Two units can be multiplied if they are part of the same unit system. If {@code multiplier} does not meet this
- * condition, an {@code IllegalArgumentException} should be thrown.
- *
*
* @param multiplier
* unit to multiply by
* @return product of two units
- * @throws IllegalArgumentException
- * if {@code multiplier} is not compatible for multiplication as described above
* @throws NullPointerException
* if {@code multiplier} is null
* @since 2018-12-22
@@ -251,32 +249,28 @@ public class LinearUnit extends AbstractUnit {
public LinearUnit times(final LinearUnit multiplier) {
Objects.requireNonNull(multiplier, "other must not be null");
- // check that these units can be multiplied
- if (!this.getSystem().equals(multiplier.getSystem()))
- throw new IllegalArgumentException(
- String.format("Incompatible units for multiplication \"%s\" and \"%s\".", this, multiplier));
-
// multiply the units
- final BaseUnit base = this.getBase().times(multiplier.getBase());
- return new LinearUnit(base, this.getConversionFactor() * multiplier.getConversionFactor());
+ final ObjectProduct base = this.getBase().times(multiplier.getBase());
+ return valueOf(base, this.getConversionFactor() * multiplier.getConversionFactor());
}
/**
* Returns this unit but to an exponent.
*
* @param exponent
- * exponent to exponientate unit to
- * @return exponientated unit
+ * exponent to exponentiate unit to
+ * @return exponentiated unit
* @since 2019-01-15
* @since v0.1.0
*/
public LinearUnit toExponent(final int exponent) {
- return new LinearUnit(this.getBase().toExponent(exponent), Math.pow(this.conversionFactor, exponent));
+ return valueOf(this.getBase().toExponent(exponent), Math.pow(this.conversionFactor, exponent));
}
+ // returns a definition of the unit
@Override
public String toString() {
- return super.toString() + String.format(" (equal to %s * base)", this.getConversionFactor());
+ return Double.toString(this.conversionFactor) + " * " + this.getBase().toString(BaseUnit::getSymbol);
}
/**
--
cgit v1.2.3
From 1bf43ad95e70019a69e91e09ff74f677082ed6f5 Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Mon, 21 Oct 2019 15:17:50 -0400
Subject: Made improvements and corrections to the documentation.
---
src/org/unitConverter/converterGUI/UnitConverterGUI.java | 2 +-
src/org/unitConverter/converterGUI/package-info.java | 2 +-
src/org/unitConverter/math/package-info.java | 3 ++-
src/org/unitConverter/unit/LinearUnit.java | 8 ++++----
src/org/unitConverter/unit/Unit.java | 14 ++++++++++++--
src/org/unitConverter/unit/package-info.java | 3 ++-
6 files changed, 22 insertions(+), 10 deletions(-)
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/converterGUI/UnitConverterGUI.java b/src/org/unitConverter/converterGUI/UnitConverterGUI.java
index 4598971..511e47b 100644
--- a/src/org/unitConverter/converterGUI/UnitConverterGUI.java
+++ b/src/org/unitConverter/converterGUI/UnitConverterGUI.java
@@ -47,8 +47,8 @@ import org.unitConverter.unit.BaseDimension;
import org.unitConverter.unit.LinearUnit;
import org.unitConverter.unit.SI;
import org.unitConverter.unit.Unit;
-import org.unitConverter.unit.UnitPrefix;
import org.unitConverter.unit.UnitDatabase;
+import org.unitConverter.unit.UnitPrefix;
/**
* @author Adrien Hopkins
diff --git a/src/org/unitConverter/converterGUI/package-info.java b/src/org/unitConverter/converterGUI/package-info.java
index 1555291..d85ecab 100644
--- a/src/org/unitConverter/converterGUI/package-info.java
+++ b/src/org/unitConverter/converterGUI/package-info.java
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
/**
- * All classes that work to convert units.
+ * The GUI interface of the Unit Converter.
*
* @author Adrien Hopkins
* @since 2019-01-25
diff --git a/src/org/unitConverter/math/package-info.java b/src/org/unitConverter/math/package-info.java
index 65d6b23..65727e4 100644
--- a/src/org/unitConverter/math/package-info.java
+++ b/src/org/unitConverter/math/package-info.java
@@ -15,9 +15,10 @@
* along with this program. If not, see .
*/
/**
- * A module that is capable of parsing expressions of things, like mathematical expressions or unit expressions.
+ * Supplementary classes that are not related to units, but are necessary for their function.
*
* @author Adrien Hopkins
* @since 2019-03-14
+ * @since v0.2.0
*/
package org.unitConverter.math;
\ No newline at end of file
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index c397250..1918d6b 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -167,8 +167,8 @@ public final class LinearUnit extends Unit {
/**
* Returns the difference of this unit and another.
*
- * Two units can be subtracted if they have the same base. If {@code subtrahend} does not meet this condition, an
- * {@code IllegalArgumentException} will be thrown.
+ * Two units can be subtracted if they have the same base. Note that {@link #canConvertTo} can be used to determine
+ * this. If {@code subtrahend} does not meet this condition, an {@code IllegalArgumentException} will be thrown.
*
*
* @param subtrahend
@@ -196,8 +196,8 @@ public final class LinearUnit extends Unit {
/**
* Returns the sum of this unit and another.
*
- * Two units can be added if they have the same base. If {@code addend} does not meet this condition, an
- * {@code IllegalArgumentException} will be thrown.
+ * Two units can be added if they have the same base. Note that {@link #canConvertTo} can be used to determine this.
+ * If {@code addend} does not meet this condition, an {@code IllegalArgumentException} will be thrown.
*
*
* @param addend
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java
index d4eb86e..7971a41 100644
--- a/src/org/unitConverter/unit/Unit.java
+++ b/src/org/unitConverter/unit/Unit.java
@@ -52,7 +52,7 @@ public abstract class Unit {
* @throws NullPointerException
* if any argument is null
*/
- public static Unit fromConversionFunctions(final ObjectProduct base,
+ public static final Unit fromConversionFunctions(final ObjectProduct base,
final DoubleUnaryOperator converterFrom, final DoubleUnaryOperator converterTo) {
return FunctionalUnit.valueOf(base, converterFrom, converterTo);
}
@@ -121,6 +121,9 @@ public abstract class Unit {
* If this unit is a base unit, this method should return {@code value}.
*
*
+ * @implSpec This method is used by {@link #convertTo}, and its behaviour affects the behaviour of
+ * {@code convertTo}.
+ *
* @param value
* value expressed in base unit
* @return value expressed in this unit
@@ -132,6 +135,10 @@ public abstract class Unit {
/**
* Converts a value expressed in this unit to a value expressed in {@code other}.
*
+ * @implSpec If unit conversion is possible, this implementation returns
+ * {@code other.convertFromBase(this.convertToBase(value))}. Therefore, overriding either of those methods
+ * will change the output of this method.
+ *
* @param other
* unit to convert to
* @param value
@@ -140,7 +147,7 @@ public abstract class Unit {
* @since 2019-05-22
* @throws IllegalArgumentException
* if {@code other} is incompatible for conversion with this unit (as tested by
- * {@link IUnit#canConvertTo}).
+ * {@link Unit#canConvertTo}).
* @throws NullPointerException
* if other is null
*/
@@ -162,6 +169,9 @@ public abstract class Unit {
* If this unit is a base unit, this method should return {@code value}.
*
*
+ * @implSpec This method is used by {@link #convertTo}, and its behaviour affects the behaviour of
+ * {@code convertTo}.
+ *
* @param value
* value expressed in this unit
* @return value expressed in base unit
diff --git a/src/org/unitConverter/unit/package-info.java b/src/org/unitConverter/unit/package-info.java
index 2d83e1f..2f0e097 100644
--- a/src/org/unitConverter/unit/package-info.java
+++ b/src/org/unitConverter/unit/package-info.java
@@ -15,9 +15,10 @@
* along with this program. If not, see .
*/
/**
- * The new definition for units.
+ * Everything to do with the units that make up Unit Converter.
*
* @author Adrien Hopkins
* @since 2019-10-16
+ * @since v0.1.0
*/
package org.unitConverter.unit;
\ No newline at end of file
--
cgit v1.2.3
From 3c23fd15b88396868101457256173c0c2c29df5c Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Mon, 21 Oct 2019 21:27:59 -0400
Subject: Added unit names and the NameSymbol.
---
src/org/unitConverter/unit/BaseUnit.java | 54 ++--
src/org/unitConverter/unit/FunctionalUnit.java | 45 ++--
src/org/unitConverter/unit/LinearUnit.java | 12 +-
src/org/unitConverter/unit/Unit.java | 329 +++++++++++++++++++++++--
4 files changed, 374 insertions(+), 66 deletions(-)
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/unit/BaseUnit.java b/src/org/unitConverter/unit/BaseUnit.java
index 8f44861..8fd0664 100644
--- a/src/org/unitConverter/unit/BaseUnit.java
+++ b/src/org/unitConverter/unit/BaseUnit.java
@@ -16,10 +16,15 @@
*/
package org.unitConverter.unit;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
/**
* A unit that other units are defined by.
+ *
+ * Note that BaseUnits must have names and symbols. This is because they are used for toString code. Therefore,
+ * the Optionals provided by {@link #getPrimaryName} and {@link #getSymbol} will always contain a value.
*
* @author Adrien Hopkins
* @since 2019-10-16
@@ -38,19 +43,34 @@ public final class BaseUnit extends Unit {
* @since 2019-10-16
*/
public static BaseUnit valueOf(final BaseDimension dimension, final String name, final String symbol) {
- return new BaseUnit(dimension, name, symbol);
+ return new BaseUnit(dimension, name, symbol, new HashSet<>());
+ }
+
+ /**
+ * Gets a base unit from the dimension it measures, its name and its symbol.
+ *
+ * @param dimension
+ * dimension measured by this unit
+ * @param name
+ * name of unit
+ * @param symbol
+ * symbol of unit
+ * @return base unit
+ * @since 2019-10-21
+ */
+ public static BaseUnit valueOf(final BaseDimension dimension, final String name, final String symbol,
+ final Set otherNames) {
+ return new BaseUnit(dimension, name, symbol, otherNames);
}
private final BaseDimension dimension;
- private final String name;
- private final String symbol;
/**
* Creates the {@code BaseUnit}.
*
* @param dimension
* dimension of unit
- * @param name
+ * @param primaryName
* name of unit
* @param symbol
* symbol of unit
@@ -58,11 +78,10 @@ public final class BaseUnit extends Unit {
* if any argument is null
* @since 2019-10-16
*/
- private BaseUnit(final BaseDimension dimension, final String name, final String symbol) {
- super();
+ private BaseUnit(final BaseDimension dimension, final String primaryName, final String symbol,
+ final Set otherNames) {
+ super(primaryName, symbol, otherNames);
this.dimension = Objects.requireNonNull(dimension, "dimension must not be null.");
- this.name = Objects.requireNonNull(name, "name must not be null.");
- this.symbol = Objects.requireNonNull(symbol, "symbol must not be null.");
}
/**
@@ -94,24 +113,9 @@ public final class BaseUnit extends Unit {
return this.dimension;
}
- /**
- * @return name
- * @since 2019-10-16
- */
- public final String getName() {
- return this.name;
- }
-
- /**
- * @return symbol
- * @since 2019-10-16
- */
- public final String getSymbol() {
- return this.symbol;
- }
-
@Override
public String toString() {
- return String.format("%s (%s)", this.getName(), this.getSymbol());
+ return this.getPrimaryName().orElse("Unnamed unit")
+ + (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "");
}
}
diff --git a/src/org/unitConverter/unit/FunctionalUnit.java b/src/org/unitConverter/unit/FunctionalUnit.java
index 7ddd876..e2ab6e7 100644
--- a/src/org/unitConverter/unit/FunctionalUnit.java
+++ b/src/org/unitConverter/unit/FunctionalUnit.java
@@ -29,7 +29,21 @@ import org.unitConverter.math.ObjectProduct;
*/
final class FunctionalUnit extends Unit {
/**
- * Returns a unit from its base and the functions it uses to convert to and from its base.
+ * A function that accepts a value expressed in the unit's base and returns that value expressed in this unit.
+ *
+ * @since 2019-05-22
+ */
+ private final DoubleUnaryOperator converterFrom;
+
+ /**
+ * A function that accepts a value expressed in the unit and returns that value expressed in the unit's base.
+ *
+ * @since 2019-05-22
+ */
+ private final DoubleUnaryOperator converterTo;
+
+ /**
+ * Creates the {@code FunctionalUnit}.
*
* @param base
* unit's base
@@ -39,30 +53,17 @@ final class FunctionalUnit extends Unit {
* @param converterTo
* function that accepts a value expressed in the unit and returns that value expressed in the unit's
* base.
- * @return a unit that uses the provided functions to convert.
- * @since 2019-05-22
* @throws NullPointerException
* if any argument is null
+ * @since 2019-05-22
*/
- public static FunctionalUnit valueOf(final ObjectProduct base, final DoubleUnaryOperator converterFrom,
+ public FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom,
final DoubleUnaryOperator converterTo) {
- return new FunctionalUnit(base, converterFrom, converterTo);
+ super(base, NameSymbol.EMPTY);
+ this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null.");
+ this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null.");
}
- /**
- * A function that accepts a value expressed in the unit's base and returns that value expressed in this unit.
- *
- * @since 2019-05-22
- */
- private final DoubleUnaryOperator converterFrom;
-
- /**
- * A function that accepts a value expressed in the unit and returns that value expressed in the unit's base.
- *
- * @since 2019-05-22
- */
- private final DoubleUnaryOperator converterTo;
-
/**
* Creates the {@code FunctionalUnit}.
*
@@ -78,9 +79,9 @@ final class FunctionalUnit extends Unit {
* if any argument is null
* @since 2019-05-22
*/
- private FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom,
- final DoubleUnaryOperator converterTo) {
- super(base);
+ public FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom,
+ final DoubleUnaryOperator converterTo, final NameSymbol ns) {
+ super(base, ns);
this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null.");
this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null.");
}
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 1918d6b..2a55dea 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -40,7 +40,7 @@ public final class LinearUnit extends Unit {
* @since 2019-10-16
*/
public static LinearUnit fromUnitValue(final Unit unit, final double value) {
- return new LinearUnit(unit.getBase(), unit.convertToBase(value));
+ return new LinearUnit(unit.getBase(), NameSymbol.EMPTY, unit.convertToBase(value));
}
/**
@@ -55,7 +55,7 @@ public final class LinearUnit extends Unit {
* @since 2019-10-16
*/
public static LinearUnit valueOf(final ObjectProduct unitBase, final double conversionFactor) {
- return new LinearUnit(unitBase, conversionFactor);
+ return new LinearUnit(unitBase, NameSymbol.EMPTY, conversionFactor);
}
/**
@@ -78,8 +78,8 @@ public final class LinearUnit extends Unit {
* conversion factor between base and unit
* @since 2019-10-16
*/
- private LinearUnit(final ObjectProduct unitBase, final double conversionFactor) {
- super(unitBase);
+ private LinearUnit(final ObjectProduct unitBase, final NameSymbol ns, final double conversionFactor) {
+ super(unitBase, ns);
this.conversionFactor = conversionFactor;
}
@@ -270,7 +270,9 @@ public final class LinearUnit extends Unit {
// returns a definition of the unit
@Override
public String toString() {
- return Double.toString(this.conversionFactor) + " * " + this.getBase().toString(BaseUnit::getSymbol);
+ return this.getPrimaryName().orElse("Unnamed unit")
+ + (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "") + ", "
+ + Double.toString(this.conversionFactor) + " * " + this.getBase().toString(u -> u.getSymbol().get());
}
/**
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java
index 7971a41..d65e14f 100644
--- a/src/org/unitConverter/unit/Unit.java
+++ b/src/org/unitConverter/unit/Unit.java
@@ -16,9 +16,14 @@
*/
package org.unitConverter.unit;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
import java.util.function.DoubleUnaryOperator;
import org.unitConverter.math.ObjectProduct;
@@ -30,6 +35,222 @@ import org.unitConverter.math.ObjectProduct;
* @since 2019-10-16
*/
public abstract class Unit {
+ /**
+ * A class that can be used to specify names and a symbol for a unit.
+ *
+ * @author Adrien Hopkins
+ * @since 2019-10-21
+ */
+ public static final class NameSymbol {
+ public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), Optional.empty(), new HashSet<>());
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and no other names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if name or symbol is null
+ */
+ public static final NameSymbol of(final String name, final String symbol) {
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), new HashSet<>());
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final Set otherNames) {
+ return new NameSymbol(Optional.of(name), Optional.of(symbol),
+ new HashSet<>(Objects.requireNonNull(otherNames, "otherNames must not be null.")));
+ }
+
+ /**
+ * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String... otherNames) {
+ return new NameSymbol(Optional.of(name), Optional.of(symbol),
+ new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, "otherNames must not be null."))));
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and an additional name.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @param name2
+ * alternate name
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String name2) {
+ final Set otherNames = new HashSet<>();
+ otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @param name2
+ * alternate name
+ * @param name3
+ * alternate name
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String name2,
+ final String name3) {
+ final Set otherNames = new HashSet<>();
+ otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
+ otherNames.add(Objects.requireNonNull(name3, "name3 must not be null."));
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @param name2
+ * alternate name
+ * @param name3
+ * alternate name
+ * @param name4
+ * alternate name
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String name2,
+ final String name3, final String name4) {
+ final Set otherNames = new HashSet<>();
+ otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
+ otherNames.add(Objects.requireNonNull(name3, "name3 must not be null."));
+ otherNames.add(Objects.requireNonNull(name4, "name4 must not be null."));
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, no symbol, and no other names.
+ *
+ * @param name
+ * name to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if name is null
+ */
+ public static final NameSymbol ofName(final String name) {
+ return new NameSymbol(Optional.of(name), Optional.empty(), new HashSet<>());
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a symbol and no names.
+ *
+ * @param symbol
+ * symbol to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if symbol is null
+ */
+ public static final NameSymbol ofSymbol(final String symbol) {
+ return new NameSymbol(Optional.empty(), Optional.of(symbol), new HashSet<>());
+ }
+
+ private final Optional primaryName;
+ private final Optional symbol;
+
+ private final Set otherNames;
+
+ /**
+ * Creates the {@code NameSymbol}.
+ *
+ * @param primaryName
+ * primary name of unit
+ * @param symbol
+ * symbol used to represent unit
+ * @param otherNames
+ * other names and/or spellings
+ * @since 2019-10-21
+ */
+ private NameSymbol(final Optional primaryName, final Optional symbol,
+ final Set otherNames) {
+ this.primaryName = primaryName;
+ this.symbol = symbol;
+ this.otherNames = Collections.unmodifiableSet(otherNames);
+ }
+
+ /**
+ * @return otherNames
+ * @since 2019-10-21
+ */
+ public final Set getOtherNames() {
+ return this.otherNames;
+ }
+
+ /**
+ * @return primaryName
+ * @since 2019-10-21
+ */
+ public final Optional getPrimaryName() {
+ return this.primaryName;
+ }
+
+ /**
+ * @return symbol
+ * @since 2019-10-21
+ */
+ public final Optional getSymbol() {
+ return this.symbol;
+ }
+ }
+
/**
* Returns a unit from its base and the functions it uses to convert to and from its base.
*
@@ -54,7 +275,36 @@ public abstract class Unit {
*/
public static final Unit fromConversionFunctions(final ObjectProduct base,
final DoubleUnaryOperator converterFrom, final DoubleUnaryOperator converterTo) {
- return FunctionalUnit.valueOf(base, converterFrom, converterTo);
+ return new FunctionalUnit(base, converterFrom, converterTo);
+ }
+
+ /**
+ * Returns a unit from its base and the functions it uses to convert to and from its base.
+ *
+ *
+ * For example, to get a unit representing the degree Celsius, the following code can be used:
+ *
+ * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);}
+ *
+ *
+ * @param base
+ * unit's base
+ * @param converterFrom
+ * function that accepts a value expressed in the unit's base and returns that value expressed in this
+ * unit.
+ * @param converterTo
+ * function that accepts a value expressed in the unit and returns that value expressed in the unit's
+ * base.
+ * @param ns
+ * names and symbol of unit
+ * @return a unit that uses the provided functions to convert.
+ * @since 2019-05-22
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final Unit fromConversionFunctions(final ObjectProduct base,
+ final DoubleUnaryOperator converterFrom, final DoubleUnaryOperator converterTo, final NameSymbol ns) {
+ return new FunctionalUnit(base, converterFrom, converterTo, ns);
}
/**
@@ -64,6 +314,21 @@ public abstract class Unit {
*/
private final ObjectProduct unitBase;
+ /**
+ * The primary name used by this unit.
+ */
+ private final Optional primaryName;
+
+ /**
+ * A short symbol used to represent this unit.
+ */
+ private final Optional symbol;
+
+ /**
+ * A set of any additional names and/or spellings that the unit uses.
+ */
+ private final Set otherNames;
+
/**
* Cache storing the result of getDimension()
*
@@ -72,27 +337,37 @@ public abstract class Unit {
private transient ObjectProduct dimension = null;
/**
- * A constructor that constructs {@code BaseUnit} instances.
+ * Creates the {@code AbstractUnit}.
*
+ * @param unitBase
+ * base of unit
+ * @param ns
+ * names and symbol of unit
* @since 2019-10-16
+ * @throws NullPointerException
+ * if unitBase or ns is null
*/
- Unit() {
- if (this instanceof BaseUnit) {
- this.unitBase = ObjectProduct.oneOf((BaseUnit) this);
- } else
- throw new AssertionError();
+ protected Unit(final ObjectProduct unitBase, final NameSymbol ns) {
+ this.unitBase = Objects.requireNonNull(unitBase, "unitBase must not be null.");
+ this.primaryName = Objects.requireNonNull(ns, "ns must not be null.").getPrimaryName();
+ this.symbol = ns.getSymbol();
+ this.otherNames = ns.getOtherNames();
}
/**
- * Creates the {@code AbstractUnit}.
+ * A constructor that constructs {@code BaseUnit} instances.
*
- * @param unitBase
* @since 2019-10-16
- * @throws NullPointerException
- * if unitBase is null
*/
- protected Unit(final ObjectProduct unitBase) {
- this.unitBase = Objects.requireNonNull(unitBase, "unitBase must not be null.");
+ Unit(final String primaryName, final String symbol, final Set otherNames) {
+ if (this instanceof BaseUnit) {
+ this.unitBase = ObjectProduct.oneOf((BaseUnit) this);
+ } else
+ throw new AssertionError();
+ this.primaryName = Optional.of(primaryName);
+ this.symbol = Optional.of(symbol);
+ this.otherNames = Collections.unmodifiableSet(
+ new HashSet<>(Objects.requireNonNull(otherNames, "additionalNames must not be null.")));
}
/**
@@ -208,8 +483,34 @@ public abstract class Unit {
return this.dimension;
}
+ /**
+ * @return additionalNames
+ * @since 2019-10-21
+ */
+ public final Set getOtherNames() {
+ return this.otherNames;
+ }
+
+ /**
+ * @return primaryName
+ * @since 2019-10-21
+ */
+ public final Optional getPrimaryName() {
+ return this.primaryName;
+ }
+
+ /**
+ * @return symbol
+ * @since 2019-10-21
+ */
+ public final Optional getSymbol() {
+ return this.symbol;
+ }
+
@Override
public String toString() {
- return "Unit derived from base " + this.getBase().toString();
+ return this.getPrimaryName().orElse("Unnamed unit")
+ + (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "")
+ + ", derived from " + this.getBase().toString();
}
}
--
cgit v1.2.3
From 8ec94bea790cc010c29cd8de86e47117ff331979 Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Mon, 21 Oct 2019 21:41:26 -0400
Subject: Added new ways to create named units.
---
src/org/unitConverter/unit/BaseUnit.java | 11 ++++++
src/org/unitConverter/unit/LinearUnit.java | 56 ++++++++++++++++++++++++++++--
src/org/unitConverter/unit/Unit.java | 13 +++++++
3 files changed, 77 insertions(+), 3 deletions(-)
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/unit/BaseUnit.java b/src/org/unitConverter/unit/BaseUnit.java
index 8fd0664..e9ef3fa 100644
--- a/src/org/unitConverter/unit/BaseUnit.java
+++ b/src/org/unitConverter/unit/BaseUnit.java
@@ -118,4 +118,15 @@ public final class BaseUnit extends Unit {
return this.getPrimaryName().orElse("Unnamed unit")
+ (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "");
}
+
+ @Override
+ public BaseUnit withName(final NameSymbol ns) {
+ Objects.requireNonNull(ns, "ns must not be null.");
+ if (!ns.getPrimaryName().isPresent())
+ throw new IllegalArgumentException("BaseUnits must have primary names.");
+ if (!ns.getSymbol().isPresent())
+ throw new IllegalArgumentException("BaseUnits must have symbols.");
+ return BaseUnit.valueOf(this.getBaseDimension(), ns.getPrimaryName().get(), ns.getSymbol().get(),
+ ns.getOtherNames());
+ }
}
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 2a55dea..7b7338b 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -38,9 +38,32 @@ public final class LinearUnit extends Unit {
* value to convert
* @return value expressed as a {@code LinearUnit}
* @since 2019-10-16
+ * @throws NullPointerException
+ * if unit is null
*/
public static LinearUnit fromUnitValue(final Unit unit, final double value) {
- return new LinearUnit(unit.getBase(), NameSymbol.EMPTY, unit.convertToBase(value));
+ return new LinearUnit(Objects.requireNonNull(unit, "unit must not be null.").getBase(),
+ unit.convertToBase(value), NameSymbol.EMPTY);
+ }
+
+ /**
+ * Gets a {@code LinearUnit} from a unit and a value. For example, converts '59 °F' to a linear unit with the value
+ * of '288.15 K'
+ *
+ * @param unit
+ * unit to convert
+ * @param value
+ * value to convert
+ * @param ns
+ * name(s) and symbol of unit
+ * @return value expressed as a {@code LinearUnit}
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if unit or ns is null
+ */
+ public static LinearUnit fromUnitValue(final Unit unit, final double value, final NameSymbol ns) {
+ return new LinearUnit(Objects.requireNonNull(unit, "unit must not be null.").getBase(),
+ unit.convertToBase(value), ns);
}
/**
@@ -53,9 +76,31 @@ public final class LinearUnit extends Unit {
* number to multiply base by
* @return product of base and conversion factor
* @since 2019-10-16
+ * @throws NullPointerException
+ * if unitBase is null
*/
public static LinearUnit valueOf(final ObjectProduct unitBase, final double conversionFactor) {
- return new LinearUnit(unitBase, NameSymbol.EMPTY, conversionFactor);
+ return new LinearUnit(unitBase, conversionFactor, NameSymbol.EMPTY);
+ }
+
+ /**
+ * Gets a {@code LinearUnit} from a unit base and a conversion factor. In other words, gets the product of
+ * {@code unitBase} and {@code conversionFactor}, expressed as a {@code LinearUnit}.
+ *
+ * @param unitBase
+ * unit base to multiply by
+ * @param conversionFactor
+ * number to multiply base by
+ * @param ns
+ * name(s) and symbol of unit
+ * @return product of base and conversion factor
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if unitBase is null
+ */
+ public static LinearUnit valueOf(final ObjectProduct unitBase, final double conversionFactor,
+ final NameSymbol ns) {
+ return new LinearUnit(unitBase, conversionFactor, ns);
}
/**
@@ -78,7 +123,7 @@ public final class LinearUnit extends Unit {
* conversion factor between base and unit
* @since 2019-10-16
*/
- private LinearUnit(final ObjectProduct unitBase, final NameSymbol ns, final double conversionFactor) {
+ private LinearUnit(final ObjectProduct unitBase, final double conversionFactor, final NameSymbol ns) {
super(unitBase, ns);
this.conversionFactor = conversionFactor;
}
@@ -275,6 +320,11 @@ public final class LinearUnit extends Unit {
+ Double.toString(this.conversionFactor) + " * " + this.getBase().toString(u -> u.getSymbol().get());
}
+ @Override
+ public LinearUnit withName(final NameSymbol ns) {
+ return valueOf(this.getBase(), this.getConversionFactor(), ns);
+ }
+
/**
* Returns the result of applying {@code prefix} to this unit.
*
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java
index d65e14f..d848ea1 100644
--- a/src/org/unitConverter/unit/Unit.java
+++ b/src/org/unitConverter/unit/Unit.java
@@ -513,4 +513,17 @@ public abstract class Unit {
+ (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "")
+ ", derived from " + this.getBase().toString();
}
+
+ /**
+ * @param ns
+ * name(s) and symbol to use
+ * @return a copy of this unit with provided name(s) and symbol
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if ns is null
+ */
+ public Unit withName(final NameSymbol ns) {
+ return fromConversionFunctions(this.getBase(), this::convertFromBase, this::convertToBase,
+ Objects.requireNonNull(ns, "ns must not be null."));
+ }
}
--
cgit v1.2.3
From a966676c629f7f14fcbba82a9ada5e2cbeca8314 Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Tue, 26 Nov 2019 15:20:04 -0500
Subject: Updated the documentation of existing classes.
---
src/org/unitConverter/math/ObjectProduct.java | 8 ++++++++
src/org/unitConverter/unit/BaseDimension.java | 6 ++++++
src/org/unitConverter/unit/BaseUnit.java | 3 +++
src/org/unitConverter/unit/FunctionalUnit.java | 10 ++++++++++
src/org/unitConverter/unit/LinearUnit.java | 27 ++++++++++++++++++++++++--
src/org/unitConverter/unit/SI.java | 24 +++++++++++++----------
src/org/unitConverter/unit/Unit.java | 3 ++-
src/org/unitConverter/unit/UnitDatabase.java | 7 +++++--
src/org/unitConverter/unit/UnitPrefix.java | 19 +++++++++++++++++-
9 files changed, 91 insertions(+), 16 deletions(-)
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/math/ObjectProduct.java b/src/org/unitConverter/math/ObjectProduct.java
index 0cf89ec..29d0f6e 100644
--- a/src/org/unitConverter/math/ObjectProduct.java
+++ b/src/org/unitConverter/math/ObjectProduct.java
@@ -238,6 +238,14 @@ public final class ObjectProduct {
return new ObjectProduct<>(map);
}
+ /**
+ * Converts this product to a string using the objects' {@link Object#toString()} method. If objects have a long
+ * toString representation, it is recommended to use {@link #toString(Function)} instead to shorten the returned
+ * string.
+ *
+ *
+ * {@inheritDoc}
+ */
@Override
public String toString() {
return this.toString(Object::toString);
diff --git a/src/org/unitConverter/unit/BaseDimension.java b/src/org/unitConverter/unit/BaseDimension.java
index 35acd18..8e63a17 100644
--- a/src/org/unitConverter/unit/BaseDimension.java
+++ b/src/org/unitConverter/unit/BaseDimension.java
@@ -39,7 +39,13 @@ public final class BaseDimension {
return new BaseDimension(name, symbol);
}
+ /**
+ * The name of the dimension.
+ */
private final String name;
+ /**
+ * The symbol used by the dimension. Symbols should be short, generally one or two characters.
+ */
private final String symbol;
/**
diff --git a/src/org/unitConverter/unit/BaseUnit.java b/src/org/unitConverter/unit/BaseUnit.java
index e9ef3fa..d9f7965 100644
--- a/src/org/unitConverter/unit/BaseUnit.java
+++ b/src/org/unitConverter/unit/BaseUnit.java
@@ -63,6 +63,9 @@ public final class BaseUnit extends Unit {
return new BaseUnit(dimension, name, symbol, otherNames);
}
+ /**
+ * The dimension measured by this base unit.
+ */
private final BaseDimension dimension;
/**
diff --git a/src/org/unitConverter/unit/FunctionalUnit.java b/src/org/unitConverter/unit/FunctionalUnit.java
index e2ab6e7..586e0d7 100644
--- a/src/org/unitConverter/unit/FunctionalUnit.java
+++ b/src/org/unitConverter/unit/FunctionalUnit.java
@@ -86,11 +86,21 @@ final class FunctionalUnit extends Unit {
this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null.");
}
+ /**
+ * {@inheritDoc}
+ *
+ * Uses {@code converterFrom} to convert.
+ */
@Override
public double convertFromBase(final double value) {
return this.converterFrom.applyAsDouble(value);
}
+ /**
+ * {@inheritDoc}
+ *
+ * Uses {@code converterTo} to convert.
+ */
@Override
public double convertToBase(final double value) {
return this.converterTo.applyAsDouble(value);
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 7b7338b..1532fc4 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -128,11 +128,21 @@ public final class LinearUnit extends Unit {
this.conversionFactor = conversionFactor;
}
+ /**
+ * {@inheritDoc}
+ *
+ * Converts by dividing by {@code conversionFactor}
+ */
@Override
protected double convertFromBase(final double value) {
return value / this.getConversionFactor();
}
+ /**
+ * {@inheritDoc}
+ *
+ * Converts by multiplying by {@code conversionFactor}
+ */
@Override
protected double convertToBase(final double value) {
return value * this.getConversionFactor();
@@ -170,6 +180,11 @@ public final class LinearUnit extends Unit {
return valueOf(base, this.getConversionFactor() / divisor.getConversionFactor());
}
+ /**
+ * {@inheritDoc}
+ *
+ * Uses the base and conversion factor of units to test for equality.
+ */
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof LinearUnit))
@@ -187,6 +202,11 @@ public final class LinearUnit extends Unit {
return this.conversionFactor;
}
+ /**
+ * {@inheritDoc}
+ *
+ * Uses the base and conversion factor to compute a hash code.
+ */
@Override
public int hashCode() {
return 31 * this.getBase().hashCode() + DecimalComparison.hash(this.getConversionFactor());
@@ -234,7 +254,7 @@ public final class LinearUnit extends Unit {
throw new IllegalArgumentException(
String.format("Incompatible units for subtraction \"%s\" and \"%s\".", this, subtrahendend));
- // add the units
+ // subtract the units
return valueOf(this.getBase(), this.getConversionFactor() - subtrahendend.getConversionFactor());
}
@@ -312,7 +332,10 @@ public final class LinearUnit extends Unit {
return valueOf(this.getBase().toExponent(exponent), Math.pow(this.conversionFactor, exponent));
}
- // returns a definition of the unit
+ /**
+ * @return a string providing a definition of this unit
+ * @since 2019-10-21
+ */
@Override
public String toString() {
return this.getPrimaryName().orElse("Unnamed unit")
diff --git a/src/org/unitConverter/unit/SI.java b/src/org/unitConverter/unit/SI.java
index 45a81e2..19d63e6 100644
--- a/src/org/unitConverter/unit/SI.java
+++ b/src/org/unitConverter/unit/SI.java
@@ -17,6 +17,7 @@
package org.unitConverter.unit;
import org.unitConverter.math.ObjectProduct;
+import org.unitConverter.unit.Unit.NameSymbol;
/**
* All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI.
@@ -115,9 +116,9 @@ public final class SI {
public static final ObjectProduct REFLACTIVE_PERMEABILITY = EMPTY.times(EMPTY);
public static final ObjectProduct ANGLE = LENGTH.dividedBy(LENGTH);
public static final ObjectProduct SOLID_ANGLE = AREA.dividedBy(AREA);
+
// derived dimensions with named SI units
public static final ObjectProduct FREQUENCY = EMPTY.dividedBy(TIME);
-
public static final ObjectProduct FORCE = MASS.times(ACCELERATION);
public static final ObjectProduct ENERGY = FORCE.times(LENGTH);
public static final ObjectProduct POWER = ENERGY.dividedBy(TIME);
@@ -142,15 +143,18 @@ public final class SI {
/// The units of the SI
public static final LinearUnit ONE = LinearUnit.valueOf(ObjectProduct.empty(), 1);
- public static final LinearUnit METRE = BaseUnits.METRE.asLinearUnit();
- public static final LinearUnit KILOGRAM = BaseUnits.KILOGRAM.asLinearUnit();
- public static final LinearUnit SECOND = BaseUnits.SECOND.asLinearUnit();
- public static final LinearUnit AMPERE = BaseUnits.AMPERE.asLinearUnit();
- public static final LinearUnit KELVIN = BaseUnits.KELVIN.asLinearUnit();
- public static final LinearUnit MOLE = BaseUnits.MOLE.asLinearUnit();
- public static final LinearUnit CANDELA = BaseUnits.CANDELA.asLinearUnit();
- public static final LinearUnit BIT = BaseUnits.BIT.asLinearUnit();
- public static final LinearUnit DOLLAR = BaseUnits.DOLLAR.asLinearUnit();
+ public static final LinearUnit METRE = BaseUnits.METRE.asLinearUnit()
+ .withName(NameSymbol.of("metre", "m", "meter"));
+ public static final LinearUnit KILOGRAM = BaseUnits.KILOGRAM.asLinearUnit()
+ .withName(NameSymbol.of("kilogram", "kg"));
+ public static final LinearUnit SECOND = BaseUnits.SECOND.asLinearUnit()
+ .withName(NameSymbol.of("second", "s", "sec"));
+ public static final LinearUnit AMPERE = BaseUnits.AMPERE.asLinearUnit().withName(NameSymbol.of("ampere", "A"));
+ public static final LinearUnit KELVIN = BaseUnits.KELVIN.asLinearUnit().withName(NameSymbol.of("kelvin", "K"));
+ public static final LinearUnit MOLE = BaseUnits.MOLE.asLinearUnit().withName(NameSymbol.of("mole", "mol"));
+ public static final LinearUnit CANDELA = BaseUnits.CANDELA.asLinearUnit().withName(NameSymbol.of("candela", "cd"));
+ public static final LinearUnit BIT = BaseUnits.BIT.asLinearUnit().withName(NameSymbol.of("bit", "b"));
+ public static final LinearUnit DOLLAR = BaseUnits.DOLLAR.asLinearUnit().withName(NameSymbol.of("dollar", "$"));
// Non-base units
public static final LinearUnit RADIAN = METRE.dividedBy(METRE);
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java
index d848ea1..737802a 100644
--- a/src/org/unitConverter/unit/Unit.java
+++ b/src/org/unitConverter/unit/Unit.java
@@ -511,7 +511,8 @@ public abstract class Unit {
public String toString() {
return this.getPrimaryName().orElse("Unnamed unit")
+ (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "")
- + ", derived from " + this.getBase().toString();
+ + ", derived from " + this.getBase().toString(u -> u.getSymbol().get())
+ + (this.getOtherNames().isEmpty() ? "" : ", also called " + String.join(", ", this.getOtherNames()));
}
/**
diff --git a/src/org/unitConverter/unit/UnitDatabase.java b/src/org/unitConverter/unit/UnitDatabase.java
index a2b11c3..5985c80 100644
--- a/src/org/unitConverter/unit/UnitDatabase.java
+++ b/src/org/unitConverter/unit/UnitDatabase.java
@@ -1609,10 +1609,13 @@ public final class UnitDatabase {
return Collections.unmodifiableMap(this.prefixes);
}
+ /**
+ * @return a string stating the number of units, prefixes and dimensions in the database
+ */
@Override
public String toString() {
- return String.format("Unit Database with %d units and %d unit prefixes", this.prefixlessUnits.size(),
- this.prefixes.size());
+ return String.format("Unit Database with %d units, %d unit prefixes and %d dimensions",
+ this.prefixlessUnits.size(), this.prefixes.size(), this.dimensions.size());
}
/**
diff --git a/src/org/unitConverter/unit/UnitPrefix.java b/src/org/unitConverter/unit/UnitPrefix.java
index 514fa1c..360b0c1 100644
--- a/src/org/unitConverter/unit/UnitPrefix.java
+++ b/src/org/unitConverter/unit/UnitPrefix.java
@@ -80,6 +80,11 @@ public final class UnitPrefix {
return valueOf(this.getMultiplier() / other.getMultiplier());
}
+ /**
+ * {@inheritDoc}
+ *
+ * Uses the prefix's multiplier to determine equality.
+ */
@Override
public boolean equals(final Object obj) {
if (this == obj)
@@ -92,10 +97,19 @@ public final class UnitPrefix {
return DecimalComparison.equals(this.getMultiplier(), other.getMultiplier());
}
+ /**
+ * @return prefix's multiplier
+ * @since 2019-11-26
+ */
public double getMultiplier() {
return this.multiplier;
}
+ /**
+ * {@inheritDoc}
+ *
+ * Uses the prefix's multiplier to determine a hash code.
+ */
@Override
public int hashCode() {
return DecimalComparison.hash(this.getMultiplier());
@@ -139,8 +153,11 @@ public final class UnitPrefix {
return valueOf(Math.pow(this.getMultiplier(), exponent));
}
+ /**
+ * @return a string describing the prefix and its multiplier
+ */
@Override
public String toString() {
- return String.format("Unit prefix equal to %s", this.multiplier);
+ return String.format("Unit prefix with multiplier %s", this.multiplier);
}
}
--
cgit v1.2.3
From bff8f363ce5e2ca84da1d57a470f0648c4b338e6 Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Tue, 26 Nov 2019 20:53:27 -0500
Subject: Prefixes can now have names.
---
src/org/unitConverter/math/ObjectProduct.java | 4 +-
src/org/unitConverter/unit/LinearUnit.java | 26 ++-
src/org/unitConverter/unit/NameSymbol.java | 277 ++++++++++++++++++++++++++
src/org/unitConverter/unit/SI.java | 1 -
src/org/unitConverter/unit/Unit.java | 217 --------------------
src/org/unitConverter/unit/UnitDatabase.java | 3 +-
src/org/unitConverter/unit/UnitPrefix.java | 85 +++++++-
7 files changed, 388 insertions(+), 225 deletions(-)
create mode 100644 src/org/unitConverter/unit/NameSymbol.java
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/math/ObjectProduct.java b/src/org/unitConverter/math/ObjectProduct.java
index 29d0f6e..bf00647 100644
--- a/src/org/unitConverter/math/ObjectProduct.java
+++ b/src/org/unitConverter/math/ObjectProduct.java
@@ -92,8 +92,8 @@ public final class ObjectProduct {
* @since 2019-10-16
*/
private ObjectProduct(final Map exponents) {
- this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections
- .conditionalExistenceMap(new HashMap<>(exponents), e -> !Integer.valueOf(0).equals(e.getValue())));
+ this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections.conditionalExistenceMap(exponents,
+ e -> !Integer.valueOf(0).equals(e.getValue())));
}
/**
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 1532fc4..1e5ae53 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -350,14 +350,38 @@ public final class LinearUnit extends Unit {
/**
* Returns the result of applying {@code prefix} to this unit.
+ *
+ * If this unit and the provided prefix have a primary name, the returned unit will have a primary name (prefix's
+ * name + unit's name).
+ * If this unit and the provided prefix have a symbol, the returned unit will have a symbol.
+ * This method ignores alternate names of both this unit and the provided prefix.
*
* @param prefix
* prefix to apply
* @return unit with prefix
* @since 2019-03-18
* @since v0.2.0
+ * @throws NullPointerException
+ * if prefix is null
*/
public LinearUnit withPrefix(final UnitPrefix prefix) {
- return this.times(prefix.getMultiplier());
+ final LinearUnit unit = this.times(prefix.getMultiplier());
+
+ // create new name and symbol, if possible
+ final String name;
+ if (this.getPrimaryName().isPresent() && prefix.getPrimaryName().isPresent()) {
+ name = prefix.getPrimaryName().get() + this.getPrimaryName().get();
+ } else {
+ name = null;
+ }
+
+ final String symbol;
+ if (this.getSymbol().isPresent() && prefix.getSymbol().isPresent()) {
+ symbol = prefix.getSymbol().get() + this.getSymbol().get();
+ } else {
+ symbol = null;
+ }
+
+ return unit.withName(NameSymbol.ofNullable(name, symbol));
}
}
diff --git a/src/org/unitConverter/unit/NameSymbol.java b/src/org/unitConverter/unit/NameSymbol.java
new file mode 100644
index 0000000..96fab45
--- /dev/null
+++ b/src/org/unitConverter/unit/NameSymbol.java
@@ -0,0 +1,277 @@
+/**
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A class that can be used to specify names and a symbol for a unit.
+ *
+ * @author Adrien Hopkins
+ * @since 2019-10-21
+ */
+public final class NameSymbol {
+ public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), Optional.empty(), new HashSet<>());
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and no other names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if name or symbol is null
+ */
+ public static final NameSymbol of(final String name, final String symbol) {
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), new HashSet<>());
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final Set otherNames) {
+ return new NameSymbol(Optional.of(name), Optional.of(symbol),
+ new HashSet<>(Objects.requireNonNull(otherNames, "otherNames must not be null.")));
+ }
+
+ /**
+ * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String... otherNames) {
+ return new NameSymbol(Optional.of(name), Optional.of(symbol),
+ new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, "otherNames must not be null."))));
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and an additional name.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @param name2
+ * alternate name
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String name2) {
+ final Set otherNames = new HashSet<>();
+ otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @param name2
+ * alternate name
+ * @param name3
+ * alternate name
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String name2, final String name3) {
+ final Set otherNames = new HashSet<>();
+ otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
+ otherNames.add(Objects.requireNonNull(name3, "name3 must not be null."));
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @param name2
+ * alternate name
+ * @param name3
+ * alternate name
+ * @param name4
+ * alternate name
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if any argument is null
+ */
+ public static final NameSymbol of(final String name, final String symbol, final String name2, final String name3,
+ final String name4) {
+ final Set otherNames = new HashSet<>();
+ otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
+ otherNames.add(Objects.requireNonNull(name3, "name3 must not be null."));
+ otherNames.add(Objects.requireNonNull(name4, "name4 must not be null."));
+ return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, no symbol, and no other names.
+ *
+ * @param name
+ * name to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if name is null
+ */
+ public static final NameSymbol ofName(final String name) {
+ return new NameSymbol(Optional.of(name), Optional.empty(), new HashSet<>());
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * If any argument is null, this static factory replaces it with an empty Optional or empty Set.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @return NameSymbol instance
+ * @since 2019-11-26
+ */
+ public static final NameSymbol ofNullable(final String name, final String symbol, final Set otherNames) {
+ return new NameSymbol(Optional.ofNullable(name), Optional.ofNullable(symbol),
+ otherNames == null ? new HashSet<>() : new HashSet<>(otherNames));
+ }
+
+ /**
+ * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
+ *
+ * If any argument is null, this static factory replaces it with an empty Optional or empty Set.
+ *
+ * @param name
+ * name to use
+ * @param symbol
+ * symbol to use
+ * @param otherNames
+ * other names to use
+ * @return NameSymbol instance
+ * @since 2019-11-26
+ */
+ public static final NameSymbol ofNullable(final String name, final String symbol, final String... otherNames) {
+ return new NameSymbol(Optional.ofNullable(name), Optional.ofNullable(symbol),
+ otherNames == null ? new HashSet<>() : new HashSet<>(Arrays.asList(otherNames)));
+ }
+
+ /**
+ * Gets a {@code NameSymbol} with a symbol and no names.
+ *
+ * @param symbol
+ * symbol to use
+ * @return NameSymbol instance
+ * @since 2019-10-21
+ * @throws NullPointerException
+ * if symbol is null
+ */
+ public static final NameSymbol ofSymbol(final String symbol) {
+ return new NameSymbol(Optional.empty(), Optional.of(symbol), new HashSet<>());
+ }
+
+ private final Optional primaryName;
+ private final Optional symbol;
+
+ private final Set otherNames;
+
+ /**
+ * Creates the {@code NameSymbol}.
+ *
+ * @param primaryName
+ * primary name of unit
+ * @param symbol
+ * symbol used to represent unit
+ * @param otherNames
+ * other names and/or spellings
+ * @since 2019-10-21
+ */
+ private NameSymbol(final Optional primaryName, final Optional symbol,
+ final Set otherNames) {
+ this.primaryName = primaryName;
+ this.symbol = symbol;
+ this.otherNames = Collections.unmodifiableSet(otherNames);
+ }
+
+ /**
+ * @return otherNames
+ * @since 2019-10-21
+ */
+ public final Set getOtherNames() {
+ return this.otherNames;
+ }
+
+ /**
+ * @return primaryName
+ * @since 2019-10-21
+ */
+ public final Optional getPrimaryName() {
+ return this.primaryName;
+ }
+
+ /**
+ * @return symbol
+ * @since 2019-10-21
+ */
+ public final Optional getSymbol() {
+ return this.symbol;
+ }
+}
\ No newline at end of file
diff --git a/src/org/unitConverter/unit/SI.java b/src/org/unitConverter/unit/SI.java
index 19d63e6..c8d228c 100644
--- a/src/org/unitConverter/unit/SI.java
+++ b/src/org/unitConverter/unit/SI.java
@@ -17,7 +17,6 @@
package org.unitConverter.unit;
import org.unitConverter.math.ObjectProduct;
-import org.unitConverter.unit.Unit.NameSymbol;
/**
* All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI.
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java
index 737802a..35b32fc 100644
--- a/src/org/unitConverter/unit/Unit.java
+++ b/src/org/unitConverter/unit/Unit.java
@@ -16,7 +16,6 @@
*/
package org.unitConverter.unit;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -35,222 +34,6 @@ import org.unitConverter.math.ObjectProduct;
* @since 2019-10-16
*/
public abstract class Unit {
- /**
- * A class that can be used to specify names and a symbol for a unit.
- *
- * @author Adrien Hopkins
- * @since 2019-10-21
- */
- public static final class NameSymbol {
- public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), Optional.empty(), new HashSet<>());
-
- /**
- * Gets a {@code NameSymbol} with a primary name, a symbol and no other names.
- *
- * @param name
- * name to use
- * @param symbol
- * symbol to use
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if name or symbol is null
- */
- public static final NameSymbol of(final String name, final String symbol) {
- return new NameSymbol(Optional.of(name), Optional.of(symbol), new HashSet<>());
- }
-
- /**
- * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
- *
- * @param name
- * name to use
- * @param symbol
- * symbol to use
- * @param otherNames
- * other names to use
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if any argument is null
- */
- public static final NameSymbol of(final String name, final String symbol, final Set otherNames) {
- return new NameSymbol(Optional.of(name), Optional.of(symbol),
- new HashSet<>(Objects.requireNonNull(otherNames, "otherNames must not be null.")));
- }
-
- /**
- * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
- *
- * @param name
- * name to use
- * @param symbol
- * symbol to use
- * @param otherNames
- * other names to use
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if any argument is null
- */
- public static final NameSymbol of(final String name, final String symbol, final String... otherNames) {
- return new NameSymbol(Optional.of(name), Optional.of(symbol),
- new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, "otherNames must not be null."))));
- }
-
- /**
- * Gets a {@code NameSymbol} with a primary name, a symbol and an additional name.
- *
- * @param name
- * name to use
- * @param symbol
- * symbol to use
- * @param otherNames
- * other names to use
- * @param name2
- * alternate name
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if any argument is null
- */
- public static final NameSymbol of(final String name, final String symbol, final String name2) {
- final Set otherNames = new HashSet<>();
- otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
- return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
- }
-
- /**
- * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
- *
- * @param name
- * name to use
- * @param symbol
- * symbol to use
- * @param otherNames
- * other names to use
- * @param name2
- * alternate name
- * @param name3
- * alternate name
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if any argument is null
- */
- public static final NameSymbol of(final String name, final String symbol, final String name2,
- final String name3) {
- final Set otherNames = new HashSet<>();
- otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
- otherNames.add(Objects.requireNonNull(name3, "name3 must not be null."));
- return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
- }
-
- /**
- * Gets a {@code NameSymbol} with a primary name, a symbol and additional names.
- *
- * @param name
- * name to use
- * @param symbol
- * symbol to use
- * @param otherNames
- * other names to use
- * @param name2
- * alternate name
- * @param name3
- * alternate name
- * @param name4
- * alternate name
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if any argument is null
- */
- public static final NameSymbol of(final String name, final String symbol, final String name2,
- final String name3, final String name4) {
- final Set otherNames = new HashSet<>();
- otherNames.add(Objects.requireNonNull(name2, "name2 must not be null."));
- otherNames.add(Objects.requireNonNull(name3, "name3 must not be null."));
- otherNames.add(Objects.requireNonNull(name4, "name4 must not be null."));
- return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames);
- }
-
- /**
- * Gets a {@code NameSymbol} with a primary name, no symbol, and no other names.
- *
- * @param name
- * name to use
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if name is null
- */
- public static final NameSymbol ofName(final String name) {
- return new NameSymbol(Optional.of(name), Optional.empty(), new HashSet<>());
- }
-
- /**
- * Gets a {@code NameSymbol} with a symbol and no names.
- *
- * @param symbol
- * symbol to use
- * @return NameSymbol instance
- * @since 2019-10-21
- * @throws NullPointerException
- * if symbol is null
- */
- public static final NameSymbol ofSymbol(final String symbol) {
- return new NameSymbol(Optional.empty(), Optional.of(symbol), new HashSet<>());
- }
-
- private final Optional primaryName;
- private final Optional symbol;
-
- private final Set otherNames;
-
- /**
- * Creates the {@code NameSymbol}.
- *
- * @param primaryName
- * primary name of unit
- * @param symbol
- * symbol used to represent unit
- * @param otherNames
- * other names and/or spellings
- * @since 2019-10-21
- */
- private NameSymbol(final Optional primaryName, final Optional symbol,
- final Set otherNames) {
- this.primaryName = primaryName;
- this.symbol = symbol;
- this.otherNames = Collections.unmodifiableSet(otherNames);
- }
-
- /**
- * @return otherNames
- * @since 2019-10-21
- */
- public final Set getOtherNames() {
- return this.otherNames;
- }
-
- /**
- * @return primaryName
- * @since 2019-10-21
- */
- public final Optional getPrimaryName() {
- return this.primaryName;
- }
-
- /**
- * @return symbol
- * @since 2019-10-21
- */
- public final Optional getSymbol() {
- return this.symbol;
- }
- }
-
/**
* Returns a unit from its base and the functions it uses to convert to and from its base.
*
diff --git a/src/org/unitConverter/unit/UnitDatabase.java b/src/org/unitConverter/unit/UnitDatabase.java
index 6a89b67..9df34a7 100644
--- a/src/org/unitConverter/unit/UnitDatabase.java
+++ b/src/org/unitConverter/unit/UnitDatabase.java
@@ -974,12 +974,13 @@ public final class UnitDatabase {
*/
private static final Map EXPRESSION_REPLACEMENTS = new HashMap<>();
+ // add data to expression replacements
static {
// place brackets around any expression of the form "number unit", with or without the space
EXPRESSION_REPLACEMENTS.put(Pattern.compile("((?:-?[1-9]\\d*|0)" // integer
+ "(?:\\.\\d+)?)" // optional decimal point with numbers after it
+ "\\s*" // optional space(s)
- + "([a-zA-Z]+)" // unit name
+ + "([a-zA-Z]+)" // any string of letters
+ "(?!-?\\d)" // no number directly afterwards (avoids matching "1e3")
), "\\($1 $2\\)");
}
diff --git a/src/org/unitConverter/unit/UnitPrefix.java b/src/org/unitConverter/unit/UnitPrefix.java
index 360b0c1..31cc0b3 100644
--- a/src/org/unitConverter/unit/UnitPrefix.java
+++ b/src/org/unitConverter/unit/UnitPrefix.java
@@ -16,6 +16,10 @@
*/
package org.unitConverter.unit;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
import org.unitConverter.math.DecimalComparison;
/**
@@ -34,9 +38,40 @@ public final class UnitPrefix {
* @since 2019-10-16
*/
public static UnitPrefix valueOf(final double multiplier) {
- return new UnitPrefix(multiplier);
+ return new UnitPrefix(multiplier, NameSymbol.EMPTY);
+ }
+
+ /**
+ * Gets a {@code UnitPrefix} from a multiplier and a name
+ *
+ * @param multiplier
+ * multiplier of prefix
+ * @param ns
+ * name(s) and symbol of prefix
+ * @return prefix
+ * @since 2019-10-16
+ * @throws NullPointerException
+ * if ns is null
+ */
+ public static UnitPrefix valueOf(final double multiplier, final NameSymbol ns) {
+ return new UnitPrefix(multiplier, Objects.requireNonNull(ns, "ns must not be null."));
}
+ /**
+ * This prefix's primary name
+ */
+ private final Optional primaryName;
+
+ /**
+ * This prefix's symbol
+ */
+ private final Optional symbol;
+
+ /**
+ * Other names and symbols used by this prefix
+ */
+ private final Set otherNames;
+
/**
* The number that this prefix multiplies units by
*
@@ -51,8 +86,11 @@ public final class UnitPrefix {
* @since 2019-01-14
* @since v0.2.0
*/
- private UnitPrefix(final double multiplier) {
+ private UnitPrefix(final double multiplier, final NameSymbol ns) {
this.multiplier = multiplier;
+ this.primaryName = ns.getPrimaryName();
+ this.symbol = ns.getSymbol();
+ this.otherNames = ns.getOtherNames();
}
/**
@@ -105,6 +143,30 @@ public final class UnitPrefix {
return this.multiplier;
}
+ /**
+ * @return other names
+ * @since 2019-11-26
+ */
+ public final Set getOtherNames() {
+ return this.otherNames;
+ }
+
+ /**
+ * @return primary name
+ * @since 2019-11-26
+ */
+ public final Optional getPrimaryName() {
+ return this.primaryName;
+ }
+
+ /**
+ * @return symbol
+ * @since 2019-11-26
+ */
+ public final Optional getSymbol() {
+ return this.symbol;
+ }
+
/**
* {@inheritDoc}
*
@@ -158,6 +220,23 @@ public final class UnitPrefix {
*/
@Override
public String toString() {
- return String.format("Unit prefix with multiplier %s", this.multiplier);
+ if (this.primaryName.isPresent())
+ return String.format("%s (\u00D7 %s)", this.primaryName.get(), this.multiplier);
+ else if (this.symbol.isPresent())
+ return String.format("%s (\u00D7 %s)", this.symbol.get(), this.multiplier);
+ else
+ return String.format("Unit Prefix (\u00D7 %s)", this.multiplier);
+ }
+
+ /**
+ * @param ns
+ * name(s) and symbol to use
+ * @return copy of this prefix with provided name(s) and symbol
+ * @since 2019-11-26
+ * @throws NullPointerException
+ * if ns is null
+ */
+ public UnitPrefix withName(final NameSymbol ns) {
+ return valueOf(this.multiplier, ns);
}
}
--
cgit v1.2.3
From b495b7029ebdcd56a41ea09811343a55c432b0a0 Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Sun, 26 Jul 2020 14:43:11 -0500
Subject: Added UnitValue and LinearUnitValue
---
src/org/unitConverter/unit/LinearUnit.java | 12 +-
src/org/unitConverter/unit/LinearUnitValue.java | 300 ++++++++++++++++++++++++
src/org/unitConverter/unit/UnitValue.java | 114 +++++++++
3 files changed, 420 insertions(+), 6 deletions(-)
create mode 100644 src/org/unitConverter/unit/LinearUnitValue.java
create mode 100644 src/org/unitConverter/unit/UnitValue.java
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 1e5ae53..762572a 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -246,16 +246,16 @@ public final class LinearUnit extends Unit {
* @since 2019-03-17
* @since v0.2.0
*/
- public LinearUnit minus(final LinearUnit subtrahendend) {
- Objects.requireNonNull(subtrahendend, "addend must not be null.");
+ public LinearUnit minus(final LinearUnit subtrahend) {
+ Objects.requireNonNull(subtrahend, "addend must not be null.");
// reject subtrahends that cannot be added to this unit
- if (!this.getBase().equals(subtrahendend.getBase()))
+ if (!this.getBase().equals(subtrahend.getBase()))
throw new IllegalArgumentException(
- String.format("Incompatible units for subtraction \"%s\" and \"%s\".", this, subtrahendend));
+ String.format("Incompatible units for subtraction \"%s\" and \"%s\".", this, subtrahend));
// subtract the units
- return valueOf(this.getBase(), this.getConversionFactor() - subtrahendend.getConversionFactor());
+ return valueOf(this.getBase(), this.getConversionFactor() - subtrahend.getConversionFactor());
}
/**
@@ -347,7 +347,7 @@ public final class LinearUnit extends Unit {
public LinearUnit withName(final NameSymbol ns) {
return valueOf(this.getBase(), this.getConversionFactor(), ns);
}
-
+
/**
* Returns the result of applying {@code prefix} to this unit.
*
diff --git a/src/org/unitConverter/unit/LinearUnitValue.java b/src/org/unitConverter/unit/LinearUnitValue.java
new file mode 100644
index 0000000..8daabf7
--- /dev/null
+++ b/src/org/unitConverter/unit/LinearUnitValue.java
@@ -0,0 +1,300 @@
+/**
+ *
+ */
+package org.unitConverter.unit;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * A possibly uncertain value expressed in a linear unit.
+ *
+ * Unless otherwise indicated, all methods in this class throw a
+ * {@code NullPointerException} when an argument is null.
+ *
+ * @author Adrien Hopkins
+ * @since 2020-07-26
+ */
+public final class LinearUnitValue {
+ private final LinearUnit unit;
+ private final double value;
+ private final double uncertainty;
+
+ /**
+ * Gets an exact {@code UnitValue}
+ *
+ * @param unit unit to express with
+ * @param value value to express
+ * @return exact {@code UnitValue} instance
+ * @since 2020-07-26
+ */
+ public static final LinearUnitValue getExact(LinearUnit unit, double value) {
+ return new LinearUnitValue(Objects.requireNonNull(unit, "unit must not be null"), value, 0);
+ }
+
+ /**
+ * Gets an uncertain {@code UnitValue}
+ *
+ * @param unit unit to express with
+ * @param value value to express
+ * @param uncertainty absolute uncertainty of value
+ * @return uncertain {@code UnitValue} instance
+ * @since 2020-07-26
+ */
+ public static final LinearUnitValue of(LinearUnit unit, double value, double uncertainty) {
+ return new LinearUnitValue(Objects.requireNonNull(unit, "unit must not be null"), value, uncertainty);
+ }
+
+ /**
+ * @param unit unit to express as
+ * @param value value to express
+ * @param uncertainty absolute uncertainty of value
+ * @since 2020-07-26
+ */
+ private LinearUnitValue(LinearUnit unit, double value, double uncertainty) {
+ this.unit = unit;
+ this.value = value;
+ this.uncertainty = uncertainty;
+ }
+
+ /**
+ * @param other a {@code LinearUnit}
+ * @return true iff this value can be represented with {@code other}.
+ * @since 2020-07-26
+ */
+ public final boolean canConvertTo(LinearUnit other) {
+ return this.unit.canConvertTo(other);
+ }
+
+ /**
+ * Returns a LinearUnitValue that represents the same value expressed in a
+ * different unit
+ *
+ * @param other new unit to express value in
+ * @return value expressed in {@code other}
+ * @since 2020-07-26
+ */
+ public final LinearUnitValue convertTo(LinearUnit other) {
+ return LinearUnitValue.of(other, this.unit.convertTo(other, value), this.unit.convertTo(other, uncertainty));
+ }
+
+ /**
+ * Returns true if this and obj represent the same value, regardless of whether
+ * or not they are expressed in the same unit. So (1000 m).equals(1 km) returns
+ * true.
+ *
+ * @since 2020-07-26
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof LinearUnitValue))
+ return false;
+ LinearUnitValue other = (LinearUnitValue) obj;
+ return Objects.equals(this.unit.getBase(), other.unit.getBase())
+ && Double.doubleToLongBits(this.unit.convertToBase(this.getValue())) == Double
+ .doubleToLongBits(other.unit.convertToBase(other.getValue()))
+ && Double.doubleToLongBits(this.getRelativeUncertainty()) == Double
+ .doubleToLongBits(other.getRelativeUncertainty());
+ }
+
+ /**
+ * @param other another {@code LinearUnitValue}
+ * @return true iff this and other are within each other's uncertainty range
+ *
+ * @since 2020-07-26
+ */
+ public boolean equivalent(LinearUnitValue other) {
+ if (other == null || !Objects.equals(this.unit.getBase(), other.unit.getBase()))
+ return false;
+ double thisBaseValue = this.unit.convertToBase(this.value);
+ double otherBaseValue = other.unit.convertToBase(other.value);
+ double thisBaseUncertainty = this.unit.convertToBase(this.uncertainty);
+ double otherBaseUncertainty = other.unit.convertToBase(other.uncertainty);
+ return Math.abs(thisBaseValue - otherBaseValue) <= Math.min(thisBaseUncertainty, otherBaseUncertainty);
+ }
+
+ /**
+ * @return the unit
+ *
+ * @since 2020-07-26
+ */
+ public final LinearUnit getUnit() {
+ return unit;
+ }
+
+ /**
+ * @return the value
+ *
+ * @since 2020-07-26
+ */
+ public final double getValue() {
+ return value;
+ }
+
+ /**
+ * @return absolute uncertainty of value
+ *
+ * @since 2020-07-26
+ */
+ public final double getUncertainty() {
+ return uncertainty;
+ }
+
+ /**
+ * @return relative uncertainty of value
+ *
+ * @since 2020-07-26
+ */
+ public final double getRelativeUncertainty() {
+ return uncertainty / value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.unit.getBase(), this.unit.convertToBase(this.getValue()), this.getRelativeUncertainty());
+ }
+
+ /**
+ * @return true iff the value has no uncertainty
+ *
+ * @since 2020-07-26
+ */
+ public final boolean isExact() {
+ return uncertainty == 0;
+ }
+
+ /**
+ * Returns the sum of this value and another, expressed in this value's unit
+ *
+ * @param addend
+ * value to add
+ * @return sum of values
+ * @throws IllegalArgumentException
+ * if {@code addend} has a unit that is not compatible for addition
+ * @since 2020-07-26
+ */
+ public LinearUnitValue plus(LinearUnitValue addend) {
+ Objects.requireNonNull(addend, "addend may not be null");
+
+ if (!this.canConvertTo(addend.unit))
+ throw new IllegalArgumentException(
+ String.format("Incompatible units for addition \"%s\" and \"%s\".", this.unit, addend.unit));
+
+ final LinearUnitValue otherConverted = addend.convertTo(this.unit);
+ return LinearUnitValue.of(this.unit, this.value + otherConverted.value, Math.hypot(this.uncertainty, otherConverted.uncertainty));
+ }
+
+ /**
+ * Returns the difference of this value and another, expressed in this value's unit
+ *
+ * @param subtrahend
+ * value to subtract
+ * @return difference of values
+ * @throws IllegalArgumentException
+ * if {@code subtrahend} has a unit that is not compatible for addition
+ * @since 2020-07-26
+ */
+ public LinearUnitValue minus(LinearUnitValue subtrahend) {
+ Objects.requireNonNull(subtrahend, "subtrahend may not be null");
+
+ if (!this.canConvertTo(subtrahend.unit))
+ throw new IllegalArgumentException(
+ String.format("Incompatible units for subtraction \"%s\" and \"%s\".", this.unit, subtrahend.unit));
+
+ final LinearUnitValue otherConverted = subtrahend.convertTo(this.unit);
+ return LinearUnitValue.of(this.unit, this.value - otherConverted.value, Math.hypot(this.uncertainty, otherConverted.uncertainty));
+ }
+
+ @Override
+ public String toString() {
+ return this.toString(!this.isExact());
+ }
+
+ /**
+ * Returns a string representing the object.
+ * If the attached unit has a name or symbol, the string looks like "12 km".
+ * Otherwise, it looks like "13 unnamed unit (= 2 m/s)".
+ *
+ * If showUncertainty is true, strings like "35 ± 8" are shown instead of single
+ * numbers.
+ *
+ * Non-exact values are rounded intelligently based on their uncertainty.
+ *
+ * @since 2020-07-26
+ */
+ public String toString(boolean showUncertainty) {
+ Optional primaryName = this.unit.getPrimaryName();
+ Optional symbol = this.unit.getSymbol();
+ String chosenName = symbol.orElse(primaryName.orElse(null));
+
+ final double baseValue = this.unit.convertToBase(this.value);
+ final double baseUncertainty = this.unit.convertToBase(this.uncertainty);
+
+ // get rounded strings
+ final String valueString, baseValueString, uncertaintyString, baseUncertaintyString;
+ if (this.isExact()) {
+ valueString = Double.toString(value);
+ baseValueString = Double.toString(baseValue);
+ uncertaintyString = "0";
+ baseUncertaintyString = "0";
+ } else {
+ final BigDecimal bigValue = BigDecimal.valueOf(this.value);
+ final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty);
+
+ // round based on uncertainty
+ // if uncertainty starts with 1 (ignoring zeroes and the decimal point), rounds
+ // so that uncertainty has 2 significant digits.
+ // otherwise, rounds so that uncertainty has 1 significant digits.
+ // the value is rounded to the same number of decimal places as the uncertainty.
+ BigDecimal roundedUncertainty = bigUncertainty
+ .setScale(bigUncertainty.scale() - bigUncertainty.precision() + 2, RoundingMode.HALF_EVEN);
+ if (roundedUncertainty.unscaledValue().intValue() >= 20) {
+ roundedUncertainty = bigUncertainty.setScale(bigUncertainty.scale() - bigUncertainty.precision() + 1,
+ RoundingMode.HALF_EVEN);
+ }
+ final BigDecimal roundedValue = bigValue.setScale(roundedUncertainty.scale(), RoundingMode.HALF_EVEN);
+
+ valueString = roundedValue.toString();
+ uncertaintyString = roundedUncertainty.toString();
+
+ if (primaryName.isEmpty() && symbol.isEmpty()) {
+ final BigDecimal bigBaseValue = BigDecimal.valueOf(baseValue);
+ final BigDecimal bigBaseUncertainty = BigDecimal.valueOf(baseUncertainty);
+
+ BigDecimal roundedBaseUncertainty = bigBaseUncertainty.setScale(
+ bigBaseUncertainty.scale() - bigBaseUncertainty.precision() + 2, RoundingMode.HALF_EVEN);
+ if (roundedBaseUncertainty.unscaledValue().intValue() >= 20) {
+ roundedBaseUncertainty = bigBaseUncertainty.setScale(
+ bigBaseUncertainty.scale() - bigBaseUncertainty.precision() + 1, RoundingMode.HALF_EVEN);
+ }
+ final BigDecimal roundedBaseValue = bigBaseValue.setScale(roundedBaseUncertainty.scale(),
+ RoundingMode.HALF_EVEN);
+
+ baseValueString = roundedBaseValue.toString();
+ baseUncertaintyString = roundedBaseUncertainty.toString();
+ } else {
+ // unused
+ baseValueString = "";
+ baseUncertaintyString = "";
+ }
+ }
+
+ // create string
+ if (showUncertainty) {
+ if (primaryName.isEmpty() && symbol.isEmpty()) {
+ return String.format("(%s ± %s) unnamed unit (= %s ± %s %s)", valueString, uncertaintyString,
+ baseValueString, baseUncertaintyString, this.unit.getBase());
+ } else {
+ return String.format("(%s ± %s) %s", valueString, uncertaintyString, chosenName);
+ }
+ } else {
+ if (primaryName.isEmpty() && symbol.isEmpty()) {
+ return String.format("%s unnamed unit (= %s %s)", valueString, baseValueString, this.unit.getBase());
+ } else {
+ return String.format("%s %s", valueString, chosenName);
+ }
+ }
+ }
+}
diff --git a/src/org/unitConverter/unit/UnitValue.java b/src/org/unitConverter/unit/UnitValue.java
new file mode 100644
index 0000000..9e565d9
--- /dev/null
+++ b/src/org/unitConverter/unit/UnitValue.java
@@ -0,0 +1,114 @@
+package org.unitConverter.unit;
+
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * A value expressed in a unit.
+ *
+ * Unless otherwise indicated, all methods in this class throw a
+ * {@code NullPointerException} when an argument is null.
+ *
+ * @author Adrien Hopkins
+ * @since 2020-07-26
+ */
+public final class UnitValue {
+ /**
+ * @param unit unit to use
+ * @param value value to use
+ * @return {@code UnitValue} instance
+ */
+ public static UnitValue of(Unit unit, double value) {
+ return new UnitValue(Objects.requireNonNull(unit, "unit must not be null"), value);
+ }
+
+ private final Unit unit;
+ private final double value;
+
+ /**
+ * @param unit the unit being used
+ * @param value the value being represented
+ */
+ private UnitValue(Unit unit, double value) {
+ this.unit = unit;
+ this.value = value;
+ }
+
+ /**
+ * @return the unit
+ */
+ public final Unit getUnit() {
+ return unit;
+ }
+
+ /**
+ * @return the value
+ */
+ public final double getValue() {
+ return value;
+ }
+
+ /**
+ * Converts this {@code UnitValue} into an equivalent {@code LinearUnitValue} by
+ * using this unit's base unit.
+ *
+ * @param newName A new name for the base unit. Use {@link NameSymbol#EMPTY} if
+ * you don't want one.
+ */
+ public final LinearUnitValue asLinearUnitValue(NameSymbol newName) {
+ LinearUnit base = LinearUnit.valueOf(unit.getBase(), 1, newName);
+ return LinearUnitValue.getExact(base, base.convertToBase(value));
+ }
+
+ /**
+ * @param other a {@code Unit}
+ * @return true iff this value can be represented with {@code other}.
+ */
+ public final boolean canConvertTo(Unit other) {
+ return this.unit.canConvertTo(other);
+ }
+
+ /**
+ * Returns a UnitValue that represents the same value expressed in a
+ * different unit
+ *
+ * @param other new unit to express value in
+ * @return value expressed in {@code other}
+ */
+ public final UnitValue convertTo(Unit other) {
+ return UnitValue.of(other, this.getUnit().convertTo(other, this.getValue()));
+ }
+
+ /**
+ * Returns true if this and obj represent the same value, regardless of whether
+ * or not they are expressed in the same unit. So (1000 m).equals(1 km) returns
+ * true.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof UnitValue))
+ return false;
+ final UnitValue other = (UnitValue) obj;
+ return Objects.equals(this.unit.getBase(), other.unit.getBase())
+ && Double.doubleToLongBits(this.unit.convertToBase(this.getValue())) == Double
+ .doubleToLongBits(other.unit.convertToBase(other.getValue()));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.unit.getBase(), this.unit.convertFromBase(this.getValue()));
+ }
+
+ @Override
+ public String toString() {
+ Optional primaryName = this.getUnit().getPrimaryName();
+ Optional symbol = this.getUnit().getSymbol();
+ if (primaryName.isEmpty() && symbol.isEmpty()) {
+ double baseValue = this.getUnit().convertToBase(this.getValue());
+ return String.format("%s unnamed unit (= %s %s)", this.getValue(), baseValue, this.getUnit().getBase());
+ } else {
+ String unitName = symbol.orElse(primaryName.get());
+ return this.getValue() + " " + unitName;
+ }
+ }
+}
--
cgit v1.2.3
From 5a7e8f6fcb175b238eb1d5481513b35039107a3e Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Mon, 7 Sep 2020 15:15:20 -0500
Subject: Created an UncertainDouble class for uncertainty operations.
---
.settings/org.eclipse.jdt.core.prefs | 100 ++++++
src/org/unitConverter/math/DecimalComparison.java | 207 +++++++----
src/org/unitConverter/math/UncertainDouble.java | 411 ++++++++++++++++++++++
src/org/unitConverter/unit/LinearUnit.java | 302 +++++++++-------
src/org/unitConverter/unit/LinearUnitValue.java | 252 +++----------
src/org/unitConverter/unit/UnitDatabase.java | 6 +-
src/org/unitConverter/unit/UnitTest.java | 7 +-
7 files changed, 885 insertions(+), 400 deletions(-)
create mode 100644 src/org/unitConverter/math/UncertainDouble.java
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index ea7a397..f77f6a1 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,13 @@
eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
@@ -6,11 +15,102 @@ org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=error
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=info
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=info
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=error
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=info
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=info
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=info
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=info
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=info
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=ignore
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=error
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=info
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=info
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=disabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=info
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=info
+org.eclipse.jdt.core.compiler.problem.unusedParameter=info
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=info
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=info
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
diff --git a/src/org/unitConverter/math/DecimalComparison.java b/src/org/unitConverter/math/DecimalComparison.java
index 859e8da..0f5b91e 100644
--- a/src/org/unitConverter/math/DecimalComparison.java
+++ b/src/org/unitConverter/math/DecimalComparison.java
@@ -27,42 +27,45 @@ import java.math.BigDecimal;
*/
public final class DecimalComparison {
/**
- * The value used for double comparison. If two double values are within this value multiplied by the larger value,
- * they are considered equal.
+ * The value used for double comparison. If two double values are within this
+ * value multiplied by the larger value, they are considered equal.
*
* @since 2019-03-18
* @since v0.2.0
*/
public static final double DOUBLE_EPSILON = 1.0e-15;
-
+
/**
- * The value used for float comparison. If two float values are within this value multiplied by the larger value,
- * they are considered equal.
+ * The value used for float comparison. If two float values are within this
+ * value multiplied by the larger value, they are considered equal.
*
* @since 2019-03-18
* @since v0.2.0
*/
public static final float FLOAT_EPSILON = 1.0e-6f;
-
+
/**
* Tests for equality of double values using {@link #DOUBLE_EPSILON}.
*
- * WARNING: this method is not technically transitive. If a and b are off by slightly less than
- * {@code epsilon * max(abs(a), abs(b))}, and b and c are off by slightly less than
- * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) will both return true, but equals(a, c)
- * will return false. However, this situation is very unlikely to ever happen in a real programming situation.
+ * WARNING: this method is not technically transitive. If a
+ * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))},
+ * and b and c are off by slightly less than
+ * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c)
+ * will both return true, but equals(a, c) will return false. However, this
+ * situation is very unlikely to ever happen in a real programming situation.
*
* If this does become a concern, some ways to solve this problem:
*
- *
Raise the value of epsilon using {@link #equals(double, double, double)} (this does not make a violation of
- * transitivity impossible, it just significantly reduces the chances of it happening)
- *
Use {@link BigDecimal} instead of {@code double} (this will make a violation of transitivity 100% impossible)
+ *
Raise the value of epsilon using
+ * {@link #equals(double, double, double)} (this does not make a violation of
+ * transitivity impossible, it just significantly reduces the chances of it
+ * happening)
+ *
Use {@link BigDecimal} instead of {@code double} (this will make a
+ * violation of transitivity 100% impossible)
*
*
- * @param a
- * first value to test
- * @param b
- * second value to test
+ * @param a first value to test
+ * @param b second value to test
* @return whether they are equal
* @since 2019-03-18
* @since v0.2.0
@@ -71,57 +74,61 @@ public final class DecimalComparison {
public static final boolean equals(final double a, final double b) {
return DecimalComparison.equals(a, b, DOUBLE_EPSILON);
}
-
+
/**
* Tests for double equality using a custom epsilon value.
*
*
- * WARNING: this method is not technically transitive. If a and b are off by slightly less than
- * {@code epsilon * max(abs(a), abs(b))}, and b and c are off by slightly less than
- * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) will both return true, but equals(a, c)
- * will return false. However, this situation is very unlikely to ever happen in a real programming situation.
+ * WARNING: this method is not technically transitive. If a
+ * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))},
+ * and b and c are off by slightly less than
+ * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c)
+ * will both return true, but equals(a, c) will return false. However, this
+ * situation is very unlikely to ever happen in a real programming situation.
*
* If this does become a concern, some ways to solve this problem:
*
- *
Raise the value of epsilon (this does not make a violation of transitivity impossible, it just significantly
- * reduces the chances of it happening)
- *
Use {@link BigDecimal} instead of {@code double} (this will make a violation of transitivity 100% impossible)
+ *
Raise the value of epsilon (this does not make a violation of
+ * transitivity impossible, it just significantly reduces the chances of it
+ * happening)
+ *
Use {@link BigDecimal} instead of {@code double} (this will make a
+ * violation of transitivity 100% impossible)
*
*
- * @param a
- * first value to test
- * @param b
- * second value to test
- * @param epsilon
- * allowed difference
+ * @param a first value to test
+ * @param b second value to test
+ * @param epsilon allowed difference
* @return whether they are equal
* @since 2019-03-18
* @since v0.2.0
*/
- public static final boolean equals(final double a, final double b, final double epsilon) {
+ public static final boolean equals(final double a, final double b,
+ final double epsilon) {
return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
}
-
+
/**
* Tests for equality of float values using {@link #FLOAT_EPSILON}.
*
*
- * WARNING: this method is not technically transitive. If a and b are off by slightly less than
- * {@code epsilon * max(abs(a), abs(b))}, and b and c are off by slightly less than
- * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) will both return true, but equals(a, c)
- * will return false. However, this situation is very unlikely to ever happen in a real programming situation.
+ * WARNING: this method is not technically transitive. If a
+ * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))},
+ * and b and c are off by slightly less than
+ * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c)
+ * will both return true, but equals(a, c) will return false. However, this
+ * situation is very unlikely to ever happen in a real programming situation.
*
* If this does become a concern, some ways to solve this problem:
*
- *
Raise the value of epsilon using {@link #equals(float, float, float)} (this does not make a violation of
- * transitivity impossible, it just significantly reduces the chances of it happening)
- *
Use {@link BigDecimal} instead of {@code float} (this will make a violation of transitivity 100% impossible)
+ *
Raise the value of epsilon using {@link #equals(float, float, float)}
+ * (this does not make a violation of transitivity impossible, it just
+ * significantly reduces the chances of it happening)
+ *
Use {@link BigDecimal} instead of {@code float} (this will make a
+ * violation of transitivity 100% impossible)
*
*
- * @param a
- * first value to test
- * @param b
- * second value to test
+ * @param a first value to test
+ * @param b second value to test
* @return whether they are equal
* @since 2019-03-18
* @since v0.2.0
@@ -129,53 +136,121 @@ public final class DecimalComparison {
public static final boolean equals(final float a, final float b) {
return DecimalComparison.equals(a, b, FLOAT_EPSILON);
}
-
+
/**
* Tests for float equality using a custom epsilon value.
*
*
- * WARNING: this method is not technically transitive. If a and b are off by slightly less than
- * {@code epsilon * max(abs(a), abs(b))}, and b and c are off by slightly less than
- * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) will both return true, but equals(a, c)
- * will return false. However, this situation is very unlikely to ever happen in a real programming situation.
+ * WARNING: this method is not technically transitive. If a
+ * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))},
+ * and b and c are off by slightly less than
+ * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c)
+ * will both return true, but equals(a, c) will return false. However, this
+ * situation is very unlikely to ever happen in a real programming situation.
*
* If this does become a concern, some ways to solve this problem:
*
- *
Raise the value of epsilon (this does not make a violation of transitivity impossible, it just significantly
- * reduces the chances of it happening)
- *
Use {@link BigDecimal} instead of {@code float} (this will make a violation of transitivity 100% impossible)
+ *
Raise the value of epsilon (this does not make a violation of
+ * transitivity impossible, it just significantly reduces the chances of it
+ * happening)
+ *
Use {@link BigDecimal} instead of {@code float} (this will make a
+ * violation of transitivity 100% impossible)
*
*
- * @param a
- * first value to test
- * @param b
- * second value to test
- * @param epsilon
- * allowed difference
+ * @param a first value to test
+ * @param b second value to test
+ * @param epsilon allowed difference
* @return whether they are equal
* @since 2019-03-18
* @since v0.2.0
*/
- public static final boolean equals(final float a, final float b, final float epsilon) {
+ public static final boolean equals(final float a, final float b,
+ final float epsilon) {
return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
}
-
+
+ /**
+ * Tests for equality of {@code UncertainDouble} values using
+ * {@link #DOUBLE_EPSILON}.
+ *
+ * WARNING: this method is not technically transitive. If a
+ * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))},
+ * and b and c are off by slightly less than
+ * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c)
+ * will both return true, but equals(a, c) will return false. However, this
+ * situation is very unlikely to ever happen in a real programming situation.
+ *
+ * If this does become a concern, some ways to solve this problem:
+ *
+ *
Raise the value of epsilon using
+ * {@link #equals(UncertainDouble, UncertainDouble, double)} (this does not
+ * make a violation of transitivity impossible, it just significantly reduces
+ * the chances of it happening)
+ *
Use {@link BigDecimal} instead of {@code double} (this will make a
+ * violation of transitivity 100% impossible)
+ *
+ *
+ * @param a first value to test
+ * @param b second value to test
+ * @return whether they are equal
+ * @since 2020-09-07
+ * @see #hashCode(double)
+ */
+ public static final boolean equals(final UncertainDouble a,
+ final UncertainDouble b) {
+ return DecimalComparison.equals(a.value(), b.value())
+ && DecimalComparison.equals(a.uncertainty(), b.uncertainty());
+ }
+
+ /**
+ * Tests for {@code UncertainDouble} equality using a custom epsilon value.
+ *
+ *
+ * WARNING: this method is not technically transitive. If a
+ * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))},
+ * and b and c are off by slightly less than
+ * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c)
+ * will both return true, but equals(a, c) will return false. However, this
+ * situation is very unlikely to ever happen in a real programming situation.
+ *
+ * If this does become a concern, some ways to solve this problem:
+ *
+ *
Raise the value of epsilon (this does not make a violation of
+ * transitivity impossible, it just significantly reduces the chances of it
+ * happening)
+ *
Use {@link BigDecimal} instead of {@code double} (this will make a
+ * violation of transitivity 100% impossible)
+ *
+ *
+ * @param a first value to test
+ * @param b second value to test
+ * @param epsilon allowed difference
+ * @return whether they are equal
+ * @since 2019-03-18
+ * @since v0.2.0
+ */
+ public static final boolean equals(final UncertainDouble a,
+ final UncertainDouble b, final double epsilon) {
+ return DecimalComparison.equals(a.value(), b.value(), epsilon)
+ && DecimalComparison.equals(a.uncertainty(), b.uncertainty(),
+ epsilon);
+ }
+
/**
- * Takes the hash code of doubles. Values that are equal according to {@link #equals(double, double)} will have the
- * same hash code.
+ * Takes the hash code of doubles. Values that are equal according to
+ * {@link #equals(double, double)} will have the same hash code.
*
- * @param d
- * double to hash
+ * @param d double to hash
* @return hash code of double
* @since 2019-10-16
*/
public static final int hash(final double d) {
return Float.hashCode((float) d);
}
-
+
// You may NOT get any DecimalComparison instances
private DecimalComparison() {
throw new AssertionError();
}
-
+
}
diff --git a/src/org/unitConverter/math/UncertainDouble.java b/src/org/unitConverter/math/UncertainDouble.java
new file mode 100644
index 0000000..e948df9
--- /dev/null
+++ b/src/org/unitConverter/math/UncertainDouble.java
@@ -0,0 +1,411 @@
+/**
+ * @since 2020-09-07
+ */
+package org.unitConverter.math;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A double with an associated uncertainty value. For example, 3.2 ± 0.2.
+ *
+ * All methods in this class throw a NullPointerException if any of their
+ * arguments is null.
+ *
+ * @since 2020-09-07
+ */
+public final class UncertainDouble implements Comparable {
+ /**
+ * The exact value 0
+ */
+ public static final UncertainDouble ZERO = UncertainDouble.of(0, 0);
+
+ /**
+ * A regular expression that can recognize toString forms
+ */
+ private static final Pattern TO_STRING = Pattern
+ .compile("([a-zA-Z_0-9\\.\\,]+)" // a number
+ // optional "± [number]"
+ + "(?:\\s*(?:±|\\+-)\\s*([a-zA-Z_0-9\\.\\,]+))?");
+
+ /**
+ * Parses a string in the form of {@link UncertainDouble#toString(boolean)}
+ * and returns the corresponding {@code UncertainDouble} instance.
+ *
+ * This method allows some alternative forms of the string representation,
+ * such as using "+-" instead of "±".
+ *
+ * @param s string to parse
+ * @return {@code UncertainDouble} instance
+ * @throws IllegalArgumentException if the string is invalid
+ * @since 2020-09-07
+ */
+ public static final UncertainDouble fromString(String s) {
+ Objects.requireNonNull(s, "s may not be null");
+ final Matcher matcher = TO_STRING.matcher(s);
+
+ double value, uncertainty;
+ try {
+ value = Double.parseDouble(matcher.group(1));
+ } catch (IllegalStateException | NumberFormatException e) {
+ throw new IllegalArgumentException(
+ "String " + s + " not in correct format.");
+ }
+
+ final String uncertaintyString = matcher.group(2);
+ if (uncertaintyString == null) {
+ uncertainty = 0;
+ } else {
+ try {
+ uncertainty = Double.parseDouble(uncertaintyString);
+ } catch (final NumberFormatException e) {
+ throw new IllegalArgumentException(
+ "String " + s + " not in correct format.");
+ }
+ }
+
+ return UncertainDouble.of(value, uncertainty);
+ }
+
+ /**
+ * Gets an {@code UncertainDouble} from its value and absolute
+ * uncertainty.
+ *
+ * @since 2020-09-07
+ */
+ public static final UncertainDouble of(double value, double uncertainty) {
+ return new UncertainDouble(value, uncertainty);
+ }
+
+ /**
+ * Gets an {@code UncertainDouble} from its value and relative
+ * uncertainty.
+ *
+ * @since 2020-09-07
+ */
+ public static final UncertainDouble ofRelative(double value,
+ double relativeUncertainty) {
+ return new UncertainDouble(value, value * relativeUncertainty);
+ }
+
+ private final double value;
+
+ private final double uncertainty;
+
+ /**
+ * @param value
+ * @param uncertainty
+ * @since 2020-09-07
+ */
+ private UncertainDouble(double value, double uncertainty) {
+ this.value = value;
+ // uncertainty should only ever be positive
+ this.uncertainty = Math.abs(uncertainty);
+ }
+
+ /**
+ * Compares this {@code UncertainDouble} with another
+ * {@code UncertainDouble}.
+ *
+ * This method only compares the values, not the uncertainties. So 3.1 ± 0.5
+ * is considered less than 3.2 ± 0.5, even though they are equivalent.
+ *
+ * Note: The natural ordering of this class is inconsistent with
+ * equals. Specifically, if two {@code UncertainDouble} instances {@code a}
+ * and {@code b} have the same value but different uncertainties,
+ * {@code a.compareTo(b)} will return 0 but {@code a.equals(b)} will return
+ * {@code false}.
+ */
+ @Override
+ public final int compareTo(UncertainDouble o) {
+ return Double.compare(this.value, o.value);
+ }
+
+ /**
+ * Returns the quotient of {@code this} and {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble dividedBy(UncertainDouble other) {
+ Objects.requireNonNull(other, "other may not be null");
+ return UncertainDouble.ofRelative(this.value / other.value, Math
+ .hypot(this.relativeUncertainty(), other.relativeUncertainty()));
+ }
+
+ /**
+ * Returns the quotient of {@code this} and the exact value {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble dividedByExact(double other) {
+ return UncertainDouble.of(this.value / other, this.uncertainty / other);
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof UncertainDouble))
+ return false;
+ final UncertainDouble other = (UncertainDouble) obj;
+ if (Double.doubleToLongBits(this.uncertainty) != Double
+ .doubleToLongBits(other.uncertainty))
+ return false;
+ if (Double.doubleToLongBits(this.value) != Double
+ .doubleToLongBits(other.value))
+ return false;
+ return true;
+ }
+
+ /**
+ * @param other another {@code UncertainDouble}
+ * @return true iff this and {@code other} are within each other's
+ * uncertainty range.
+ * @since 2020-09-07
+ */
+ public final boolean equivalent(UncertainDouble other) {
+ Objects.requireNonNull(other, "other may not be null");
+ return Math.abs(this.value - other.value) <= Math.min(this.uncertainty,
+ other.uncertainty);
+ }
+
+ /**
+ * Gets the preferred scale for rounding a value for toString.
+ *
+ * @since 2020-09-07
+ */
+ private final int getDisplayScale() {
+ // round based on uncertainty
+ // if uncertainty starts with 1 (ignoring zeroes and the decimal
+ // point), rounds
+ // so that uncertainty has 2 significant digits.
+ // otherwise, rounds so that uncertainty has 1 significant digits.
+ // the value is rounded to the same number of decimal places as the
+ // uncertainty.
+ final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty);
+
+ // the scale that will give the uncertainty two decimal places
+ final int twoDecimalPlacesScale = bigUncertainty.scale()
+ - bigUncertainty.precision() + 2;
+ final BigDecimal roundedUncertainty = bigUncertainty
+ .setScale(twoDecimalPlacesScale, RoundingMode.HALF_EVEN);
+
+ if (roundedUncertainty.unscaledValue().intValue() >= 20)
+ return twoDecimalPlacesScale - 1; // one decimal place
+ else
+ return twoDecimalPlacesScale;
+ }
+
+ @Override
+ public final int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits(this.uncertainty);
+ result = prime * result + (int) (temp ^ temp >>> 32);
+ temp = Double.doubleToLongBits(this.value);
+ result = prime * result + (int) (temp ^ temp >>> 32);
+ return result;
+ }
+
+ /**
+ * @return true iff the value has no uncertainty
+ *
+ * @since 2020-09-07
+ */
+ public final boolean isExact() {
+ return this.uncertainty == 0;
+ }
+
+ /**
+ * Returns the difference of {@code this} and {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble minus(UncertainDouble other) {
+ Objects.requireNonNull(other, "other may not be null");
+ return UncertainDouble.of(this.value - other.value,
+ Math.hypot(this.uncertainty, other.uncertainty));
+ }
+
+ /**
+ * Returns the difference of {@code this} and the exact value {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble minusExact(double other) {
+ return UncertainDouble.of(this.value - other, this.uncertainty);
+ }
+
+ /**
+ * Returns the sum of {@code this} and {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble plus(UncertainDouble other) {
+ Objects.requireNonNull(other, "other may not be null");
+ return UncertainDouble.of(this.value + other.value,
+ Math.hypot(this.uncertainty, other.uncertainty));
+ }
+
+ /**
+ * Returns the sum of {@code this} and the exact value {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble plusExact(double other) {
+ return UncertainDouble.of(this.value + other, this.uncertainty);
+ }
+
+ /**
+ * @return relative uncertainty
+ * @since 2020-09-07
+ */
+ public final double relativeUncertainty() {
+ return this.uncertainty / this.value;
+ }
+
+ /**
+ * Returns the product of {@code this} and {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble times(UncertainDouble other) {
+ Objects.requireNonNull(other, "other may not be null");
+ return UncertainDouble.ofRelative(this.value * other.value, Math
+ .hypot(this.relativeUncertainty(), other.relativeUncertainty()));
+ }
+
+ /**
+ * Returns the product of {@code this} and the exact value {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble timesExact(double other) {
+ return UncertainDouble.of(this.value * other, this.uncertainty * other);
+ }
+
+ /**
+ * Returns the result of {@code this} raised to the exponent {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble toExponent(UncertainDouble other) {
+ Objects.requireNonNull(other, "other may not be null");
+
+ final double result = Math.pow(this.value, other.value);
+ final double relativeUncertainty = Math.hypot(
+ other.value * this.relativeUncertainty(),
+ Math.log(this.value) * other.uncertainty);
+
+ return UncertainDouble.ofRelative(result, relativeUncertainty);
+ }
+
+ /**
+ * Returns the result of {@code this} raised the exact exponent
+ * {@code other}.
+ *
+ * @since 2020-09-07
+ */
+ public final UncertainDouble toExponentExact(double other) {
+ return UncertainDouble.ofRelative(Math.pow(this.value, other),
+ this.relativeUncertainty() * other);
+ }
+
+ /**
+ * Returns a string representation of this {@code UncertainDouble}.
+ *
+ * This method returns the same value as {@link #toString(boolean)}, but
+ * {@code showUncertainty} is true if and only if the uncertainty is
+ * non-zero.
+ *
+ *
+ *
+ * @since 2020-09-07
+ */
+ @Override
+ public final String toString() {
+ return this.toString(!this.isExact());
+ }
+
+ /**
+ * Returns a string representation of this {@code UncertainDouble}.
+ *
+ * If {@code showUncertainty} is true, the string will be of the form "VALUE
+ * ± UNCERTAINTY", and if it is false the string will be of the form "VALUE"
+ *
+ * VALUE represents a string representation of this {@code UncertainDouble}'s
+ * value. If the uncertainty is non-zero, the string will be rounded to the
+ * same precision as the uncertainty, otherwise it will not be rounded. The
+ * string is still rounded if {@code showUncertainty} is false.
+ * UNCERTAINTY represents a string representation of this
+ * {@code UncertainDouble}'s uncertainty. If the uncertainty ends in 1X
+ * (where X represents any digit) it will be rounded to two significant
+ * digits otherwise it will be rounded to one significant digit.
+ *
+ *
+ * @since 2020-09-07
+ */
+ public final String toString(boolean showUncertainty) {
+ String valueString, uncertaintyString;
+
+ // generate the string representation of value and uncertainty
+ if (this.isExact()) {
+ uncertaintyString = "0.0";
+ valueString = Double.toString(this.value);
+
+ } else {
+ // round the value and uncertainty according to getDisplayScale()
+ final BigDecimal bigValue = BigDecimal.valueOf(this.value);
+ final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty);
+
+ final int displayScale = this.getDisplayScale();
+ final BigDecimal roundedUncertainty = bigUncertainty
+ .setScale(displayScale, RoundingMode.HALF_EVEN);
+ final BigDecimal roundedValue = bigValue.setScale(displayScale,
+ RoundingMode.HALF_EVEN);
+
+ valueString = roundedValue.toString();
+ uncertaintyString = roundedUncertainty.toString();
+ }
+
+ // return "value" or "value ± uncertainty" depending on showUncertainty
+ return valueString + (showUncertainty ? " ± " + uncertaintyString : "");
+ }
+
+ /**
+ * @return absolute uncertainty
+ * @since 2020-09-07
+ */
+ public final double uncertainty() {
+ return this.uncertainty;
+ }
+
+ /**
+ * @return value without uncertainty
+ * @since 2020-09-07
+ */
+ public final double value() {
+ return this.value;
+ }
+}
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 762572a..2d63ca7 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -20,89 +20,83 @@ import java.util.Objects;
import org.unitConverter.math.DecimalComparison;
import org.unitConverter.math.ObjectProduct;
+import org.unitConverter.math.UncertainDouble;
/**
- * A unit that can be expressed as a product of its base and a number. For example, kilometres, inches and pounds.
+ * A unit that can be expressed as a product of its base and a number. For
+ * example, kilometres, inches and pounds.
*
* @author Adrien Hopkins
* @since 2019-10-16
*/
public final class LinearUnit extends Unit {
/**
- * Gets a {@code LinearUnit} from a unit and a value. For example, converts '59 °F' to a linear unit with the value
- * of '288.15 K'
+ * Gets a {@code LinearUnit} from a unit and a value. For example, converts
+ * '59 °F' to a linear unit with the value of '288.15 K'
*
- * @param unit
- * unit to convert
- * @param value
- * value to convert
+ * @param unit unit to convert
+ * @param value value to convert
* @return value expressed as a {@code LinearUnit}
* @since 2019-10-16
- * @throws NullPointerException
- * if unit is null
+ * @throws NullPointerException if unit is null
*/
public static LinearUnit fromUnitValue(final Unit unit, final double value) {
- return new LinearUnit(Objects.requireNonNull(unit, "unit must not be null.").getBase(),
+ return new LinearUnit(
+ Objects.requireNonNull(unit, "unit must not be null.").getBase(),
unit.convertToBase(value), NameSymbol.EMPTY);
}
-
+
/**
- * Gets a {@code LinearUnit} from a unit and a value. For example, converts '59 °F' to a linear unit with the value
- * of '288.15 K'
+ * Gets a {@code LinearUnit} from a unit and a value. For example, converts
+ * '59 °F' to a linear unit with the value of '288.15 K'
*
- * @param unit
- * unit to convert
- * @param value
- * value to convert
- * @param ns
- * name(s) and symbol of unit
+ * @param unit unit to convert
+ * @param value value to convert
+ * @param ns name(s) and symbol of unit
* @return value expressed as a {@code LinearUnit}
* @since 2019-10-21
- * @throws NullPointerException
- * if unit or ns is null
+ * @throws NullPointerException if unit or ns is null
*/
- public static LinearUnit fromUnitValue(final Unit unit, final double value, final NameSymbol ns) {
- return new LinearUnit(Objects.requireNonNull(unit, "unit must not be null.").getBase(),
+ public static LinearUnit fromUnitValue(final Unit unit, final double value,
+ final NameSymbol ns) {
+ return new LinearUnit(
+ Objects.requireNonNull(unit, "unit must not be null.").getBase(),
unit.convertToBase(value), ns);
}
-
+
/**
- * Gets a {@code LinearUnit} from a unit base and a conversion factor. In other words, gets the product of
- * {@code unitBase} and {@code conversionFactor}, expressed as a {@code LinearUnit}.
+ * Gets a {@code LinearUnit} from a unit base and a conversion factor. In
+ * other words, gets the product of {@code unitBase} and
+ * {@code conversionFactor}, expressed as a {@code LinearUnit}.
*
- * @param unitBase
- * unit base to multiply by
- * @param conversionFactor
- * number to multiply base by
+ * @param unitBase unit base to multiply by
+ * @param conversionFactor number to multiply base by
* @return product of base and conversion factor
* @since 2019-10-16
- * @throws NullPointerException
- * if unitBase is null
+ * @throws NullPointerException if unitBase is null
*/
- public static LinearUnit valueOf(final ObjectProduct unitBase, final double conversionFactor) {
+ public static LinearUnit valueOf(final ObjectProduct unitBase,
+ final double conversionFactor) {
return new LinearUnit(unitBase, conversionFactor, NameSymbol.EMPTY);
}
-
+
/**
- * Gets a {@code LinearUnit} from a unit base and a conversion factor. In other words, gets the product of
- * {@code unitBase} and {@code conversionFactor}, expressed as a {@code LinearUnit}.
+ * Gets a {@code LinearUnit} from a unit base and a conversion factor. In
+ * other words, gets the product of {@code unitBase} and
+ * {@code conversionFactor}, expressed as a {@code LinearUnit}.
*
- * @param unitBase
- * unit base to multiply by
- * @param conversionFactor
- * number to multiply base by
- * @param ns
- * name(s) and symbol of unit
+ * @param unitBase unit base to multiply by
+ * @param conversionFactor number to multiply base by
+ * @param ns name(s) and symbol of unit
* @return product of base and conversion factor
* @since 2019-10-21
- * @throws NullPointerException
- * if unitBase is null
+ * @throws NullPointerException if unitBase is null
*/
- public static LinearUnit valueOf(final ObjectProduct unitBase, final double conversionFactor,
- final NameSymbol ns) {
+ public static LinearUnit valueOf(final ObjectProduct unitBase,
+ final double conversionFactor, final NameSymbol ns) {
return new LinearUnit(unitBase, conversionFactor, ns);
}
-
+
/**
* The value of this unit as represented in its base form. Mathematically,
*
@@ -113,21 +107,20 @@ public final class LinearUnit extends Unit {
* @since 2019-10-16
*/
private final double conversionFactor;
-
+
/**
* Creates the {@code LinearUnit}.
*
- * @param unitBase
- * base of linear unit
- * @param conversionFactor
- * conversion factor between base and unit
+ * @param unitBase base of linear unit
+ * @param conversionFactor conversion factor between base and unit
* @since 2019-10-16
*/
- private LinearUnit(final ObjectProduct unitBase, final double conversionFactor, final NameSymbol ns) {
+ private LinearUnit(final ObjectProduct unitBase,
+ final double conversionFactor, final NameSymbol ns) {
super(unitBase, ns);
this.conversionFactor = conversionFactor;
}
-
+
/**
* {@inheritDoc}
*
@@ -137,7 +130,32 @@ public final class LinearUnit extends Unit {
protected double convertFromBase(final double value) {
return value / this.getConversionFactor();
}
-
+
+ /**
+ * Converts an {@code UncertainDouble} value expressed in this unit to an
+ * {@code UncertainValue} value expressed in {@code other}.
+ *
+ * @param other unit to convert to
+ * @param value value to convert
+ * @return converted value
+ * @since 2019-09-07
+ * @throws IllegalArgumentException if {@code other} is incompatible for
+ * conversion with this unit (as tested by
+ * {@link Unit#canConvertTo}).
+ * @throws NullPointerException if value or other is null
+ */
+ public UncertainDouble convertTo(LinearUnit other, UncertainDouble value) {
+ Objects.requireNonNull(other, "other must not be null.");
+ Objects.requireNonNull(value, "value may not be null.");
+ if (this.canConvertTo(other))
+ return value.timesExact(
+ this.getConversionFactor() / other.getConversionFactor());
+ else
+ throw new IllegalArgumentException(
+ String.format("Cannot convert from %s to %s.", this, other));
+
+ }
+
/**
* {@inheritDoc}
*
@@ -147,12 +165,20 @@ public final class LinearUnit extends Unit {
protected double convertToBase(final double value) {
return value * this.getConversionFactor();
}
-
+
+ /**
+ * Converts an {@code UncertainDouble} to the base unit.
+ *
+ * @since 2020-09-07
+ */
+ UncertainDouble convertToBase(final UncertainDouble value) {
+ return value.timesExact(this.getConversionFactor());
+ }
+
/**
* Divides this unit by a scalar.
*
- * @param divisor
- * scalar to divide by
+ * @param divisor scalar to divide by
* @return quotient
* @since 2018-12-23
* @since v0.1.0
@@ -160,26 +186,26 @@ public final class LinearUnit extends Unit {
public LinearUnit dividedBy(final double divisor) {
return valueOf(this.getBase(), this.getConversionFactor() / divisor);
}
-
+
/**
* Returns the quotient of this unit and another.
*
- * @param divisor
- * unit to divide by
+ * @param divisor unit to divide by
* @return quotient of two units
- * @throws NullPointerException
- * if {@code divisor} is null
+ * @throws NullPointerException if {@code divisor} is null
* @since 2018-12-22
* @since v0.1.0
*/
public LinearUnit dividedBy(final LinearUnit divisor) {
Objects.requireNonNull(divisor, "other must not be null");
-
+
// divide the units
- final ObjectProduct base = this.getBase().dividedBy(divisor.getBase());
- return valueOf(base, this.getConversionFactor() / divisor.getConversionFactor());
+ final ObjectProduct base = this.getBase()
+ .dividedBy(divisor.getBase());
+ return valueOf(base,
+ this.getConversionFactor() / divisor.getConversionFactor());
}
-
+
/**
* {@inheritDoc}
*
@@ -191,9 +217,10 @@ public final class LinearUnit extends Unit {
return false;
final LinearUnit other = (LinearUnit) obj;
return Objects.equals(this.getBase(), other.getBase())
- && DecimalComparison.equals(this.getConversionFactor(), other.getConversionFactor());
+ && DecimalComparison.equals(this.getConversionFactor(),
+ other.getConversionFactor());
}
-
+
/**
* @return conversion factor
* @since 2019-10-16
@@ -201,7 +228,7 @@ public final class LinearUnit extends Unit {
public double getConversionFactor() {
return this.conversionFactor;
}
-
+
/**
* {@inheritDoc}
*
@@ -209,18 +236,20 @@ public final class LinearUnit extends Unit {
*/
@Override
public int hashCode() {
- return 31 * this.getBase().hashCode() + DecimalComparison.hash(this.getConversionFactor());
+ return 31 * this.getBase().hashCode()
+ + DecimalComparison.hash(this.getConversionFactor());
}
-
+
/**
- * @return whether this unit is equivalent to a {@code BaseUnit} (i.e. there is a {@code BaseUnit b} where
+ * @return whether this unit is equivalent to a {@code BaseUnit} (i.e. there
+ * is a {@code BaseUnit b} where
* {@code b.asLinearUnit().equals(this)} returns {@code true}.)
* @since 2019-10-16
*/
public boolean isBase() {
return this.isCoherent() && this.getBase().isSingleObject();
}
-
+
/**
* @return whether this unit is coherent (i.e. has conversion factor 1)
* @since 2019-10-16
@@ -228,70 +257,73 @@ public final class LinearUnit extends Unit {
public boolean isCoherent() {
return this.getConversionFactor() == 1;
}
-
+
/**
* Returns the difference of this unit and another.
*
- * Two units can be subtracted if they have the same base. Note that {@link #canConvertTo} can be used to determine
- * this. If {@code subtrahend} does not meet this condition, an {@code IllegalArgumentException} will be thrown.
+ * Two units can be subtracted if they have the same base. Note that
+ * {@link #canConvertTo} can be used to determine this. If {@code subtrahend}
+ * does not meet this condition, an {@code IllegalArgumentException} will be
+ * thrown.
*
*
- * @param subtrahend
- * unit to subtract
+ * @param subtrahend unit to subtract
* @return difference of units
- * @throws IllegalArgumentException
- * if {@code subtrahend} is not compatible for subtraction as described above
- * @throws NullPointerException
- * if {@code subtrahend} is null
+ * @throws IllegalArgumentException if {@code subtrahend} is not compatible
+ * for subtraction as described above
+ * @throws NullPointerException if {@code subtrahend} is null
* @since 2019-03-17
* @since v0.2.0
*/
public LinearUnit minus(final LinearUnit subtrahend) {
Objects.requireNonNull(subtrahend, "addend must not be null.");
-
+
// reject subtrahends that cannot be added to this unit
if (!this.getBase().equals(subtrahend.getBase()))
- throw new IllegalArgumentException(
- String.format("Incompatible units for subtraction \"%s\" and \"%s\".", this, subtrahend));
-
+ throw new IllegalArgumentException(String.format(
+ "Incompatible units for subtraction \"%s\" and \"%s\".", this,
+ subtrahend));
+
// subtract the units
- return valueOf(this.getBase(), this.getConversionFactor() - subtrahend.getConversionFactor());
+ return valueOf(this.getBase(),
+ this.getConversionFactor() - subtrahend.getConversionFactor());
}
-
+
/**
* Returns the sum of this unit and another.
*
- * Two units can be added if they have the same base. Note that {@link #canConvertTo} can be used to determine this.
- * If {@code addend} does not meet this condition, an {@code IllegalArgumentException} will be thrown.
+ * Two units can be added if they have the same base. Note that
+ * {@link #canConvertTo} can be used to determine this. If {@code addend}
+ * does not meet this condition, an {@code IllegalArgumentException} will be
+ * thrown.
*
*
- * @param addend
- * unit to add
+ * @param addend unit to add
* @return sum of units
- * @throws IllegalArgumentException
- * if {@code addend} is not compatible for addition as described above
- * @throws NullPointerException
- * if {@code addend} is null
+ * @throws IllegalArgumentException if {@code addend} is not compatible for
+ * addition as described above
+ * @throws NullPointerException if {@code addend} is null
* @since 2019-03-17
* @since v0.2.0
*/
public LinearUnit plus(final LinearUnit addend) {
Objects.requireNonNull(addend, "addend must not be null.");
-
+
// reject addends that cannot be added to this unit
if (!this.getBase().equals(addend.getBase()))
- throw new IllegalArgumentException(
- String.format("Incompatible units for addition \"%s\" and \"%s\".", this, addend));
-
+ throw new IllegalArgumentException(String.format(
+ "Incompatible units for addition \"%s\" and \"%s\".", this,
+ addend));
+
// add the units
- return valueOf(this.getBase(), this.getConversionFactor() + addend.getConversionFactor());
+ return valueOf(this.getBase(),
+ this.getConversionFactor() + addend.getConversionFactor());
}
-
+
/**
* Multiplies this unit by a scalar.
*
- * @param multiplier
- * scalar to multiply by
+ * @param multiplier scalar to multiply by
* @return product
* @since 2018-12-23
* @since v0.1.0
@@ -299,39 +331,39 @@ public final class LinearUnit extends Unit {
public LinearUnit times(final double multiplier) {
return valueOf(this.getBase(), this.getConversionFactor() * multiplier);
}
-
+
/**
* Returns the product of this unit and another.
*
- * @param multiplier
- * unit to multiply by
+ * @param multiplier unit to multiply by
* @return product of two units
- * @throws NullPointerException
- * if {@code multiplier} is null
+ * @throws NullPointerException if {@code multiplier} is null
* @since 2018-12-22
* @since v0.1.0
*/
public LinearUnit times(final LinearUnit multiplier) {
Objects.requireNonNull(multiplier, "other must not be null");
-
+
// multiply the units
- final ObjectProduct base = this.getBase().times(multiplier.getBase());
- return valueOf(base, this.getConversionFactor() * multiplier.getConversionFactor());
+ final ObjectProduct base = this.getBase()
+ .times(multiplier.getBase());
+ return valueOf(base,
+ this.getConversionFactor() * multiplier.getConversionFactor());
}
-
+
/**
* Returns this unit but to an exponent.
*
- * @param exponent
- * exponent to exponentiate unit to
+ * @param exponent exponent to exponentiate unit to
* @return exponentiated unit
* @since 2019-01-15
* @since v0.1.0
*/
public LinearUnit toExponent(final int exponent) {
- return valueOf(this.getBase().toExponent(exponent), Math.pow(this.conversionFactor, exponent));
+ return valueOf(this.getBase().toExponent(exponent),
+ Math.pow(this.conversionFactor, exponent));
}
-
+
/**
* @return a string providing a definition of this unit
* @since 2019-10-21
@@ -339,10 +371,13 @@ public final class LinearUnit extends Unit {
@Override
public String toString() {
return this.getPrimaryName().orElse("Unnamed unit")
- + (this.getSymbol().isPresent() ? String.format(" (%s)", this.getSymbol().get()) : "") + ", "
- + Double.toString(this.conversionFactor) + " * " + this.getBase().toString(u -> u.getSymbol().get());
+ + (this.getSymbol().isPresent()
+ ? String.format(" (%s)", this.getSymbol().get())
+ : "")
+ + ", " + Double.toString(this.conversionFactor) + " * "
+ + this.getBase().toString(u -> u.getSymbol().get());
}
-
+
@Override
public LinearUnit withName(final NameSymbol ns) {
return valueOf(this.getBase(), this.getConversionFactor(), ns);
@@ -351,37 +386,38 @@ public final class LinearUnit extends Unit {
/**
* Returns the result of applying {@code prefix} to this unit.
*
- * If this unit and the provided prefix have a primary name, the returned unit will have a primary name (prefix's
- * name + unit's name).
- * If this unit and the provided prefix have a symbol, the returned unit will have a symbol.
- * This method ignores alternate names of both this unit and the provided prefix.
+ * If this unit and the provided prefix have a primary name, the returned
+ * unit will have a primary name (prefix's name + unit's name).
+ * If this unit and the provided prefix have a symbol, the returned unit will
+ * have a symbol.
+ * This method ignores alternate names of both this unit and the provided
+ * prefix.
*
- * @param prefix
- * prefix to apply
+ * @param prefix prefix to apply
* @return unit with prefix
* @since 2019-03-18
* @since v0.2.0
- * @throws NullPointerException
- * if prefix is null
+ * @throws NullPointerException if prefix is null
*/
public LinearUnit withPrefix(final UnitPrefix prefix) {
final LinearUnit unit = this.times(prefix.getMultiplier());
-
+
// create new name and symbol, if possible
final String name;
- if (this.getPrimaryName().isPresent() && prefix.getPrimaryName().isPresent()) {
+ if (this.getPrimaryName().isPresent()
+ && prefix.getPrimaryName().isPresent()) {
name = prefix.getPrimaryName().get() + this.getPrimaryName().get();
} else {
name = null;
}
-
+
final String symbol;
if (this.getSymbol().isPresent() && prefix.getSymbol().isPresent()) {
symbol = prefix.getSymbol().get() + this.getSymbol().get();
} else {
symbol = null;
}
-
+
return unit.withName(NameSymbol.ofNullable(name, symbol));
}
}
diff --git a/src/org/unitConverter/unit/LinearUnitValue.java b/src/org/unitConverter/unit/LinearUnitValue.java
index 5685a6d..d86d344 100644
--- a/src/org/unitConverter/unit/LinearUnitValue.java
+++ b/src/org/unitConverter/unit/LinearUnitValue.java
@@ -3,12 +3,11 @@
*/
package org.unitConverter.unit;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
import java.util.Objects;
import java.util.Optional;
import org.unitConverter.math.DecimalComparison;
+import org.unitConverter.math.UncertainDouble;
/**
* A possibly uncertain value expressed in a linear unit.
@@ -33,7 +32,8 @@ public final class LinearUnitValue {
public static final LinearUnitValue getExact(final LinearUnit unit,
final double value) {
return new LinearUnitValue(
- Objects.requireNonNull(unit, "unit must not be null"), value, 0);
+ Objects.requireNonNull(unit, "unit must not be null"),
+ UncertainDouble.of(value, 0));
}
/**
@@ -46,41 +46,23 @@ public final class LinearUnitValue {
* @since 2020-07-26
*/
public static final LinearUnitValue of(final LinearUnit unit,
- final double value, final double uncertainty) {
+ final UncertainDouble value) {
return new LinearUnitValue(
- Objects.requireNonNull(unit, "unit must not be null"), value,
- uncertainty);
- }
-
- /**
- * Gets an uncertain {@code LinearUnitValue}
- *
- * @param unit unit to express with
- * @param value value to express
- * @param relativeUncertainty relative uncertainty of value
- * @return uncertain {@code LinearUnitValue} instance
- * @since 2020-07-28
- */
- public static final LinearUnitValue ofRelative(final LinearUnit unit,
- final double value, final double relativeUncertainty) {
- return LinearUnitValue.of(unit, value, relativeUncertainty * value);
+ Objects.requireNonNull(unit, "unit must not be null"),
+ Objects.requireNonNull(value, "value may not be null"));
}
private final LinearUnit unit;
- private final double value;
- private final double uncertainty;
+ private final UncertainDouble value;
/**
- * @param unit unit to express as
- * @param value value to express
- * @param uncertainty absolute uncertainty of value
+ * @param unit unit to express as
+ * @param value value to express
* @since 2020-07-26
*/
- private LinearUnitValue(final LinearUnit unit, final double value,
- final double uncertainty) {
+ private LinearUnitValue(final LinearUnit unit, final UncertainDouble value) {
this.unit = unit;
this.value = value;
- this.uncertainty = uncertainty;
}
/**
@@ -89,7 +71,7 @@ public final class LinearUnitValue {
* @since 2020-08-04
*/
public final UnitValue asUnitValue() {
- return UnitValue.of(this.unit, this.value);
+ return UnitValue.of(this.unit, this.value.value());
}
/**
@@ -110,8 +92,7 @@ public final class LinearUnitValue {
* @since 2020-07-26
*/
public final LinearUnitValue convertTo(final LinearUnit other) {
- return LinearUnitValue.of(other, this.unit.convertTo(other, this.value),
- this.unit.convertTo(other, this.uncertainty));
+ return LinearUnitValue.of(other, this.unit.convertTo(other, this.value));
}
/**
@@ -122,8 +103,7 @@ public final class LinearUnitValue {
* @since 2020-07-28
*/
public LinearUnitValue dividedBy(final double divisor) {
- return LinearUnitValue.of(this.unit, this.value / divisor,
- this.uncertainty / divisor);
+ return LinearUnitValue.of(this.unit, this.value.dividedByExact(divisor));
}
/**
@@ -134,10 +114,8 @@ public final class LinearUnitValue {
* @since 2020-07-28
*/
public LinearUnitValue dividedBy(final LinearUnitValue divisor) {
- return LinearUnitValue.ofRelative(this.unit.dividedBy(divisor.unit),
- this.value / divisor.value,
- Math.hypot(this.getRelativeUncertainty(),
- divisor.getRelativeUncertainty()));
+ return LinearUnitValue.of(this.unit.dividedBy(divisor.unit),
+ this.value.dividedBy(divisor.value));
}
/**
@@ -154,12 +132,8 @@ public final class LinearUnitValue {
return false;
final LinearUnitValue other = (LinearUnitValue) obj;
return Objects.equals(this.unit.getBase(), other.unit.getBase())
- && Double.doubleToLongBits(
- this.unit.convertToBase(this.getValue())) == Double
- .doubleToLongBits(
- other.unit.convertToBase(other.getValue()))
- && Double.doubleToLongBits(this.getRelativeUncertainty()) == Double
- .doubleToLongBits(other.getRelativeUncertainty());
+ && this.unit.convertToBase(this.value)
+ .equals(other.unit.convertToBase(other.value));
}
/**
@@ -180,9 +154,7 @@ public final class LinearUnitValue {
final LinearUnitValue other = (LinearUnitValue) obj;
return Objects.equals(this.unit.getBase(), other.unit.getBase())
&& DecimalComparison.equals(this.unit.convertToBase(this.value),
- other.unit.convertToBase(other.value))
- && DecimalComparison.equals(this.getRelativeUncertainty(),
- other.getRelativeUncertainty());
+ other.unit.convertToBase(other.value));
}
/**
@@ -195,32 +167,11 @@ public final class LinearUnitValue {
if (other == null
|| !Objects.equals(this.unit.getBase(), other.unit.getBase()))
return false;
- final double thisBaseValue = this.unit.convertToBase(this.value);
- final double otherBaseValue = other.unit.convertToBase(other.value);
- final double thisBaseUncertainty = this.unit
- .convertToBase(this.uncertainty);
- final double otherBaseUncertainty = other.unit
- .convertToBase(other.uncertainty);
- return Math.abs(thisBaseValue - otherBaseValue) <= Math
- .min(thisBaseUncertainty, otherBaseUncertainty);
- }
-
- /**
- * @return relative uncertainty of value
- *
- * @since 2020-07-26
- */
- public final double getRelativeUncertainty() {
- return this.uncertainty / this.value;
- }
-
- /**
- * @return absolute uncertainty of value
- *
- * @since 2020-07-26
- */
- public final double getUncertainty() {
- return this.uncertainty;
+ final LinearUnit base = LinearUnit.valueOf(this.unit.getBase(), 1);
+ final LinearUnitValue thisBase = this.convertTo(base);
+ final LinearUnitValue otherBase = other.convertTo(base);
+
+ return thisBase.value.equivalent(otherBase.value);
}
/**
@@ -237,24 +188,22 @@ public final class LinearUnitValue {
*
* @since 2020-07-26
*/
- public final double getValue() {
+ public final UncertainDouble getValue() {
return this.value;
}
+ /**
+ * @return the exact value
+ * @since 2020-09-07
+ */
+ public final double getValueExact() {
+ return this.value.value();
+ }
+
@Override
public int hashCode() {
return Objects.hash(this.unit.getBase(),
- this.unit.convertToBase(this.getValue()),
- this.getRelativeUncertainty());
- }
-
- /**
- * @return true iff the value has no uncertainty
- *
- * @since 2020-07-26
- */
- public final boolean isExact() {
- return this.uncertainty == 0;
+ this.unit.convertToBase(this.getValue()));
}
/**
@@ -276,8 +225,8 @@ public final class LinearUnitValue {
this.unit, subtrahend.unit));
final LinearUnitValue otherConverted = subtrahend.convertTo(this.unit);
- return LinearUnitValue.of(this.unit, this.value - otherConverted.value,
- Math.hypot(this.uncertainty, otherConverted.uncertainty));
+ return LinearUnitValue.of(this.unit,
+ this.value.minus(otherConverted.value));
}
/**
@@ -298,8 +247,8 @@ public final class LinearUnitValue {
addend.unit));
final LinearUnitValue otherConverted = addend.convertTo(this.unit);
- return LinearUnitValue.of(this.unit, this.value + otherConverted.value,
- Math.hypot(this.uncertainty, otherConverted.uncertainty));
+ return LinearUnitValue.of(this.unit,
+ this.value.plus(otherConverted.value));
}
/**
@@ -310,8 +259,7 @@ public final class LinearUnitValue {
* @since 2020-07-28
*/
public LinearUnitValue times(final double multiplier) {
- return LinearUnitValue.of(this.unit, this.value * multiplier,
- this.uncertainty * multiplier);
+ return LinearUnitValue.of(this.unit, this.value.timesExact(multiplier));
}
/**
@@ -322,10 +270,8 @@ public final class LinearUnitValue {
* @since 2020-07-28
*/
public LinearUnitValue times(final LinearUnitValue multiplier) {
- return LinearUnitValue.ofRelative(this.unit.times(multiplier.unit),
- this.value * multiplier.value,
- Math.hypot(this.getRelativeUncertainty(),
- multiplier.getRelativeUncertainty()));
+ return LinearUnitValue.of(this.unit.times(multiplier.unit),
+ this.value.times(multiplier.value));
}
/**
@@ -336,14 +282,13 @@ public final class LinearUnitValue {
* @since 2020-07-28
*/
public LinearUnitValue toExponent(final int exponent) {
- return LinearUnitValue.ofRelative(this.unit.toExponent(exponent),
- Math.pow(this.value, exponent),
- this.getRelativeUncertainty() * Math.sqrt(exponent));
+ return LinearUnitValue.of(this.unit.toExponent(exponent),
+ this.value.toExponentExact(exponent));
}
@Override
public String toString() {
- return this.toString(!this.isExact());
+ return this.toString(!this.value.isExact());
}
/**
@@ -363,107 +308,22 @@ public final class LinearUnitValue {
final Optional symbol = this.unit.getSymbol();
final String chosenName = symbol.orElse(primaryName.orElse(null));
- final double baseValue = this.unit.convertToBase(this.value);
- final double baseUncertainty = this.unit.convertToBase(this.uncertainty);
+ final UncertainDouble baseValue = this.unit.convertToBase(this.value);
// get rounded strings
- String valueString, baseValueString, uncertaintyString,
- baseUncertaintyString;
- if (this.isExact()) {
- valueString = Double.toString(this.value);
- baseValueString = Double.toString(baseValue);
- uncertaintyString = "0";
- baseUncertaintyString = "0";
- } else {
- final BigDecimal bigValue = BigDecimal.valueOf(this.value);
- final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty);
-
- // round based on uncertainty
- // if uncertainty starts with 1 (ignoring zeroes and the decimal
- // point), rounds
- // so that uncertainty has 2 significant digits.
- // otherwise, rounds so that uncertainty has 1 significant digits.
- // the value is rounded to the same number of decimal places as the
- // uncertainty.
- BigDecimal roundedUncertainty = bigUncertainty.setScale(
- bigUncertainty.scale() - bigUncertainty.precision() + 2,
- RoundingMode.HALF_EVEN);
- if (roundedUncertainty.unscaledValue().intValue() >= 20) {
- roundedUncertainty = bigUncertainty.setScale(
- bigUncertainty.scale() - bigUncertainty.precision() + 1,
- RoundingMode.HALF_EVEN);
- }
- final BigDecimal roundedValue = bigValue
- .setScale(roundedUncertainty.scale(), RoundingMode.HALF_EVEN);
-
- valueString = roundedValue.toString();
- uncertaintyString = roundedUncertainty.toString();
-
- if (primaryName.isEmpty() && symbol.isEmpty()) {
- final BigDecimal bigBaseValue = BigDecimal.valueOf(baseValue);
- final BigDecimal bigBaseUncertainty = BigDecimal
- .valueOf(baseUncertainty);
-
- BigDecimal roundedBaseUncertainty = bigBaseUncertainty
- .setScale(
- bigBaseUncertainty.scale()
- - bigBaseUncertainty.precision() + 2,
- RoundingMode.HALF_EVEN);
- if (roundedBaseUncertainty.unscaledValue().intValue() >= 20) {
- roundedBaseUncertainty = bigBaseUncertainty
- .setScale(
- bigBaseUncertainty.scale()
- - bigBaseUncertainty.precision() + 1,
- RoundingMode.HALF_EVEN);
- }
- final BigDecimal roundedBaseValue = bigBaseValue.setScale(
- roundedBaseUncertainty.scale(), RoundingMode.HALF_EVEN);
-
- baseValueString = roundedBaseValue.toString();
- baseUncertaintyString = roundedBaseUncertainty.toString();
- } else {
- // unused
- baseValueString = "";
- baseUncertaintyString = "";
- }
- }
+ // if showUncertainty is true, add brackets around the string
+ final String valueString = showUncertainty ? "("
+ : "" + this.value.toString(showUncertainty)
+ + (showUncertainty ? ")" : "");
+ final String baseValueString = showUncertainty ? "("
+ : "" + baseValue.toString(showUncertainty)
+ + (showUncertainty ? ")" : "");
// create string
- if (showUncertainty) {
- if (primaryName.isEmpty() && symbol.isEmpty())
- return String.format("(%s ± %s) unnamed unit (= %s ± %s %s)",
- valueString, uncertaintyString, baseValueString,
- baseUncertaintyString, this.unit.getBase());
- else
- return String.format("(%s ± %s) %s", valueString, uncertaintyString,
- chosenName);
- } else {
- // truncate excess zeroes
- if (valueString.contains(".")) {
- while (valueString.endsWith("0")) {
- valueString = valueString.substring(0, valueString.length() - 1);
- }
- if (valueString.endsWith(".")) {
- valueString = valueString.substring(0, valueString.length() - 1);
- }
- }
-
- if (baseValueString.contains(".")) {
- while (baseValueString.endsWith("0")) {
- baseValueString = baseValueString.substring(0,
- baseValueString.length() - 1);
- }
- if (baseValueString.endsWith(".")) {
- baseValueString = baseValueString.substring(0,
- baseValueString.length() - 1);
- }
- }
-
- if (primaryName.isEmpty() && symbol.isEmpty())
- return String.format("%s unnamed unit (= %s %s)", valueString,
- baseValueString, this.unit.getBase());
- else
- return String.format("%s %s", valueString, chosenName);
- }
+ if (primaryName.isEmpty() && symbol.isEmpty())
+ return String.format("%s unnamed unit (= %s %s)", valueString,
+ baseValueString, this.unit.getBase());
+ else
+ return String.format("%s %s", valueString, chosenName);
}
}
diff --git a/src/org/unitConverter/unit/UnitDatabase.java b/src/org/unitConverter/unit/UnitDatabase.java
index 9812bd0..9ca9617 100644
--- a/src/org/unitConverter/unit/UnitDatabase.java
+++ b/src/org/unitConverter/unit/UnitDatabase.java
@@ -46,6 +46,7 @@ import org.unitConverter.math.ConditionalExistenceCollections;
import org.unitConverter.math.DecimalComparison;
import org.unitConverter.math.ExpressionParser;
import org.unitConverter.math.ObjectProduct;
+import org.unitConverter.math.UncertainDouble;
/**
* A database of units, prefixes and dimensions, and their names.
@@ -1134,7 +1135,7 @@ public final class UnitDatabase {
// exponent function - first check if o2 is a number,
if (exponentValue.canConvertTo(SI.ONE)) {
// then check if it is an integer,
- final double exponent = exponentValue.getValue();
+ final double exponent = exponentValue.getValueExact();
if (DecimalComparison.equals(exponent % 1, 0))
// then exponentiate
return base.toExponent((int) (exponent + 0.5));
@@ -1650,7 +1651,8 @@ public final class UnitDatabase {
final BigDecimal number = new BigDecimal(name);
final double uncertainty = Math.pow(10, -number.scale());
- return LinearUnitValue.of(SI.ONE, number.doubleValue(), uncertainty);
+ return LinearUnitValue.of(SI.ONE,
+ UncertainDouble.of(number.doubleValue(), uncertainty));
} catch (final NumberFormatException e) {
return LinearUnitValue.getExact(this.getLinearUnit(name), 1);
}
diff --git a/src/org/unitConverter/unit/UnitTest.java b/src/org/unitConverter/unit/UnitTest.java
index ff83805..c0711dc 100644
--- a/src/org/unitConverter/unit/UnitTest.java
+++ b/src/org/unitConverter/unit/UnitTest.java
@@ -56,9 +56,10 @@ class UnitTest {
final LinearUnitValue value4 = LinearUnitValue.getExact(SI.KILOGRAM, 60);
// make sure addition is done correctly
- assertEquals(51.576, value1.plus(value2).getValue(), 0.001);
- assertEquals(15.5, value1.plus(value3).getValue());
- assertEquals(52.076, value1.plus(value2).plus(value3).getValue(), 0.001);
+ assertEquals(51.576, value1.plus(value2).getValueExact(), 0.001);
+ assertEquals(15.5, value1.plus(value3).getValueExact());
+ assertEquals(52.076, value1.plus(value2).plus(value3).getValueExact(),
+ 0.001);
// make sure addition uses the correct unit, and is still associative
// (ignoring floating-point rounding errors)
--
cgit v1.2.3
From cd33f886dfbd35c0ee3d8cf5b553ea3481b0b3a1 Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Fri, 2 Oct 2020 10:16:10 -0500
Subject: Added Unitlike objects
---
src/org/unitConverter/math/UncertainDouble.java | 15 +-
src/org/unitConverter/unit/FunctionalUnitlike.java | 72 ++++++
src/org/unitConverter/unit/LinearUnit.java | 18 ++
src/org/unitConverter/unit/LinearUnitValue.java | 22 +-
src/org/unitConverter/unit/Nameable.java | 59 +++++
src/org/unitConverter/unit/Unit.java | 118 ++++++----
src/org/unitConverter/unit/UnitValue.java | 149 ++++++++----
src/org/unitConverter/unit/Unitlike.java | 260 +++++++++++++++++++++
src/org/unitConverter/unit/UnitlikeValue.java | 172 ++++++++++++++
9 files changed, 785 insertions(+), 100 deletions(-)
create mode 100644 src/org/unitConverter/unit/FunctionalUnitlike.java
create mode 100644 src/org/unitConverter/unit/Nameable.java
create mode 100644 src/org/unitConverter/unit/Unitlike.java
create mode 100644 src/org/unitConverter/unit/UnitlikeValue.java
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/src/org/unitConverter/math/UncertainDouble.java b/src/org/unitConverter/math/UncertainDouble.java
index e948df9..9601c75 100644
--- a/src/org/unitConverter/math/UncertainDouble.java
+++ b/src/org/unitConverter/math/UncertainDouble.java
@@ -1,5 +1,18 @@
/**
- * @since 2020-09-07
+ * Copyright (C) 2020 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.math;
diff --git a/src/org/unitConverter/unit/FunctionalUnitlike.java b/src/org/unitConverter/unit/FunctionalUnitlike.java
new file mode 100644
index 0000000..21c1fca
--- /dev/null
+++ b/src/org/unitConverter/unit/FunctionalUnitlike.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (C) 2020 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.function.DoubleFunction;
+import java.util.function.ToDoubleFunction;
+
+import org.unitConverter.math.ObjectProduct;
+
+/**
+ * A unitlike form that converts using two conversion functions.
+ *
+ * @since 2020-09-07
+ */
+final class FunctionalUnitlike extends Unitlike {
+ /**
+ * A function that accepts a value in the unitlike form's base and returns a
+ * value in the unitlike form.
+ *
+ * @since 2020-09-07
+ */
+ private final DoubleFunction converterFrom;
+
+ /**
+ * A function that accepts a value in the unitlike form and returns a value
+ * in the unitlike form's base.
+ */
+ private final ToDoubleFunction converterTo;
+
+ /**
+ * Creates the {@code FunctionalUnitlike}.
+ *
+ * @param base unitlike form's base
+ * @param converterFrom function that accepts a value in the unitlike form's
+ * base and returns a value in the unitlike form.
+ * @param converterTo function that accepts a value in the unitlike form
+ * and returns a value in the unitlike form's base.
+ * @throws NullPointerException if any argument is null
+ * @since 2019-05-22
+ */
+ protected FunctionalUnitlike(ObjectProduct unitBase, NameSymbol ns,
+ DoubleFunction converterFrom, ToDoubleFunction converterTo) {
+ super(unitBase, ns);
+ this.converterFrom = converterFrom;
+ this.converterTo = converterTo;
+ }
+
+ @Override
+ protected V convertFromBase(double value) {
+ return this.converterFrom.apply(value);
+ }
+
+ @Override
+ protected double convertToBase(V value) {
+ return this.converterTo.applyAsDouble(value);
+ }
+
+}
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java
index 2d63ca7..b7f33d5 100644
--- a/src/org/unitConverter/unit/LinearUnit.java
+++ b/src/org/unitConverter/unit/LinearUnit.java
@@ -64,6 +64,24 @@ public final class LinearUnit extends Unit {
unit.convertToBase(value), ns);
}
+ /**
+ * @return the base unit associated with {@code unit}, as a
+ * {@code LinearUnit}.
+ * @since 2020-10-02
+ */
+ public static LinearUnit getBase(final Unit unit) {
+ return new LinearUnit(unit.getBase(), 1, NameSymbol.EMPTY);
+ }
+
+ /**
+ * @return the base unit associated with {@code unitlike}, as a
+ * {@code LinearUnit}.
+ * @since 2020-10-02
+ */
+ public static LinearUnit getBase(final Unitlike> unit) {
+ return new LinearUnit(unit.getBase(), 1, NameSymbol.EMPTY);
+ }
+
/**
* Gets a {@code LinearUnit} from a unit base and a conversion factor. In
* other words, gets the product of {@code unitBase} and
diff --git a/src/org/unitConverter/unit/LinearUnitValue.java b/src/org/unitConverter/unit/LinearUnitValue.java
index d86d344..8de734e 100644
--- a/src/org/unitConverter/unit/LinearUnitValue.java
+++ b/src/org/unitConverter/unit/LinearUnitValue.java
@@ -1,5 +1,18 @@
/**
- *
+ * 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;
@@ -53,6 +66,7 @@ public final class LinearUnitValue {
}
private final LinearUnit unit;
+
private final UncertainDouble value;
/**
@@ -176,8 +190,7 @@ public final class LinearUnitValue {
/**
* @return the unit
- *
- * @since 2020-07-26
+ * @since 2020-09-29
*/
public final LinearUnit getUnit() {
return this.unit;
@@ -185,8 +198,7 @@ public final class LinearUnitValue {
/**
* @return the value
- *
- * @since 2020-07-26
+ * @since 2020-09-29
*/
public final UncertainDouble getValue() {
return this.value;
diff --git a/src/org/unitConverter/unit/Nameable.java b/src/org/unitConverter/unit/Nameable.java
new file mode 100644
index 0000000..36740ab
--- /dev/null
+++ b/src/org/unitConverter/unit/Nameable.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2020 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.Optional;
+import java.util.Set;
+
+/**
+ * An object that can hold one or more names, and possibly a symbol. The name
+ * and symbol data should be immutable.
+ *
+ * @since 2020-09-07
+ */
+public interface Nameable {
+ /**
+ * @return a {@code NameSymbol} that contains this object's primary name,
+ * symbol and other names
+ * @since 2020-09-07
+ */
+ NameSymbol getNameSymbol();
+
+ /**
+ * @return set of alternate names
+ * @since 2020-09-07
+ */
+ default Set getOtherNames() {
+ return this.getNameSymbol().getOtherNames();
+ }
+
+ /**
+ * @return preferred name of object
+ * @since 2020-09-07
+ */
+ default Optional getPrimaryName() {
+ return this.getNameSymbol().getPrimaryName();
+ }
+
+ /**
+ * @return short symbol representing object
+ * @since 2020-09-07
+ */
+ default Optional getSymbol() {
+ return this.getNameSymbol().getSymbol();
+ }
+}
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java
index eb9b000..0a3298f 100644
--- a/src/org/unitConverter/unit/Unit.java
+++ b/src/org/unitConverter/unit/Unit.java
@@ -16,12 +16,10 @@
*/
package org.unitConverter.unit;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
import java.util.function.DoubleUnaryOperator;
@@ -34,7 +32,7 @@ import org.unitConverter.math.ObjectProduct;
* @author Adrien Hopkins
* @since 2019-10-16
*/
-public abstract class Unit {
+public abstract class Unit implements Nameable {
/**
* Returns a unit from its base and the functions it uses to convert to and
* from its base.
@@ -98,19 +96,11 @@ public abstract class Unit {
private final ObjectProduct unitBase;
/**
- * The primary name used by this unit.
- */
- private final Optional primaryName;
-
- /**
- * A short symbol used to represent this unit.
- */
- private final Optional symbol;
-
- /**
- * A set of any additional names and/or spellings that the unit uses.
+ * This unit's name(s) and symbol
+ *
+ * @since 2020-09-07
*/
- private final Set otherNames;
+ private final NameSymbol nameSymbol;
/**
* Cache storing the result of getDimension()
@@ -120,20 +110,17 @@ public abstract class Unit {
private transient ObjectProduct dimension = null;
/**
- * Creates the {@code AbstractUnit}.
+ * Creates the {@code Unit}.
*
* @param unitBase base of unit
* @param ns names and symbol of unit
* @since 2019-10-16
* @throws NullPointerException if unitBase or ns is null
*/
- protected Unit(final ObjectProduct unitBase, final NameSymbol ns) {
+ Unit(ObjectProduct unitBase, NameSymbol ns) {
this.unitBase = Objects.requireNonNull(unitBase,
- "unitBase must not be null.");
- this.primaryName = Objects.requireNonNull(ns, "ns must not be null.")
- .getPrimaryName();
- this.symbol = ns.getSymbol();
- this.otherNames = ns.getOtherNames();
+ "unitBase may not be null");
+ this.nameSymbol = Objects.requireNonNull(ns, "ns may not be null");
}
/**
@@ -147,18 +134,25 @@ public abstract class Unit {
this.unitBase = ObjectProduct.oneOf((BaseUnit) this);
} else
throw new AssertionError();
- this.primaryName = Optional.of(primaryName);
- this.symbol = Optional.of(symbol);
- this.otherNames = Collections.unmodifiableSet(new HashSet<>(Objects
- .requireNonNull(otherNames, "additionalNames must not be null.")));
+ this.nameSymbol = NameSymbol.of(primaryName, symbol,
+ new HashSet<>(otherNames));
+ }
+
+ /**
+ * @return this unit as a {@link Unitlike}
+ * @since 2020-09-07
+ */
+ public final Unitlike asUnitlike() {
+ return Unitlike.fromConversionFunctions(this.getBase(),
+ this::convertFromBase, this::convertToBase, this.getNameSymbol());
}
/**
* Checks if a value expressed in this unit can be converted to a value
* expressed in {@code other}
*
- * @param other unit to test with
- * @return true if the units are compatible
+ * @param other unit or unitlike form to test with
+ * @return true if they are compatible
* @since 2019-01-13
* @since v0.1.0
* @throws NullPointerException if other is null
@@ -168,6 +162,21 @@ public abstract class Unit {
return Objects.equals(this.getBase(), other.getBase());
}
+ /**
+ * Checks if a value expressed in this unit can be converted to a value
+ * expressed in {@code other}
+ *
+ * @param other unit or unitlike form to test with
+ * @return true if they are compatible
+ * @since 2019-01-13
+ * @since v0.1.0
+ * @throws NullPointerException if other is null
+ */
+ public final boolean canConvertTo(final Unitlike other) {
+ Objects.requireNonNull(other, "other must not be null.");
+ return Objects.equals(this.getBase(), other.getBase());
+ }
+
/**
* Converts from a value expressed in this unit's base unit to a value
* expressed in this unit.
@@ -218,6 +227,34 @@ public abstract class Unit {
String.format("Cannot convert from %s to %s.", this, other));
}
+ /**
+ * Converts a value expressed in this unit to a value expressed in
+ * {@code other}.
+ *
+ * @implSpec If conversion is possible, this implementation returns
+ * {@code other.convertFromBase(this.convertToBase(value))}.
+ * Therefore, overriding either of those methods will change the
+ * output of this method.
+ *
+ * @param other unitlike form to convert to
+ * @param value value to convert
+ * @param type of value to convert to
+ * @return converted value
+ * @since 2020-09-07
+ * @throws IllegalArgumentException if {@code other} is incompatible for
+ * conversion with this unit (as tested by
+ * {@link Unit#canConvertTo}).
+ * @throws NullPointerException if other is null
+ */
+ public final W convertTo(final Unitlike other, final double value) {
+ Objects.requireNonNull(other, "other must not be null.");
+ if (this.canConvertTo(other))
+ return other.convertFromBase(this.convertToBase(value));
+ else
+ throw new IllegalArgumentException(
+ String.format("Cannot convert from %s to %s.", this, other));
+ }
+
/**
* Converts from a value expressed in this unit to a value expressed in this
* unit's base unit.
@@ -270,27 +307,12 @@ public abstract class Unit {
}
/**
- * @return additionalNames
- * @since 2019-10-21
- */
- public final Set getOtherNames() {
- return this.otherNames;
- }
-
- /**
- * @return primaryName
- * @since 2019-10-21
+ * @return the nameSymbol
+ * @since 2020-09-07
*/
- public final Optional getPrimaryName() {
- return this.primaryName;
- }
-
- /**
- * @return symbol
- * @since 2019-10-21
- */
- public final Optional getSymbol() {
- return this.symbol;
+ @Override
+ public final NameSymbol getNameSymbol() {
+ return this.nameSymbol;
}
/**
diff --git a/src/org/unitConverter/unit/UnitValue.java b/src/org/unitConverter/unit/UnitValue.java
index 9e565d9..8932ccc 100644
--- a/src/org/unitConverter/unit/UnitValue.java
+++ b/src/org/unitConverter/unit/UnitValue.java
@@ -1,3 +1,19 @@
+/**
+ * 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;
@@ -14,60 +30,57 @@ import java.util.Optional;
*/
public final class UnitValue {
/**
+ * Creates a {@code UnitValue} from a unit and the associated value.
+ *
* @param unit unit to use
* @param value value to use
* @return {@code UnitValue} instance
*/
public static UnitValue of(Unit unit, double value) {
- return new UnitValue(Objects.requireNonNull(unit, "unit must not be null"), value);
+ return new UnitValue(
+ Objects.requireNonNull(unit, "unit must not be null"), value);
}
-
+
private final Unit unit;
private final double value;
-
+
/**
* @param unit the unit being used
* @param value the value being represented
*/
- private UnitValue(Unit unit, double value) {
+ private UnitValue(Unit unit, Double value) {
this.unit = unit;
this.value = value;
}
-
+
/**
- * @return the unit
+ * @return true if this value can be converted to {@code other}.
+ * @since 2020-10-01
*/
- public final Unit getUnit() {
- return unit;
+ public final boolean canConvertTo(Unit other) {
+ return this.unit.canConvertTo(other);
}
-
+
/**
- * @return the value
+ * @return true if this value can be converted to {@code other}.
+ * @since 2020-10-01
*/
- public final double getValue() {
- return value;
+ public final boolean canConvertTo(Unitlike other) {
+ return this.unit.canConvertTo(other);
}
-
+
/**
- * Converts this {@code UnitValue} into an equivalent {@code LinearUnitValue} by
- * using this unit's base unit.
+ * Returns a UnitValue that represents the same value expressed in a
+ * different unit
*
- * @param newName A new name for the base unit. Use {@link NameSymbol#EMPTY} if
- * you don't want one.
- */
- public final LinearUnitValue asLinearUnitValue(NameSymbol newName) {
- LinearUnit base = LinearUnit.valueOf(unit.getBase(), 1, newName);
- return LinearUnitValue.getExact(base, base.convertToBase(value));
- }
-
- /**
- * @param other a {@code Unit}
- * @return true iff this value can be represented with {@code other}.
+ * @param other new unit to express value in
+ * @return value expressed in {@code other}
*/
- public final boolean canConvertTo(Unit other) {
- return this.unit.canConvertTo(other);
+ public final UnitValue convertTo(Unit other) {
+ return UnitValue.of(other,
+ this.getUnit().convertTo(other, this.getValue()));
}
-
+
/**
* Returns a UnitValue that represents the same value expressed in a
* different unit
@@ -75,39 +88,83 @@ public final class UnitValue {
* @param other new unit to express value in
* @return value expressed in {@code other}
*/
- public final UnitValue convertTo(Unit other) {
- return UnitValue.of(other, this.getUnit().convertTo(other, this.getValue()));
+ public final UnitlikeValue convertTo(Unitlike other) {
+ return UnitlikeValue.of(other,
+ this.getUnit().convertTo(other, this.getValue()));
}
-
+
+ /**
+ * Returns this unit value represented as a {@code LinearUnitValue} with this
+ * unit's base unit as the base.
+ *
+ * @param ns name and symbol for the base unit, use NameSymbol.EMPTY if not
+ * needed.
+ * @since 2020-09-29
+ */
+ public final LinearUnitValue convertToBase(NameSymbol ns) {
+ final LinearUnit base = LinearUnit.getBase(this.unit).withName(ns);
+ return this.convertToLinear(base);
+ }
+
+ /**
+ * @return a {@code LinearUnitValue} that is equivalent to this value. It
+ * will have zero uncertainty.
+ * @since 2020-09-29
+ */
+ public final LinearUnitValue convertToLinear(LinearUnit other) {
+ return LinearUnitValue.getExact(other,
+ this.getUnit().convertTo(other, this.getValue()));
+ }
+
/**
- * Returns true if this and obj represent the same value, regardless of whether
- * or not they are expressed in the same unit. So (1000 m).equals(1 km) returns
- * true.
+ * Returns true if this and obj represent the same value, regardless of
+ * whether or not they are expressed in the same unit. So (1000 m).equals(1
+ * km) returns true.
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof UnitValue))
return false;
final UnitValue other = (UnitValue) obj;
- return Objects.equals(this.unit.getBase(), other.unit.getBase())
- && Double.doubleToLongBits(this.unit.convertToBase(this.getValue())) == Double
- .doubleToLongBits(other.unit.convertToBase(other.getValue()));
+ return Objects.equals(this.getUnit().getBase(), other.getUnit().getBase())
+ && Double.doubleToLongBits(
+ this.getUnit().convertToBase(this.getValue())) == Double
+ .doubleToLongBits(
+ other.getUnit().convertToBase(other.getValue()));
}
-
+
+ /**
+ * @return the unit
+ * @since 2020-09-29
+ */
+ public final Unit getUnit() {
+ return this.unit;
+ }
+
+ /**
+ * @return the value
+ * @since 2020-09-29
+ */
+ public final double getValue() {
+ return this.value;
+ }
+
@Override
public int hashCode() {
- return Objects.hash(this.unit.getBase(), this.unit.convertFromBase(this.getValue()));
+ return Objects.hash(this.getUnit().getBase(),
+ this.getUnit().convertFromBase(this.getValue()));
}
-
+
@Override
public String toString() {
- Optional primaryName = this.getUnit().getPrimaryName();
- Optional symbol = this.getUnit().getSymbol();
+ final Optional primaryName = this.getUnit().getPrimaryName();
+ final Optional symbol = this.getUnit().getSymbol();
if (primaryName.isEmpty() && symbol.isEmpty()) {
- double baseValue = this.getUnit().convertToBase(this.getValue());
- return String.format("%s unnamed unit (= %s %s)", this.getValue(), baseValue, this.getUnit().getBase());
+ final double baseValue = this.getUnit().convertToBase(this.getValue());
+ return String.format("%s unnamed unit (= %s %s)", this.getValue(),
+ baseValue, this.getUnit().getBase());
} else {
- String unitName = symbol.orElse(primaryName.get());
+ final String unitName = symbol.orElse(primaryName.get());
return this.getValue() + " " + unitName;
}
}
diff --git a/src/org/unitConverter/unit/Unitlike.java b/src/org/unitConverter/unit/Unitlike.java
new file mode 100644
index 0000000..a6ddb04
--- /dev/null
+++ b/src/org/unitConverter/unit/Unitlike.java
@@ -0,0 +1,260 @@
+/**
+ * Copyright (C) 2020 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.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.DoubleFunction;
+import java.util.function.ToDoubleFunction;
+
+import org.unitConverter.math.ObjectProduct;
+
+/**
+ * An object that can convert a value between multiple forms (instances of the
+ * object); like a unit but the "converted value" can be any type.
+ *
+ * @since 2020-09-07
+ */
+public abstract class Unitlike implements Nameable {
+ /**
+ * Returns a unitlike form from its base and the functions it uses to convert
+ * to and from its base.
+ *
+ * @param base unitlike form's base
+ * @param converterFrom function that accepts a value expressed in the
+ * unitlike form's base and returns that value expressed
+ * in this unitlike form.
+ * @param converterTo function that accepts a value expressed in the
+ * unitlike form and returns that value expressed in the
+ * unit's base.
+ * @return a unitlike form that uses the provided functions to convert.
+ * @since 2020-09-07
+ * @throws NullPointerException if any argument is null
+ */
+ public static final Unitlike fromConversionFunctions(
+ final ObjectProduct base,
+ final DoubleFunction converterFrom,
+ final ToDoubleFunction converterTo) {
+ return new FunctionalUnitlike<>(base, NameSymbol.EMPTY, converterFrom,
+ converterTo);
+ }
+
+ /**
+ * Returns a unitlike form from its base and the functions it uses to convert
+ * to and from its base.
+ *
+ * @param base unitlike form's base
+ * @param converterFrom function that accepts a value expressed in the
+ * unitlike form's base and returns that value expressed
+ * in this unitlike form.
+ * @param converterTo function that accepts a value expressed in the
+ * unitlike form and returns that value expressed in the
+ * unit's base.
+ * @param ns names and symbol of unit
+ * @return a unitlike form that uses the provided functions to convert.
+ * @since 2020-09-07
+ * @throws NullPointerException if any argument is null
+ */
+ public static final Unitlike fromConversionFunctions(
+ final ObjectProduct base,
+ final DoubleFunction converterFrom,
+ final ToDoubleFunction converterTo, final NameSymbol ns) {
+ return new FunctionalUnitlike<>(base, ns, converterFrom, converterTo);
+ }
+
+ /**
+ * The combination of units that this unit is based on.
+ *
+ * @since 2019-10-16
+ */
+ private final ObjectProduct unitBase;
+
+ /**
+ * This unit's name(s) and symbol
+ *
+ * @since 2020-09-07
+ */
+ private final NameSymbol nameSymbol;
+
+ /**
+ * Cache storing the result of getDimension()
+ *
+ * @since 2019-10-16
+ */
+ private transient ObjectProduct dimension = null;
+
+ /**
+ * @param unitBase
+ * @since 2020-09-07
+ */
+ Unitlike(ObjectProduct unitBase, NameSymbol ns) {
+ this.unitBase = Objects.requireNonNull(unitBase,
+ "unitBase may not be null");
+ this.nameSymbol = Objects.requireNonNull(ns, "ns may not be null");
+ }
+
+ /**
+ * Checks if a value expressed in this unitlike form can be converted to a
+ * value expressed in {@code other}
+ *
+ * @param other unit or unitlike form to test with
+ * @return true if they are compatible
+ * @since 2019-01-13
+ * @since v0.1.0
+ * @throws NullPointerException if other is null
+ */
+ public final boolean canConvertTo(final Unit other) {
+ Objects.requireNonNull(other, "other must not be null.");
+ return Objects.equals(this.getBase(), other.getBase());
+ }
+
+ /**
+ * Checks if a value expressed in this unitlike form can be converted to a
+ * value expressed in {@code other}
+ *
+ * @param other unit or unitlike form to test with
+ * @return true if they are compatible
+ * @since 2019-01-13
+ * @since v0.1.0
+ * @throws NullPointerException if other is null
+ */
+ public final boolean canConvertTo(final Unitlike other) {
+ Objects.requireNonNull(other, "other must not be null.");
+ return Objects.equals(this.getBase(), other.getBase());
+ }
+
+ protected abstract V convertFromBase(double value);
+
+ /**
+ * Converts a value expressed in this unitlike form to a value expressed in
+ * {@code other}.
+ *
+ * @implSpec If conversion is possible, this implementation returns
+ * {@code other.convertFromBase(this.convertToBase(value))}.
+ * Therefore, overriding either of those methods will change the
+ * output of this method.
+ *
+ * @param other unit to convert to
+ * @param value value to convert
+ * @return converted value
+ * @since 2019-05-22
+ * @throws IllegalArgumentException if {@code other} is incompatible for
+ * conversion with this unitlike form (as
+ * tested by {@link Unit#canConvertTo}).
+ * @throws NullPointerException if other is null
+ */
+ public final double convertTo(final Unit other, final V value) {
+ Objects.requireNonNull(other, "other must not be null.");
+ if (this.canConvertTo(other))
+ return other.convertFromBase(this.convertToBase(value));
+ else
+ throw new IllegalArgumentException(
+ String.format("Cannot convert from %s to %s.", this, other));
+ }
+
+ /**
+ * Converts a value expressed in this unitlike form to a value expressed in
+ * {@code other}.
+ *
+ * @implSpec If conversion is possible, this implementation returns
+ * {@code other.convertFromBase(this.convertToBase(value))}.
+ * Therefore, overriding either of those methods will change the
+ * output of this method.
+ *
+ * @param other unitlike form to convert to
+ * @param value value to convert
+ * @param type of value to convert to
+ * @return converted value
+ * @since 2020-09-07
+ * @throws IllegalArgumentException if {@code other} is incompatible for
+ * conversion with this unitlike form (as
+ * tested by {@link Unit#canConvertTo}).
+ * @throws NullPointerException if other is null
+ */
+ public final W convertTo(final Unitlike other, final V value) {
+ Objects.requireNonNull(other, "other must not be null.");
+ if (this.canConvertTo(other))
+ return other.convertFromBase(this.convertToBase(value));
+ else
+ throw new IllegalArgumentException(
+ String.format("Cannot convert from %s to %s.", this, other));
+ }
+
+ protected abstract double convertToBase(V value);
+
+ /**
+ * @return combination of units that this unit is based on
+ * @since 2018-12-22
+ * @since v0.1.0
+ */
+ public final ObjectProduct getBase() {
+ return this.unitBase;
+ }
+
+ /**
+ * @return dimension measured by this unit
+ * @since 2018-12-22
+ * @since v0.1.0
+ */
+ public final ObjectProduct getDimension() {
+ if (this.dimension == null) {
+ final Map mapping = this.unitBase.exponentMap();
+ final Map dimensionMap = new HashMap<>();
+
+ for (final BaseUnit key : mapping.keySet()) {
+ dimensionMap.put(key.getBaseDimension(), mapping.get(key));
+ }
+
+ this.dimension = ObjectProduct.fromExponentMapping(dimensionMap);
+ }
+ return this.dimension;
+ }
+
+ /**
+ * @return the nameSymbol
+ * @since 2020-09-07
+ */
+ @Override
+ public final NameSymbol getNameSymbol() {
+ return this.nameSymbol;
+ }
+
+ @Override
+ public String toString() {
+ return this.getPrimaryName().orElse("Unnamed unitlike form")
+ + (this.getSymbol().isPresent()
+ ? String.format(" (%s)", this.getSymbol().get())
+ : "")
+ + ", derived from "
+ + this.getBase().toString(u -> u.getSymbol().get())
+ + (this.getOtherNames().isEmpty() ? ""
+ : ", also called " + String.join(", ", this.getOtherNames()));
+ }
+
+ /**
+ * @param ns name(s) and symbol to use
+ * @return a copy of this unitlike form with provided name(s) and symbol
+ * @since 2020-09-07
+ * @throws NullPointerException if ns is null
+ */
+ public Unitlike withName(final NameSymbol ns) {
+ return fromConversionFunctions(this.getBase(), this::convertFromBase,
+ this::convertToBase,
+ Objects.requireNonNull(ns, "ns must not be null."));
+ }
+}
diff --git a/src/org/unitConverter/unit/UnitlikeValue.java b/src/org/unitConverter/unit/UnitlikeValue.java
new file mode 100644
index 0000000..669a123
--- /dev/null
+++ b/src/org/unitConverter/unit/UnitlikeValue.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2020 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.Optional;
+
+/**
+ *
+ * @since 2020-09-07
+ */
+final class UnitlikeValue {
+ /**
+ * Gets a {@code UnitlikeValue}.
+ *
+ * @since 2020-10-02
+ */
+ public static UnitlikeValue of(Unitlike unitlike, V value) {
+ return new UnitlikeValue<>(unitlike, value);
+ }
+
+ private final Unitlike unitlike;
+ private final V value;
+
+ /**
+ * @param unitlike
+ * @param value
+ * @since 2020-09-07
+ */
+ private UnitlikeValue(Unitlike unitlike, V value) {
+ this.unitlike = unitlike;
+ this.value = value;
+ }
+
+ /**
+ * @return true if this value can be converted to {@code other}.
+ * @since 2020-10-01
+ */
+ public final boolean canConvertTo(Unit other) {
+ return this.unitlike.canConvertTo(other);
+ }
+
+ /**
+ * @return true if this value can be converted to {@code other}.
+ * @since 2020-10-01
+ */
+ public final boolean canConvertTo(Unitlike other) {
+ return this.unitlike.canConvertTo(other);
+ }
+
+ /**
+ * Returns a UnitValue that represents the same value expressed in a
+ * different unit
+ *
+ * @param other new unit to express value in
+ * @return value expressed in {@code other}
+ */
+ public final UnitValue convertTo(Unit other) {
+ return UnitValue.of(other,
+ this.unitlike.convertTo(other, this.getValue()));
+ }
+
+ /**
+ * Returns a UnitValue that represents the same value expressed in a
+ * different unit
+ *
+ * @param other new unit to express value in
+ * @return value expressed in {@code other}
+ */
+ public final UnitlikeValue convertTo(Unitlike other) {
+ return UnitlikeValue.of(other,
+ this.unitlike.convertTo(other, this.getValue()));
+ }
+
+ /**
+ * Returns this unit value represented as a {@code LinearUnitValue} with this
+ * unit's base unit as the base.
+ *
+ * @param ns name and symbol for the base unit, use NameSymbol.EMPTY if not
+ * needed.
+ * @since 2020-09-29
+ */
+ public final LinearUnitValue convertToBase(NameSymbol ns) {
+ final LinearUnit base = LinearUnit.getBase(this.unitlike).withName(ns);
+ return this.convertToLinear(base);
+ }
+
+ /**
+ * @return a {@code LinearUnitValue} that is equivalent to this value. It
+ * will have zero uncertainty.
+ * @since 2020-09-29
+ */
+ public final LinearUnitValue convertToLinear(LinearUnit other) {
+ return LinearUnitValue.getExact(other,
+ this.getUnitlike().convertTo(other, this.getValue()));
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof UnitlikeValue))
+ return false;
+ final UnitlikeValue> other = (UnitlikeValue>) obj;
+ if (this.getUnitlike() == null) {
+ if (other.getUnitlike() != null)
+ return false;
+ } else if (!this.getUnitlike().equals(other.getUnitlike()))
+ return false;
+ if (this.getValue() == null) {
+ if (other.getValue() != null)
+ return false;
+ } else if (!this.getValue().equals(other.getValue()))
+ return false;
+ return true;
+ }
+
+ /**
+ * @return the unitlike
+ * @since 2020-09-29
+ */
+ public final Unitlike getUnitlike() {
+ return this.unitlike;
+ }
+
+ /**
+ * @return the value
+ * @since 2020-09-29
+ */
+ public final V getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + (this.getUnitlike() == null ? 0 : this.getUnitlike().hashCode());
+ result = prime * result
+ + (this.getValue() == null ? 0 : this.getValue().hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ final Optional primaryName = this.getUnitlike().getPrimaryName();
+ final Optional symbol = this.getUnitlike().getSymbol();
+ if (primaryName.isEmpty() && symbol.isEmpty()) {
+ final double baseValue = this.getUnitlike()
+ .convertToBase(this.getValue());
+ return String.format("%s unnamed unit (= %s %s)", this.getValue(),
+ baseValue, this.getUnitlike().getBase());
+ } else {
+ final String unitName = symbol.orElse(primaryName.get());
+ return this.getValue() + " " + unitName;
+ }
+ }
+}
--
cgit v1.2.3
From 2eee97c9e64dca79fc6b1614b304b398d25a7f4b Mon Sep 17 00:00:00 2001
From: Adrien Hopkins
Date: Sat, 27 Mar 2021 16:36:39 -0500
Subject: Added automatic building with Gradle
---
.classpath | 35 +-
.gitattributes | 6 +
.gitignore | 10 +-
.project | 8 +-
.settings/org.eclipse.buildship.core.prefs | 2 +
.settings/org.eclipse.jdt.apt.core.prefs | 2 -
.settings/org.eclipse.jdt.core.prefs | 12 -
.settings/org.eclipse.m2e.core.prefs | 4 -
bin/main/.gitignore | 2 +
bin/test/.gitignore | 1 +
build.gradle | 30 +
doc/allclasses-frame.html | 45 -
doc/allclasses-index.html | 257 -
doc/allclasses-noframe.html | 45 -
doc/allclasses.html | 45 -
doc/allpackages-index.html | 187 -
doc/constant-values.html | 186 -
doc/deprecated-list.html | 124 -
doc/element-list | 4 -
doc/help-doc.html | 229 -
doc/index-files/index-1.html | 185 -
doc/index-files/index-10.html | 129 -
doc/index-files/index-11.html | 147 -
doc/index-files/index-12.html | 167 -
doc/index-files/index-13.html | 175 -
doc/index-files/index-14.html | 141 -
doc/index-files/index-15.html | 209 -
doc/index-files/index-16.html | 175 -
doc/index-files/index-17.html | 137 -
doc/index-files/index-18.html | 137 -
doc/index-files/index-19.html | 197 -
doc/index-files/index-2.html | 183 -
doc/index-files/index-20.html | 205 -
doc/index-files/index-21.html | 175 -
doc/index-files/index-22.html | 167 -
doc/index-files/index-23.html | 145 -
doc/index-files/index-24.html | 137 -
doc/index-files/index-25.html | 131 -
doc/index-files/index-3.html | 243 -
doc/index-files/index-4.html | 185 -
doc/index-files/index-5.html | 195 -
doc/index-files/index-6.html | 181 -
doc/index-files/index-7.html | 209 -
doc/index-files/index-8.html | 165 -
doc/index-files/index-9.html | 145 -
doc/index.html | 75 -
doc/jquery/external/jquery/jquery.js | 10364 -----------------
doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 335 -> 0 bytes
doc/jquery/images/ui-bg_glass_65_dadada_1x400.png | Bin 262 -> 0 bytes
doc/jquery/images/ui-bg_glass_75_dadada_1x400.png | Bin 262 -> 0 bytes
doc/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 262 -> 0 bytes
doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png | Bin 332 -> 0 bytes
.../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 280 -> 0 bytes
doc/jquery/images/ui-icons_222222_256x240.png | Bin 6922 -> 0 bytes
doc/jquery/images/ui-icons_2e83ff_256x240.png | Bin 4549 -> 0 bytes
doc/jquery/images/ui-icons_454545_256x240.png | Bin 6992 -> 0 bytes
doc/jquery/images/ui-icons_888888_256x240.png | Bin 6999 -> 0 bytes
doc/jquery/images/ui-icons_cd0a0a_256x240.png | Bin 4549 -> 0 bytes
doc/jquery/jquery-3.3.1.js | 10364 -----------------
doc/jquery/jquery-migrate-3.0.1.js | 628 -
doc/jquery/jquery-ui.css | 582 -
doc/jquery/jquery-ui.js | 2659 -----
doc/jquery/jquery-ui.min.css | 7 -
doc/jquery/jquery-ui.min.js | 6 -
doc/jquery/jquery-ui.structure.css | 156 -
doc/jquery/jquery-ui.structure.min.css | 5 -
doc/jquery/jszip-utils/dist/jszip-utils-ie.js | 56 -
doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js | 10 -
doc/jquery/jszip-utils/dist/jszip-utils.js | 118 -
doc/jquery/jszip-utils/dist/jszip-utils.min.js | 10 -
doc/jquery/jszip/dist/jszip.js | 11623 -------------------
doc/jquery/jszip/dist/jszip.min.js | 15 -
doc/member-search-index.js | 1 -
doc/member-search-index.zip | Bin 2500 -> 0 bytes
.../converterGUI/DelegateListModel.html | 959 --
.../converterGUI/FilterComparator.html | 489 -
.../unitConverter/converterGUI/GridBagBuilder.html | 1140 --
.../converterGUI/MutablePredicate.html | 428 -
.../unitConverter/converterGUI/SearchBoxList.html | 902 --
.../converterGUI/UnitConverterGUI.Presenter.html | 717 --
.../converterGUI/UnitConverterGUI.View.html | 853 --
.../converterGUI/UnitConverterGUI.html | 341 -
.../converterGUI/class-use/DelegateListModel.html | 195 -
.../converterGUI/class-use/FilterComparator.html | 149 -
.../converterGUI/class-use/GridBagBuilder.html | 225 -
.../converterGUI/class-use/MutablePredicate.html | 149 -
.../converterGUI/class-use/SearchBoxList.html | 218 -
.../class-use/UnitConverterGUI.Presenter.html | 197 -
.../class-use/UnitConverterGUI.View.html | 212 -
.../converterGUI/class-use/UnitConverterGUI.html | 149 -
.../unitConverter/converterGUI/package-frame.html | 14 -
.../converterGUI/package-summary.html | 139 -
.../unitConverter/converterGUI/package-tree.html | 127 -
.../unitConverter/converterGUI/package-use.html | 124 -
...Collections.ConditionalExistenceCollection.html | 532 -
...ceCollections.ConditionalExistenceIterator.html | 493 -
...istenceCollections.ConditionalExistenceMap.html | 570 -
...istenceCollections.ConditionalExistenceSet.html | 565 -
.../math/ConditionalExistenceCollections.html | 397 -
.../math/ConditionalExistenceCollectionsTest.html | 469 -
doc/org/unitConverter/math/DecimalComparison.html | 492 -
.../math/ExpressionParser.Builder.html | 391 -
.../ExpressionParser.PriorityBinaryOperator.html | 425 -
.../ExpressionParser.PriorityUnaryOperator.html | 425 -
.../math/ExpressionParser.TokenType.html | 445 -
doc/org/unitConverter/math/ExpressionParser.html | 349 -
.../unitConverter/math/ExpressionParserTest.html | 360 -
doc/org/unitConverter/math/ObjectProduct.html | 553 -
doc/org/unitConverter/math/ObjectProductTest.html | 366 -
...Collections.ConditionalExistenceCollection.html | 149 -
...ceCollections.ConditionalExistenceIterator.html | 197 -
...istenceCollections.ConditionalExistenceMap.html | 149 -
...istenceCollections.ConditionalExistenceSet.html | 149 -
.../class-use/ConditionalExistenceCollections.html | 124 -
.../ConditionalExistenceCollectionsTest.html | 149 -
.../math/class-use/DecimalComparison.html | 124 -
.../math/class-use/ExpressionParser.Builder.html | 184 -
.../ExpressionParser.PriorityBinaryOperator.html | 221 -
.../ExpressionParser.PriorityUnaryOperator.html | 239 -
.../math/class-use/ExpressionParser.TokenType.html | 212 -
.../math/class-use/ExpressionParser.html | 166 -
.../math/class-use/ExpressionParserTest.html | 149 -
.../math/class-use/ObjectProduct.html | 515 -
.../math/class-use/ObjectProductTest.html | 149 -
doc/org/unitConverter/math/package-frame.html | 24 -
doc/org/unitConverter/math/package-summary.html | 183 -
doc/org/unitConverter/math/package-tree.html | 141 -
doc/org/unitConverter/math/package-use.html | 194 -
doc/org/unitConverter/package-frame.html | 14 -
doc/org/unitConverter/package-summary.html | 141 -
doc/org/unitConverter/package-tree.html | 127 -
doc/org/unitConverter/package-use.html | 124 -
doc/org/unitConverter/unit/BaseDimension.html | 313 -
doc/org/unitConverter/unit/BaseUnit.html | 452 -
.../unitConverter/unit/BritishImperial.Area.html | 349 -
.../unitConverter/unit/BritishImperial.Length.html | 443 -
.../unitConverter/unit/BritishImperial.Mass.html | 388 -
.../unitConverter/unit/BritishImperial.Volume.html | 414 -
doc/org/unitConverter/unit/BritishImperial.html | 384 -
doc/org/unitConverter/unit/FunctionalUnit.html | 504 -
doc/org/unitConverter/unit/LinearUnit.html | 800 --
doc/org/unitConverter/unit/NameSymbol.html | 641 -
doc/org/unitConverter/unit/SI.BaseDimensions.html | 347 -
doc/org/unitConverter/unit/SI.BaseUnits.html | 347 -
doc/org/unitConverter/unit/SI.Constants.html | 284 -
doc/org/unitConverter/unit/SI.Dimensions.html | 789 --
doc/org/unitConverter/unit/SI.html | 1313 ---
doc/org/unitConverter/unit/USCustomary.Area.html | 336 -
doc/org/unitConverter/unit/USCustomary.Length.html | 492 -
doc/org/unitConverter/unit/USCustomary.Mass.html | 388 -
doc/org/unitConverter/unit/USCustomary.Volume.html | 583 -
doc/org/unitConverter/unit/USCustomary.html | 423 -
doc/org/unitConverter/unit/Unit.html | 632 -
...Map.PrefixedUnitEntrySet.PrefixedUnitEntry.html | 499 -
...ixedUnitEntrySet.PrefixedUnitEntryIterator.html | 542 -
...abase.PrefixedUnitMap.PrefixedUnitEntrySet.html | 761 --
...efixedUnitNameSet.PrefixedUnitNameIterator.html | 542 -
...tabase.PrefixedUnitMap.PrefixedUnitNameSet.html | 754 --
.../unit/UnitDatabase.PrefixedUnitMap.html | 930 --
doc/org/unitConverter/unit/UnitDatabase.html | 789 --
doc/org/unitConverter/unit/UnitDatabaseTest.html | 643 -
doc/org/unitConverter/unit/UnitPrefix.html | 570 -
doc/org/unitConverter/unit/UnitTest.html | 420 -
.../unit/class-use/BaseDimension.html | 470 -
doc/org/unitConverter/unit/class-use/BaseUnit.html | 296 -
.../unit/class-use/BritishImperial.Area.html | 124 -
.../unit/class-use/BritishImperial.Length.html | 124 -
.../unit/class-use/BritishImperial.Mass.html | 124 -
.../unit/class-use/BritishImperial.Volume.html | 124 -
.../unit/class-use/BritishImperial.html | 124 -
.../unit/class-use/FunctionalUnit.html | 199 -
.../unitConverter/unit/class-use/LinearUnit.html | 926 --
.../unitConverter/unit/class-use/NameSymbol.html | 324 -
.../unit/class-use/SI.BaseDimensions.html | 124 -
.../unitConverter/unit/class-use/SI.BaseUnits.html | 124 -
.../unitConverter/unit/class-use/SI.Constants.html | 124 -
.../unit/class-use/SI.Dimensions.html | 124 -
doc/org/unitConverter/unit/class-use/SI.html | 124 -
.../unit/class-use/USCustomary.Area.html | 124 -
.../unit/class-use/USCustomary.Length.html | 124 -
.../unit/class-use/USCustomary.Mass.html | 124 -
.../unit/class-use/USCustomary.Volume.html | 124 -
.../unitConverter/unit/class-use/USCustomary.html | 124 -
doc/org/unitConverter/unit/class-use/Unit.html | 312 -
...Map.PrefixedUnitEntrySet.PrefixedUnitEntry.html | 149 -
...ixedUnitEntrySet.PrefixedUnitEntryIterator.html | 149 -
...abase.PrefixedUnitMap.PrefixedUnitEntrySet.html | 149 -
...efixedUnitNameSet.PrefixedUnitNameIterator.html | 149 -
...tabase.PrefixedUnitMap.PrefixedUnitNameSet.html | 149 -
.../class-use/UnitDatabase.PrefixedUnitMap.html | 233 -
.../unitConverter/unit/class-use/UnitDatabase.html | 124 -
.../unit/class-use/UnitDatabaseTest.html | 149 -
.../unitConverter/unit/class-use/UnitPrefix.html | 381 -
doc/org/unitConverter/unit/class-use/UnitTest.html | 149 -
doc/org/unitConverter/unit/package-frame.html | 41 -
doc/org/unitConverter/unit/package-summary.html | 279 -
doc/org/unitConverter/unit/package-tree.html | 161 -
doc/org/unitConverter/unit/package-use.html | 186 -
doc/overview-frame.html | 24 -
doc/overview-summary.html | 155 -
doc/overview-tree.html | 169 -
doc/package-list | 4 -
doc/package-search-index.js | 1 -
doc/package-search-index.zip | Bin 252 -> 0 bytes
doc/resources/glass.png | Bin 499 -> 0 bytes
doc/resources/x.png | Bin 394 -> 0 bytes
doc/script.js | 30 -
doc/search.js | 326 -
doc/stylesheet.css | 906 --
doc/type-search-index.js | 1 -
doc/type-search-index.zip | Bin 397 -> 0 bytes
gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes
gradle/wrapper/gradle-wrapper.properties | 5 +
gradlew | 183 +
gradlew.bat | 103 +
pom.xml | 55 -
settings.gradle | 10 +
settings.txt | 4 +
src/about.txt | 12 -
.../converterGUI/DefaultPrefixRepetitionRule.java | 95 +
.../converterGUI/DelegateListModel.java | 242 +
.../converterGUI/FilterComparator.java | 129 +
.../unitConverter/converterGUI/GridBagBuilder.java | 479 +
.../converterGUI/MutablePredicate.java | 70 +
.../unitConverter/converterGUI/SearchBoxList.java | 307 +
.../converterGUI/UnitConverterGUI.java | 1426 +++
.../unitConverter/converterGUI/package-info.java | 24 +
.../math/ConditionalExistenceCollections.java | 468 +
.../org/unitConverter/math/DecimalComparison.java | 256 +
.../org/unitConverter/math/ExpressionParser.java | 708 ++
.../java/org/unitConverter/math/ObjectProduct.java | 284 +
.../org/unitConverter/math/UncertainDouble.java | 419 +
.../java/org/unitConverter/math/package-info.java | 24 +
src/main/java/org/unitConverter/package-info.java | 24 +
.../java/org/unitConverter/unit/BaseDimension.java | 87 +
src/main/java/org/unitConverter/unit/BaseUnit.java | 133 +
.../org/unitConverter/unit/BritishImperial.java | 116 +
.../org/unitConverter/unit/FunctionalUnit.java | 109 +
.../org/unitConverter/unit/FunctionalUnitlike.java | 72 +
.../java/org/unitConverter/unit/LinearUnit.java | 441 +
.../org/unitConverter/unit/LinearUnitValue.java | 341 +
.../java/org/unitConverter/unit/MultiUnit.java | 160 +
.../java/org/unitConverter/unit/NameSymbol.java | 280 +
src/main/java/org/unitConverter/unit/Nameable.java | 59 +
src/main/java/org/unitConverter/unit/SI.java | 479 +
.../java/org/unitConverter/unit/USCustomary.java | 135 +
src/main/java/org/unitConverter/unit/Unit.java | 377 +
.../java/org/unitConverter/unit/UnitDatabase.java | 1991 ++++
.../java/org/unitConverter/unit/UnitPrefix.java | 242 +
.../java/org/unitConverter/unit/UnitValue.java | 172 +
src/main/java/org/unitConverter/unit/Unitlike.java | 260 +
.../java/org/unitConverter/unit/UnitlikeValue.java | 174 +
.../java/org/unitConverter/unit/package-info.java | 24 +
src/main/resources/about.txt | 12 +
.../converterGUI/DefaultPrefixRepetitionRule.java | 95 -
.../converterGUI/DelegateListModel.java | 242 -
.../converterGUI/FilterComparator.java | 129 -
.../unitConverter/converterGUI/GridBagBuilder.java | 479 -
.../converterGUI/MutablePredicate.java | 70 -
.../unitConverter/converterGUI/SearchBoxList.java | 307 -
.../converterGUI/UnitConverterGUI.java | 1424 ---
.../unitConverter/converterGUI/package-info.java | 24 -
.../math/ConditionalExistenceCollections.java | 468 -
.../math/ConditionalExistenceCollectionsTest.java | 159 -
src/org/unitConverter/math/DecimalComparison.java | 256 -
src/org/unitConverter/math/ExpressionParser.java | 708 --
.../unitConverter/math/ExpressionParserTest.java | 52 -
src/org/unitConverter/math/ObjectProduct.java | 284 -
src/org/unitConverter/math/ObjectProductTest.java | 78 -
src/org/unitConverter/math/UncertainDouble.java | 419 -
src/org/unitConverter/math/package-info.java | 24 -
src/org/unitConverter/package-info.java | 24 -
src/org/unitConverter/unit/BaseDimension.java | 87 -
src/org/unitConverter/unit/BaseUnit.java | 133 -
src/org/unitConverter/unit/BritishImperial.java | 116 -
src/org/unitConverter/unit/FunctionalUnit.java | 109 -
src/org/unitConverter/unit/FunctionalUnitlike.java | 72 -
src/org/unitConverter/unit/LinearUnit.java | 441 -
src/org/unitConverter/unit/LinearUnitValue.java | 341 -
src/org/unitConverter/unit/MultiUnit.java | 160 -
src/org/unitConverter/unit/MultiUnitTest.java | 106 -
src/org/unitConverter/unit/NameSymbol.java | 280 -
src/org/unitConverter/unit/Nameable.java | 59 -
src/org/unitConverter/unit/SI.java | 479 -
src/org/unitConverter/unit/USCustomary.java | 135 -
src/org/unitConverter/unit/Unit.java | 377 -
src/org/unitConverter/unit/UnitDatabase.java | 1991 ----
src/org/unitConverter/unit/UnitDatabaseTest.java | 309 -
src/org/unitConverter/unit/UnitPrefix.java | 242 -
src/org/unitConverter/unit/UnitTest.java | 146 -
src/org/unitConverter/unit/UnitValue.java | 172 -
src/org/unitConverter/unit/Unitlike.java | 260 -
src/org/unitConverter/unit/UnitlikeValue.java | 174 -
src/org/unitConverter/unit/package-info.java | 24 -
.../math/ConditionalExistenceCollectionsTest.java | 159 +
.../unitConverter/math/ExpressionParserTest.java | 52 +
.../org/unitConverter/math/ObjectProductTest.java | 78 +
.../java/org/unitConverter/unit/MultiUnitTest.java | 106 +
.../org/unitConverter/unit/UnitDatabaseTest.java | 309 +
src/test/java/org/unitConverter/unit/UnitTest.java | 146 +
300 files changed, 11841 insertions(+), 97539 deletions(-)
create mode 100644 .gitattributes
create mode 100644 .settings/org.eclipse.buildship.core.prefs
delete mode 100644 .settings/org.eclipse.jdt.apt.core.prefs
delete mode 100644 .settings/org.eclipse.m2e.core.prefs
create mode 100644 bin/main/.gitignore
create mode 100644 bin/test/.gitignore
create mode 100644 build.gradle
delete mode 100644 doc/allclasses-frame.html
delete mode 100644 doc/allclasses-index.html
delete mode 100644 doc/allclasses-noframe.html
delete mode 100644 doc/allclasses.html
delete mode 100644 doc/allpackages-index.html
delete mode 100644 doc/constant-values.html
delete mode 100644 doc/deprecated-list.html
delete mode 100644 doc/element-list
delete mode 100644 doc/help-doc.html
delete mode 100644 doc/index-files/index-1.html
delete mode 100644 doc/index-files/index-10.html
delete mode 100644 doc/index-files/index-11.html
delete mode 100644 doc/index-files/index-12.html
delete mode 100644 doc/index-files/index-13.html
delete mode 100644 doc/index-files/index-14.html
delete mode 100644 doc/index-files/index-15.html
delete mode 100644 doc/index-files/index-16.html
delete mode 100644 doc/index-files/index-17.html
delete mode 100644 doc/index-files/index-18.html
delete mode 100644 doc/index-files/index-19.html
delete mode 100644 doc/index-files/index-2.html
delete mode 100644 doc/index-files/index-20.html
delete mode 100644 doc/index-files/index-21.html
delete mode 100644 doc/index-files/index-22.html
delete mode 100644 doc/index-files/index-23.html
delete mode 100644 doc/index-files/index-24.html
delete mode 100644 doc/index-files/index-25.html
delete mode 100644 doc/index-files/index-3.html
delete mode 100644 doc/index-files/index-4.html
delete mode 100644 doc/index-files/index-5.html
delete mode 100644 doc/index-files/index-6.html
delete mode 100644 doc/index-files/index-7.html
delete mode 100644 doc/index-files/index-8.html
delete mode 100644 doc/index-files/index-9.html
delete mode 100644 doc/index.html
delete mode 100644 doc/jquery/external/jquery/jquery.js
delete mode 100644 doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png
delete mode 100644 doc/jquery/images/ui-bg_glass_65_dadada_1x400.png
delete mode 100644 doc/jquery/images/ui-bg_glass_75_dadada_1x400.png
delete mode 100644 doc/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png
delete mode 100644 doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png
delete mode 100644 doc/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png
delete mode 100644 doc/jquery/images/ui-icons_222222_256x240.png
delete mode 100644 doc/jquery/images/ui-icons_2e83ff_256x240.png
delete mode 100644 doc/jquery/images/ui-icons_454545_256x240.png
delete mode 100644 doc/jquery/images/ui-icons_888888_256x240.png
delete mode 100644 doc/jquery/images/ui-icons_cd0a0a_256x240.png
delete mode 100644 doc/jquery/jquery-3.3.1.js
delete mode 100644 doc/jquery/jquery-migrate-3.0.1.js
delete mode 100644 doc/jquery/jquery-ui.css
delete mode 100644 doc/jquery/jquery-ui.js
delete mode 100644 doc/jquery/jquery-ui.min.css
delete mode 100644 doc/jquery/jquery-ui.min.js
delete mode 100644 doc/jquery/jquery-ui.structure.css
delete mode 100644 doc/jquery/jquery-ui.structure.min.css
delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils-ie.js
delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js
delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils.js
delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils.min.js
delete mode 100644 doc/jquery/jszip/dist/jszip.js
delete mode 100644 doc/jquery/jszip/dist/jszip.min.js
delete mode 100644 doc/member-search-index.js
delete mode 100644 doc/member-search-index.zip
delete mode 100644 doc/org/unitConverter/converterGUI/DelegateListModel.html
delete mode 100644 doc/org/unitConverter/converterGUI/FilterComparator.html
delete mode 100644 doc/org/unitConverter/converterGUI/GridBagBuilder.html
delete mode 100644 doc/org/unitConverter/converterGUI/MutablePredicate.html
delete mode 100644 doc/org/unitConverter/converterGUI/SearchBoxList.html
delete mode 100644 doc/org/unitConverter/converterGUI/UnitConverterGUI.Presenter.html
delete mode 100644 doc/org/unitConverter/converterGUI/UnitConverterGUI.View.html
delete mode 100644 doc/org/unitConverter/converterGUI/UnitConverterGUI.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/DelegateListModel.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/FilterComparator.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/GridBagBuilder.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/MutablePredicate.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/SearchBoxList.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.Presenter.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.View.html
delete mode 100644 doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.html
delete mode 100644 doc/org/unitConverter/converterGUI/package-frame.html
delete mode 100644 doc/org/unitConverter/converterGUI/package-summary.html
delete mode 100644 doc/org/unitConverter/converterGUI/package-tree.html
delete mode 100644 doc/org/unitConverter/converterGUI/package-use.html
delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceCollection.html
delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceIterator.html
delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceMap.html
delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceSet.html
delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.html
delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollectionsTest.html
delete mode 100644 doc/org/unitConverter/math/DecimalComparison.html
delete mode 100644 doc/org/unitConverter/math/ExpressionParser.Builder.html
delete mode 100644 doc/org/unitConverter/math/ExpressionParser.PriorityBinaryOperator.html
delete mode 100644 doc/org/unitConverter/math/ExpressionParser.PriorityUnaryOperator.html
delete mode 100644 doc/org/unitConverter/math/ExpressionParser.TokenType.html
delete mode 100644 doc/org/unitConverter/math/ExpressionParser.html
delete mode 100644 doc/org/unitConverter/math/ExpressionParserTest.html
delete mode 100644 doc/org/unitConverter/math/ObjectProduct.html
delete mode 100644 doc/org/unitConverter/math/ObjectProductTest.html
delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceCollection.html
delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceIterator.html
delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceMap.html
delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceSet.html
delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.html
delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollectionsTest.html
delete mode 100644 doc/org/unitConverter/math/class-use/DecimalComparison.html
delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.Builder.html
delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.PriorityBinaryOperator.html
delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.PriorityUnaryOperator.html
delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.TokenType.html
delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.html
delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParserTest.html
delete mode 100644 doc/org/unitConverter/math/class-use/ObjectProduct.html
delete mode 100644 doc/org/unitConverter/math/class-use/ObjectProductTest.html
delete mode 100644 doc/org/unitConverter/math/package-frame.html
delete mode 100644 doc/org/unitConverter/math/package-summary.html
delete mode 100644 doc/org/unitConverter/math/package-tree.html
delete mode 100644 doc/org/unitConverter/math/package-use.html
delete mode 100644 doc/org/unitConverter/package-frame.html
delete mode 100644 doc/org/unitConverter/package-summary.html
delete mode 100644 doc/org/unitConverter/package-tree.html
delete mode 100644 doc/org/unitConverter/package-use.html
delete mode 100644 doc/org/unitConverter/unit/BaseDimension.html
delete mode 100644 doc/org/unitConverter/unit/BaseUnit.html
delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Area.html
delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Length.html
delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Mass.html
delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Volume.html
delete mode 100644 doc/org/unitConverter/unit/BritishImperial.html
delete mode 100644 doc/org/unitConverter/unit/FunctionalUnit.html
delete mode 100644 doc/org/unitConverter/unit/LinearUnit.html
delete mode 100644 doc/org/unitConverter/unit/NameSymbol.html
delete mode 100644 doc/org/unitConverter/unit/SI.BaseDimensions.html
delete mode 100644 doc/org/unitConverter/unit/SI.BaseUnits.html
delete mode 100644 doc/org/unitConverter/unit/SI.Constants.html
delete mode 100644 doc/org/unitConverter/unit/SI.Dimensions.html
delete mode 100644 doc/org/unitConverter/unit/SI.html
delete mode 100644 doc/org/unitConverter/unit/USCustomary.Area.html
delete mode 100644 doc/org/unitConverter/unit/USCustomary.Length.html
delete mode 100644 doc/org/unitConverter/unit/USCustomary.Mass.html
delete mode 100644 doc/org/unitConverter/unit/USCustomary.Volume.html
delete mode 100644 doc/org/unitConverter/unit/USCustomary.html
delete mode 100644 doc/org/unitConverter/unit/Unit.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.html
delete mode 100644 doc/org/unitConverter/unit/UnitDatabaseTest.html
delete mode 100644 doc/org/unitConverter/unit/UnitPrefix.html
delete mode 100644 doc/org/unitConverter/unit/UnitTest.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BaseDimension.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BaseUnit.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Area.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Length.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Mass.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Volume.html
delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.html
delete mode 100644 doc/org/unitConverter/unit/class-use/FunctionalUnit.html
delete mode 100644 doc/org/unitConverter/unit/class-use/LinearUnit.html
delete mode 100644 doc/org/unitConverter/unit/class-use/NameSymbol.html
delete mode 100644 doc/org/unitConverter/unit/class-use/SI.BaseDimensions.html
delete mode 100644 doc/org/unitConverter/unit/class-use/SI.BaseUnits.html
delete mode 100644 doc/org/unitConverter/unit/class-use/SI.Constants.html
delete mode 100644 doc/org/unitConverter/unit/class-use/SI.Dimensions.html
delete mode 100644 doc/org/unitConverter/unit/class-use/SI.html
delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Area.html
delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Length.html
delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Mass.html
delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Volume.html
delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.html
delete mode 100644 doc/org/unitConverter/unit/class-use/Unit.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabaseTest.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitPrefix.html
delete mode 100644 doc/org/unitConverter/unit/class-use/UnitTest.html
delete mode 100644 doc/org/unitConverter/unit/package-frame.html
delete mode 100644 doc/org/unitConverter/unit/package-summary.html
delete mode 100644 doc/org/unitConverter/unit/package-tree.html
delete mode 100644 doc/org/unitConverter/unit/package-use.html
delete mode 100644 doc/overview-frame.html
delete mode 100644 doc/overview-summary.html
delete mode 100644 doc/overview-tree.html
delete mode 100644 doc/package-list
delete mode 100644 doc/package-search-index.js
delete mode 100644 doc/package-search-index.zip
delete mode 100644 doc/resources/glass.png
delete mode 100644 doc/resources/x.png
delete mode 100644 doc/script.js
delete mode 100644 doc/search.js
delete mode 100644 doc/stylesheet.css
delete mode 100644 doc/type-search-index.js
delete mode 100644 doc/type-search-index.zip
create mode 100644 gradle/wrapper/gradle-wrapper.jar
create mode 100644 gradle/wrapper/gradle-wrapper.properties
create mode 100644 gradlew
create mode 100644 gradlew.bat
delete mode 100644 pom.xml
create mode 100644 settings.gradle
create mode 100644 settings.txt
delete mode 100644 src/about.txt
create mode 100644 src/main/java/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/DelegateListModel.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/FilterComparator.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/GridBagBuilder.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/MutablePredicate.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/SearchBoxList.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java
create mode 100644 src/main/java/org/unitConverter/converterGUI/package-info.java
create mode 100644 src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java
create mode 100644 src/main/java/org/unitConverter/math/DecimalComparison.java
create mode 100644 src/main/java/org/unitConverter/math/ExpressionParser.java
create mode 100644 src/main/java/org/unitConverter/math/ObjectProduct.java
create mode 100644 src/main/java/org/unitConverter/math/UncertainDouble.java
create mode 100644 src/main/java/org/unitConverter/math/package-info.java
create mode 100644 src/main/java/org/unitConverter/package-info.java
create mode 100644 src/main/java/org/unitConverter/unit/BaseDimension.java
create mode 100644 src/main/java/org/unitConverter/unit/BaseUnit.java
create mode 100644 src/main/java/org/unitConverter/unit/BritishImperial.java
create mode 100644 src/main/java/org/unitConverter/unit/FunctionalUnit.java
create mode 100644 src/main/java/org/unitConverter/unit/FunctionalUnitlike.java
create mode 100644 src/main/java/org/unitConverter/unit/LinearUnit.java
create mode 100644 src/main/java/org/unitConverter/unit/LinearUnitValue.java
create mode 100644 src/main/java/org/unitConverter/unit/MultiUnit.java
create mode 100644 src/main/java/org/unitConverter/unit/NameSymbol.java
create mode 100644 src/main/java/org/unitConverter/unit/Nameable.java
create mode 100644 src/main/java/org/unitConverter/unit/SI.java
create mode 100644 src/main/java/org/unitConverter/unit/USCustomary.java
create mode 100644 src/main/java/org/unitConverter/unit/Unit.java
create mode 100644 src/main/java/org/unitConverter/unit/UnitDatabase.java
create mode 100644 src/main/java/org/unitConverter/unit/UnitPrefix.java
create mode 100644 src/main/java/org/unitConverter/unit/UnitValue.java
create mode 100644 src/main/java/org/unitConverter/unit/Unitlike.java
create mode 100644 src/main/java/org/unitConverter/unit/UnitlikeValue.java
create mode 100644 src/main/java/org/unitConverter/unit/package-info.java
create mode 100644 src/main/resources/about.txt
delete mode 100644 src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java
delete mode 100644 src/org/unitConverter/converterGUI/DelegateListModel.java
delete mode 100644 src/org/unitConverter/converterGUI/FilterComparator.java
delete mode 100644 src/org/unitConverter/converterGUI/GridBagBuilder.java
delete mode 100644 src/org/unitConverter/converterGUI/MutablePredicate.java
delete mode 100644 src/org/unitConverter/converterGUI/SearchBoxList.java
delete mode 100644 src/org/unitConverter/converterGUI/UnitConverterGUI.java
delete mode 100644 src/org/unitConverter/converterGUI/package-info.java
delete mode 100644 src/org/unitConverter/math/ConditionalExistenceCollections.java
delete mode 100644 src/org/unitConverter/math/ConditionalExistenceCollectionsTest.java
delete mode 100644 src/org/unitConverter/math/DecimalComparison.java
delete mode 100644 src/org/unitConverter/math/ExpressionParser.java
delete mode 100644 src/org/unitConverter/math/ExpressionParserTest.java
delete mode 100644 src/org/unitConverter/math/ObjectProduct.java
delete mode 100644 src/org/unitConverter/math/ObjectProductTest.java
delete mode 100644 src/org/unitConverter/math/UncertainDouble.java
delete mode 100644 src/org/unitConverter/math/package-info.java
delete mode 100644 src/org/unitConverter/package-info.java
delete mode 100644 src/org/unitConverter/unit/BaseDimension.java
delete mode 100644 src/org/unitConverter/unit/BaseUnit.java
delete mode 100644 src/org/unitConverter/unit/BritishImperial.java
delete mode 100644 src/org/unitConverter/unit/FunctionalUnit.java
delete mode 100644 src/org/unitConverter/unit/FunctionalUnitlike.java
delete mode 100644 src/org/unitConverter/unit/LinearUnit.java
delete mode 100644 src/org/unitConverter/unit/LinearUnitValue.java
delete mode 100644 src/org/unitConverter/unit/MultiUnit.java
delete mode 100644 src/org/unitConverter/unit/MultiUnitTest.java
delete mode 100644 src/org/unitConverter/unit/NameSymbol.java
delete mode 100644 src/org/unitConverter/unit/Nameable.java
delete mode 100644 src/org/unitConverter/unit/SI.java
delete mode 100644 src/org/unitConverter/unit/USCustomary.java
delete mode 100644 src/org/unitConverter/unit/Unit.java
delete mode 100644 src/org/unitConverter/unit/UnitDatabase.java
delete mode 100644 src/org/unitConverter/unit/UnitDatabaseTest.java
delete mode 100644 src/org/unitConverter/unit/UnitPrefix.java
delete mode 100644 src/org/unitConverter/unit/UnitTest.java
delete mode 100644 src/org/unitConverter/unit/UnitValue.java
delete mode 100644 src/org/unitConverter/unit/Unitlike.java
delete mode 100644 src/org/unitConverter/unit/UnitlikeValue.java
delete mode 100644 src/org/unitConverter/unit/package-info.java
create mode 100644 src/test/java/org/unitConverter/math/ConditionalExistenceCollectionsTest.java
create mode 100644 src/test/java/org/unitConverter/math/ExpressionParserTest.java
create mode 100644 src/test/java/org/unitConverter/math/ObjectProductTest.java
create mode 100644 src/test/java/org/unitConverter/unit/MultiUnitTest.java
create mode 100644 src/test/java/org/unitConverter/unit/UnitDatabaseTest.java
create mode 100644 src/test/java/org/unitConverter/unit/UnitTest.java
(limited to 'src/org/unitConverter/unit/LinearUnit.java')
diff --git a/.classpath b/.classpath
index a6325e3..66f8050 100644
--- a/.classpath
+++ b/.classpath
@@ -1,33 +1,32 @@
-
-
-
+
-
-
+
+
-
+
-
+
+
-
+
-
-
-
-
+
+
+
-
+
-
-
-
-
+
+
+
-
+
+
+
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..00a51af
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,6 @@
+#
+# https://help.github.com/articles/dealing-with-line-endings/
+#
+# These are explicitly windows files and should use crlf
+*.bat text eol=crlf
+
diff --git a/.gitignore b/.gitignore
index 1d7e13f..1b6985c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
-bin/
-target/
-*.class
-*~
-settings.txt
\ No newline at end of file
+# Ignore Gradle project-specific cache directory
+.gradle
+
+# Ignore Gradle build output directory
+build
diff --git a/.project b/.project
index 56f686e..2debd0a 100644
--- a/.project
+++ b/.project
@@ -1,7 +1,7 @@
- Unit Converter
-
+ UnitConverter
+ Project UnitConverter created by Buildship.
@@ -11,13 +11,13 @@
- org.eclipse.m2e.core.maven2Builder
+ org.eclipse.buildship.core.gradleprojectbuilder
- org.eclipse.m2e.core.maven2Natureorg.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..e889521
--- /dev/null
+++ b/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=
+eclipse.preferences.version=1
diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs
deleted file mode 100644
index d4313d4..0000000
--- a/.settings/org.eclipse.jdt.apt.core.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.apt.aptEnabled=false
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 01cf56c..18ad895 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,16 +1,4 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
-org.eclipse.jdt.core.compiler.processAnnotations=disabled
-org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/bin/main/.gitignore b/bin/main/.gitignore
new file mode 100644
index 0000000..b2d0b77
--- /dev/null
+++ b/bin/main/.gitignore
@@ -0,0 +1,2 @@
+/about.txt
+/org/
diff --git a/bin/test/.gitignore b/bin/test/.gitignore
new file mode 100644
index 0000000..cf1db2e
--- /dev/null
+++ b/bin/test/.gitignore
@@ -0,0 +1 @@
+/org/
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..9d054c3
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,30 @@
+plugins {
+ id "java"
+ id "application"
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_11
+}
+
+mainClassName = "org.unitConverter.converterGUI.UnitConverterGUI"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
+}
+
+test {
+ useJUnitPlatform()
+ testLogging {
+ events 'passed', 'skipped', 'failed'
+ }
+}
+
+run {
+}
\ No newline at end of file
diff --git a/doc/allclasses-frame.html b/doc/allclasses-frame.html
deleted file mode 100644
index d043203..0000000
--- a/doc/allclasses-frame.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-All Classes
-
-
-
-
-
-
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
-
-
-
-
-
Overview
-
The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.
-
-
-
Package
-
Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:
-
-
Interfaces (italic)
-
Classes
-
Enums
-
Exceptions
-
Errors
-
Annotation Types
-
-
-
-
Class/Interface
-
Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
-
-
Class inheritance diagram
-
Direct Subclasses
-
All Known Subinterfaces
-
All Known Implementing Classes
-
Class/interface declaration
-
Class/interface description
-
-
-
Nested Class Summary
-
Field Summary
-
Constructor Summary
-
Method Summary
-
-
-
Field Detail
-
Constructor Detail
-
Method Detail
-
-
Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
-
-
-
Annotation Type
-
Each annotation type has its own separate page with the following sections:
-
-
Annotation Type declaration
-
Annotation Type description
-
Required Element Summary
-
Optional Element Summary
-
Element Detail
-
-
-
-
Enum
-
Each enum has its own separate page with the following sections:
-
-
Enum declaration
-
Enum description
-
Enum Constant Summary
-
Enum Constant Detail
-
-
-
-
Use
-
Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
-
-
-
Tree (Class Hierarchy)
-
There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.
-
-
When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
-
When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
-
-
-
-
Deprecated API
-
The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.
-
-
-
Index
-
The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
-
-
-
Prev/Next
-
These links take you to the next or previous class, interface, package, or related page.
-
-
-
Frames/No Frames
-
These links show and hide the HTML frames. All pages are available with or without frames.
-
-
-
All Classes
-
The All Classes link shows all classes and interfaces except non-static nested types.
-
-
-
Serialized Form
-
Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.