tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

units_converter.h (9235B)


      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 "fixedstring.h"
     12 #include "measunit_impl.h"
     13 #include "unicode/errorcode.h"
     14 #include "unicode/stringpiece.h"
     15 #include "unicode/uobject.h"
     16 #include "units_converter.h"
     17 #include "units_data.h"
     18 
     19 U_NAMESPACE_BEGIN
     20 namespace units {
     21 
     22 /* Internal Structure */
     23 
     24 // Constants corresponding to unitConstants in CLDR's units.xml.
     25 enum Constants {
     26    CONSTANT_FT2M,       // ft_to_m
     27    CONSTANT_PI,         // PI
     28    CONSTANT_GRAVITY,    // Gravity of earth (9.80665 m/s^2), "g".
     29    CONSTANT_G,          // Newtonian constant of gravitation, "G".
     30    CONSTANT_GAL_IMP2M3, // Gallon imp to m3
     31    CONSTANT_LB2KG,      // Pound to Kilogram
     32    CONSTANT_GLUCOSE_MOLAR_MASS,
     33    CONSTANT_ITEM_PER_MOLE,
     34    CONSTANT_METERS_PER_AU,
     35    CONSTANT_SEC_PER_JULIAN_YEAR,
     36    CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND,
     37    CONSTANT_SHO_TO_M3,   // https://en.wikipedia.org/wiki/Japanese_units_of_measurement
     38    CONSTANT_TSUBO_TO_M2, // https://en.wikipedia.org/wiki/Japanese_units_of_measurement
     39    CONSTANT_SHAKU_TO_M,  // https://en.wikipedia.org/wiki/Japanese_units_of_measurement
     40    CONSTANT_AMU,         // Atomic Mass Unit https://www.nist.gov/pml/special-publication-811/nist-guide-si-chapter-5-units-outside-si#table7
     41 
     42    // Must be the last element.
     43    CONSTANTS_COUNT
     44 };
     45 
     46 // These values are a hard-coded subset of unitConstants in the units
     47 // resources file. A unit test checks that all constants in the resource
     48 // file are at least recognised by the code. Derived constants' values or
     49 // hard-coded derivations are not checked.
     50 // In ICU4J, these constants live in UnitConverter.Factor.getConversionRate().
     51 static const double constantsValues[CONSTANTS_COUNT] = {
     52    0.3048,                    // CONSTANT_FT2M
     53    411557987.0 / 131002976.0, // CONSTANT_PI
     54    9.80665,                   // CONSTANT_GRAVITY
     55    6.67408E-11,               // CONSTANT_G
     56    0.00454609,                // CONSTANT_GAL_IMP2M3
     57    0.45359237,                // CONSTANT_LB2KG
     58    180.1557,                  // CONSTANT_GLUCOSE_MOLAR_MASS
     59    6.02214076E+23,            // CONSTANT_ITEM_PER_MOLE
     60    149597870700,              // CONSTANT_METERS_PER_AU
     61    31557600,                  // CONSTANT_SEC_PER_JULIAN_YEAR
     62    299792458,                 // CONSTANT_SPEED_OF_LIGHT_METERS_PER_SECOND
     63    2401.0 / (1331.0 * 1000.0),
     64    400.0 / 121.0,
     65    4.0 / 121.0,
     66    1.66053878283E-27,         // CONSTANT_AMU
     67 };
     68 
     69 typedef enum Signum {
     70    NEGATIVE = -1,
     71    POSITIVE = 1,
     72 } Signum;
     73 
     74 /* Represents a conversion factor */
     75 struct U_I18N_API_CLASS Factor {
     76    double factorNum = 1;
     77    double factorDen = 1;
     78    double offset = 0;
     79    bool reciprocal = false;
     80 
     81    // Exponents for the symbolic constants
     82    int32_t constantExponents[CONSTANTS_COUNT] = {};
     83 
     84    void multiplyBy(const Factor &rhs);
     85    void divideBy(const Factor &rhs);
     86    void divideBy(const uint64_t constant);
     87 
     88    // Apply the power to the factor.
     89    void power(int32_t power);
     90 
     91    // Apply SI or binary prefix to the Factor.
     92    void applyPrefix(UMeasurePrefix unitPrefix);
     93 
     94    // Does an in-place substitution of the "symbolic constants" based on
     95    // constantExponents (resetting the exponents).
     96    //
     97    // In ICU4J, see UnitConverter.Factor.getConversionRate().
     98    U_I18N_API void substituteConstants();
     99 };
    100 
    101 struct ConversionInfo {
    102    double conversionRate;
    103    double offset;
    104    bool reciprocal;
    105 };
    106 
    107 /*
    108 * Adds a single factor element to the `Factor`. e.g "ft3m", "2.333" or "cup2m3". But not "cup2m3^3".
    109 */
    110 void U_I18N_API addSingleFactorConstant(StringPiece baseStr, int32_t power, Signum sigNum,
    111                                        Factor &factor, UErrorCode &status);
    112 
    113 /**
    114 * Represents the conversion rate between `source` and `target`.
    115 * TODO ICU-22683: COnsider moving the handling of special mappings (e.g. beaufort) to a separate
    116 * struct.
    117 */
    118 struct ConversionRate : public UMemory {
    119    const MeasureUnitImpl source;
    120    const MeasureUnitImpl target;
    121    FixedString specialSource;
    122    FixedString specialTarget;
    123    double factorNum = 1;
    124    double factorDen = 1;
    125    double sourceOffset = 0;
    126    double targetOffset = 0;
    127    bool reciprocal = false;
    128 
    129    ConversionRate(MeasureUnitImpl &&source, MeasureUnitImpl &&target)
    130        : source(std::move(source)), target(std::move(target)), specialSource(), specialTarget() {}
    131 };
    132 
    133 enum Convertibility {
    134    RECIPROCAL,
    135    CONVERTIBLE,
    136    UNCONVERTIBLE,
    137 };
    138 
    139 MeasureUnitImpl extractCompoundBaseUnit(const MeasureUnitImpl& source,
    140                                        const ConversionRates& conversionRates,
    141                                        UErrorCode& status);
    142 
    143 /**
    144 * Check if the convertibility between `source` and `target`.
    145 * For example:
    146 *    `meter` and `foot` are `CONVERTIBLE`.
    147 *    `meter-per-second` and `second-per-meter` are `RECIPROCAL`.
    148 *    `meter` and `pound` are `UNCONVERTIBLE`.
    149 *
    150 * NOTE:
    151 *    Only works with SINGLE and COMPOUND units. If one of the units is a
    152 *    MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity.
    153 */
    154 Convertibility U_I18N_API extractConvertibility(const MeasureUnitImpl &source,
    155                                                const MeasureUnitImpl &target,
    156                                                const ConversionRates &conversionRates,
    157                                                UErrorCode &status);
    158 
    159 /**
    160 * Converts from a source `MeasureUnit` to a target `MeasureUnit`.
    161 *
    162 * NOTE:
    163 *    Only works with SINGLE and COMPOUND units. If one of the units is a
    164 *    MIXED unit, an error will occur. For more information, see UMeasureUnitComplexity.
    165 */
    166 class U_I18N_API_CLASS UnitsConverter : public UMemory {
    167  public:
    168    /**
    169     * Constructor of `UnitConverter`.
    170     * NOTE:
    171     *   - source and target must be under the same category
    172     *      - e.g. meter to mile --> both of them are length units.
    173     * NOTE:
    174     *    This constructor creates an instance of `ConversionRates` internally.
    175     *
    176     * @param sourceIdentifier represents the source unit identifier.
    177     * @param targetIdentifier represents the target unit identifier.
    178     * @param status
    179     */
    180    U_I18N_API UnitsConverter(StringPiece sourceIdentifier, StringPiece targetIdentifier,
    181                              UErrorCode &status);
    182 
    183    /**
    184     * Constructor of `UnitConverter`.
    185     * NOTE:
    186     *   - source and target must be under the same category
    187     *      - e.g. meter to mile --> both of them are length units.
    188     *
    189     * @param source represents the source unit.
    190     * @param target represents the target unit.
    191     * @param ratesInfo Contains all the needed conversion rates.
    192     * @param status
    193     */
    194    U_I18N_API UnitsConverter(const MeasureUnitImpl &source, const MeasureUnitImpl &target,
    195                              const ConversionRates &ratesInfo, UErrorCode &status);
    196 
    197    /**
    198     * Compares two single units and returns 1 if the first one is greater, -1 if the second
    199     * one is greater and 0 if they are equal.
    200     *
    201     * NOTE:
    202     *  Compares only single units that are convertible.
    203     */
    204    static int32_t compareTwoUnits(const MeasureUnitImpl &firstUnit, const MeasureUnitImpl &SecondUnit,
    205                                   const ConversionRates &ratesInfo, UErrorCode &status);
    206 
    207    /**
    208     * Convert a measurement expressed in the source unit to a measurement
    209     * expressed in the target unit.
    210     *
    211     * @param inputValue the value to be converted.
    212     * @return the converted value.
    213     */
    214    U_I18N_API double convert(double inputValue) const;
    215 
    216    /**
    217     * The inverse of convert(): convert a measurement expressed in the target
    218     * unit to a measurement expressed in the source unit.
    219     *
    220     * @param inputValue the value to be converted.
    221     * @return the converted value.
    222     */
    223    U_I18N_API double convertInverse(double inputValue) const;
    224 
    225    U_I18N_API ConversionInfo getConversionInfo() const;
    226 
    227  private:
    228    ConversionRate conversionRate_;
    229 
    230    /**
    231     * Initialises the object.
    232     */
    233    void init(const ConversionRates &ratesInfo, UErrorCode &status);
    234 
    235    /**
    236     * Convert from what should be discrete scale values for a particular unit like beaufort
    237     * to a corresponding value in the base unit (which can have any decimal value, like meters/sec).
    238     * This can handle different scales, specified by minBaseForScaleValues[].
    239     */
    240    double scaleToBase(double scaleValue, double minBaseForScaleValues[], int scaleMax) const;
    241 
    242    /**
    243     * Convert from a value in the base unit (which can have any decimal value, like meters/sec) to a corresponding
    244     * discrete value in a scale (like beaufort), where each scale value represents a range of base values.
    245     * This can handle different scales, specified by minBaseForScaleValues[].
    246     */
    247    double baseToScale(double baseValue, double minBaseForScaleValues[], int scaleMax) const;
    248 
    249 };
    250 
    251 } // namespace units
    252 U_NAMESPACE_END
    253 
    254 #endif //__UNITS_CONVERTER_H__
    255 
    256 #endif /* #if !UCONFIG_NO_FORMATTING */