summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/dimension/UnitDimension.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/unitConverter/dimension/UnitDimension.java')
-rwxr-xr-xsrc/org/unitConverter/dimension/UnitDimension.java241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/org/unitConverter/dimension/UnitDimension.java b/src/org/unitConverter/dimension/UnitDimension.java
new file mode 100755
index 0000000..dbeaeff
--- /dev/null
+++ b/src/org/unitConverter/dimension/UnitDimension.java
@@ -0,0 +1,241 @@
+/**
+ * Copyright (C) 2018 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 <https://www.gnu.org/licenses/>.
+ */
+package org.unitConverter.dimension;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * An object that represents what a unit measures, like length, mass, area, energy, etc.
+ *
+ * @author Adrien Hopkins
+ * @since 2018-12-11
+ * @since v0.1.0
+ */
+public final class UnitDimension {
+ /**
+ * The unit dimension where every exponent is zero
+ *
+ * @since 2018-12-12
+ * @since v0.1.0
+ */
+ public static final UnitDimension EMPTY = new UnitDimension(new HashMap<>());
+
+ /**
+ * Gets an UnitDimension that has 1 of a certain dimension and nothing else
+ *
+ * @param dimension
+ * dimension to get
+ * @return unit dimension
+ * @since 2018-12-11
+ * @since v0.1.0
+ */
+ public static final UnitDimension getBase(final BaseDimension dimension) {
+ final Map<BaseDimension, Integer> map = new HashMap<>();
+ map.put(dimension, 1);
+ return new UnitDimension(map);
+ }
+
+ /**
+ * The base dimensions that make up this dimension.
+ *
+ * @since 2018-12-11
+ * @since v0.1.0
+ */
+ final Map<BaseDimension, Integer> exponents;
+
+ /**
+ * Creates the {@code UnitDimension}.
+ *
+ * @param exponents
+ * base dimensions that make up this dimension
+ * @since 2018-12-11
+ * @since v0.1.0
+ */
+ private UnitDimension(final Map<BaseDimension, Integer> exponents) {
+ this.exponents = new HashMap<>(exponents);
+ }
+
+ /**
+ * Divides this dimension by another
+ *
+ * @param other
+ * other dimension
+ * @return quotient of two dimensions
+ * @since 2018-12-11
+ * @since v0.1.0
+ */
+ public UnitDimension dividedBy(final UnitDimension other) {
+ final Map<BaseDimension, Integer> map = new HashMap<>(this.exponents);
+
+ for (final BaseDimension key : other.exponents.keySet()) {
+ if (map.containsKey(key)) {
+ // add the dimensions
+ map.put(key, map.get(key) - other.exponents.get(key));
+ } else {
+ map.put(key, -other.exponents.get(key));
+ }
+ }
+ return new UnitDimension(map);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof UnitDimension))
+ return false;
+ final UnitDimension other = (UnitDimension) obj;
+
+ // anything with a value of 0 is equal to a nonexistent value
+ for (final BaseDimension b : this.getBaseSet()) {
+ if (this.exponents.get(b) != other.exponents.get(b))
+ if (!(this.exponents.get(b) == 0 && !other.exponents.containsKey(b)))
+ return false;
+ }
+ for (final BaseDimension b : other.getBaseSet()) {
+ if (this.exponents.get(b) != other.exponents.get(b))
+ if (!(other.exponents.get(b) == 0 && !this.exponents.containsKey(b)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return a set of all of the base dimensions with non-zero exponents that make up this dimension.
+ * @since 2018-12-12
+ * @since v0.1.0
+ */
+ public final Set<BaseDimension> getBaseSet() {
+ final Set<BaseDimension> dimensions = new HashSet<>();
+
+ // add all dimensions with a nonzero exponent - they shouldn't be there in the first place
+ for (final BaseDimension dimension : this.exponents.keySet()) {
+ if (!this.exponents.get(dimension).equals(0)) {
+ dimensions.add(dimension);
+ }
+ }
+
+ return dimensions;
+ }
+
+ /**
+ * Gets the exponent for a specific dimension.
+ *
+ * @param dimension
+ * dimension to check
+ * @return exponent for that dimension
+ * @since 2018-12-12
+ * @since v0.1.0
+ */
+ public int getExponent(final BaseDimension dimension) {
+ return this.exponents.getOrDefault(dimension, 0);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.exponents);
+ }
+
+ /**
+ * @return true if this dimension is a base, i.e. it has one exponent of one and no other nonzero exponents
+ * @since 2019-01-15
+ * @since v0.1.0
+ */
+ public boolean isBase() {
+ int oneCount = 0;
+ boolean twoOrMore = false; // has exponents of 2 or more
+ for (final BaseDimension b : this.getBaseSet()) {
+ if (this.exponents.get(b) == 1) {
+ oneCount++;
+ } else if (this.exponents.get(b) != 0) {
+ twoOrMore = true;
+ }
+ }
+ return (oneCount == 0 || oneCount == 1) && !twoOrMore;
+ }
+
+ /**
+ * Multiplies this dimension by another
+ *
+ * @param other
+ * other dimension
+ * @return product of two dimensions
+ * @since 2018-12-11
+ * @since v0.1.0
+ */
+ public UnitDimension times(final UnitDimension other) {
+ final Map<BaseDimension, Integer> map = new HashMap<>(this.exponents);
+
+ for (final BaseDimension key : other.exponents.keySet()) {
+ if (map.containsKey(key)) {
+ // add the dimensions
+ map.put(key, map.get(key) + other.exponents.get(key));
+ } else {
+ map.put(key, other.exponents.get(key));
+ }
+ }
+ return new UnitDimension(map);
+ }
+
+ /**
+ * Returns this dimension, but to an exponent
+ *
+ * @param exp
+ * exponent
+ * @return result of exponientation
+ * @since 2019-01-15
+ * @since v0.1.0
+ */
+ public UnitDimension toExponent(final int exp) {
+ final Map<BaseDimension, Integer> map = new HashMap<>(this.exponents);
+ for (final BaseDimension key : this.exponents.keySet()) {
+ map.put(key, this.getExponent(key) * exp);
+ }
+ return new UnitDimension(map);
+ }
+
+ @Override
+ public String toString() {
+ final List<String> positiveStringComponents = new ArrayList<>();
+ final List<String> negativeStringComponents = new ArrayList<>();
+
+ // for each base dimension that makes up this dimension, add it and its exponent
+ for (final BaseDimension dimension : this.getBaseSet()) {
+ final int exponent = this.exponents.get(dimension);
+ if (exponent > 0) {
+ positiveStringComponents.add(String.format("%s^%d", dimension.getSymbol(), exponent));
+ } else if (exponent < 0) {
+ negativeStringComponents.add(String.format("%s^%d", dimension.getSymbol(), -exponent));
+ }
+ }
+
+ final String positiveString = positiveStringComponents.isEmpty() ? "1"
+ : String.join(" ", positiveStringComponents);
+ final String negativeString = negativeStringComponents.isEmpty() ? ""
+ : " / " + String.join(" ", negativeStringComponents);
+
+ return positiveString + negativeString;
+ }
+}