diff options
author | mcheshkov <mcheshkov@yandex-team.ru> | 2022-02-10 16:46:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:15 +0300 |
commit | e9d19cec64684c9c1e6b0c98297e5b895cf904fe (patch) | |
tree | 2768b1223e96a8a0610a93d18425d9647c1123c8 /contrib/libs/icu/i18n/number_roundingutils.h | |
parent | 60040c91ffe701a84689b2c6310ff845e65cff42 (diff) | |
download | ydb-e9d19cec64684c9c1e6b0c98297e5b895cf904fe.tar.gz |
Restoring authorship annotation for <mcheshkov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/icu/i18n/number_roundingutils.h')
-rw-r--r-- | contrib/libs/icu/i18n/number_roundingutils.h | 398 |
1 files changed, 199 insertions, 199 deletions
diff --git a/contrib/libs/icu/i18n/number_roundingutils.h b/contrib/libs/icu/i18n/number_roundingutils.h index 3e37f31954..1a13504b89 100644 --- a/contrib/libs/icu/i18n/number_roundingutils.h +++ b/contrib/libs/icu/i18n/number_roundingutils.h @@ -1,199 +1,199 @@ -// © 2017 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING -#ifndef __NUMBER_ROUNDINGUTILS_H__ -#define __NUMBER_ROUNDINGUTILS_H__ - -#include "number_types.h" - -U_NAMESPACE_BEGIN -namespace number { -namespace impl { -namespace roundingutils { - -enum Section { - SECTION_LOWER_EDGE = -1, - SECTION_UPPER_EDGE = -2, - SECTION_LOWER = 1, - SECTION_MIDPOINT = 2, - SECTION_UPPER = 3 -}; - -/** - * Converts a rounding mode and metadata about the quantity being rounded to a boolean determining - * whether the value should be rounded toward infinity or toward zero. - * - * <p>The parameters are of type int because benchmarks on an x86-64 processor against OpenJDK - * showed that ints were demonstrably faster than enums in switch statements. - * - * @param isEven Whether the digit immediately before the rounding magnitude is even. - * @param isNegative Whether the quantity is negative. - * @param section Whether the part of the quantity to the right of the rounding magnitude is - * exactly halfway between two digits, whether it is in the lower part (closer to zero), or - * whether it is in the upper part (closer to infinity). See {@link #SECTION_LOWER}, {@link - * #SECTION_MIDPOINT}, and {@link #SECTION_UPPER}. - * @param roundingMode The integer version of the {@link RoundingMode}, which you can get via - * {@link RoundingMode#ordinal}. - * @param status Error code, set to U_FORMAT_INEXACT_ERROR if the rounding mode is kRoundUnnecessary. - * @return true if the number should be rounded toward zero; false if it should be rounded toward - * infinity. - */ -inline bool -getRoundingDirection(bool isEven, bool isNegative, Section section, RoundingMode roundingMode, - UErrorCode &status) { - switch (roundingMode) { - case RoundingMode::UNUM_ROUND_UP: - // round away from zero - return false; - - case RoundingMode::UNUM_ROUND_DOWN: - // round toward zero - return true; - - case RoundingMode::UNUM_ROUND_CEILING: - // round toward positive infinity - return isNegative; - - case RoundingMode::UNUM_ROUND_FLOOR: - // round toward negative infinity - return !isNegative; - - case RoundingMode::UNUM_ROUND_HALFUP: - switch (section) { - case SECTION_MIDPOINT: - return false; - case SECTION_LOWER: - return true; - case SECTION_UPPER: - return false; - default: - break; - } - break; - - case RoundingMode::UNUM_ROUND_HALFDOWN: - switch (section) { - case SECTION_MIDPOINT: - return true; - case SECTION_LOWER: - return true; - case SECTION_UPPER: - return false; - default: - break; - } - break; - - case RoundingMode::UNUM_ROUND_HALFEVEN: - switch (section) { - case SECTION_MIDPOINT: - return isEven; - case SECTION_LOWER: - return true; - case SECTION_UPPER: - return false; - default: - break; - } - break; - - default: - break; - } - - status = U_FORMAT_INEXACT_ERROR; - return false; -} - -/** - * Gets whether the given rounding mode's rounding boundary is at the midpoint. The rounding - * boundary is the point at which a number switches from being rounded down to being rounded up. - * For example, with rounding mode HALF_EVEN, HALF_UP, or HALF_DOWN, the rounding boundary is at - * the midpoint, and this function would return true. However, for UP, DOWN, CEILING, and FLOOR, - * the rounding boundary is at the "edge", and this function would return false. - * - * @param roundingMode The integer version of the {@link RoundingMode}. - * @return true if rounding mode is HALF_EVEN, HALF_UP, or HALF_DOWN; false otherwise. - */ -inline bool roundsAtMidpoint(int roundingMode) { - switch (roundingMode) { - case RoundingMode::UNUM_ROUND_UP: - case RoundingMode::UNUM_ROUND_DOWN: - case RoundingMode::UNUM_ROUND_CEILING: - case RoundingMode::UNUM_ROUND_FLOOR: - return false; - - default: - return true; - } -} - -/** - * Computes the number of fraction digits in a double. Used for computing maxFrac for an increment. - * Calls into the DoubleToStringConverter library to do so. - * - * @param singleDigit An output parameter; set to a number if that is the - * only digit in the double, or -1 if there is more than one digit. - */ -digits_t doubleFractionLength(double input, int8_t* singleDigit); - -} // namespace roundingutils - - -/** - * Encapsulates a Precision and a RoundingMode and performs rounding on a DecimalQuantity. - * - * This class does not exist in Java: instead, the base Precision class is used. - */ -class RoundingImpl { - public: - RoundingImpl() = default; // defaults to pass-through rounder - - RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode, - const CurrencyUnit& currency, UErrorCode& status); - - static RoundingImpl passThrough(); - - /** Required for ScientificFormatter */ - bool isSignificantDigits() const; - - /** - * Rounding endpoint used by Engineering and Compact notation. Chooses the most appropriate multiplier (magnitude - * adjustment), applies the adjustment, rounds, and returns the chosen multiplier. - * - * <p> - * In most cases, this is simple. However, when rounding the number causes it to cross a multiplier boundary, we - * need to re-do the rounding. For example, to display 999,999 in Engineering notation with 2 sigfigs, first you - * guess the multiplier to be -3. However, then you end up getting 1000E3, which is not the correct output. You then - * change your multiplier to be -6, and you get 1.0E6, which is correct. - * - * @param input The quantity to process. - * @param producer Function to call to return a multiplier based on a magnitude. - * @return The number of orders of magnitude the input was adjusted by this method. - */ - int32_t - chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, - UErrorCode &status); - - void apply(impl::DecimalQuantity &value, UErrorCode &status) const; - - /** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */ - void apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode status); - - private: - Precision fPrecision; - UNumberFormatRoundingMode fRoundingMode; - bool fPassThrough = true; // default value -}; - - -} // namespace impl -} // namespace number -U_NAMESPACE_END - -#endif //__NUMBER_ROUNDINGUTILS_H__ - -#endif /* #if !UCONFIG_NO_FORMATTING */ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#ifndef __NUMBER_ROUNDINGUTILS_H__ +#define __NUMBER_ROUNDINGUTILS_H__ + +#include "number_types.h" + +U_NAMESPACE_BEGIN +namespace number { +namespace impl { +namespace roundingutils { + +enum Section { + SECTION_LOWER_EDGE = -1, + SECTION_UPPER_EDGE = -2, + SECTION_LOWER = 1, + SECTION_MIDPOINT = 2, + SECTION_UPPER = 3 +}; + +/** + * Converts a rounding mode and metadata about the quantity being rounded to a boolean determining + * whether the value should be rounded toward infinity or toward zero. + * + * <p>The parameters are of type int because benchmarks on an x86-64 processor against OpenJDK + * showed that ints were demonstrably faster than enums in switch statements. + * + * @param isEven Whether the digit immediately before the rounding magnitude is even. + * @param isNegative Whether the quantity is negative. + * @param section Whether the part of the quantity to the right of the rounding magnitude is + * exactly halfway between two digits, whether it is in the lower part (closer to zero), or + * whether it is in the upper part (closer to infinity). See {@link #SECTION_LOWER}, {@link + * #SECTION_MIDPOINT}, and {@link #SECTION_UPPER}. + * @param roundingMode The integer version of the {@link RoundingMode}, which you can get via + * {@link RoundingMode#ordinal}. + * @param status Error code, set to U_FORMAT_INEXACT_ERROR if the rounding mode is kRoundUnnecessary. + * @return true if the number should be rounded toward zero; false if it should be rounded toward + * infinity. + */ +inline bool +getRoundingDirection(bool isEven, bool isNegative, Section section, RoundingMode roundingMode, + UErrorCode &status) { + switch (roundingMode) { + case RoundingMode::UNUM_ROUND_UP: + // round away from zero + return false; + + case RoundingMode::UNUM_ROUND_DOWN: + // round toward zero + return true; + + case RoundingMode::UNUM_ROUND_CEILING: + // round toward positive infinity + return isNegative; + + case RoundingMode::UNUM_ROUND_FLOOR: + // round toward negative infinity + return !isNegative; + + case RoundingMode::UNUM_ROUND_HALFUP: + switch (section) { + case SECTION_MIDPOINT: + return false; + case SECTION_LOWER: + return true; + case SECTION_UPPER: + return false; + default: + break; + } + break; + + case RoundingMode::UNUM_ROUND_HALFDOWN: + switch (section) { + case SECTION_MIDPOINT: + return true; + case SECTION_LOWER: + return true; + case SECTION_UPPER: + return false; + default: + break; + } + break; + + case RoundingMode::UNUM_ROUND_HALFEVEN: + switch (section) { + case SECTION_MIDPOINT: + return isEven; + case SECTION_LOWER: + return true; + case SECTION_UPPER: + return false; + default: + break; + } + break; + + default: + break; + } + + status = U_FORMAT_INEXACT_ERROR; + return false; +} + +/** + * Gets whether the given rounding mode's rounding boundary is at the midpoint. The rounding + * boundary is the point at which a number switches from being rounded down to being rounded up. + * For example, with rounding mode HALF_EVEN, HALF_UP, or HALF_DOWN, the rounding boundary is at + * the midpoint, and this function would return true. However, for UP, DOWN, CEILING, and FLOOR, + * the rounding boundary is at the "edge", and this function would return false. + * + * @param roundingMode The integer version of the {@link RoundingMode}. + * @return true if rounding mode is HALF_EVEN, HALF_UP, or HALF_DOWN; false otherwise. + */ +inline bool roundsAtMidpoint(int roundingMode) { + switch (roundingMode) { + case RoundingMode::UNUM_ROUND_UP: + case RoundingMode::UNUM_ROUND_DOWN: + case RoundingMode::UNUM_ROUND_CEILING: + case RoundingMode::UNUM_ROUND_FLOOR: + return false; + + default: + return true; + } +} + +/** + * Computes the number of fraction digits in a double. Used for computing maxFrac for an increment. + * Calls into the DoubleToStringConverter library to do so. + * + * @param singleDigit An output parameter; set to a number if that is the + * only digit in the double, or -1 if there is more than one digit. + */ +digits_t doubleFractionLength(double input, int8_t* singleDigit); + +} // namespace roundingutils + + +/** + * Encapsulates a Precision and a RoundingMode and performs rounding on a DecimalQuantity. + * + * This class does not exist in Java: instead, the base Precision class is used. + */ +class RoundingImpl { + public: + RoundingImpl() = default; // defaults to pass-through rounder + + RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode, + const CurrencyUnit& currency, UErrorCode& status); + + static RoundingImpl passThrough(); + + /** Required for ScientificFormatter */ + bool isSignificantDigits() const; + + /** + * Rounding endpoint used by Engineering and Compact notation. Chooses the most appropriate multiplier (magnitude + * adjustment), applies the adjustment, rounds, and returns the chosen multiplier. + * + * <p> + * In most cases, this is simple. However, when rounding the number causes it to cross a multiplier boundary, we + * need to re-do the rounding. For example, to display 999,999 in Engineering notation with 2 sigfigs, first you + * guess the multiplier to be -3. However, then you end up getting 1000E3, which is not the correct output. You then + * change your multiplier to be -6, and you get 1.0E6, which is correct. + * + * @param input The quantity to process. + * @param producer Function to call to return a multiplier based on a magnitude. + * @return The number of orders of magnitude the input was adjusted by this method. + */ + int32_t + chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, + UErrorCode &status); + + void apply(impl::DecimalQuantity &value, UErrorCode &status) const; + + /** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */ + void apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode status); + + private: + Precision fPrecision; + UNumberFormatRoundingMode fRoundingMode; + bool fPassThrough = true; // default value +}; + + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif //__NUMBER_ROUNDINGUTILS_H__ + +#endif /* #if !UCONFIG_NO_FORMATTING */ |