/src/icu/source/i18n/units_converter.h
Line | Count | Source (jump to first uncovered line) |
1 | | // © 2020 and later: Unicode, Inc. and others. |
2 | | // License & terms of use: http://www.unicode.org/copyright.html |
3 | | |
4 | | #include "unicode/utypes.h" |
5 | | |
6 | | #if !UCONFIG_NO_FORMATTING |
7 | | #ifndef __UNITS_CONVERTER_H__ |
8 | | #define __UNITS_CONVERTER_H__ |
9 | | |
10 | | #include "cmemory.h" |
11 | | #include "measunit_impl.h" |
12 | | #include "unicode/errorcode.h" |
13 | | #include "unicode/stringpiece.h" |
14 | | #include "unicode/uobject.h" |
15 | | #include "units_converter.h" |
16 | | #include "units_data.h" |
17 | | |
18 | | U_NAMESPACE_BEGIN |
19 | | namespace units { |
20 | | |
21 | | /* Internal Structure */ |
22 | | |
23 | | // Constants corresponding to unitConstants in CLDR's units.xml. |
24 | | enum Constants { |
25 | | CONSTANT_FT2M, // ft_to_m |
26 | | CONSTANT_PI, // PI |
27 | | CONSTANT_GRAVITY, // Gravity of earth (9.80665 m/s^2), "g". |
28 | | CONSTANT_G, // Newtonian constant of gravitation, "G". |
29 | | CONSTANT_GAL_IMP2M3, // Gallon imp to m3 |
30 | | CONSTANT_LB2KG, // Pound to Kilogram |
31 | | CONSTANT_GLUCOSE_MOLAR_MASS, |
32 | | CONSTANT_ITEM_PER_MOLE, |
33 | | |
34 | | // Must be the last element. |
35 | | CONSTANTS_COUNT |
36 | | }; |
37 | | |
38 | | // These values are a hard-coded subset of unitConstants in the units |
39 | | // resources file. A unit test checks that all constants in the resource |
40 | | // file are at least recognised by the code. Derived constants' values or |
41 | | // hard-coded derivations are not checked. |
42 | | // In ICU4J, these constants live in UnitConverter.Factor.getConversionRate(). |
43 | | static const double constantsValues[CONSTANTS_COUNT] = { |
44 | | 0.3048, // CONSTANT_FT2M |
45 | | 411557987.0 / 131002976.0, // CONSTANT_PI |
46 | | 9.80665, // CONSTANT_GRAVITY |
47 | | 6.67408E-11, // CONSTANT_G |
48 | | 0.00454609, // CONSTANT_GAL_IMP2M3 |
49 | | 0.45359237, // CONSTANT_LB2KG |
50 | | 180.1557, // CONSTANT_GLUCOSE_MOLAR_MASS |
51 | | 6.02214076E+23, // CONSTANT_ITEM_PER_MOLE |
52 | | }; |
53 | | |
54 | | typedef enum Signum { |
55 | | NEGATIVE = -1, |
56 | | POSITIVE = 1, |
57 | | } Signum; |
58 | | |
59 | | /* Represents a conversion factor */ |
60 | | struct U_I18N_API Factor { |
61 | | double factorNum = 1; |
62 | | double factorDen = 1; |
63 | | double offset = 0; |
64 | | bool reciprocal = false; |
65 | | |
66 | | // Exponents for the symbolic constants |
67 | | int32_t constantExponents[CONSTANTS_COUNT] = {}; |
68 | | |
69 | | void multiplyBy(const Factor &rhs); |
70 | | void divideBy(const Factor &rhs); |
71 | | |
72 | | // Apply the power to the factor. |
73 | | void power(int32_t power); |
74 | | |
75 | | // Apply SI or binary prefix to the Factor. |
76 | | void applyPrefix(UMeasurePrefix unitPrefix); |
77 | | |
78 | | // Does an in-place substitution of the "symbolic constants" based on |
79 | | // constantExponents (resetting the exponents). |
80 | | // |
81 | | // In ICU4J, see UnitConverter.Factor.getConversionRate(). |
82 | | void substituteConstants(); |
83 | | }; |
84 | | |
85 | | struct U_I18N_API ConversionInfo { |
86 | | double conversionRate; |
87 | | double offset; |
88 | | bool reciprocal; |
89 | | }; |
90 | | |
91 | | /* |
92 | | * Adds a single factor element to the `Factor`. e.g "ft3m", "2.333" or "cup2m3". But not "cup2m3^3". |
93 | | */ |
94 | | void U_I18N_API addSingleFactorConstant(StringPiece baseStr, int32_t power, Signum sigNum, |
95 | | Factor &factor, UErrorCode &status); |
96 | | |
97 | | /** |
98 | | * Represents the conversion rate between `source` and `target`. |
99 | | */ |
100 | | struct U_I18N_API ConversionRate : public UMemory { |
101 | | const MeasureUnitImpl source; |
102 | | const MeasureUnitImpl target; |
103 | | double factorNum = 1; |
104 | | double factorDen = 1; |
105 | | double sourceOffset = 0; |
106 | | double targetOffset = 0; |
107 | | bool reciprocal = false; |
108 | | |
109 | | ConversionRate(MeasureUnitImpl &&source, MeasureUnitImpl &&target) |
110 | 0 | : source(std::move(source)), target(std::move(target)) {} |
111 | | }; |
112 | | |
113 | | enum Convertibility { |
114 | | RECIPROCAL, |
115 | | CONVERTIBLE, |
116 | | UNCONVERTIBLE, |
117 | | }; |
118 | | |
119 | | MeasureUnitImpl U_I18N_API extractCompoundBaseUnit(const MeasureUnitImpl &source, |
120 | | const ConversionRates &conversionRates, |
121 | | UErrorCode &status); |
122 | | |
123 | | /** |
124 | | * Check if the convertibility between `source` and `target`. |
125 | | * For example: |
126 | | * `meter` and `foot` are `CONVERTIBLE`. |
127 | | * `meter-per-second` and `second-per-meter` are `RECIPROCAL`. |
128 | | * `meter` and `pound` are `UNCONVERTIBLE`. |
129 | | * |
130 | | * NOTE: |
131 | | * Only works with SINGLE and COMPOUND units. If one of the units is a |
132 | | * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity. |
133 | | */ |
134 | | Convertibility U_I18N_API extractConvertibility(const MeasureUnitImpl &source, |
135 | | const MeasureUnitImpl &target, |
136 | | const ConversionRates &conversionRates, |
137 | | UErrorCode &status); |
138 | | |
139 | | /** |
140 | | * Converts from a source `MeasureUnit` to a target `MeasureUnit`. |
141 | | * |
142 | | * NOTE: |
143 | | * Only works with SINGLE and COMPOUND units. If one of the units is a |
144 | | * MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity. |
145 | | */ |
146 | | class U_I18N_API UnitsConverter : public UMemory { |
147 | | public: |
148 | | /** |
149 | | * Constructor of `UnitConverter`. |
150 | | * NOTE: |
151 | | * - source and target must be under the same category |
152 | | * - e.g. meter to mile --> both of them are length units. |
153 | | * NOTE: |
154 | | * This constructor creates an instance of `ConversionRates` internally. |
155 | | * |
156 | | * @param sourceIdentifier represents the source unit identifier. |
157 | | * @param targetIdentifier represents the target unit identifier. |
158 | | * @param status |
159 | | */ |
160 | | UnitsConverter(StringPiece sourceIdentifier, StringPiece targetIdentifier, UErrorCode &status); |
161 | | |
162 | | /** |
163 | | * Constructor of `UnitConverter`. |
164 | | * NOTE: |
165 | | * - source and target must be under the same category |
166 | | * - e.g. meter to mile --> both of them are length units. |
167 | | * |
168 | | * @param source represents the source unit. |
169 | | * @param target represents the target unit. |
170 | | * @param ratesInfo Contains all the needed conversion rates. |
171 | | * @param status |
172 | | */ |
173 | | UnitsConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target, |
174 | | const ConversionRates &ratesInfo, UErrorCode &status); |
175 | | |
176 | | /** |
177 | | * Compares two single units and returns 1 if the first one is greater, -1 if the second |
178 | | * one is greater and 0 if they are equal. |
179 | | * |
180 | | * NOTE: |
181 | | * Compares only single units that are convertible. |
182 | | */ |
183 | | static int32_t compareTwoUnits(const MeasureUnitImpl &firstUnit, const MeasureUnitImpl &SecondUnit, |
184 | | const ConversionRates &ratesInfo, UErrorCode &status); |
185 | | |
186 | | /** |
187 | | * Convert a measurement expressed in the source unit to a measurement |
188 | | * expressed in the target unit. |
189 | | * |
190 | | * @param inputValue the value to be converted. |
191 | | * @return the converted value. |
192 | | */ |
193 | | double convert(double inputValue) const; |
194 | | |
195 | | /** |
196 | | * The inverse of convert(): convert a measurement expressed in the target |
197 | | * unit to a measurement expressed in the source unit. |
198 | | * |
199 | | * @param inputValue the value to be converted. |
200 | | * @return the converted value. |
201 | | */ |
202 | | double convertInverse(double inputValue) const; |
203 | | |
204 | | ConversionInfo getConversionInfo() const; |
205 | | |
206 | | private: |
207 | | ConversionRate conversionRate_; |
208 | | |
209 | | /** |
210 | | * Initialises the object. |
211 | | */ |
212 | | void init(const ConversionRates &ratesInfo, UErrorCode &status); |
213 | | }; |
214 | | |
215 | | } // namespace units |
216 | | U_NAMESPACE_END |
217 | | |
218 | | #endif //__UNITS_CONVERTER_H__ |
219 | | |
220 | | #endif /* #if !UCONFIG_NO_FORMATTING */ |