1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
// © 2020 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
#include <_foundation_unicode/utypes.h>
#if !UCONFIG_NO_FORMATTING
#ifndef __UNITS_CONVERTER_H__
#define __UNITS_CONVERTER_H__
#include "cmemory.h"
#include "measunit_impl.h"
#include <_foundation_unicode/errorcode.h>
#include <_foundation_unicode/stringpiece.h>
#include <_foundation_unicode/uobject.h>
#include "units_converter.h"
#include "units_data.h"
U_NAMESPACE_BEGIN
namespace units {
/* Internal Structure */
// Constants corresponding to unitConstants in CLDR's units.xml.
enum Constants {
CONSTANT_FT2M, // ft_to_m
CONSTANT_PI, // PI
CONSTANT_GRAVITY, // Gravity of earth (9.80665 m/s^2), "g".
CONSTANT_G, // Newtonian constant of gravitation, "G".
CONSTANT_GAL_IMP2M3, // Gallon imp to m3
CONSTANT_LB2KG, // Pound to Kilogram
CONSTANT_GLUCOSE_MOLAR_MASS,
CONSTANT_ITEM_PER_MOLE,
CONSTANT_METERS_PER_AU,
CONSTANT_SEC_PER_JULIAN_YEAR,
CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND,
CONSTANT_SHO_TO_M3, // https://en.wikipedia.org/wiki/Japanese_units_of_measurement
CONSTANT_TSUBO_TO_M2, // https://en.wikipedia.org/wiki/Japanese_units_of_measurement
CONSTANT_SHAKU_TO_M, // https://en.wikipedia.org/wiki/Japanese_units_of_measurement
CONSTANT_AMU, // Atomic Mass Unit https://www.nist.gov/pml/special-publication-811/nist-guide-si-chapter-5-units-outside-si#table7
// 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.
// In ICU4J, these constants live in UnitConverter.Factor.getConversionRate().
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
180.1557, // CONSTANT_GLUCOSE_MOLAR_MASS
6.02214076E+23, // CONSTANT_ITEM_PER_MOLE
149597870700, // CONSTANT_METERS_PER_AU
31557600, // CONSTANT_SEC_PER_JULIAN_YEAR
299792458, // CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND
2401.0 / (1331.0 * 1000.0),
400.0 / 121.0,
4.0 / 121.0,
1.66053878283E-27, // CONSTANT_AMU
};
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;
// Exponents for the symbolic constants
int32_t constantExponents[CONSTANTS_COUNT] = {};
void multiplyBy(const Factor &rhs);
void divideBy(const Factor &rhs);
// Apply the power to the factor.
void power(int32_t power);
// Apply SI or binary prefix to the Factor.
void applyPrefix(UMeasurePrefix unitPrefix);
// Does an in-place substitution of the "symbolic constants" based on
// constantExponents (resetting the exponents).
//
// In ICU4J, see UnitConverter.Factor.getConversionRate().
void substituteConstants();
};
struct U_I18N_API ConversionInfo {
double conversionRate;
double offset;
bool reciprocal;
};
/*
* 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 UnitsConverter : 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.
* NOTE:
* This constructor creates an instance of `ConversionRates` internally.
*
* @param sourceIdentifier represents the source unit identifier.
* @param targetIdentifier represents the target unit identifier.
* @param status
*/
UnitsConverter(StringPiece sourceIdentifier, StringPiece targetIdentifier, UErrorCode &status);
/**
* 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
*/
UnitsConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target,
const ConversionRates &ratesInfo, UErrorCode &status);
/**
* Compares two single units and returns 1 if the first one is greater, -1 if the second
* one is greater and 0 if they are equal.
*
* NOTE:
* Compares only single units that are convertible.
*/
static int32_t compareTwoUnits(const MeasureUnitImpl &firstUnit, const MeasureUnitImpl &SecondUnit,
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;
ConversionInfo getConversionInfo() const;
private:
ConversionRate conversionRate_;
/**
* Initialises the object.
*/
void init(const ConversionRates &ratesInfo, UErrorCode &status);
};
} // namespace units
U_NAMESPACE_END
#endif //__UNITS_CONVERTER_H__
#endif /* #if !UCONFIG_NO_FORMATTING */
|