164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others. 264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 51b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 1997-2015, International Business Machines 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File DIGITLST.CPP 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History: 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Date Name Description 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 03/21/97 clhuang Converted from java. 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 03/21/97 clhuang Implemented with new APIs. 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 03/27/97 helena Updated to pass the simple test after code review. 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 03/31/97 aliu Moved isLONG_MIN to here, and fixed it. 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char. 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Reworked representation by replacing fDecimalAt 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* with fExponent. 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 04/16/97 aliu Rewrote set() and getDouble() to use sprintf/atof 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* to do digit conversion. 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 09/09/97 aliu Modified for exponential notation support. 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 08/02/98 stephen Added nearest/even rounding 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Fixed bug in fitsIntoLong 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru****************************************************************************** 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/ 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if defined(__CYGWIN__) && !defined(_GNU_SOURCE) 3064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#define _GNU_SOURCE 3164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 3264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "digitlst.h" 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 3664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/putil.h" 3827f654740f2a26ad62a5c155af9199af9e69b889claireho#include "charstr.h" 3950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "cmemory.h" 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h" 41103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "mutex.h" 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "putilimp.h" 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h" 44c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "digitinterval.h" 4564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#include "ucln_in.h" 4664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#include "umutex.h" 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdlib.h> 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <limits.h> 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <string.h> 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h> 5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <limits> 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 5364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if !defined(U_USE_STRTOD_L) 5464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# if U_PLATFORM_USES_ONLY_WIN32_API 5564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# define U_USE_STRTOD_L 1 5664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# elif defined(U_HAVE_STRTOD_L) 5764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# define U_USE_STRTOD_L U_HAVE_STRTOD_L 5864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# else 5964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# define U_USE_STRTOD_L 0 6064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# endif 6164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 6264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 6364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if U_USE_STRTOD_L && !U_PLATFORM_USES_ONLY_WIN32_API 6464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# if U_PLATFORM == U_PF_CYGWIN 6564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# include <locale.h> 6664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# else 6764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# include <xlocale.h> 6864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# endif 6964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 7064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *************************************************************************** 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// class DigitList 7350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// A wrapper onto decNumber. 7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Used to be standalone. 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *************************************************************************** 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This is the zero digit. The base for the digits returned by getDigit() 7927f654740f2a26ad62a5c155af9199af9e69b889claireho * Note that it is the platform invariant digit, and is not Unicode. 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kZero '0' 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Only for 32 bit numbers. Ignore the negative sign. */ 8554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const char LONG_MIN_REP[] = "2147483648"; 8654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const char I64_MIN_REP[] = "9223372036854775808"; 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// default constructor 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::DigitList() 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 9650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&fContext, DEC_INIT_BASE); 9750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.traps = 0; 9850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); 9927f654740f2a26ad62a5c155af9199af9e69b889claireho fContext.digits = fStorage.getCapacity(); 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 10127f654740f2a26ad62a5c155af9199af9e69b889claireho fDecNumber = fStorage.getAlias(); 10250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(fDecNumber); 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 104103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalSetDouble(0.0); 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 107bbb04983e06b0e11d9f393bbd3850bbe8f47f6d0Jean-Baptiste Queru// ------------------------------------- 108bbb04983e06b0e11d9f393bbd3850bbe8f47f6d0Jean-Baptiste Queru 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDigitList::~DigitList() 110bbb04983e06b0e11d9f393bbd3850bbe8f47f6d0Jean-Baptiste Queru{ 111bbb04983e06b0e11d9f393bbd3850bbe8f47f6d0Jean-Baptiste Queru} 112bbb04983e06b0e11d9f393bbd3850bbe8f47f6d0Jean-Baptiste Queru 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// copy constructor 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::DigitList(const DigitList &other) 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 11827f654740f2a26ad62a5c155af9199af9e69b889claireho fDecNumber = fStorage.getAlias(); 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *this = other; 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// assignment operator 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList& 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::operator=(const DigitList& other) 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (this != &other) 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(&fContext, &other.fContext, sizeof(decContext)); 13250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 13327f654740f2a26ad62a5c155af9199af9e69b889claireho if (other.fStorage.getCapacity() > fStorage.getCapacity()) { 13427f654740f2a26ad62a5c155af9199af9e69b889claireho fDecNumber = fStorage.resize(other.fStorage.getCapacity()); 13527f654740f2a26ad62a5c155af9199af9e69b889claireho } 13627f654740f2a26ad62a5c155af9199af9e69b889claireho // Always reset the fContext.digits, even if fDecNumber was not reallocated, 13727f654740f2a26ad62a5c155af9199af9e69b889claireho // because above we copied fContext from other.fContext. 13827f654740f2a26ad62a5c155af9199af9e69b889claireho fContext.digits = fStorage.getCapacity(); 13950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(fDecNumber, other.fDecNumber); 14050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius { 142103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // fDouble is lazily created and cached. 143103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Avoid potential races with that happening with other.fDouble 144103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // while we are doing the assignment. 145103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius Mutex mutex; 146103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 147103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if(other.fHave==kDouble) { 1488de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert fUnion.fDouble = other.fUnion.fDouble; 149103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 150103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fHave = other.fHave; 151103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return *this; 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// operator == (does not exactly match the old DigitList function) 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::operator==(const DigitList& that) const 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (this == &that) { 16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return TRUE; 16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber n; // Has space for only a none digit value. 16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext c; 16750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&c, DEC_INIT_BASE); 16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c.digits = 1; 16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c.traps = 0; 17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c); 17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool result = decNumberIsZero(&n); 17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// comparison function. Returns 17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Not Comparable : -2 17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// < : -1 18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// == : 0 18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// > : +1 18250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t DigitList::compare(const DigitList &other) { 18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber result; 18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t savedDigits = fContext.digits; 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.digits = 1; 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext); 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.digits = savedDigits; 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(&result)) { 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (decNumberIsSpecial(&result)) { 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return -2; 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (result.bits & DECNEG) { 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return -1; 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Reduce - remove trailing zero digits. 20250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 20350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::reduce() { 20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext); 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// trim - remove trailing fraction zero digits. 21050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 21150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::trim() { 21250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberTrim(fDecNumber); 21350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 21650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Resets the digit list; sets all the digits to zero. 21750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 21850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 21950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::clear() 22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(fDecNumber); 22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); 223103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalSetDouble(0.0); 22450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Formats a int64_t number into a base 10 string representation, and NULL terminates it. 229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param number The number to format 23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @param outputStr The string to output to. Must be at least MAX_DIGITS+2 in length (21), 23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * to hold the longest int64_t value. 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the number of digits written, not including the sign. 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t 23550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoformatBase10(int64_t number, char *outputStr) { 23650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The number is output backwards, starting with the LSD. 23750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Fill the buffer from the far end. After the number is complete, 23850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // slide the string contents to the front. 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const int32_t MAX_IDX = MAX_DIGITS+2; 24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t destIdx = MAX_IDX; 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho outputStr[--destIdx] = 0; 24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int64_t n = number; 24550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (number < 0) { // Negative numbers are slightly larger than a postive 24650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho outputStr[--destIdx] = (char)(-(n % 10) + kZero); 24750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n /= -10; 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 24950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { 25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho outputStr[--destIdx] = (char)(n % 10 + kZero); 25150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n /= 10; 25250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while (n > 0); 25350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 25450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (number < 0) { 25550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho outputStr[--destIdx] = '-'; 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 25850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Slide the number to the start of the output str 25950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(destIdx >= 0); 26050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t length = MAX_IDX - destIdx; 26150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memmove(outputStr, outputStr+MAX_IDX-length, length); 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 26350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return length; 26450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 26550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 26650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 26750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// 269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// setRoundingMode() 270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// For most modes, the meaning and names are the same between the decNumber library 271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// (which DigitList follows) and the ICU Formatting Rounding Mode values. 272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// The flag constants are different, however. 273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// 274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Note that ICU's kRoundingUnnecessary is not implemented directly by DigitList. 275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// This mode, inherited from Java, means that numbers that would not format exactly 276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// will return an error when formatting is attempted. 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 27850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::setRoundingMode(DecimalFormat::ERoundingMode m) { 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho enum rounding r; 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (m) { 28350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundCeiling: r = DEC_ROUND_CEILING; break; 28450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundFloor: r = DEC_ROUND_FLOOR; break; 28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundDown: r = DEC_ROUND_DOWN; break; 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundUp: r = DEC_ROUND_UP; break; 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break; 28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break; 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DecimalFormat::kRoundHalfUp: r = DEC_ROUND_HALF_UP; break; 290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break; 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // TODO: how to report the problem? 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Leave existing mode unchanged. 29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho r = uprv_decContextGetRounding(&fContext); 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetRounding(&fContext, r); 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::setPositive(UBool s) { 30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (s) { 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->bits &= ~DECNEG; 30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->bits |= DECNEG; 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 310103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 31450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 31550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::setDecimalAt(int32_t d) { 31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN 31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(d-1>-999999999); 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(d-1< 999999999); 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t adjustedDigits = fDecNumber->digits; 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(fDecNumber)) { 32150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Account for difference in how zero is represented between DigitList & decNumber. 32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjustedDigits = 0; 323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->exponent = d - adjustedDigits; 325103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t 32950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::getDecimalAt() { 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) { 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return fDecNumber->exponent; // Exponent should be zero for these cases. 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return fDecNumber->exponent + fDecNumber->digits; 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 33750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 33850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::setCount(int32_t c) { 33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(c <= fContext.digits); 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c == 0) { 34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // For a value of zero, DigitList sets all fields to zero, while 34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // decNumber keeps one digit (with that digit being a zero) 34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c = 1; 34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->lsu[0] = 0; 345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->digits = c; 347103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 35050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t 35150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::getCount() const { 35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) { 35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The extra test for exponent==0 is needed because parsing sometimes appends 35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // zero digits. It's bogus, decimalFormatter parsing needs to be cleaned up. 35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return fDecNumber->digits; 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 36150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 36250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::setDigit(int32_t i, char v) { 36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t count = fDecNumber->digits; 36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(i<count); 36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(v>='0' && v<='9'); 36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho v &= 0x0f; 36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->lsu[count-i-1] = v; 368103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 37150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehochar 37250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::getDigit(int32_t i) { 37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t count = fDecNumber->digits; 37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(i<count); 37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return fDecNumber->lsu[count-i-1] + '0'; 37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 37827f654740f2a26ad62a5c155af9199af9e69b889claireho// copied from DigitList::getDigit() 37927f654740f2a26ad62a5c155af9199af9e69b889clairehouint8_t 38027f654740f2a26ad62a5c155af9199af9e69b889clairehoDigitList::getDigitValue(int32_t i) { 38127f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t count = fDecNumber->digits; 38227f654740f2a26ad62a5c155af9199af9e69b889claireho U_ASSERT(i<count); 38327f654740f2a26ad62a5c155af9199af9e69b889claireho return fDecNumber->lsu[count-i-1]; 38427f654740f2a26ad62a5c155af9199af9e69b889claireho} 38527f654740f2a26ad62a5c155af9199af9e69b889claireho 38650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Appends the digit to the digit list if it's not out of scope. 38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Ignores the digit, otherwise. 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// 39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// This function is horribly inefficient to implement with decNumber because 39150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// the digits are stored least significant first, which requires moving all 39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// existing digits down one to make space for the new one to be appended. 39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// 39450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 39550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::append(char digit) 39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(digit>='0' && digit<='9'); 39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Ignore digits which exceed the precision we can represent 39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // And don't fix for larger precision. Fix callers instead. 40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(fDecNumber)) { 40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Zero needs to be special cased because of the difference in the way 40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // that the old DigitList and decNumber represent it. 40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // digit cout was zero for digitList, is one for decNumber 40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->lsu[0] = digit & 0x0f; 40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->digits = 1; 40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->exponent--; // To match the old digit list implementation. 40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t nDigits = fDecNumber->digits; 40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (nDigits < fContext.digits) { 41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int i; 41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=nDigits; i>0; i--) { 41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->lsu[i] = fDecNumber->lsu[i-1]; 41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->lsu[0] = digit & 0x0f; 41550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->digits++; 41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // DigitList emulation - appending doesn't change the magnitude of existing 41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // digits. With decNumber's decimal being after the 41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // least signficant digit, we need to adjust the exponent. 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fDecNumber->exponent--; 42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 422103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 428103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Currently, getDouble() depends on strtod() to do its conversion. 429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * WARNING!! 431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This is an extremely costly function. ~1/2 of the conversion time 432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * can be linked to this function. 433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble 43550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::getDouble() const 436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 437103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius { 438103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius Mutex mutex; 439103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (fHave == kDouble) { 440103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fUnion.fDouble; 441103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 444103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius double tDouble = 0.0; 44550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (isZero()) { 446103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tDouble = 0.0; 44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(fDecNumber)) { 448103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tDouble /= -1; 44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 45050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (isInfinite()) { 45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (std::numeric_limits<double>::has_infinity) { 452103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tDouble = std::numeric_limits<double>::infinity(); 45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tDouble = std::numeric_limits<double>::max(); 45550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!isPositive()) { 457103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tDouble = -tDouble; //this was incorrectly "-fDouble" originally. 458103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho MaybeStackArray<char, MAX_DBL_DIGITS+18> s; 46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Note: 14 is a magic constant from the decNumber library documentation, 46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // the max number of extra characters beyond the number of digits 46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // needed to represent the number in string form. Add a few more 46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // for the additional digits we retain. 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Round down to appx. double precision, if the number is longer than that. 46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Copy the number first, so that we don't modify the original. 46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (getCount() > MAX_DBL_DIGITS + 3) { 46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList numToConvert(*this); 47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. 47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho numToConvert.round(MAX_DBL_DIGITS+3); 47254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias()); 47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // TODO: how many extra digits should be included for an accurate conversion? 47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 47554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_decNumberToString(this->fDecNumber, s.getAlias()); 47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); 47864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *end = NULL; 48064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert tDouble = decimalStrToDouble(s.getAlias(), &end); 481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 482103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius { 483103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius Mutex mutex; 484103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius DigitList *nonConstThis = const_cast<DigitList *>(this); 485103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius nonConstThis->internalSetDouble(tDouble); 486103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 487103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return tDouble; 488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 49064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if U_USE_STRTOD_L && U_PLATFORM_USES_ONLY_WIN32_API 49164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# define locale_t _locale_t 49264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# define freelocale _free_locale 49364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# define strtod_l _strtod_l 49464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 49564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 49664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if U_USE_STRTOD_L 49764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic locale_t gCLocale = (locale_t)0; 49864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 49964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic icu::UInitOnce gCLocaleInitOnce = U_INITONCE_INITIALIZER; 50064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 50164339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertU_CDECL_BEGIN 50264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Cleanup callback func 50364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic UBool U_CALLCONV digitList_cleanup(void) 50464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert{ 50564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if U_USE_STRTOD_L 50664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert if (gCLocale != (locale_t)0) { 50764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert freelocale(gCLocale); 50864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert } 50964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 51064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert return TRUE; 51164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert} 51264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// C Locale initialization func 51364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic void U_CALLCONV initCLocale(void) { 51464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert ucln_i18n_registerCleanup(UCLN_I18N_DIGITLIST, digitList_cleanup); 51564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if U_USE_STRTOD_L 51664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# if U_PLATFORM_USES_ONLY_WIN32_API 51764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert gCLocale = _create_locale(LC_ALL, "C"); 51864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# else 51964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert gCLocale = newlocale(LC_ALL_MASK, "C", (locale_t)0); 52064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert# endif 52164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 52264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert} 52364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertU_CDECL_END 52464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 52564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertdouble 52664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDigitList::decimalStrToDouble(char *decstr, char **end) { 52764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert umtx_initOnce(gCLocaleInitOnce, &initCLocale); 52864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#if U_USE_STRTOD_L 52964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert return strtod_l(decstr, end, gCLocale); 53064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#else 53164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert char *decimalPt = strchr(decstr, '.'); 53264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert if (decimalPt) { 53364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert // We need to know the decimal separator character that will be used with strtod(). 53464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert // Depends on the C runtime global locale. 53564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert // Most commonly is '.' 53664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert char rep[MAX_DIGITS]; 53764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert sprintf(rep, "%+1.1f", 1.0); 53864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *decimalPt = rep[2]; 53964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert } 54064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert return uprv_strtod(decstr, end); 54164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#endif 54264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert} 54364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert 544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * convert this number to an int32_t. Round if there is a fractional part. 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Return zero if the number cannot be represented. 549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t DigitList::getLong() /*const*/ 551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t result = 0; 553c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (getUpperExponent() > 10) { 55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Overflow, absolute value too big. 55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 55750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fDecNumber->exponent != 0) { 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Force to an integer, with zero exponent, rounding if necessary. 55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // (decNumberToInt32 will only work if the exponent is exactly zero.) 56050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList copy(*this); 56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList zero; 56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext); 56350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = uprv_decNumberToInt32(copy.fDecNumber, &fContext); 56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = uprv_decNumberToInt32(fDecNumber, &fContext); 566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 570103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 5723ef011cb2ded20c46f764e284c6a10f49a9923f8claireho * convert this number to an int64_t. Truncate if there is a fractional part. 57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Return zero if the number cannot be represented. 574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint64_t DigitList::getInt64() /*const*/ { 5768de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert // TODO: fast conversion if fHave == fDouble 5778de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert 5783ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // Truncate if non-integer. 57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Return 0 if out of range. 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digits) 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // 582c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (getUpperExponent() > 19) { 58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Overflow, absolute value too big. 58450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5873ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // The number of integer digits may differ from the number of digits stored 5883ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // in the decimal number. 5893ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // for 12.345 numIntDigits = 2, number->digits = 5 5903ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // for 12E4 numIntDigits = 6, number->digits = 2 5913ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // The conversion ignores the fraction digits in the first case, 5923ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // and fakes up extra zero digits in the second. 5933ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // TODO: It would be faster to store a table of powers of ten to multiply by 5943ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // instead of looping over zero digits, multiplying each time. 595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 596c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t numIntDigits = getUpperExponent(); 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint64_t value = 0; 5983ef011cb2ded20c46f764e284c6a10f49a9923f8claireho for (int32_t i = 0; i < numIntDigits; i++) { 5993ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // Loop is iterating over digits starting with the most significant. 6003ef011cb2ded20c46f764e284c6a10f49a9923f8claireho // Numbers are stored with the least significant digit at index zero. 6013ef011cb2ded20c46f764e284c6a10f49a9923f8claireho int32_t digitIndex = fDecNumber->digits - i - 1; 6023ef011cb2ded20c46f764e284c6a10f49a9923f8claireho int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0; 60350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho value = value * (uint64_t)10 + (uint64_t)v; 60450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 6053ef011cb2ded20c46f764e284c6a10f49a9923f8claireho 6063ef011cb2ded20c46f764e284c6a10f49a9923f8claireho if (decNumberIsNegative(fDecNumber)) { 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho value = ~value; 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho value += 1; 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int64_t svalue = (int64_t)value; 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Check overflow. It's convenient that the MSD is 9 only on overflow, the amount of 61350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // overflow can't wrap too far. The test will also fail -0, but 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // that does no harm; the right answer is 0. 6153ef011cb2ded20c46f764e284c6a10f49a9923f8claireho if (numIntDigits == 19) { 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (( decNumberIsNegative(fDecNumber) && svalue>0) || 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (!decNumberIsNegative(fDecNumber) && svalue<0)) { 61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho svalue = 0; 619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return svalue; 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 625103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/** 62750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Return a string form of this number. 62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Format is as defined by the decNumber library, for interchange of 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * decimal numbers. 63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 63127f654740f2a26ad62a5c155af9199af9e69b889clairehovoid DigitList::getDecimal(CharString &str, UErrorCode &status) { 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 63527f654740f2a26ad62a5c155af9199af9e69b889claireho 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // A decimal number in string form can, worst case, be 14 characters longer 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // than the number of digits. So says the decNumber library doc. 63827f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t maxLength = fDecNumber->digits + 14; 63927f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t capacity = 0; 64027f654740f2a26ad62a5c155af9199af9e69b889claireho char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status); 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 64250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; // Memory allocation error on growing the string. 64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64427f654740f2a26ad62a5c155af9199af9e69b889claireho U_ASSERT(capacity >= maxLength); 64527f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_decNumberToString(this->fDecNumber, buffer); 64627f654740f2a26ad62a5c155af9199af9e69b889claireho U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength); 64727f654740f2a26ad62a5c155af9199af9e69b889claireho str.append(buffer, -1, status); 648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Return true if this is an integer value that can be held 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * by an int32_t type. 653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/ 656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 65750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(this->fDecNumber)) { 65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // NaN or Infinity. Does not fit in int32. 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberTrim(this->fDecNumber); 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fDecNumber->exponent < 0) { 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Number contains fraction digits. 664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (fDecNumber->bits & DECNEG) != 0) { 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Negative Zero, not ingored. Cannot represent as a long. 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 671c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (getUpperExponent() < 10) { 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The number is 9 or fewer digits. 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The max and min int32 are 10 digts, so this number fits. 67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // This is the common case. 675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // TODO: Should cache these constants; construction is relatively costly. 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // But not of huge consequence; they're only needed for 10 digit ints. 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 68150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList min32; min32.set("-2147483648", status); 68250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (this->compare(min32) < 0) { 68350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 68450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList max32; max32.set("2147483647", status); 68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (this->compare(max32) > 0) { 68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return true; 69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return true if the number represented by this object can fit into 699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * a long. 700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/ 703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 70450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(this->fDecNumber)) { 70550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // NaN or Infinity. Does not fit in int32. 70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 70850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberTrim(this->fDecNumber); 70950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fDecNumber->exponent < 0) { 71050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Number contains fraction digits. 711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && 71450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (fDecNumber->bits & DECNEG) != 0) { 71550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Negative Zero, not ingored. Cannot represent as a long. 71650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 71750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 718c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (getUpperExponent() < 19) { 71950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The number is 18 or fewer digits. 72050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The max and min int64 are 19 digts, so this number fits. 72150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // This is the common case. 722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 72350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 72550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // TODO: Should cache these constants; construction is relatively costly. 72650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // But not of huge consequence; they're only needed for 19 digit ints. 72750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 72850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList min64; min64.set("-9223372036854775808", status); 72950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (this->compare(min64) < 0) { 73050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 73150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DigitList max64; max64.set("9223372036854775807", status); 73350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (this->compare(max64) > 0) { 73450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 73650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 73750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 73850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 73950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return true; 740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 74650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::set(int32_t source) 747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 74850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho set((int64_t)source); 749103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalSetDouble(source); 750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 754103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Set an int64, via decnumber 755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 75750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::set(int64_t source) 758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 75950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char str[MAX_DIGITS+2]; // Leave room for sign and trailing nul. 76050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho formatBase10(source, str); 76150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(uprv_strlen(str) < sizeof(str)); 762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromString(fDecNumber, str, &fContext); 7641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert internalSetDouble(static_cast<double>(source)); 765103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 766103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 76750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 76850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/** 76950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Set the DigitList from a decimal number string. 77050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 77127f654740f2a26ad62a5c155af9199af9e69b889claireho * The incoming string _must_ be nul terminated, even though it is arriving 77250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * as a StringPiece because that is what the decNumber library wants. 77350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * We can get away with this for an internal function; it would not 77450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * be acceptable for a public API. 77550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 77650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 77764339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDigitList::set(StringPiece source, UErrorCode &status, uint32_t /*fastpathBits*/) { 77850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 77950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 78050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 78150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 78254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if 0 78354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if(fastpathBits==(kFastpathOk|kNoDecimal)) { 78454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t size = source.size(); 78554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char *data = source.data(); 78654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int64_t r = 0; 78754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int64_t m = 1; 78854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // fast parse 78954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius while(size>0) { 79054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius char ch = data[--size]; 79154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if(ch=='+') { 79254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius break; 79354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else if(ch=='-') { 79454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius r = -r; 79554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius break; 79654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 79754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int64_t d = ch-'0'; 79854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius //printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m); 79954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius r+=(d)*m; 80054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius m *= 10; 80154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 80254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 80354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius //printf("R=%d\n", r); 80454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius set(r); 80554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else 80654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#endif 80754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius { 80854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // Figure out a max number of digits to use during the conversion, and 80954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // resize the number up if necessary. 81054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t numDigits = source.length(); 81154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (numDigits > fContext.digits) { 81227f654740f2a26ad62a5c155af9199af9e69b889claireho // fContext.digits == fStorage.getCapacity() 81327f654740f2a26ad62a5c155af9199af9e69b889claireho decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity()); 81450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (t == NULL) { 81554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius status = U_MEMORY_ALLOCATION_ERROR; 81654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius return; 81750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 81827f654740f2a26ad62a5c155af9199af9e69b889claireho fDecNumber = t; 81927f654740f2a26ad62a5c155af9199af9e69b889claireho fContext.digits = numDigits; 82054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 82127f654740f2a26ad62a5c155af9199af9e69b889claireho 82254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius fContext.status = 0; 82354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_decNumberFromString(fDecNumber, source.data(), &fContext); 82454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if ((fContext.status & DEC_Conversion_syntax) != 0) { 82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_DECIMAL_NUMBER_SYNTAX_ERROR; 82654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 82750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 828103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 82950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Set the digit list to a representation of the given double value. 833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This method supports both fixed-point and exponential notation. 83450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @param source Value to be converted. 835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 83750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::set(double source) 838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // for now, simple implementation; later, do proper IEEE stuff 840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough) 841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 842103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Generate a representation of the form /[+-][0-9].[0-9]+e[+-][0-9]+/ 843103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Can also generate /[+-]nan/ or /[+-]inf/ 844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // TODO: Use something other than sprintf() here, since it's behavior is somewhat platform specific. 845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // That is why infinity is special cased here. 846103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (uprv_isInfinite(source)) { 847103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (uprv_isNegativeInfinity(source)) { 848103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_strcpy(rep,"-inf"); // Handle negative infinity 849103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 850103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_strcpy(rep,"inf"); 851103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 852103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 853103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source); 854103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 85550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(uprv_strlen(rep) < sizeof(rep)); 856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 857103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // uprv_decNumberFromString() will parse the string expecting '.' as a 858103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // decimal separator, however sprintf() can use ',' in certain locales. 859103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Overwrite a ',' with '.' here before proceeding. 860103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius char *decimalSeparator = strchr(rep, ','); 861103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (decimalSeparator != NULL) { 862103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius *decimalSeparator = '.'; 863103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 864103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 86550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Create a decNumber from the string. 86650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromString(fDecNumber, rep, &fContext); 86750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberTrim(fDecNumber); 868103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalSetDouble(source); 86950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 87150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 87350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 87450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Multiply 87550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * The number will be expanded if need be to retain full precision. 87650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * In practice, for formatting, multiply is by 10, 100 or 1000, so more digits 87750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * will not be required for this use. 87850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 87950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 88050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::mult(const DigitList &other, UErrorCode &status) { 881c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (U_FAILURE(status)) { 882c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return; 883c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 88450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.status = 0; 88550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t requiredDigits = this->digits() + other.digits(); 88650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (requiredDigits > fContext.digits) { 88750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho reduce(); // Remove any trailing zeros 88850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t requiredDigits = this->digits() + other.digits(); 88950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ensureCapacity(requiredDigits, status); 890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 89150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext); 892103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 89350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 89550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 89650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 89750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 89850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Divide 89950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * The number will _not_ be expanded for inexact results. 90050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * TODO: probably should expand some, for rounding increments that 90150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * could add a few digits, e.g. .25, but not expand arbitrarily. 90250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 90350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 90450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::div(const DigitList &other, UErrorCode &status) { 90550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 90850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext); 909103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 91050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 91250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 91450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 91550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * ensureCapacity. Grow the digit storage for the number if it's less than the requested 91650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * amount. Never reduce it. Available size is kept in fContext.digits. 91750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 91850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 91950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) { 92050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 92150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 92350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (requestedCapacity <= 0) { 92450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ILLEGAL_ARGUMENT_ERROR; 92550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 92650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 92750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (requestedCapacity > DEC_MAX_DIGITS) { 92850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Don't report an error for requesting too much. 92950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Arithemetic Results will be rounded to what can be supported. 93050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // At 999,999,999 max digits, exceeding the limit is not too likely! 93150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho requestedCapacity = DEC_MAX_DIGITS; 932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 93350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (requestedCapacity > fContext.digits) { 93427f654740f2a26ad62a5c155af9199af9e69b889claireho decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity()); 93550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (newBuffer == NULL) { 93650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 93750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 93850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 93950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.digits = requestedCapacity; 94027f654740f2a26ad62a5c155af9199af9e69b889claireho fDecNumber = newBuffer; 941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Round the representation to the given number of digits. 948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param maximumDigits The maximum number of digits to be shown. 949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Upon return, count will be less than or equal to maximumDigits. 950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::round(int32_t maximumDigits) 953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 954c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert reduce(); 955c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (maximumDigits >= fDecNumber->digits) { 956c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return; 957c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 95850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t savedDigits = fContext.digits; 95950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.digits = maximumDigits; 96050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext); 96150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fContext.digits = savedDigits; 96250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberTrim(fDecNumber); 963c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert reduce(); 964103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 96850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 96950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::roundFixedPoint(int32_t maximumFractionDigits) { 970c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert reduce(); // Remove trailing zeros. 97150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fDecNumber->exponent >= -maximumFractionDigits) { 97250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 97450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber scale; // Dummy decimal number, but with the desired number of 97550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&scale); // fraction digits. 97650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho scale.exponent = -maximumFractionDigits; 97750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho scale.lsu[0] = 1; 97850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 97950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext); 980c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert reduce(); 981103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalClear(); 982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ------------------------------------- 985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 98750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDigitList::toIntegralValue() { 98850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext); 989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 99150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 99250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDigitList::isZero() const 995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 99650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return decNumberIsZero(fDecNumber); 997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 999c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert// ------------------------------------- 1000c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertint32_t 1001c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::getUpperExponent() const { 1002c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return fDecNumber->digits + fDecNumber->exponent; 1003c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1004c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1005c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitInterval & 1006c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::getSmallestInterval(DigitInterval &result) const { 1007c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert result.setLeastSignificantInclusive(fDecNumber->exponent); 1008c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert result.setMostSignificantExclusive(getUpperExponent()); 1009c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return result; 1010c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1011c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1012c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertuint8_t 1013c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::getDigitByExponent(int32_t exponent) const { 1014c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t idx = exponent - fDecNumber->exponent; 1015c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (idx < 0 || idx >= fDecNumber->digits) { 1016c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return 0; 1017c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1018c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return fDecNumber->lsu[idx]; 1019c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1020c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1021c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertvoid 1022c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::appendDigitsTo(CharString &str, UErrorCode &status) const { 1023c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status); 1024c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1025c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1026c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertvoid 1027c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) { 1028c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert reduce(); 1029c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (maxSigDigits < fDecNumber->digits) { 1030c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t minExponent = getUpperExponent() - maxSigDigits; 1031c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (exponent < minExponent) { 1032c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert exponent = minExponent; 1033c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1034c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1035c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (exponent <= fDecNumber->exponent) { 1036c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return; 1037c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1038c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t digits = getUpperExponent() - exponent; 1039c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (digits > 0) { 1040c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert round(digits); 1041c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } else { 1042c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert roundFixedPoint(-exponent); 1043c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1044c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1045c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1046c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertvoid 1047c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::quantize(const DigitList &quantity, UErrorCode &status) { 1048c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (U_FAILURE(status)) { 1049c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return; 1050c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1051c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert div(quantity, status); 1052c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert roundAtExponent(0); 1053c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert mult(quantity, status); 1054c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert reduce(); 1055c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1056c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1057c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertint32_t 1058c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::getScientificExponent( 1059c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t minIntDigitCount, int32_t exponentMultiplier) const { 1060c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert // The exponent for zero is always zero. 1061c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (isZero()) { 1062c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return 0; 1063c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1064c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t intDigitCount = getUpperExponent(); 1065c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t exponent; 1066c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (intDigitCount >= minIntDigitCount) { 1067c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t maxAdjustment = intDigitCount - minIntDigitCount; 1068c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier; 1069c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } else { 1070c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t minAdjustment = minIntDigitCount - intDigitCount; 1071c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplier) * -exponentMultiplier; 1072c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 1073c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return exponent; 1074c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1075c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1076c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertint32_t 1077c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::toScientific( 1078c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t minIntDigitCount, int32_t exponentMultiplier) { 1079c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t exponent = getScientificExponent( 1080c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert minIntDigitCount, exponentMultiplier); 1081c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert shiftDecimalRight(-exponent); 1082c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return exponent; 1083c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1084c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1085c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertvoid 1086c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitList::shiftDecimalRight(int32_t n) { 1087c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert fDecNumber->exponent += n; 1088c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert internalClear(); 1089c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 1090c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif // #if !UCONFIG_NO_FORMATTING 1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof 1095