summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp
diff options
context:
space:
mode:
authorDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
committerDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
commitc6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch)
tree1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp
parent07ee7222e389b0777456b427a55c22d0e6ffd267 (diff)
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp')
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp253
1 files changed, 0 insertions, 253 deletions
diff --git a/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp b/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp
deleted file mode 100644
index 27f835e6dd4..00000000000
--- a/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-// © 2020 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-
-#include "unicode/utypes.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-#include <cmath>
-
-#include "cmemory.h"
-#include "number_decimalquantity.h"
-#include "number_roundingutils.h"
-#include "uarrsort.h"
-#include "uassert.h"
-#include "unicode/fmtable.h"
-#include "unicode/localpointer.h"
-#include "unicode/measunit.h"
-#include "unicode/measure.h"
-#include "units_complexconverter.h"
-#include "units_converter.h"
-
-U_NAMESPACE_BEGIN
-namespace units {
-
-ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnitImpl &inputUnit,
- const MeasureUnitImpl &outputUnits,
- const ConversionRates &ratesInfo, UErrorCode &status)
- : units_(outputUnits.extractIndividualUnits(status)) {
- if (U_FAILURE(status)) {
- return;
- }
-
- U_ASSERT(units_.length() != 0);
-
- // Save the desired order of output units before we sort units_
- for (int32_t i = 0; i < units_.length(); i++) {
- outputUnits_.emplaceBackAndCheckErrorCode(status, units_[i]->copy(status).build(status));
- }
-
- // NOTE:
- // This comparator is used to sort the units in a descending order. Therefore, we return -1 if
- // the left is bigger than right and so on.
- auto descendingCompareUnits = [](const void *context, const void *left, const void *right) {
- UErrorCode status = U_ZERO_ERROR;
-
- const auto *leftPointer = static_cast<const MeasureUnitImpl *const *>(left);
- const auto *rightPointer = static_cast<const MeasureUnitImpl *const *>(right);
-
- UnitConverter fromLeftToRight(**leftPointer, //
- **rightPointer, //
- *static_cast<const ConversionRates *>(context), //
- status);
-
- double rightFromOneLeft = fromLeftToRight.convert(1.0);
- if (std::abs(rightFromOneLeft - 1.0) < 0.0000000001) { // Equals To
- return 0;
- } else if (rightFromOneLeft > 1.0) { // Greater Than
- return -1;
- }
-
- return 1; // Less Than
- };
-
- uprv_sortArray(units_.getAlias(), //
- units_.length(), //
- sizeof units_[0], /* NOTE: we have already asserted that the units_ is not empty.*/ //
- descendingCompareUnits, //
- &ratesInfo, //
- false, //
- &status //
- );
-
- // In case the `outputUnits` are `UMEASURE_UNIT_MIXED` such as `foot+inch`. In this case we need more
- // converters to convert from the `inputUnit` to the first unit in the `outputUnits`. Then, a
- // converter from the first unit in the `outputUnits` to the second unit and so on.
- // For Example:
- // - inputUnit is `meter`
- // - outputUnits is `foot+inch`
- // - Therefore, we need to have two converters:
- // 1. a converter from `meter` to `foot`
- // 2. a converter from `foot` to `inch`
- // - Therefore, if the input is `2 meter`:
- // 1. convert `meter` to `foot` --> 2 meter to 6.56168 feet
- // 2. convert the residual of 6.56168 feet (0.56168) to inches, which will be (6.74016
- // inches)
- // 3. then, the final result will be (6 feet and 6.74016 inches)
- for (int i = 0, n = units_.length(); i < n; i++) {
- if (i == 0) { // first element
- unitConverters_.emplaceBackAndCheckErrorCode(status, inputUnit, *units_[i], ratesInfo,
- status);
- } else {
- unitConverters_.emplaceBackAndCheckErrorCode(status, *units_[i - 1], *units_[i], ratesInfo,
- status);
- }
-
- if (U_FAILURE(status)) {
- return;
- }
- }
-}
-
-UBool ComplexUnitsConverter::greaterThanOrEqual(double quantity, double limit) const {
- U_ASSERT(unitConverters_.length() > 0);
-
- // First converter converts to the biggest quantity.
- double newQuantity = unitConverters_[0]->convert(quantity);
- return newQuantity >= limit;
-}
-
-MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity,
- icu::number::impl::RoundingImpl *rounder,
- UErrorCode &status) const {
- // TODO(hugovdm): return an error for "foot-and-foot"?
- MaybeStackVector<Measure> result;
- int sign = 1;
- if (quantity < 0) {
- quantity *= -1;
- sign = -1;
- }
-
- // For N converters:
- // - the first converter converts from the input unit to the largest unit,
- // - N-1 converters convert to bigger units for which we want integers,
- // - the Nth converter (index N-1) converts to the smallest unit, for which
- // we keep a double.
- MaybeStackArray<int64_t, 5> intValues(unitConverters_.length() - 1, status);
- if (U_FAILURE(status)) {
- return result;
- }
- uprv_memset(intValues.getAlias(), 0, (unitConverters_.length() - 1) * sizeof(int64_t));
-
- for (int i = 0, n = unitConverters_.length(); i < n; ++i) {
- quantity = (*unitConverters_[i]).convert(quantity);
- if (i < n - 1) {
- // The double type has 15 decimal digits of precision. For choosing
- // whether to use the current unit or the next smaller unit, we
- // therefore nudge up the number with which the thresholding
- // decision is made. However after the thresholding, we use the
- // original values to ensure unbiased accuracy (to the extent of
- // double's capabilities).
- int64_t roundedQuantity = floor(quantity * (1 + DBL_EPSILON));
- intValues[i] = roundedQuantity;
-
- // Keep the residual of the quantity.
- // For example: `3.6 feet`, keep only `0.6 feet`
- //
- // When the calculation is near enough +/- DBL_EPSILON, we round to
- // zero. (We also ensure no negative values here.)
- if ((quantity - roundedQuantity) / quantity < DBL_EPSILON) {
- quantity = 0;
- } else {
- quantity -= roundedQuantity;
- }
- } else { // LAST ELEMENT
- if (rounder == nullptr) {
- // Nothing to do for the last element.
- break;
- }
-
- // Round the last value
- // TODO(ICU-21288): get smarter about precision for mixed units.
- number::impl::DecimalQuantity quant;
- quant.setToDouble(quantity);
- rounder->apply(quant, status);
- if (U_FAILURE(status)) {
- return result;
- }
- quantity = quant.toDouble();
- if (i == 0) {
- // Last element is also the first element, so we're done
- break;
- }
-
- // Check if there's a carry, and bubble it back up the resulting intValues.
- int64_t carry = floor(unitConverters_[i]->convertInverse(quantity) * (1 + DBL_EPSILON));
- if (carry <= 0) {
- break;
- }
- quantity -= unitConverters_[i]->convert(carry);
- intValues[i - 1] += carry;
-
- // We don't use the first converter: that one is for the input unit
- for (int32_t j = i - 1; j > 0; j--) {
- carry = floor(unitConverters_[j]->convertInverse(intValues[j]) * (1 + DBL_EPSILON));
- if (carry <= 0) {
- break;
- }
- intValues[j] -= round(unitConverters_[j]->convert(carry));
- intValues[j - 1] += carry;
- }
- }
- }
-
- // Package values into Measure instances in result:
- for (int i = 0, n = unitConverters_.length(); i < n; ++i) {
- if (i < n - 1) {
- Formattable formattableQuantity(intValues[i] * sign);
- // Measure takes ownership of the MeasureUnit*
- MeasureUnit *type = new MeasureUnit(units_[i]->copy(status).build(status));
- if (result.emplaceBackAndCheckErrorCode(status, formattableQuantity, type, status) ==
- nullptr) {
- // Ownership wasn't taken
- U_ASSERT(U_FAILURE(status));
- delete type;
- }
- if (U_FAILURE(status)) {
- return result;
- }
- } else { // LAST ELEMENT
- // Add the last element, not an integer:
- Formattable formattableQuantity(quantity * sign);
- // Measure takes ownership of the MeasureUnit*
- MeasureUnit *type = new MeasureUnit(units_[i]->copy(status).build(status));
- if (result.emplaceBackAndCheckErrorCode(status, formattableQuantity, type, status) ==
- nullptr) {
- // Ownership wasn't taken
- U_ASSERT(U_FAILURE(status));
- delete type;
- }
- if (U_FAILURE(status)) {
- return result;
- }
- U_ASSERT(result.length() == i + 1);
- U_ASSERT(result[i] != nullptr);
- }
- }
-
- MaybeStackVector<Measure> orderedResult;
- int32_t unitsCount = outputUnits_.length();
- U_ASSERT(unitsCount == units_.length());
- Measure **arr = result.getAlias();
- // O(N^2) is fine: mixed units' unitsCount is usually 2 or 3.
- for (int32_t i = 0; i < unitsCount; i++) {
- for (int32_t j = i; j < unitsCount; j++) {
- // Find the next expected unit, and swap it into place.
- U_ASSERT(result[j] != nullptr);
- if (result[j]->getUnit() == *outputUnits_[i]) {
- if (j != i) {
- Measure *tmp = arr[j];
- arr[j] = arr[i];
- arr[i] = tmp;
- }
- }
- }
- }
-
- return result;
-}
-
-} // namespace units
-U_NAMESPACE_END
-
-#endif /* #if !UCONFIG_NO_FORMATTING */