summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/i18n/units_converter.h
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/i18n/units_converter.h')
-rw-r--r--intl/icu/source/i18n/units_converter.h226
1 files changed, 226 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/units_converter.h b/intl/icu/source/i18n/units_converter.h
new file mode 100644
index 0000000000..fd1d6ec422
--- /dev/null
+++ b/intl/icu/source/i18n/units_converter.h
@@ -0,0 +1,226 @@
+// © 2020 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+#ifndef __UNITS_CONVERTER_H__
+#define __UNITS_CONVERTER_H__
+
+#include "cmemory.h"
+#include "measunit_impl.h"
+#include "unicode/errorcode.h"
+#include "unicode/stringpiece.h"
+#include "unicode/uobject.h"
+#include "units_converter.h"
+#include "units_data.h"
+
+U_NAMESPACE_BEGIN
+namespace units {
+
+/* Internal Structure */
+
+// Constants corresponding to unitConstants in CLDR's units.xml.
+enum Constants {
+ CONSTANT_FT2M, // ft_to_m
+ CONSTANT_PI, // PI
+ CONSTANT_GRAVITY, // Gravity of earth (9.80665 m/s^2), "g".
+ CONSTANT_G, // Newtonian constant of gravitation, "G".
+ CONSTANT_GAL_IMP2M3, // Gallon imp to m3
+ CONSTANT_LB2KG, // Pound to Kilogram
+ CONSTANT_GLUCOSE_MOLAR_MASS,
+ CONSTANT_ITEM_PER_MOLE,
+ CONSTANT_METERS_PER_AU,
+ CONSTANT_SEC_PER_JULIAN_YEAR,
+ CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND,
+
+ // Must be the last element.
+ CONSTANTS_COUNT
+};
+
+// These values are a hard-coded subset of unitConstants in the units
+// resources file. A unit test checks that all constants in the resource
+// file are at least recognised by the code. Derived constants' values or
+// hard-coded derivations are not checked.
+// In ICU4J, these constants live in UnitConverter.Factor.getConversionRate().
+static const double constantsValues[CONSTANTS_COUNT] = {
+ 0.3048, // CONSTANT_FT2M
+ 411557987.0 / 131002976.0, // CONSTANT_PI
+ 9.80665, // CONSTANT_GRAVITY
+ 6.67408E-11, // CONSTANT_G
+ 0.00454609, // CONSTANT_GAL_IMP2M3
+ 0.45359237, // CONSTANT_LB2KG
+ 180.1557, // CONSTANT_GLUCOSE_MOLAR_MASS
+ 6.02214076E+23, // CONSTANT_ITEM_PER_MOLE
+ 149597870700, // CONSTANT_METERS_PER_AU
+ 31557600, // CONSTANT_SEC_PER_JULIAN_YEAR
+ 299792458, // CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND
+};
+
+typedef enum Signum {
+ NEGATIVE = -1,
+ POSITIVE = 1,
+} Signum;
+
+/* Represents a conversion factor */
+struct U_I18N_API Factor {
+ double factorNum = 1;
+ double factorDen = 1;
+ double offset = 0;
+ bool reciprocal = false;
+
+ // Exponents for the symbolic constants
+ int32_t constantExponents[CONSTANTS_COUNT] = {};
+
+ void multiplyBy(const Factor &rhs);
+ void divideBy(const Factor &rhs);
+
+ // Apply the power to the factor.
+ void power(int32_t power);
+
+ // Apply SI or binary prefix to the Factor.
+ void applyPrefix(UMeasurePrefix unitPrefix);
+
+ // Does an in-place substitution of the "symbolic constants" based on
+ // constantExponents (resetting the exponents).
+ //
+ // In ICU4J, see UnitConverter.Factor.getConversionRate().
+ void substituteConstants();
+};
+
+struct U_I18N_API ConversionInfo {
+ double conversionRate;
+ double offset;
+ bool reciprocal;
+};
+
+/*
+ * Adds a single factor element to the `Factor`. e.g "ft3m", "2.333" or "cup2m3". But not "cup2m3^3".
+ */
+void U_I18N_API addSingleFactorConstant(StringPiece baseStr, int32_t power, Signum sigNum,
+ Factor &factor, UErrorCode &status);
+
+/**
+ * Represents the conversion rate between `source` and `target`.
+ */
+struct U_I18N_API ConversionRate : public UMemory {
+ const MeasureUnitImpl source;
+ const MeasureUnitImpl target;
+ double factorNum = 1;
+ double factorDen = 1;
+ double sourceOffset = 0;
+ double targetOffset = 0;
+ bool reciprocal = false;
+
+ ConversionRate(MeasureUnitImpl &&source, MeasureUnitImpl &&target)
+ : source(std::move(source)), target(std::move(target)) {}
+};
+
+enum Convertibility {
+ RECIPROCAL,
+ CONVERTIBLE,
+ UNCONVERTIBLE,
+};
+
+MeasureUnitImpl U_I18N_API extractCompoundBaseUnit(const MeasureUnitImpl &source,
+ const ConversionRates &conversionRates,
+ UErrorCode &status);
+
+/**
+ * Check if the convertibility between `source` and `target`.
+ * For example:
+ * `meter` and `foot` are `CONVERTIBLE`.
+ * `meter-per-second` and `second-per-meter` are `RECIPROCAL`.
+ * `meter` and `pound` are `UNCONVERTIBLE`.
+ *
+ * NOTE:
+ * Only works with SINGLE and COMPOUND units. If one of the units is a
+ * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity.
+ */
+Convertibility U_I18N_API extractConvertibility(const MeasureUnitImpl &source,
+ const MeasureUnitImpl &target,
+ const ConversionRates &conversionRates,
+ UErrorCode &status);
+
+/**
+ * Converts from a source `MeasureUnit` to a target `MeasureUnit`.
+ *
+ * NOTE:
+ * Only works with SINGLE and COMPOUND units. If one of the units is a
+ * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity.
+ */
+class U_I18N_API UnitsConverter : public UMemory {
+ public:
+ /**
+ * Constructor of `UnitConverter`.
+ * NOTE:
+ * - source and target must be under the same category
+ * - e.g. meter to mile --> both of them are length units.
+ * NOTE:
+ * This constructor creates an instance of `ConversionRates` internally.
+ *
+ * @param sourceIdentifier represents the source unit identifier.
+ * @param targetIdentifier represents the target unit identifier.
+ * @param status
+ */
+ UnitsConverter(StringPiece sourceIdentifier, StringPiece targetIdentifier, UErrorCode &status);
+
+ /**
+ * Constructor of `UnitConverter`.
+ * NOTE:
+ * - source and target must be under the same category
+ * - e.g. meter to mile --> both of them are length units.
+ *
+ * @param source represents the source unit.
+ * @param target represents the target unit.
+ * @param ratesInfo Contains all the needed conversion rates.
+ * @param status
+ */
+ UnitsConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target,
+ const ConversionRates &ratesInfo, UErrorCode &status);
+
+ /**
+ * Compares two single units and returns 1 if the first one is greater, -1 if the second
+ * one is greater and 0 if they are equal.
+ *
+ * NOTE:
+ * Compares only single units that are convertible.
+ */
+ static int32_t compareTwoUnits(const MeasureUnitImpl &firstUnit, const MeasureUnitImpl &SecondUnit,
+ const ConversionRates &ratesInfo, UErrorCode &status);
+
+ /**
+ * Convert a measurement expressed in the source unit to a measurement
+ * expressed in the target unit.
+ *
+ * @param inputValue the value to be converted.
+ * @return the converted value.
+ */
+ double convert(double inputValue) const;
+
+ /**
+ * The inverse of convert(): convert a measurement expressed in the target
+ * unit to a measurement expressed in the source unit.
+ *
+ * @param inputValue the value to be converted.
+ * @return the converted value.
+ */
+ double convertInverse(double inputValue) const;
+
+ ConversionInfo getConversionInfo() const;
+
+ private:
+ ConversionRate conversionRate_;
+
+ /**
+ * Initialises the object.
+ */
+ void init(const ConversionRates &ratesInfo, UErrorCode &status);
+};
+
+} // namespace units
+U_NAMESPACE_END
+
+#endif //__UNITS_CONVERTER_H__
+
+#endif /* #if !UCONFIG_NO_FORMATTING */