}
template<typename Derived>
-Derived NumberFormatterSettings<Derived>::multiplier(const Multiplier& multiplier) const& {
+Derived NumberFormatterSettings<Derived>::scale(const Scale& scale) const& {
Derived copy(*this);
- copy.fMacros.multiplier = multiplier;
+ copy.fMacros.scale = scale;
return copy;
}
template<typename Derived>
-Derived NumberFormatterSettings<Derived>::multiplier(const Multiplier& multiplier)&& {
+Derived NumberFormatterSettings<Derived>::scale(const Scale& scale)&& {
Derived move(std::move(*this));
- move.fMacros.multiplier = multiplier;
+ move.fMacros.scale = scale;
return move;
}
/// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR ///
/////////////////////////////////////////////////////////////////////////////////////
- // Multiplier (compatibility mode value).
- if (macros.multiplier.isValid()) {
- fMicros.helpers.multiplier.setAndChain(macros.multiplier, chain);
+ // Multiplier
+ if (macros.scale.isValid()) {
+ fMicros.helpers.multiplier.setAndChain(macros.scale, chain);
chain = &fMicros.helpers.multiplier;
}
// MULTIPLIERS //
/////////////////
- macros.multiplier = multiplierFromProperties(properties);
+ macros.scale = scaleFromProperties(properties);
//////////////////////
// PROPERTY EXPORTS //
using namespace icu::numparse::impl;
-Multiplier::Multiplier(int32_t magnitude, DecNum* arbitraryToAdopt)
+Scale::Scale(int32_t magnitude, DecNum* arbitraryToAdopt)
: fMagnitude(magnitude), fArbitrary(arbitraryToAdopt), fError(U_ZERO_ERROR) {
if (fArbitrary != nullptr) {
// Attempt to convert the DecNum to a magnitude multiplier.
if (fArbitrary->getRawDecNumber()->digits == 1 && fArbitrary->getRawDecNumber()->lsu[0] == 1 &&
!fArbitrary->isNegative()) {
// Success!
- fMagnitude = fArbitrary->getRawDecNumber()->exponent;
+ fMagnitude += fArbitrary->getRawDecNumber()->exponent;
delete fArbitrary;
fArbitrary = nullptr;
}
}
}
-Multiplier::Multiplier(const Multiplier& other)
+Scale::Scale(const Scale& other)
: fMagnitude(other.fMagnitude), fArbitrary(nullptr), fError(other.fError) {
if (other.fArbitrary != nullptr) {
UErrorCode localStatus = U_ZERO_ERROR;
}
}
-Multiplier& Multiplier::operator=(const Multiplier& other) {
+Scale& Scale::operator=(const Scale& other) {
fMagnitude = other.fMagnitude;
if (other.fArbitrary != nullptr) {
UErrorCode localStatus = U_ZERO_ERROR;
return *this;
}
-Multiplier::Multiplier(Multiplier&& src) U_NOEXCEPT
+Scale::Scale(Scale&& src) U_NOEXCEPT
: fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) {
// Take ownership away from src if necessary
src.fArbitrary = nullptr;
}
-Multiplier& Multiplier::operator=(Multiplier&& src) U_NOEXCEPT {
+Scale& Scale::operator=(Scale&& src) U_NOEXCEPT {
fMagnitude = src.fMagnitude;
fArbitrary = src.fArbitrary;
fError = src.fError;
return *this;
}
-Multiplier::~Multiplier() {
+Scale::~Scale() {
delete fArbitrary;
}
-Multiplier Multiplier::none() {
+Scale Scale::none() {
return {0, nullptr};
}
-Multiplier Multiplier::powerOfTen(int32_t power) {
+Scale Scale::powerOfTen(int32_t power) {
return {power, nullptr};
}
-Multiplier Multiplier::arbitraryDecimal(StringPiece multiplicand) {
+Scale Scale::byDecimal(StringPiece multiplicand) {
UErrorCode localError = U_ZERO_ERROR;
LocalPointer<DecNum> decnum(new DecNum(), localError);
if (U_FAILURE(localError)) {
return {0, decnum.orphan()};
}
-Multiplier Multiplier::arbitraryDouble(double multiplicand) {
+Scale Scale::byDouble(double multiplicand) {
UErrorCode localError = U_ZERO_ERROR;
LocalPointer<DecNum> decnum(new DecNum(), localError);
if (U_FAILURE(localError)) {
return {0, decnum.orphan()};
}
-void Multiplier::applyTo(impl::DecimalQuantity& quantity) const {
+Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) {
+ UErrorCode localError = U_ZERO_ERROR;
+ LocalPointer<DecNum> decnum(new DecNum(), localError);
+ if (U_FAILURE(localError)) {
+ return {localError};
+ }
+ decnum->setTo(multiplicand, localError);
+ if (U_FAILURE(localError)) {
+ return {localError};
+ }
+ return {power, decnum.orphan()};
+}
+
+void Scale::applyTo(impl::DecimalQuantity& quantity) const {
quantity.adjustMagnitude(fMagnitude);
if (fArbitrary != nullptr) {
UErrorCode localStatus = U_ZERO_ERROR;
}
}
-void Multiplier::applyReciprocalTo(impl::DecimalQuantity& quantity) const {
+void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const {
quantity.adjustMagnitude(-fMagnitude);
if (fArbitrary != nullptr) {
UErrorCode localStatus = U_ZERO_ERROR;
void
-MultiplierFormatHandler::setAndChain(const Multiplier& multiplier, const MicroPropsGenerator* parent) {
+MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
this->multiplier = multiplier;
this->parent = parent;
}
// NOTE: MultiplierParseHandler is declared in the header numparse_validators.h
-MultiplierParseHandler::MultiplierParseHandler(::icu::number::Multiplier multiplier)
+MultiplierParseHandler::MultiplierParseHandler(::icu::number::Scale multiplier)
: fMultiplier(std::move(multiplier)) {}
void MultiplierParseHandler::postProcess(ParsedNumber& result) const {
}
UnicodeString MultiplierParseHandler::toString() const {
- return u"<Multiplier>";
+ return u"<Scale>";
}
*/
class MultiplierFormatHandler : public MicroPropsGenerator, public UMemory {
public:
- void setAndChain(const Multiplier& multiplier, const MicroPropsGenerator* parent);
+ void setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent);
void processQuantity(DecimalQuantity& quantity, MicroProps& micros,
UErrorCode& status) const U_OVERRIDE;
private:
- Multiplier multiplier;
+ Scale multiplier;
const MicroPropsGenerator *parent;
};
-/** Gets a Multiplier from a DecimalFormatProperties. In Java, defined in RoundingUtils.java */
-static inline Multiplier multiplierFromProperties(const DecimalFormatProperties& properties) {
- if (properties.magnitudeMultiplier != 0) {
- return Multiplier::powerOfTen(properties.magnitudeMultiplier);
- } else if (properties.multiplier != 1) {
- return Multiplier::arbitraryDouble(properties.multiplier);
+/** Gets a Scale from a DecimalFormatProperties. In Java, defined in RoundingUtils.java */
+static inline Scale scaleFromProperties(const DecimalFormatProperties& properties) {
+ int32_t magnitudeMultiplier = properties.magnitudeMultiplier + properties.scaleMultiplier;
+ int32_t arbitraryMultiplier = properties.multiplier;
+ if (magnitudeMultiplier != 0 && arbitraryMultiplier != 1) {
+ return Scale::byDoubleAndPowerOfTen(arbitraryMultiplier, magnitudeMultiplier);
+ } else if (magnitudeMultiplier != 0) {
+ return Scale::powerOfTen(magnitudeMultiplier);
+ } else if (arbitraryMultiplier != 1) {
+ return Scale::byDouble(arbitraryMultiplier);
} else {
- return Multiplier::none();
+ return Scale::none();
}
}
b.add(u"currency", STEM_CURRENCY, status);
b.add(u"integer-width", STEM_INTEGER_WIDTH, status);
b.add(u"numbering-system", STEM_NUMBERING_SYSTEM, status);
- b.add(u"multiply", STEM_MULTIPLY, status);
+ b.add(u"scale", STEM_SCALE, status);
if (U_FAILURE(status)) { return; }
// Build the CharsTrie
case STATE_CURRENCY_UNIT:
case STATE_INTEGER_WIDTH:
case STATE_NUMBERING_SYSTEM:
- case STATE_MULTIPLY:
+ case STATE_SCALE:
// segment.setLength(U16_LENGTH(cp)); // for error message
// throw new SkeletonSyntaxException("Stem requires an option", segment);
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
CHECK_NULL(seen, symbols, status);
return STATE_NUMBERING_SYSTEM;
- case STEM_MULTIPLY:
- CHECK_NULL(seen, multiplier, status);
- return STATE_MULTIPLY;
+ case STEM_SCALE:
+ CHECK_NULL(seen, scale, status);
+ return STATE_SCALE;
default:
U_ASSERT(false);
case STATE_NUMBERING_SYSTEM:
blueprint_helpers::parseNumberingSystemOption(segment, macros, status);
return STATE_NULL;
- case STATE_MULTIPLY:
- blueprint_helpers::parseMultiplierOption(segment, macros, status);
+ case STATE_SCALE:
+ blueprint_helpers::parseScaleOption(segment, macros, status);
return STATE_NULL;
default:
break;
sb.append(u' ');
}
if (U_FAILURE(status)) { return; }
- if (GeneratorHelpers::multiplier(macros, sb, status)) {
+ if (GeneratorHelpers::scale(macros, sb, status)) {
sb.append(u' ');
}
if (U_FAILURE(status)) { return; }
sb.append(UnicodeString(ns.getName(), -1, US_INV));
}
-void blueprint_helpers::parseMultiplierOption(const StringSegment& segment, MacroProps& macros,
+void blueprint_helpers::parseScaleOption(const StringSegment& segment, MacroProps& macros,
UErrorCode& status) {
// Need to do char <-> UChar conversion...
CharString buffer;
}
// NOTE: The constructor will optimize the decnum for us if possible.
- macros.multiplier = {0, decnum.orphan()};
+ macros.scale = {0, decnum.orphan()};
}
void
-blueprint_helpers::generateMultiplierOption(int32_t magnitude, const DecNum* arbitrary, UnicodeString& sb,
+blueprint_helpers::generateScaleOption(int32_t magnitude, const DecNum* arbitrary, UnicodeString& sb,
UErrorCode& status) {
// Utilize DecimalQuantity/double_conversion to format this for us.
DecimalQuantity dq;
return true;
}
-bool GeneratorHelpers::multiplier(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) {
- if (!macros.multiplier.isValid()) {
+bool GeneratorHelpers::scale(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) {
+ if (!macros.scale.isValid()) {
return false; // Default or Bogus
}
- sb.append(u"multiply/", -1);
- blueprint_helpers::generateMultiplierOption(
- macros.multiplier.fMagnitude,
- macros.multiplier.fArbitrary,
+ sb.append(u"scale/", -1);
+ blueprint_helpers::generateScaleOption(
+ macros.scale.fMagnitude,
+ macros.scale.fArbitrary,
sb,
status);
return true;
STATE_CURRENCY_UNIT,
STATE_INTEGER_WIDTH,
STATE_NUMBERING_SYSTEM,
- STATE_MULTIPLY,
+ STATE_SCALE,
};
/**
STEM_CURRENCY,
STEM_INTEGER_WIDTH,
STEM_NUMBERING_SYSTEM,
- STEM_MULTIPLY,
+ STEM_SCALE,
};
/**
void generateNumberingSystemOption(const NumberingSystem& ns, UnicodeString& sb, UErrorCode& status);
-void parseMultiplierOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status);
+void parseScaleOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status);
-void generateMultiplierOption(int32_t magnitude, const DecNum* arbitrary, UnicodeString& sb,
+void generateScaleOption(int32_t magnitude, const DecNum* arbitrary, UnicodeString& sb,
UErrorCode& status);
} // namespace blueprint_helpers
static bool decimal(const MacroProps& macros, UnicodeString& sb, UErrorCode& status);
- static bool multiplier(const MacroProps& macros, UnicodeString& sb, UErrorCode& status);
+ static bool scale(const MacroProps& macros, UnicodeString& sb, UErrorCode& status);
};
bool unitWidth = false;
bool sign = false;
bool decimal = false;
- bool multiplier = false;
+ bool scale = false;
};
} // namespace impl
parser->addMatcher(parser->fLocalValidators.decimalSeparator = {patternHasDecimalSeparator});
}
// The multiplier takes care of scaling percentages.
- Multiplier multiplier = multiplierFromProperties(properties);
+ Scale multiplier = scaleFromProperties(properties);
if (multiplier.isValid()) {
parser->addMatcher(parser->fLocalValidators.multiplier = {multiplier});
}
public:
MultiplierParseHandler() = default; // leaves instance in valid but undefined state
- MultiplierParseHandler(::icu::number::Multiplier multiplier);
+ MultiplierParseHandler(::icu::number::Scale multiplier);
void postProcess(ParsedNumber& result) const U_OVERRIDE;
UnicodeString toString() const U_OVERRIDE;
private:
- ::icu::number::Multiplier fMultiplier;
+ ::icu::number::Scale fMultiplier;
};
* A class that defines a quantity by which a number should be multiplied when formatting.
*
* <p>
- * To create a Multiplier, use one of the factory methods.
+ * To create a Scale, use one of the factory methods.
*
* @draft ICU 62
*/
-class U_I18N_API Multiplier : public UMemory {
+class U_I18N_API Scale : public UMemory {
public:
/**
* Do not change the value of numbers when formatting or parsing.
*
- * @return A Multiplier to prevent any multiplication.
+ * @return A Scale to prevent any multiplication.
* @draft ICU 62
*/
- static Multiplier none();
+ static Scale none();
/**
- * Multiply numbers by 100 before formatting. Useful for combining with a percent unit:
+ * Multiply numbers by a power of ten before formatting. Useful for combining with a percent unit:
*
* <pre>
- * NumberFormatter::with().unit(NoUnit::percent()).multiplier(Multiplier::powerOfTen(2))
+ * NumberFormatter::with().unit(NoUnit::percent()).multiplier(Scale::powerOfTen(2))
* </pre>
*
- * @return A Multiplier for passing to the setter in NumberFormatter.
+ * @return A Scale for passing to the setter in NumberFormatter.
* @draft ICU 62
*/
- static Multiplier powerOfTen(int32_t power);
+ static Scale powerOfTen(int32_t power);
/**
* Multiply numbers by an arbitrary value before formatting. Useful for unit conversions.
*
* Also see the version of this method that takes a double.
*
- * @return A Multiplier for passing to the setter in NumberFormatter.
+ * @return A Scale for passing to the setter in NumberFormatter.
* @draft ICU 62
*/
- static Multiplier arbitraryDecimal(StringPiece multiplicand);
+ static Scale byDecimal(StringPiece multiplicand);
/**
* Multiply numbers by an arbitrary value before formatting. Useful for unit conversions.
*
* This method takes a double; also see the version of this method that takes an exact decimal.
*
- * @return A Multiplier for passing to the setter in NumberFormatter.
+ * @return A Scale for passing to the setter in NumberFormatter.
* @draft ICU 62
*/
- static Multiplier arbitraryDouble(double multiplicand);
+ static Scale byDouble(double multiplicand);
+
+ /**
+ * Multiply a number by both a power of ten and by an arbitrary double value.
+ *
+ * @return A Scale for passing to the setter in NumberFormatter.
+ * @draft ICU 62
+ */
+ static Scale byDoubleAndPowerOfTen(double multiplicand, int32_t power);
// We need a custom destructor for the DecNum, which means we need to declare
// the copy/move constructor/assignment quartet.
/** @draft ICU 62 */
- Multiplier(const Multiplier& other);
+ Scale(const Scale& other);
/** @draft ICU 62 */
- Multiplier& operator=(const Multiplier& other);
+ Scale& operator=(const Scale& other);
/** @draft ICU 62 */
- Multiplier(Multiplier&& src) U_NOEXCEPT;
+ Scale(Scale&& src) U_NOEXCEPT;
/** @draft ICU 62 */
- Multiplier& operator=(Multiplier&& src) U_NOEXCEPT;
+ Scale& operator=(Scale&& src) U_NOEXCEPT;
/** @draft ICU 62 */
- ~Multiplier();
+ ~Scale();
/** @internal */
- Multiplier(int32_t magnitude, impl::DecNum* arbitraryToAdopt);
+ Scale(int32_t magnitude, impl::DecNum* arbitraryToAdopt);
private:
int32_t fMagnitude;
impl::DecNum* fArbitrary;
UErrorCode fError;
- Multiplier(UErrorCode error) : fMagnitude(0), fArbitrary(nullptr), fError(error) {}
+ Scale(UErrorCode error) : fMagnitude(0), fArbitrary(nullptr), fError(error) {}
- Multiplier() : fMagnitude(0), fArbitrary(nullptr), fError(U_ZERO_ERROR) {}
+ Scale() : fMagnitude(0), fArbitrary(nullptr), fError(U_ZERO_ERROR) {}
bool isValid() const {
return fMagnitude != 0 || fArbitrary != nullptr;
UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_COUNT;
/** @internal */
- Multiplier multiplier; // = Multiplier(); (benign value)
+ Scale scale; // = Scale(); (benign value)
/** @internal */
AffixPatternProvider* affixProvider = nullptr; // no ownership
bool copyErrorTo(UErrorCode &status) const {
return notation.copyErrorTo(status) || rounder.copyErrorTo(status) ||
padder.copyErrorTo(status) || integerWidth.copyErrorTo(status) ||
- symbols.copyErrorTo(status) || multiplier.copyErrorTo(status);
+ symbols.copyErrorTo(status) || scale.copyErrorTo(status);
}
};
Derived decimal(const UNumberDecimalSeparatorDisplay &style) &&;
/**
- * Sets a multiplier to be used to scale the number by an arbitrary amount before formatting. Most
- * common values:
+ * Sets a scale (multiplier) to be used to scale the number by an arbitrary amount before formatting.
+ * Most common values:
*
* <ul>
* <li>Multiply by 100: useful for percentages.
* </ul>
*
* <p>
- * Pass an element from a {@link Multiplier} factory method to this setter. For example:
+ * Pass an element from a {@link Scale} factory method to this setter. For example:
*
* <pre>
- * NumberFormatter::with().multiplier(Multiplier::powerOfTen(2))
+ * NumberFormatter::with().scale(Scale::powerOfTen(2))
* </pre>
*
* <p>
* The default is to not apply any multiplier.
*
- * @param style
- * The decimal separator display strategy to use when rendering numbers.
+ * @param scale
+ * The scale to apply when rendering numbers.
* @return The fluent chain
* @draft ICU 60
*/
- Derived multiplier(const Multiplier &style) const &;
+ Derived scale(const Scale &scale) const &;
/**
- * Overload of multiplier() for use on an rvalue reference.
+ * Overload of scale() for use on an rvalue reference.
*
- * @param style
- * The multiplier separator display strategy to use when rendering numbers.
+ * @param scale
+ * The scale to apply when rendering numbers.
* @return The fluent chain.
- * @see #multiplier
+ * @see #scale
* @draft ICU 62
*/
- Derived multiplier(const Multiplier &style) &&;
+ Derived scale(const Scale &scale) &&;
#ifndef U_HIDE_INTERNAL_API
//void symbolsOverride();
void sign();
void decimal();
- void multiplier();
+ void scale();
void locale();
void formatTypes();
void errors();
//TESTCASE_AUTO(symbolsOverride);
TESTCASE_AUTO(sign);
TESTCASE_AUTO(decimal);
- TESTCASE_AUTO(multiplier);
+ TESTCASE_AUTO(scale);
TESTCASE_AUTO(locale);
TESTCASE_AUTO(formatTypes);
TESTCASE_AUTO(errors);
u"0.");
}
-void NumberFormatterApiTest::multiplier() {
+void NumberFormatterApiTest::scale() {
assertFormatDescending(
u"Multiplier None",
- u"multiply/1",
- NumberFormatter::with().multiplier(Multiplier::none()),
+ u"scale/1",
+ NumberFormatter::with().scale(Scale::none()),
Locale::getEnglish(),
u"87,650",
u"8,765",
assertFormatDescending(
u"Multiplier Power of Ten",
- u"multiply/1000000",
- NumberFormatter::with().multiplier(Multiplier::powerOfTen(6)),
+ u"scale/1000000",
+ NumberFormatter::with().scale(Scale::powerOfTen(6)),
Locale::getEnglish(),
u"87,650,000,000",
u"8,765,000,000",
assertFormatDescending(
u"Multiplier Arbitrary Double",
- u"multiply/5.2",
- NumberFormatter::with().multiplier(Multiplier::arbitraryDouble(5.2)),
+ u"scale/5.2",
+ NumberFormatter::with().scale(Scale::byDouble(5.2)),
Locale::getEnglish(),
u"455,780",
u"45,578",
assertFormatDescending(
u"Multiplier Arbitrary BigDecimal",
- u"multiply/5.2",
- NumberFormatter::with().multiplier(Multiplier::arbitraryDecimal({"5.2", -1})),
+ u"scale/5.2",
+ NumberFormatter::with().scale(Scale::byDecimal({"5.2", -1})),
Locale::getEnglish(),
u"455,780",
u"45,578",
u"0.045578",
u"0");
+ assertFormatDescending(
+ u"Multiplier Arbitrary Double And Power Of Ten",
+ u"scale/5200",
+ NumberFormatter::with().scale(Scale::byDoubleAndPowerOfTen(5.2, 3)),
+ Locale::getEnglish(),
+ u"455,780,000",
+ u"45,578,000",
+ u"4,557,800",
+ u"455,780",
+ u"45,578",
+ u"4,557.8",
+ u"455.78",
+ u"45.578",
+ u"0");
+
assertFormatDescending(
u"Multiplier Zero",
- u"multiply/0",
- NumberFormatter::with().multiplier(Multiplier::arbitraryDouble(0)),
+ u"scale/0",
+ NumberFormatter::with().scale(Scale::byDouble(0)),
Locale::getEnglish(),
u"0",
u"0",
assertFormatSingle(
u"Multiplier Skeleton Scientific Notation and Percent",
- u"percent multiply/1E2",
- NumberFormatter::with().unit(NoUnit::percent()).multiplier(Multiplier::powerOfTen(2)),
+ u"percent scale/1E2",
+ NumberFormatter::with().unit(NoUnit::percent()).scale(Scale::powerOfTen(2)),
Locale::getEnglish(),
0.5,
u"50%");
assertFormatSingle(
u"Negative Multiplier",
- u"multiply/-5.2",
- NumberFormatter::with().multiplier(Multiplier::arbitraryDouble(-5.2)),
+ u"scale/-5.2",
+ NumberFormatter::with().scale(Scale::byDouble(-5.2)),
Locale::getEnglish(),
2,
u"-10.4");
assertFormatSingle(
u"Negative One Multiplier",
- u"multiply/-1",
- NumberFormatter::with().multiplier(Multiplier::arbitraryDouble(-1)),
+ u"scale/-1",
+ NumberFormatter::with().scale(Scale::byDouble(-1)),
Locale::getEnglish(),
444444,
u"-444,444");
+
+ assertFormatSingle(
+ u"Two-Type Multiplier with Overlap",
+ u"scale/10000",
+ NumberFormatter::with().scale(Scale::byDoubleAndPowerOfTen(100, 2)),
+ Locale::getEnglish(),
+ 2,
+ u"20,000");
}
void NumberFormatterApiTest::locale() {
u"unit-width-hidden",
u"decimal-auto",
u"decimal-always",
- u"multiply/5.2",
- u"multiply/-5.2",
- u"multiply/100",
- u"multiply/1E2",
- u"multiply/1",
+ u"scale/5.2",
+ u"scale/-5.2",
+ u"scale/100",
+ u"scale/1E2",
+ u"scale/1",
u"latin",
u"numbering-system/arab",
u"numbering-system/latn",
u"round-increment/xxx",
u"round-increment/NaN",
u"round-increment/0.1.2",
- u"multiply/xxx",
- u"multiply/NaN",
- u"multiply/0.1.2",
- u"multiply/français", // non-invariant characters for C++
+ u"scale/xxx",
+ u"scale/NaN",
+ u"scale/0.1.2",
+ u"scale/français", // non-invariant characters for C++
u"currency/dummy",
u"measure-unit/foo",
u"integer-width/xxx",
u"currency",
u"integer-width",
u"numbering-system",
- u"multiply"};
+ u"scale"};
static const char16_t* suffixes[] = {u"", u"/ceiling", u" scientific", u"/ceiling scientific"};
for (auto& stem : stems) {
import com.ibm.icu.impl.Utility;
import com.ibm.icu.number.IntegerWidth;
-import com.ibm.icu.number.Multiplier;
+import com.ibm.icu.number.Scale;
import com.ibm.icu.number.Notation;
import com.ibm.icu.number.NumberFormatter.DecimalSeparatorDisplay;
import com.ibm.icu.number.NumberFormatter.SignDisplay;
public UnitWidth unitWidth;
public SignDisplay sign;
public DecimalSeparatorDisplay decimal;
- public Multiplier multiplier;
+ public Scale scale;
public AffixPatternProvider affixProvider; // not in API; for JDK compatibility mode only
public PluralRules rules; // not in API; could be made public in the future
public Long threshold; // not in API; controls internal self-regulation threshold
decimal = fallback.decimal;
if (affixProvider == null)
affixProvider = fallback.affixProvider;
- if (multiplier == null)
- multiplier = fallback.multiplier;
+ if (scale == null)
+ scale = fallback.scale;
if (rules == null)
rules = fallback.rules;
if (loc == null)
sign,
decimal,
affixProvider,
- multiplier,
+ scale,
rules,
loc);
}
&& Utility.equals(sign, other.sign)
&& Utility.equals(decimal, other.decimal)
&& Utility.equals(affixProvider, other.affixProvider)
- && Utility.equals(multiplier, other.multiplier)
+ && Utility.equals(scale, other.scale)
&& Utility.equals(rules, other.rules)
&& Utility.equals(loc, other.loc);
}
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.impl.number;
-import com.ibm.icu.number.Multiplier;
+import com.ibm.icu.number.Scale;
/**
- * Wraps a {@link Multiplier} for use in the number formatting pipeline.
+ * Wraps a {@link Scale} for use in the number formatting pipeline.
*/
public class MultiplierFormatHandler implements MicroPropsGenerator {
- final Multiplier multiplier;
+ final Scale multiplier;
final MicroPropsGenerator parent;
- public MultiplierFormatHandler(Multiplier multiplier, MicroPropsGenerator parent) {
+ public MultiplierFormatHandler(Scale multiplier, MicroPropsGenerator parent) {
this.multiplier = multiplier;
this.parent = parent;
}
import java.math.MathContext;
import java.math.RoundingMode;
-import com.ibm.icu.number.Multiplier;
+import com.ibm.icu.number.Scale;
/** @author sffc */
public class RoundingUtils {
return MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[roundingMode.ordinal()];
}
- public static Multiplier multiplierFromProperties(DecimalFormatProperties properties) {
+ public static Scale scaleFromProperties(DecimalFormatProperties properties) {
MathContext mc = getMathContextOr34Digits(properties);
if (properties.getMagnitudeMultiplier() != 0) {
- return Multiplier.powerOfTen(properties.getMagnitudeMultiplier()).withMathContext(mc);
+ return Scale.powerOfTen(properties.getMagnitudeMultiplier()).withMathContext(mc);
} else if (properties.getMultiplier() != null) {
- return Multiplier.arbitrary(properties.getMultiplier()).withMathContext(mc);
+ return Scale.byBigDecimal(properties.getMultiplier()).withMathContext(mc);
} else {
return null;
}
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.impl.number.parse;
-import com.ibm.icu.number.Multiplier;
+import com.ibm.icu.number.Scale;
/**
- * Wraps a {@link Multiplier} for use in the number parsing pipeline.
+ * Wraps a {@link Scale} for use in the number parsing pipeline.
*/
public class MultiplierParseHandler extends ValidationMatcher {
- private final Multiplier multiplier;
+ private final Scale multiplier;
- public MultiplierParseHandler(Multiplier multiplier) {
+ public MultiplierParseHandler(Scale multiplier) {
this.multiplier = multiplier;
}
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
import com.ibm.icu.impl.number.PropertiesAffixPatternProvider;
import com.ibm.icu.impl.number.RoundingUtils;
-import com.ibm.icu.number.Multiplier;
+import com.ibm.icu.number.Scale;
import com.ibm.icu.number.NumberFormatter.GroupingStrategy;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.util.Currency;
parser.addMatcher(RequireDecimalSeparatorValidator.getInstance(patternHasDecimalSeparator));
}
// The multiplier takes care of scaling percentages.
- Multiplier multiplier = RoundingUtils.multiplierFromProperties(properties);
+ Scale multiplier = RoundingUtils.scaleFromProperties(properties);
if (multiplier != null) {
parser.addMatcher(new MultiplierParseHandler(multiplier));
}
/// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR ///
/////////////////////////////////////////////////////////////////////////////////////
- // Multiplier (compatibility mode value).
- if (macros.multiplier != null) {
- chain = new MultiplierFormatHandler(macros.multiplier, chain);
+ // Multiplier
+ if (macros.scale != null) {
+ chain = new MultiplierFormatHandler(macros.scale, chain);
}
// Rounding strategy
static final int KEY_UNIT_WIDTH = 9;
static final int KEY_SIGN = 10;
static final int KEY_DECIMAL = 11;
- static final int KEY_MULTIPLIER = 12;
+ static final int KEY_SCALE = 12;
static final int KEY_THRESHOLD = 13;
static final int KEY_PER_UNIT = 14;
static final int KEY_MAX = 15;
}
/**
- * Sets a multiplier to be used to scale the number by an arbitrary amount before formatting. Most
- * common values:
+ * Sets a scale (multiplier) to be used to scale the number by an arbitrary amount before formatting.
+ * Most common values:
*
* <ul>
* <li>Multiply by 100: useful for percentages.
* </ul>
*
* <p>
- * Pass an element from a {@link Multiplier} factory method to this setter. For example:
+ * Pass an element from a {@link Scale} factory method to this setter. For example:
*
* <pre>
- * NumberFormatter.with().multiplier(Multiplier.powerOfTen(2))
+ * NumberFormatter.with().scale(Scale.powerOfTen(2))
* </pre>
*
* <p>
* The default is to not apply any multiplier.
*
- * @param multiplier
+ * @param scale
* An amount to be multiplied against numbers before formatting.
* @return The fluent chain
- * @see Multiplier
+ * @see Scale
* @draft ICU 62
* @provisional This API might change or be removed in a future release.
*/
- public T multiplier(Multiplier multiplier) {
- return create(KEY_MULTIPLIER, multiplier);
+ public T scale(Scale scale) {
+ return create(KEY_SCALE, scale);
}
/**
macros.decimal = (DecimalSeparatorDisplay) current.value;
}
break;
- case KEY_MULTIPLIER:
- if (macros.multiplier == null) {
- macros.multiplier = (Multiplier) current.value;
+ case KEY_SCALE:
+ if (macros.scale == null) {
+ macros.scale = (Scale) current.value;
}
break;
case KEY_THRESHOLD:
// MULTIPLIERS //
/////////////////
- macros.multiplier = RoundingUtils.multiplierFromProperties(properties);
+ macros.scale = RoundingUtils.scaleFromProperties(properties);
//////////////////////
// PROPERTY EXPORTS //
STATE_CURRENCY_UNIT,
STATE_INTEGER_WIDTH,
STATE_NUMBERING_SYSTEM,
- STATE_MULTIPLY,
+ STATE_SCALE,
}
/**
STEM_CURRENCY,
STEM_INTEGER_WIDTH,
STEM_NUMBERING_SYSTEM,
- STEM_MULTIPLY,
+ STEM_SCALE,
};
/** For mapping from ordinal back to StemEnum in Java. */
b.add("currency", StemEnum.STEM_CURRENCY.ordinal());
b.add("integer-width", StemEnum.STEM_INTEGER_WIDTH.ordinal());
b.add("numbering-system", StemEnum.STEM_NUMBERING_SYSTEM.ordinal());
- b.add("multiply", StemEnum.STEM_MULTIPLY.ordinal());
+ b.add("scale", StemEnum.STEM_SCALE.ordinal());
// Build the CharsTrie
// TODO: Use SLOW or FAST here?
case STATE_CURRENCY_UNIT:
case STATE_INTEGER_WIDTH:
case STATE_NUMBERING_SYSTEM:
- case STATE_MULTIPLY:
+ case STATE_SCALE:
segment.setLength(Character.charCount(cp)); // for error message
throw new SkeletonSyntaxException("Stem requires an option", segment);
default:
checkNull(macros.symbols, segment);
return ParseState.STATE_NUMBERING_SYSTEM;
- case STEM_MULTIPLY:
- checkNull(macros.multiplier, segment);
- return ParseState.STATE_MULTIPLY;
+ case STEM_SCALE:
+ checkNull(macros.scale, segment);
+ return ParseState.STATE_SCALE;
default:
throw new AssertionError();
case STATE_NUMBERING_SYSTEM:
BlueprintHelpers.parseNumberingSystemOption(segment, macros);
return ParseState.STATE_NULL;
- case STATE_MULTIPLY:
- BlueprintHelpers.parseMultiplierOption(segment, macros);
+ case STATE_SCALE:
+ BlueprintHelpers.parseScaleOption(segment, macros);
return ParseState.STATE_NULL;
default:
break;
if (macros.decimal != null && GeneratorHelpers.decimal(macros, sb)) {
sb.append(' ');
}
- if (macros.multiplier != null && GeneratorHelpers.multiplier(macros, sb)) {
+ if (macros.scale != null && GeneratorHelpers.scale(macros, sb)) {
sb.append(' ');
}
sb.append(ns.getName());
}
- private static void parseMultiplierOption(StringSegment segment, MacroProps macros) {
+ private static void parseScaleOption(StringSegment segment, MacroProps macros) {
// Call segment.subSequence() because segment.toString() doesn't create a clean string.
String str = segment.subSequence(0, segment.length()).toString();
BigDecimal bd;
try {
bd = new BigDecimal(str);
} catch (NumberFormatException e) {
- throw new SkeletonSyntaxException("Invalid multiplier", segment, e);
+ throw new SkeletonSyntaxException("Invalid scale", segment, e);
}
- // NOTE: If bd is a power of ten, the Multiplier API optimizes it for us.
- macros.multiplier = Multiplier.arbitrary(bd);
+ // NOTE: If bd is a power of ten, the Scale API optimizes it for us.
+ macros.scale = Scale.byBigDecimal(bd);
}
- private static void generateMultiplierOption(Multiplier multiplier, StringBuilder sb) {
- BigDecimal bd = multiplier.arbitrary;
+ private static void generateScaleOption(Scale scale, StringBuilder sb) {
+ BigDecimal bd = scale.arbitrary;
if (bd == null) {
bd = BigDecimal.ONE;
}
- bd = bd.scaleByPowerOfTen(multiplier.magnitude);
+ bd = bd.scaleByPowerOfTen(scale.magnitude);
sb.append(bd.toPlainString());
}
}
return true;
}
- private static boolean multiplier(MacroProps macros, StringBuilder sb) {
- if (!macros.multiplier.isValid()) {
+ private static boolean scale(MacroProps macros, StringBuilder sb) {
+ if (!macros.scale.isValid()) {
return false; // Default value
}
- sb.append("multiply/");
- BlueprintHelpers.generateMultiplierOption(macros.multiplier, sb);
+ sb.append("scale/");
+ BlueprintHelpers.generateScaleOption(macros.scale, sb);
return true;
}
* @provisional This API might change or be removed in a future release.
* @see NumberFormatter
*/
-public class Multiplier {
+public class Scale {
- private static final Multiplier DEFAULT = new Multiplier(0, null);
- private static final Multiplier HUNDRED = new Multiplier(2, null);
- private static final Multiplier THOUSAND = new Multiplier(3, null);
+ private static final Scale DEFAULT = new Scale(0, null);
+ private static final Scale HUNDRED = new Scale(2, null);
+ private static final Scale THOUSAND = new Scale(3, null);
private static final BigDecimal BIG_DECIMAL_100 = BigDecimal.valueOf(100);
private static final BigDecimal BIG_DECIMAL_1000 = BigDecimal.valueOf(1000);
final BigDecimal reciprocal;
final MathContext mc;
- private Multiplier(int magnitude, BigDecimal arbitrary) {
+ private Scale(int magnitude, BigDecimal arbitrary) {
this(magnitude, arbitrary, RoundingUtils.DEFAULT_MATH_CONTEXT_34_DIGITS);
}
- private Multiplier(int magnitude, BigDecimal arbitrary, MathContext mc) {
+ private Scale(int magnitude, BigDecimal arbitrary, MathContext mc) {
if (arbitrary != null) {
// Attempt to convert the BigDecimal to a magnitude multiplier.
arbitrary = arbitrary.stripTrailingZeros();
if (arbitrary.precision() == 1 && arbitrary.unscaledValue().equals(BigInteger.ONE)) {
// Success!
- magnitude = -arbitrary.scale();
+ magnitude -= arbitrary.scale();
arbitrary = null;
}
}
* @provisional This API might change or be removed in a future release.
* @see NumberFormatter
*/
- public static Multiplier none() {
+ public static Scale none() {
return DEFAULT;
}
* @provisional This API might change or be removed in a future release.
* @see NumberFormatter
*/
- public static Multiplier powerOfTen(int power) {
+ public static Scale powerOfTen(int power) {
if (power == 0) {
return DEFAULT;
} else if (power == 2) {
} else if (power == 3) {
return THOUSAND;
} else {
- return new Multiplier(power, null);
+ return new Scale(power, null);
}
}
* @provisional This API might change or be removed in a future release.
* @see NumberFormatter
*/
- public static Multiplier arbitrary(BigDecimal multiplicand) {
+ public static Scale byBigDecimal(BigDecimal multiplicand) {
if (multiplicand.compareTo(BigDecimal.ONE) == 0) {
return DEFAULT;
} else if (multiplicand.compareTo(BIG_DECIMAL_100) == 0) {
} else if (multiplicand.compareTo(BIG_DECIMAL_1000) == 0) {
return THOUSAND;
} else {
- return new Multiplier(0, multiplicand);
+ return new Scale(0, multiplicand);
}
}
* @provisional This API might change or be removed in a future release.
* @see NumberFormatter
*/
- public static Multiplier arbitrary(double multiplicand) {
+ public static Scale byDouble(double multiplicand) {
if (multiplicand == 1) {
return DEFAULT;
} else if (multiplicand == 100.0) {
} else if (multiplicand == 1000.0) {
return THOUSAND;
} else {
- return new Multiplier(0, BigDecimal.valueOf(multiplicand));
+ return new Scale(0, BigDecimal.valueOf(multiplicand));
}
}
+ /**
+ * Multiply a number by both a power of ten and by an arbitrary double value before formatting.
+ *
+ * @return A Multiplier for passing to the setter in NumberFormatter.
+ * @draft ICU 62
+ * @provisional This API might change or be removed in a future release.
+ * @see NumberFormatter
+ */
+ public static Scale byDoubleAndPowerOfTen(double multiplicand, int power) {
+ return new Scale(power, BigDecimal.valueOf(multiplicand));
+ }
+
/**
* Returns whether the multiplier will change the number.
*/
* @deprecated ICU 62 This API is ICU internal only.
*/
@Deprecated
- public Multiplier withMathContext(MathContext mc) {
+ public Scale withMathContext(MathContext mc) {
// TODO: Make this public?
if (this.mc.equals(mc)) {
return this;
}
- return new Multiplier(magnitude, arbitrary, mc);
+ return new Scale(magnitude, arbitrary, mc);
}
/**
import com.ibm.icu.number.FractionRounder;
import com.ibm.icu.number.IntegerWidth;
import com.ibm.icu.number.LocalizedNumberFormatter;
-import com.ibm.icu.number.Multiplier;
import com.ibm.icu.number.Notation;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.number.NumberFormatter.DecimalSeparatorDisplay;
import com.ibm.icu.number.NumberFormatter.SignDisplay;
import com.ibm.icu.number.NumberFormatter.UnitWidth;
import com.ibm.icu.number.Rounder;
+import com.ibm.icu.number.Scale;
import com.ibm.icu.number.ScientificNotation;
import com.ibm.icu.number.UnlocalizedNumberFormatter;
import com.ibm.icu.text.DecimalFormatSymbols;
}
@Test
- public void multiplier() {
+ public void scale() {
assertFormatDescending(
"Multiplier None",
- "multiply/1",
- NumberFormatter.with().multiplier(Multiplier.none()),
+ "scale/1",
+ NumberFormatter.with().scale(Scale.none()),
ULocale.ENGLISH,
"87,650",
"8,765",
assertFormatDescending(
"Multiplier Power of Ten",
- "multiply/1000000",
- NumberFormatter.with().multiplier(Multiplier.powerOfTen(6)),
+ "scale/1000000",
+ NumberFormatter.with().scale(Scale.powerOfTen(6)),
ULocale.ENGLISH,
"87,650,000,000",
"8,765,000,000",
assertFormatDescending(
"Multiplier Arbitrary Double",
- "multiply/5.2",
- NumberFormatter.with().multiplier(Multiplier.arbitrary(5.2)),
+ "scale/5.2",
+ NumberFormatter.with().scale(Scale.byDouble(5.2)),
ULocale.ENGLISH,
"455,780",
"45,578",
assertFormatDescending(
"Multiplier Arbitrary BigDecimal",
- "multiply/5.2",
- NumberFormatter.with().multiplier(Multiplier.arbitrary(new BigDecimal("5.2"))),
+ "scale/5.2",
+ NumberFormatter.with().scale(Scale.byBigDecimal(new BigDecimal("5.2"))),
ULocale.ENGLISH,
"455,780",
"45,578",
"0.045578",
"0");
+ assertFormatDescending(
+ "Multiplier Arbitrary Double And Power Of Ten",
+ "scale/5200",
+ NumberFormatter.with().scale(Scale.byDoubleAndPowerOfTen(5.2, 3)),
+ ULocale.ENGLISH,
+ "455,780,000",
+ "45,578,000",
+ "4,557,800",
+ "455,780",
+ "45,578",
+ "4,557.8",
+ "455.78",
+ "45.578",
+ "0");
+
assertFormatDescending(
"Multiplier Zero",
- "multiply/0",
- NumberFormatter.with().multiplier(Multiplier.arbitrary(0)),
+ "scale/0",
+ NumberFormatter.with().scale(Scale.byDouble(0)),
ULocale.ENGLISH,
"0",
"0",
assertFormatSingle(
"Multiplier Skeleton Scientific Notation and Percent",
- "percent multiply/1E2",
- NumberFormatter.with().unit(NoUnit.PERCENT).multiplier(Multiplier.powerOfTen(2)),
+ "percent scale/1E2",
+ NumberFormatter.with().unit(NoUnit.PERCENT).scale(Scale.powerOfTen(2)),
ULocale.ENGLISH,
0.5,
"50%");
assertFormatSingle(
"Negative Multiplier",
- "multiply/-5.2",
- NumberFormatter.with().multiplier(Multiplier.arbitrary(-5.2)),
+ "scale/-5.2",
+ NumberFormatter.with().scale(Scale.byDouble(-5.2)),
ULocale.ENGLISH,
2,
"-10.4");
assertFormatSingle(
"Negative One Multiplier",
- "multiply/-1",
- NumberFormatter.with().multiplier(Multiplier.arbitrary(-1)),
+ "scale/-1",
+ NumberFormatter.with().scale(Scale.byDouble(-1)),
ULocale.ENGLISH,
444444,
"-444,444");
+
+ assertFormatSingle(
+ "Two-Type Multiplier with Overlap",
+ "scale/10000",
+ NumberFormatter.with().scale(Scale.byDoubleAndPowerOfTen(100, 2)),
+ ULocale.ENGLISH,
+ 2,
+ "20,000");
}
@Test
"unit-width-hidden",
"decimal-auto",
"decimal-always",
- "multiply/5.2",
- "multiply/-5.2",
- "multiply/100",
- "multiply/1E2",
- "multiply/1",
+ "scale/5.2",
+ "scale/-5.2",
+ "scale/100",
+ "scale/1E2",
+ "scale/1",
"latin",
"numbering-system/arab",
"numbering-system/latn",
"round-increment/xxx",
"round-increment/NaN",
"round-increment/0.1.2",
- "multiply/xxx",
- "multiply/NaN",
- "multiply/0.1.2",
- "multiply/français", // non-invariant characters for C++
+ "scale/xxx",
+ "scale/NaN",
+ "scale/0.1.2",
+ "scale/français", // non-invariant characters for C++
"currency/dummy",
"measure-unit/foo",
"integer-width/xxx",
"currency",
"integer-width",
"numbering-system",
- "multiply" };
+ "scale" };
String[] suffixes = { "", "/ceiling", " scientific", "/ceiling scientific" };
for (String stem : stems) {