| // © 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 */ |
| |
| enum Constants { |
| CONSTANT_FT2M, // ft2m stands for foot to meter. |
| CONSTANT_PI, // PI |
| CONSTANT_GRAVITY, // Gravity |
| CONSTANT_G, |
| CONSTANT_GAL_IMP2M3, // Gallon imp to m3 |
| CONSTANT_LB2KG, // Pound to Kilogram |
| |
| // 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. |
| 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 |
| }; |
| |
| 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; |
| int32_t constants[CONSTANTS_COUNT] = {}; |
| |
| void multiplyBy(const Factor &rhs); |
| void divideBy(const Factor &rhs); |
| |
| // Apply the power to the factor. |
| void power(int32_t power); |
| |
| // Flip the `Factor`, for example, factor= 2/3, flippedFactor = 3/2 |
| void flip(); |
| |
| // Apply SI prefix to the `Factor` |
| void applySiPrefix(UMeasureSIPrefix siPrefix); |
| void substituteConstants(); |
| }; |
| |
| /* |
| * 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 UnitConverter : 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. |
| * |
| * @param source represents the source unit. |
| * @param target represents the target unit. |
| * @param ratesInfo Contains all the needed conversion rates. |
| * @param status |
| */ |
| UnitConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target, |
| 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; |
| |
| private: |
| ConversionRate conversionRate_; |
| }; |
| |
| } // namespace units |
| U_NAMESPACE_END |
| |
| #endif //__UNITS_CONVERTER_H__ |
| |
| #endif /* #if !UCONFIG_NO_FORMATTING */ |