1*0e209d39SAndroid Build Coastguard Worker // © 2020 and later: Unicode, Inc. and others. 2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html 3*0e209d39SAndroid Build Coastguard Worker 4*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h" 5*0e209d39SAndroid Build Coastguard Worker 6*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_FORMATTING 7*0e209d39SAndroid Build Coastguard Worker #ifndef __UNITS_COMPLEXCONVERTER_H__ 8*0e209d39SAndroid Build Coastguard Worker #define __UNITS_COMPLEXCONVERTER_H__ 9*0e209d39SAndroid Build Coastguard Worker 10*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h" 11*0e209d39SAndroid Build Coastguard Worker #include "measunit_impl.h" 12*0e209d39SAndroid Build Coastguard Worker #include "number_roundingutils.h" 13*0e209d39SAndroid Build Coastguard Worker #include "unicode/errorcode.h" 14*0e209d39SAndroid Build Coastguard Worker #include "unicode/measure.h" 15*0e209d39SAndroid Build Coastguard Worker #include "units_converter.h" 16*0e209d39SAndroid Build Coastguard Worker #include "units_data.h" 17*0e209d39SAndroid Build Coastguard Worker 18*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN 19*0e209d39SAndroid Build Coastguard Worker 20*0e209d39SAndroid Build Coastguard Worker // Export explicit template instantiations of MaybeStackArray, MemoryPool and 21*0e209d39SAndroid Build Coastguard Worker // MaybeStackVector. This is required when building DLLs for Windows. (See 22*0e209d39SAndroid Build Coastguard Worker // datefmt.h, collationiterator.h, erarules.h and others for similar examples.) 23*0e209d39SAndroid Build Coastguard Worker // 24*0e209d39SAndroid Build Coastguard Worker // Note: These need to be outside of the units namespace, or Clang will generate 25*0e209d39SAndroid Build Coastguard Worker // a compile error. 26*0e209d39SAndroid Build Coastguard Worker #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN 27*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackArray<units::UnitsConverter*, 8>; 28*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MemoryPool<units::UnitsConverter, 8>; 29*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackVector<units::UnitsConverter, 8>; 30*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackArray<MeasureUnitImpl*, 8>; 31*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MemoryPool<MeasureUnitImpl, 8>; 32*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackVector<MeasureUnitImpl, 8>; 33*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackArray<MeasureUnit*, 8>; 34*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MemoryPool<MeasureUnit, 8>; 35*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackVector<MeasureUnit, 8>; 36*0e209d39SAndroid Build Coastguard Worker #endif 37*0e209d39SAndroid Build Coastguard Worker 38*0e209d39SAndroid Build Coastguard Worker namespace units { 39*0e209d39SAndroid Build Coastguard Worker 40*0e209d39SAndroid Build Coastguard Worker /** 41*0e209d39SAndroid Build Coastguard Worker * Converts from single or compound unit to single, compound or mixed units. 42*0e209d39SAndroid Build Coastguard Worker * For example, from `meter` to `foot+inch`. 43*0e209d39SAndroid Build Coastguard Worker * 44*0e209d39SAndroid Build Coastguard Worker * DESIGN: 45*0e209d39SAndroid Build Coastguard Worker * This class uses `UnitsConverter` in order to perform the single converter (i.e. converters from a 46*0e209d39SAndroid Build Coastguard Worker * single unit to another single unit). Therefore, `ComplexUnitsConverter` class contains multiple 47*0e209d39SAndroid Build Coastguard Worker * instances of the `UnitsConverter` to perform the conversion. 48*0e209d39SAndroid Build Coastguard Worker */ 49*0e209d39SAndroid Build Coastguard Worker class U_I18N_API ComplexUnitsConverter : public UMemory { 50*0e209d39SAndroid Build Coastguard Worker public: 51*0e209d39SAndroid Build Coastguard Worker /** 52*0e209d39SAndroid Build Coastguard Worker * Constructs `ComplexUnitsConverter` for an `targetUnit` that could be Single, Compound or Mixed. 53*0e209d39SAndroid Build Coastguard Worker * In case of: 54*0e209d39SAndroid Build Coastguard Worker * 1- Single and Compound units, 55*0e209d39SAndroid Build Coastguard Worker * the conversion will not perform anything, the input will be equal to the output. 56*0e209d39SAndroid Build Coastguard Worker * 2- Mixed Unit 57*0e209d39SAndroid Build Coastguard Worker * the conversion will consider the input is the biggest unit. And will convert it to be spread 58*0e209d39SAndroid Build Coastguard Worker * through the target units. For example: if target unit is "inch-and-foot", and the input is 2.5. 59*0e209d39SAndroid Build Coastguard Worker * The converter will consider the input value in "foot", because foot is the biggest unit. 60*0e209d39SAndroid Build Coastguard Worker * Then, it will convert 2.5 feet to "inch-and-foot". 61*0e209d39SAndroid Build Coastguard Worker * 62*0e209d39SAndroid Build Coastguard Worker * @param targetUnit could be any units type (single, compound or mixed). 63*0e209d39SAndroid Build Coastguard Worker * @param ratesInfo 64*0e209d39SAndroid Build Coastguard Worker * @param status 65*0e209d39SAndroid Build Coastguard Worker */ 66*0e209d39SAndroid Build Coastguard Worker ComplexUnitsConverter(const MeasureUnitImpl &targetUnit, const ConversionRates &ratesInfo, 67*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 68*0e209d39SAndroid Build Coastguard Worker /** 69*0e209d39SAndroid Build Coastguard Worker * Constructor of `ComplexUnitsConverter`. 70*0e209d39SAndroid Build Coastguard Worker * NOTE: 71*0e209d39SAndroid Build Coastguard Worker * - inputUnit and outputUnits must be under the same category 72*0e209d39SAndroid Build Coastguard Worker * - e.g. meter to feet and inches --> all of them are length units. 73*0e209d39SAndroid Build Coastguard Worker * 74*0e209d39SAndroid Build Coastguard Worker * @param inputUnit represents the source unit. (should be single or compound unit). 75*0e209d39SAndroid Build Coastguard Worker * @param outputUnits represents the output unit. could be any type. (single, compound or mixed). 76*0e209d39SAndroid Build Coastguard Worker * @param status 77*0e209d39SAndroid Build Coastguard Worker */ 78*0e209d39SAndroid Build Coastguard Worker ComplexUnitsConverter(StringPiece inputUnitIdentifier, StringPiece outputUnitsIdentifier, 79*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 80*0e209d39SAndroid Build Coastguard Worker 81*0e209d39SAndroid Build Coastguard Worker /** 82*0e209d39SAndroid Build Coastguard Worker * Constructor of `ComplexUnitsConverter`. 83*0e209d39SAndroid Build Coastguard Worker * NOTE: 84*0e209d39SAndroid Build Coastguard Worker * - inputUnit and outputUnits must be under the same category 85*0e209d39SAndroid Build Coastguard Worker * - e.g. meter to feet and inches --> all of them are length units. 86*0e209d39SAndroid Build Coastguard Worker * 87*0e209d39SAndroid Build Coastguard Worker * @param inputUnit represents the source unit. (should be single or compound unit). 88*0e209d39SAndroid Build Coastguard Worker * @param outputUnits represents the output unit. could be any type. (single, compound or mixed). 89*0e209d39SAndroid Build Coastguard Worker * @param ratesInfo a ConversionRates instance containing the unit conversion rates. 90*0e209d39SAndroid Build Coastguard Worker * @param status 91*0e209d39SAndroid Build Coastguard Worker */ 92*0e209d39SAndroid Build Coastguard Worker ComplexUnitsConverter(const MeasureUnitImpl &inputUnit, const MeasureUnitImpl &outputUnits, 93*0e209d39SAndroid Build Coastguard Worker const ConversionRates &ratesInfo, UErrorCode &status); 94*0e209d39SAndroid Build Coastguard Worker 95*0e209d39SAndroid Build Coastguard Worker // Returns true if the specified `quantity` of the `inputUnit`, expressed in terms of the biggest 96*0e209d39SAndroid Build Coastguard Worker // unit in the MeasureUnit `outputUnit`, is greater than or equal to `limit`. 97*0e209d39SAndroid Build Coastguard Worker // For example, if the input unit is `meter` and the target unit is `foot+inch`. Therefore, this 98*0e209d39SAndroid Build Coastguard Worker // function will convert the `quantity` from `meter` to `foot`, then, it will compare the value in 99*0e209d39SAndroid Build Coastguard Worker // `foot` with the `limit`. 100*0e209d39SAndroid Build Coastguard Worker UBool greaterThanOrEqual(double quantity, double limit) const; 101*0e209d39SAndroid Build Coastguard Worker 102*0e209d39SAndroid Build Coastguard Worker // Returns outputMeasures which is an array with the corresponding values. 103*0e209d39SAndroid Build Coastguard Worker // - E.g. converting meters to feet and inches. 104*0e209d39SAndroid Build Coastguard Worker // 1 meter --> 3 feet, 3.3701 inches 105*0e209d39SAndroid Build Coastguard Worker // NOTE: 106*0e209d39SAndroid Build Coastguard Worker // the smallest element is the only element that could have fractional values. And all 107*0e209d39SAndroid Build Coastguard Worker // other elements are floored to the nearest integer 108*0e209d39SAndroid Build Coastguard Worker MaybeStackVector<Measure> 109*0e209d39SAndroid Build Coastguard Worker convert(double quantity, icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const; 110*0e209d39SAndroid Build Coastguard Worker 111*0e209d39SAndroid Build Coastguard Worker // TODO(ICU-21937): Make it private after submitting the public units conversion API. 112*0e209d39SAndroid Build Coastguard Worker MaybeStackVector<UnitsConverter> unitsConverters_; 113*0e209d39SAndroid Build Coastguard Worker 114*0e209d39SAndroid Build Coastguard Worker // TODO(ICU-21937): Make it private after submitting the public units conversion API. 115*0e209d39SAndroid Build Coastguard Worker // Individual units of mixed units, sorted big to small, with indices 116*0e209d39SAndroid Build Coastguard Worker // indicating the requested output mixed unit order. 117*0e209d39SAndroid Build Coastguard Worker MaybeStackVector<MeasureUnitImplWithIndex> units_; 118*0e209d39SAndroid Build Coastguard Worker 119*0e209d39SAndroid Build Coastguard Worker private: 120*0e209d39SAndroid Build Coastguard Worker // Sorts units_, which must be populated before calling this, and populates 121*0e209d39SAndroid Build Coastguard Worker // unitsConverters_. 122*0e209d39SAndroid Build Coastguard Worker void init(const MeasureUnitImpl &inputUnit, const ConversionRates &ratesInfo, UErrorCode &status); 123*0e209d39SAndroid Build Coastguard Worker 124*0e209d39SAndroid Build Coastguard Worker // Applies the rounder to the quantity (last element) and bubble up any carried value to all the 125*0e209d39SAndroid Build Coastguard Worker // intValues. 126*0e209d39SAndroid Build Coastguard Worker // TODO(ICU-21288): get smarter about precision for mixed units. 127*0e209d39SAndroid Build Coastguard Worker void applyRounder(MaybeStackArray<int64_t, 5> &intValues, double &quantity, 128*0e209d39SAndroid Build Coastguard Worker icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const; 129*0e209d39SAndroid Build Coastguard Worker }; 130*0e209d39SAndroid Build Coastguard Worker 131*0e209d39SAndroid Build Coastguard Worker } // namespace units 132*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END 133*0e209d39SAndroid Build Coastguard Worker 134*0e209d39SAndroid Build Coastguard Worker #endif //__UNITS_COMPLEXCONVERTER_H__ 135*0e209d39SAndroid Build Coastguard Worker 136*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */ 137