12e5b6d6dSopenharmony_ci// © 2020 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci 42e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 52e5b6d6dSopenharmony_ci 62e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING 72e5b6d6dSopenharmony_ci#ifndef __UNITS_CONVERTER_H__ 82e5b6d6dSopenharmony_ci#define __UNITS_CONVERTER_H__ 92e5b6d6dSopenharmony_ci 102e5b6d6dSopenharmony_ci#include "cmemory.h" 112e5b6d6dSopenharmony_ci#include "measunit_impl.h" 122e5b6d6dSopenharmony_ci#include "unicode/errorcode.h" 132e5b6d6dSopenharmony_ci#include "unicode/stringpiece.h" 142e5b6d6dSopenharmony_ci#include "unicode/uobject.h" 152e5b6d6dSopenharmony_ci#include "units_converter.h" 162e5b6d6dSopenharmony_ci#include "units_data.h" 172e5b6d6dSopenharmony_ci 182e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN 192e5b6d6dSopenharmony_cinamespace units { 202e5b6d6dSopenharmony_ci 212e5b6d6dSopenharmony_ci/* Internal Structure */ 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_ci// Constants corresponding to unitConstants in CLDR's units.xml. 242e5b6d6dSopenharmony_cienum Constants { 252e5b6d6dSopenharmony_ci CONSTANT_FT2M, // ft_to_m 262e5b6d6dSopenharmony_ci CONSTANT_PI, // PI 272e5b6d6dSopenharmony_ci CONSTANT_GRAVITY, // Gravity of earth (9.80665 m/s^2), "g". 282e5b6d6dSopenharmony_ci CONSTANT_G, // Newtonian constant of gravitation, "G". 292e5b6d6dSopenharmony_ci CONSTANT_GAL_IMP2M3, // Gallon imp to m3 302e5b6d6dSopenharmony_ci CONSTANT_LB2KG, // Pound to Kilogram 312e5b6d6dSopenharmony_ci CONSTANT_GLUCOSE_MOLAR_MASS, 322e5b6d6dSopenharmony_ci CONSTANT_ITEM_PER_MOLE, 332e5b6d6dSopenharmony_ci CONSTANT_METERS_PER_AU, 342e5b6d6dSopenharmony_ci CONSTANT_SEC_PER_JULIAN_YEAR, 352e5b6d6dSopenharmony_ci CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND, 362e5b6d6dSopenharmony_ci 372e5b6d6dSopenharmony_ci // Must be the last element. 382e5b6d6dSopenharmony_ci CONSTANTS_COUNT 392e5b6d6dSopenharmony_ci}; 402e5b6d6dSopenharmony_ci 412e5b6d6dSopenharmony_ci// These values are a hard-coded subset of unitConstants in the units 422e5b6d6dSopenharmony_ci// resources file. A unit test checks that all constants in the resource 432e5b6d6dSopenharmony_ci// file are at least recognised by the code. Derived constants' values or 442e5b6d6dSopenharmony_ci// hard-coded derivations are not checked. 452e5b6d6dSopenharmony_ci// In ICU4J, these constants live in UnitConverter.Factor.getConversionRate(). 462e5b6d6dSopenharmony_cistatic const double constantsValues[CONSTANTS_COUNT] = { 472e5b6d6dSopenharmony_ci 0.3048, // CONSTANT_FT2M 482e5b6d6dSopenharmony_ci 411557987.0 / 131002976.0, // CONSTANT_PI 492e5b6d6dSopenharmony_ci 9.80665, // CONSTANT_GRAVITY 502e5b6d6dSopenharmony_ci 6.67408E-11, // CONSTANT_G 512e5b6d6dSopenharmony_ci 0.00454609, // CONSTANT_GAL_IMP2M3 522e5b6d6dSopenharmony_ci 0.45359237, // CONSTANT_LB2KG 532e5b6d6dSopenharmony_ci 180.1557, // CONSTANT_GLUCOSE_MOLAR_MASS 542e5b6d6dSopenharmony_ci 6.02214076E+23, // CONSTANT_ITEM_PER_MOLE 552e5b6d6dSopenharmony_ci 149597870700, // CONSTANT_METERS_PER_AU 562e5b6d6dSopenharmony_ci 31557600, // CONSTANT_SEC_PER_JULIAN_YEAR 572e5b6d6dSopenharmony_ci 299792458, // CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND 582e5b6d6dSopenharmony_ci}; 592e5b6d6dSopenharmony_ci 602e5b6d6dSopenharmony_citypedef enum Signum { 612e5b6d6dSopenharmony_ci NEGATIVE = -1, 622e5b6d6dSopenharmony_ci POSITIVE = 1, 632e5b6d6dSopenharmony_ci} Signum; 642e5b6d6dSopenharmony_ci 652e5b6d6dSopenharmony_ci/* Represents a conversion factor */ 662e5b6d6dSopenharmony_cistruct U_I18N_API Factor { 672e5b6d6dSopenharmony_ci double factorNum = 1; 682e5b6d6dSopenharmony_ci double factorDen = 1; 692e5b6d6dSopenharmony_ci double offset = 0; 702e5b6d6dSopenharmony_ci bool reciprocal = false; 712e5b6d6dSopenharmony_ci 722e5b6d6dSopenharmony_ci // Exponents for the symbolic constants 732e5b6d6dSopenharmony_ci int32_t constantExponents[CONSTANTS_COUNT] = {}; 742e5b6d6dSopenharmony_ci 752e5b6d6dSopenharmony_ci void multiplyBy(const Factor &rhs); 762e5b6d6dSopenharmony_ci void divideBy(const Factor &rhs); 772e5b6d6dSopenharmony_ci 782e5b6d6dSopenharmony_ci // Apply the power to the factor. 792e5b6d6dSopenharmony_ci void power(int32_t power); 802e5b6d6dSopenharmony_ci 812e5b6d6dSopenharmony_ci // Apply SI or binary prefix to the Factor. 822e5b6d6dSopenharmony_ci void applyPrefix(UMeasurePrefix unitPrefix); 832e5b6d6dSopenharmony_ci 842e5b6d6dSopenharmony_ci // Does an in-place substitution of the "symbolic constants" based on 852e5b6d6dSopenharmony_ci // constantExponents (resetting the exponents). 862e5b6d6dSopenharmony_ci // 872e5b6d6dSopenharmony_ci // In ICU4J, see UnitConverter.Factor.getConversionRate(). 882e5b6d6dSopenharmony_ci void substituteConstants(); 892e5b6d6dSopenharmony_ci}; 902e5b6d6dSopenharmony_ci 912e5b6d6dSopenharmony_cistruct U_I18N_API ConversionInfo { 922e5b6d6dSopenharmony_ci double conversionRate; 932e5b6d6dSopenharmony_ci double offset; 942e5b6d6dSopenharmony_ci bool reciprocal; 952e5b6d6dSopenharmony_ci}; 962e5b6d6dSopenharmony_ci 972e5b6d6dSopenharmony_ci/* 982e5b6d6dSopenharmony_ci * Adds a single factor element to the `Factor`. e.g "ft3m", "2.333" or "cup2m3". But not "cup2m3^3". 992e5b6d6dSopenharmony_ci */ 1002e5b6d6dSopenharmony_civoid U_I18N_API addSingleFactorConstant(StringPiece baseStr, int32_t power, Signum sigNum, 1012e5b6d6dSopenharmony_ci Factor &factor, UErrorCode &status); 1022e5b6d6dSopenharmony_ci 1032e5b6d6dSopenharmony_ci/** 1042e5b6d6dSopenharmony_ci * Represents the conversion rate between `source` and `target`. 1052e5b6d6dSopenharmony_ci */ 1062e5b6d6dSopenharmony_cistruct U_I18N_API ConversionRate : public UMemory { 1072e5b6d6dSopenharmony_ci const MeasureUnitImpl source; 1082e5b6d6dSopenharmony_ci const MeasureUnitImpl target; 1092e5b6d6dSopenharmony_ci double factorNum = 1; 1102e5b6d6dSopenharmony_ci double factorDen = 1; 1112e5b6d6dSopenharmony_ci double sourceOffset = 0; 1122e5b6d6dSopenharmony_ci double targetOffset = 0; 1132e5b6d6dSopenharmony_ci bool reciprocal = false; 1142e5b6d6dSopenharmony_ci 1152e5b6d6dSopenharmony_ci ConversionRate(MeasureUnitImpl &&source, MeasureUnitImpl &&target) 1162e5b6d6dSopenharmony_ci : source(std::move(source)), target(std::move(target)) {} 1172e5b6d6dSopenharmony_ci}; 1182e5b6d6dSopenharmony_ci 1192e5b6d6dSopenharmony_cienum Convertibility { 1202e5b6d6dSopenharmony_ci RECIPROCAL, 1212e5b6d6dSopenharmony_ci CONVERTIBLE, 1222e5b6d6dSopenharmony_ci UNCONVERTIBLE, 1232e5b6d6dSopenharmony_ci}; 1242e5b6d6dSopenharmony_ci 1252e5b6d6dSopenharmony_ciMeasureUnitImpl U_I18N_API extractCompoundBaseUnit(const MeasureUnitImpl &source, 1262e5b6d6dSopenharmony_ci const ConversionRates &conversionRates, 1272e5b6d6dSopenharmony_ci UErrorCode &status); 1282e5b6d6dSopenharmony_ci 1292e5b6d6dSopenharmony_ci/** 1302e5b6d6dSopenharmony_ci * Check if the convertibility between `source` and `target`. 1312e5b6d6dSopenharmony_ci * For example: 1322e5b6d6dSopenharmony_ci * `meter` and `foot` are `CONVERTIBLE`. 1332e5b6d6dSopenharmony_ci * `meter-per-second` and `second-per-meter` are `RECIPROCAL`. 1342e5b6d6dSopenharmony_ci * `meter` and `pound` are `UNCONVERTIBLE`. 1352e5b6d6dSopenharmony_ci * 1362e5b6d6dSopenharmony_ci * NOTE: 1372e5b6d6dSopenharmony_ci * Only works with SINGLE and COMPOUND units. If one of the units is a 1382e5b6d6dSopenharmony_ci * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity. 1392e5b6d6dSopenharmony_ci */ 1402e5b6d6dSopenharmony_ciConvertibility U_I18N_API extractConvertibility(const MeasureUnitImpl &source, 1412e5b6d6dSopenharmony_ci const MeasureUnitImpl &target, 1422e5b6d6dSopenharmony_ci const ConversionRates &conversionRates, 1432e5b6d6dSopenharmony_ci UErrorCode &status); 1442e5b6d6dSopenharmony_ci 1452e5b6d6dSopenharmony_ci/** 1462e5b6d6dSopenharmony_ci * Converts from a source `MeasureUnit` to a target `MeasureUnit`. 1472e5b6d6dSopenharmony_ci * 1482e5b6d6dSopenharmony_ci * NOTE: 1492e5b6d6dSopenharmony_ci * Only works with SINGLE and COMPOUND units. If one of the units is a 1502e5b6d6dSopenharmony_ci * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity. 1512e5b6d6dSopenharmony_ci */ 1522e5b6d6dSopenharmony_ciclass U_I18N_API UnitsConverter : public UMemory { 1532e5b6d6dSopenharmony_ci public: 1542e5b6d6dSopenharmony_ci /** 1552e5b6d6dSopenharmony_ci * Constructor of `UnitConverter`. 1562e5b6d6dSopenharmony_ci * NOTE: 1572e5b6d6dSopenharmony_ci * - source and target must be under the same category 1582e5b6d6dSopenharmony_ci * - e.g. meter to mile --> both of them are length units. 1592e5b6d6dSopenharmony_ci * NOTE: 1602e5b6d6dSopenharmony_ci * This constructor creates an instance of `ConversionRates` internally. 1612e5b6d6dSopenharmony_ci * 1622e5b6d6dSopenharmony_ci * @param sourceIdentifier represents the source unit identifier. 1632e5b6d6dSopenharmony_ci * @param targetIdentifier represents the target unit identifier. 1642e5b6d6dSopenharmony_ci * @param status 1652e5b6d6dSopenharmony_ci */ 1662e5b6d6dSopenharmony_ci UnitsConverter(StringPiece sourceIdentifier, StringPiece targetIdentifier, UErrorCode &status); 1672e5b6d6dSopenharmony_ci 1682e5b6d6dSopenharmony_ci /** 1692e5b6d6dSopenharmony_ci * Constructor of `UnitConverter`. 1702e5b6d6dSopenharmony_ci * NOTE: 1712e5b6d6dSopenharmony_ci * - source and target must be under the same category 1722e5b6d6dSopenharmony_ci * - e.g. meter to mile --> both of them are length units. 1732e5b6d6dSopenharmony_ci * 1742e5b6d6dSopenharmony_ci * @param source represents the source unit. 1752e5b6d6dSopenharmony_ci * @param target represents the target unit. 1762e5b6d6dSopenharmony_ci * @param ratesInfo Contains all the needed conversion rates. 1772e5b6d6dSopenharmony_ci * @param status 1782e5b6d6dSopenharmony_ci */ 1792e5b6d6dSopenharmony_ci UnitsConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target, 1802e5b6d6dSopenharmony_ci const ConversionRates &ratesInfo, UErrorCode &status); 1812e5b6d6dSopenharmony_ci 1822e5b6d6dSopenharmony_ci /** 1832e5b6d6dSopenharmony_ci * Compares two single units and returns 1 if the first one is greater, -1 if the second 1842e5b6d6dSopenharmony_ci * one is greater and 0 if they are equal. 1852e5b6d6dSopenharmony_ci * 1862e5b6d6dSopenharmony_ci * NOTE: 1872e5b6d6dSopenharmony_ci * Compares only single units that are convertible. 1882e5b6d6dSopenharmony_ci */ 1892e5b6d6dSopenharmony_ci static int32_t compareTwoUnits(const MeasureUnitImpl &firstUnit, const MeasureUnitImpl &SecondUnit, 1902e5b6d6dSopenharmony_ci const ConversionRates &ratesInfo, UErrorCode &status); 1912e5b6d6dSopenharmony_ci 1922e5b6d6dSopenharmony_ci /** 1932e5b6d6dSopenharmony_ci * Convert a measurement expressed in the source unit to a measurement 1942e5b6d6dSopenharmony_ci * expressed in the target unit. 1952e5b6d6dSopenharmony_ci * 1962e5b6d6dSopenharmony_ci * @param inputValue the value to be converted. 1972e5b6d6dSopenharmony_ci * @return the converted value. 1982e5b6d6dSopenharmony_ci */ 1992e5b6d6dSopenharmony_ci double convert(double inputValue) const; 2002e5b6d6dSopenharmony_ci 2012e5b6d6dSopenharmony_ci /** 2022e5b6d6dSopenharmony_ci * The inverse of convert(): convert a measurement expressed in the target 2032e5b6d6dSopenharmony_ci * unit to a measurement expressed in the source unit. 2042e5b6d6dSopenharmony_ci * 2052e5b6d6dSopenharmony_ci * @param inputValue the value to be converted. 2062e5b6d6dSopenharmony_ci * @return the converted value. 2072e5b6d6dSopenharmony_ci */ 2082e5b6d6dSopenharmony_ci double convertInverse(double inputValue) const; 2092e5b6d6dSopenharmony_ci 2102e5b6d6dSopenharmony_ci ConversionInfo getConversionInfo() const; 2112e5b6d6dSopenharmony_ci 2122e5b6d6dSopenharmony_ci private: 2132e5b6d6dSopenharmony_ci ConversionRate conversionRate_; 2142e5b6d6dSopenharmony_ci 2152e5b6d6dSopenharmony_ci /** 2162e5b6d6dSopenharmony_ci * Initialises the object. 2172e5b6d6dSopenharmony_ci */ 2182e5b6d6dSopenharmony_ci void init(const ConversionRates &ratesInfo, UErrorCode &status); 2192e5b6d6dSopenharmony_ci}; 2202e5b6d6dSopenharmony_ci 2212e5b6d6dSopenharmony_ci} // namespace units 2222e5b6d6dSopenharmony_ciU_NAMESPACE_END 2232e5b6d6dSopenharmony_ci 2242e5b6d6dSopenharmony_ci#endif //__UNITS_CONVERTER_H__ 2252e5b6d6dSopenharmony_ci 2262e5b6d6dSopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */ 227