xref: /aosp_15_r20/external/icu/libicu/cts_headers/units_complexconverter.h (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
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