1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 1997-2010, International Business Machines 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* File DIGITLST.CPP 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Modification History: 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Date Name Description 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 03/21/97 clhuang Converted from java. 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 03/21/97 clhuang Implemented with new APIs. 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 03/27/97 helena Updated to pass the simple test after code review. 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 03/31/97 aliu Moved isLONG_MIN to here, and fixed it. 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char. 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Reworked representation by replacing fDecimalAt 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* with fExponent. 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 04/16/97 aliu Rewrote set() and getDouble() to use sprintf/atof 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* to do digit conversion. 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 09/09/97 aliu Modified for exponential notation support. 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 08/02/98 stephen Added nearest/even rounding 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Fixed bug in fitsIntoLong 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)****************************************************************************** 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/ 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "digitlst.h" 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_FORMATTING 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/putil.h" 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "charstr.h" 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h" 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cstring.h" 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "putilimp.h" 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uassert.h" 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <stdlib.h> 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <limits.h> 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <string.h> 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <stdio.h> 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <limits> 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// *************************************************************************** 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class DigitList 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// A wrapper onto decNumber. 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Used to be standalone. 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// *************************************************************************** 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This is the zero digit. The base for the digits returned by getDigit() 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Note that it is the platform invariant digit, and is not Unicode. 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define kZero '0' 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static char gDecimal = 0; 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Only for 32 bit numbers. Ignore the negative sign. */ 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char LONG_MIN_REP[] = "2147483648"; 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char I64_MIN_REP[] = "9223372036854775808"; 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_BEGIN 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)loadDecimalChar() { 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (gDecimal == 0) { 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char rep[MAX_DIGITS]; 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // For machines that decide to change the decimal on you, 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // and try to be too smart with localization. 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // This normally should be just a '.'. 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) sprintf(rep, "%+1.1f", 1.0); 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) gDecimal = rep[2]; 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// default constructor 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::DigitList() 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decContextDefault(&fContext, DEC_INIT_BASE); 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.traps = 0; 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = fStorage.getCapacity(); 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber = fStorage.getAlias(); 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberZero(fDecNumber); 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDouble = 0.0; 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = TRUE; 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::~DigitList() 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// copy constructor 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::DigitList(const DigitList &other) 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber = fStorage.getAlias(); 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *this = other; 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// assignment operator 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList& 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::operator=(const DigitList& other) 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (this != &other) 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memcpy(&fContext, &other.fContext, sizeof(decContext)); 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (other.fStorage.getCapacity() > fStorage.getCapacity()) { 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber = fStorage.resize(other.fStorage.getCapacity()); 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Always reset the fContext.digits, even if fDecNumber was not reallocated, 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // because above we copied fContext from other.fContext. 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = fStorage.getCapacity(); 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberCopy(fDecNumber, other.fDecNumber); 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDouble = other.fDouble; 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = other.fHaveDouble; 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return *this; 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// operator == (does not exactly match the old DigitList function) 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::operator==(const DigitList& that) const 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (this == &that) { 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decNumber n; // Has space for only a none digit value. 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decContext c; 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decContextDefault(&c, DEC_INIT_BASE); 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) c.digits = 1; 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) c.traps = 0; 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c); 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool result = decNumberIsZero(&n); 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// comparison function. Returns 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Not Comparable : -2 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// < : -1 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// == : 0 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// > : +1 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t DigitList::compare(const DigitList &other) { 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decNumber result; 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t savedDigits = fContext.digits; 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = 1; 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext); 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = savedDigits; 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(&result)) { 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (decNumberIsSpecial(&result)) { 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return -2; 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (result.bits & DECNEG) { 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return -1; 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 1; 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Reduce - remove trailing zero digits. 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::reduce() { 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext); 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// trim - remove trailing fraction zero digits. 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::trim() { 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberTrim(fDecNumber); 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Resets the digit list; sets all the digits to zero. 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::clear() 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberZero(fDecNumber); 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDouble = 0.0; 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = TRUE; 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Formats a int64_t number into a base 10 string representation, and NULL terminates it. 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param number The number to format 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param outputStr The string to output to. Must be at least MAX_DIGITS+2 in length (21), 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * to hold the longest int64_t value. 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @return the number of digits written, not including the sign. 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)formatBase10(int64_t number, char *outputStr) { 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The number is output backwards, starting with the LSD. 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Fill the buffer from the far end. After the number is complete, 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // slide the string contents to the front. 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const int32_t MAX_IDX = MAX_DIGITS+2; 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t destIdx = MAX_IDX; 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outputStr[--destIdx] = 0; 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int64_t n = number; 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (number < 0) { // Negative numbers are slightly larger than a postive 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outputStr[--destIdx] = (char)(-(n % 10) + kZero); 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) n /= -10; 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) do { 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outputStr[--destIdx] = (char)(n % 10 + kZero); 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) n /= 10; 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } while (n > 0); 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (number < 0) { 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outputStr[--destIdx] = '-'; 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Slide the number to the start of the output str 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(destIdx >= 0); 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length = MAX_IDX - destIdx; 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memmove(outputStr, outputStr+MAX_IDX-length, length); 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return length; 241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) { 248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) enum rounding r; 249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) switch (m) { 251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundCeiling: r = DEC_ROUND_CEILING; break; 252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundFloor: r = DEC_ROUND_FLOOR; break; 253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundDown: r = DEC_ROUND_DOWN; break; 254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundUp: r = DEC_ROUND_UP; break; 255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break; 256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break; 257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case DecimalFormat::kRoundHalfUp: r = DEC_ROUND_HALF_UP; break; 258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) default: 259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: how to report the problem? 260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Leave existing mode unchanged. 261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) r = uprv_decContextGetRounding(&fContext); 262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decContextSetRounding(&fContext, r); 264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::setPositive(UBool s) { 272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (s) { 273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->bits &= ~DECNEG; 274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->bits |= DECNEG; 276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::setDecimalAt(int32_t d) { 283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN 284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(d-1>-999999999); 285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(d-1< 999999999); 286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t adjustedDigits = fDecNumber->digits; 287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(fDecNumber)) { 288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Account for difference in how zero is represented between DigitList & decNumber. 289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) adjustedDigits = 0; 290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->exponent = d - adjustedDigits; 292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t 296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::getDecimalAt() { 297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN 298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) { 299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDecNumber->exponent; // Exponent should be zero for these cases. 300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDecNumber->exponent + fDecNumber->digits; 302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::setCount(int32_t c) { 306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(c <= fContext.digits); 307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (c == 0) { 308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // For a value of zero, DigitList sets all fields to zero, while 309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // decNumber keeps one digit (with that digit being a zero) 310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) c = 1; 311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->lsu[0] = 0; 312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->digits = c; 314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t 318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::getCount() const { 319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) { 320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The extra test for exponent==0 is needed because parsing sometimes appends 321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // zero digits. It's bogus, decimalFormatter parsing needs to be cleaned up. 322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDecNumber->digits; 325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::setDigit(int32_t i, char v) { 330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t count = fDecNumber->digits; 331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(i<count); 332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(v>='0' && v<='9'); 333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) v &= 0x0f; 334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->lsu[count-i-1] = v; 335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)char 339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::getDigit(int32_t i) { 340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t count = fDecNumber->digits; 341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(i<count); 342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDecNumber->lsu[count-i-1] + '0'; 343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// copied from DigitList::getDigit() 346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uint8_t 347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::getDigitValue(int32_t i) { 348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t count = fDecNumber->digits; 349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(i<count); 350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDecNumber->lsu[count-i-1]; 351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Appends the digit to the digit list if it's not out of scope. 355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Ignores the digit, otherwise. 356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// This function is horribly inefficient to implement with decNumber because 358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// the digits are stored least significant first, which requires moving all 359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// existing digits down one to make space for the new one to be appended. 360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::append(char digit) 363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(digit>='0' && digit<='9'); 365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Ignore digits which exceed the precision we can represent 366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // And don't fix for larger precision. Fix callers instead. 367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(fDecNumber)) { 368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Zero needs to be special cased because of the difference in the way 369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // that the old DigitList and decNumber represent it. 370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // digit cout was zero for digitList, is one for decNumber 371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->lsu[0] = digit & 0x0f; 372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->digits = 1; 373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->exponent--; // To match the old digit list implementation. 374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t nDigits = fDecNumber->digits; 376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (nDigits < fContext.digits) { 377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int i; 378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (i=nDigits; i>0; i--) { 379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->lsu[i] = fDecNumber->lsu[i-1]; 380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->lsu[0] = digit & 0x0f; 382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->digits++; 383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // DigitList emulation - appending doesn't change the magnitude of existing 384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // digits. With decNumber's decimal being after the 385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // least signficant digit, we need to adjust the exponent. 386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber->exponent--; 387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Currently, getDouble() depends on atof() to do its conversion. 396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * WARNING!! 398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This is an extremely costly function. ~1/2 of the conversion time 399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * can be linked to this function. 400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)double 402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::getDouble() const 403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: fix thread safety. Can probably be finessed some by analyzing 405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // what public const functions can see which DigitLists. 406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Like precompute fDouble for DigitLists coming in from a parse 407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // or from a Formattable::set(), but not for any others. 408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fHaveDouble) { 409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDouble; 410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList *nonConstThis = const_cast<DigitList *>(this); 412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isZero()) { 414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fDouble = 0.0; 415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsNegative(fDecNumber)) { 416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fDouble /= -1; 417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (isInfinite()) { 419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (std::numeric_limits<double>::has_infinity) { 420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fDouble = std::numeric_limits<double>::infinity(); 421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fDouble = std::numeric_limits<double>::max(); 423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!isPositive()) { 425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fDouble = -fDouble; 426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) MaybeStackArray<char, MAX_DBL_DIGITS+18> s; 429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Note: 14 is a magic constant from the decNumber library documentation, 430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // the max number of extra characters beyond the number of digits 431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // needed to represent the number in string form. Add a few more 432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // for the additional digits we retain. 433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Round down to appx. double precision, if the number is longer than that. 435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Copy the number first, so that we don't modify the original. 436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (getCount() > MAX_DBL_DIGITS + 3) { 437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList numToConvert(*this); 438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. 439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) numToConvert.round(MAX_DBL_DIGITS+3); 440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberToString(numToConvert.fDecNumber, s); 441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: how many extra digits should be included for an accurate conversion? 442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberToString(this->fDecNumber, s); 444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); 446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) loadDecimalChar(); 448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (gDecimal != '.') { 449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char *decimalPt = strchr(s, '.'); 450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decimalPt != NULL) { 451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *decimalPt = gDecimal; 452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char *end = NULL; 455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fDouble = uprv_strtod(s, &end); 456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->fHaveDouble = TRUE; 458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fDouble; 459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * convert this number to an int32_t. Round if there is a fractional part. 465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return zero if the number cannot be represented. 466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t DigitList::getLong() /*const*/ 468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t result = 0; 470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->digits + fDecNumber->exponent > 10) { 471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Overflow, absolute value too big. 472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->exponent != 0) { 475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Force to an integer, with zero exponent, rounding if necessary. 476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // (decNumberToInt32 will only work if the exponent is exactly zero.) 477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList copy(*this); 478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList zero; 479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext); 480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = uprv_decNumberToInt32(copy.fDecNumber, &fContext); 481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = uprv_decNumberToInt32(fDecNumber, &fContext); 483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * convert this number to an int64_t. Round if there is a fractional part. 490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return zero if the number cannot be represented. 491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int64_t DigitList::getInt64() /*const*/ { 493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Round if non-integer. (Truncate or round?) 494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Return 0 if out of range. 495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digits) 496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // 497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->digits + fDecNumber->exponent > 19) { 498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Overflow, absolute value too big. 499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decNumber *workingNum = fDecNumber; 502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->exponent != 0) { 504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Force to an integer, with zero exponent, rounding if necessary. 505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList copy(*this); 506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList zero; 507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext); 508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) workingNum = copy.fDecNumber; 509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uint64_t value = 0; 512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t numDigits = workingNum->digits; 513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (int i = numDigits-1; i>=0 ; --i) { 514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int v = workingNum->lsu[i]; 515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) value = value * (uint64_t)10 + (uint64_t)v; 516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsNegative(workingNum)) { 518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) value = ~value; 519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) value += 1; 520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int64_t svalue = (int64_t)value; 522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Check overflow. It's convenient that the MSD is 9 only on overflow, the amount of 524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // overflow can't wrap too far. The test will also fail -0, but 525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // that does no harm; the right answer is 0. 526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (numDigits == 19) { 527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (( decNumberIsNegative(fDecNumber) && svalue>0) || 528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (!decNumberIsNegative(fDecNumber) && svalue<0)) { 529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) svalue = 0; 530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return svalue; 534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return a string form of this number. 539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Format is as defined by the decNumber library, for interchange of 540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * decimal numbers. 541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void DigitList::getDecimal(CharString &str, UErrorCode &status) { 543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // A decimal number in string form can, worst case, be 14 characters longer 548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // than the number of digits. So says the decNumber library doc. 549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t maxLength = fDecNumber->digits + 14; 550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t capacity = 0; 551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status); 552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; // Memory allocation error on growing the string. 554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(capacity >= maxLength); 556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberToString(this->fDecNumber, buffer); 557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength); 558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) str.append(buffer, -1, status); 559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return true if this is an integer value that can be held 563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * by an int32_t type. 564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool 566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/ 567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsSpecial(this->fDecNumber)) { 569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // NaN or Infinity. Does not fit in int32. 570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberTrim(this->fDecNumber); 573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->exponent < 0) { 574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Number contains fraction digits. 575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && 578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (fDecNumber->bits & DECNEG) != 0) { 579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Negative Zero, not ingored. Cannot represent as a long. 580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->digits + fDecNumber->exponent < 10) { 583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The number is 9 or fewer digits. 584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The max and min int32 are 10 digts, so this number fits. 585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // This is the common case. 586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: Should cache these constants; construction is relatively costly. 590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // But not of huge consequence; they're only needed for 10 digit ints. 591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList min32; min32.set("-2147483648", status); 593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (this->compare(min32) < 0) { 594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList max32; max32.set("2147483647", status); 597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (this->compare(max32) > 0) { 598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return true; 604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return true if the number represented by this object can fit into 610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * a long. 611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool 613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/ 614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsSpecial(this->fDecNumber)) { 616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // NaN or Infinity. Does not fit in int32. 617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberTrim(this->fDecNumber); 620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->exponent < 0) { 621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Number contains fraction digits. 622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && 625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (fDecNumber->bits & DECNEG) != 0) { 626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Negative Zero, not ingored. Cannot represent as a long. 627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->digits + fDecNumber->exponent < 19) { 630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The number is 18 or fewer digits. 631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The max and min int64 are 19 digts, so this number fits. 632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // This is the common case. 633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: Should cache these constants; construction is relatively costly. 637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // But not of huge consequence; they're only needed for 19 digit ints. 638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList min64; min64.set("-9223372036854775808", status); 640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (this->compare(min64) < 0) { 641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DigitList max64; max64.set("9223372036854775807", status); 644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (this->compare(max64) > 0) { 645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return true; 651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::set(int32_t source) 658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) set((int64_t)source); 660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDouble = source; 661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = TRUE; 662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param maximumDigits The maximum digits to be generated. If zero, 667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * there is no maximum -- generate all digits. 668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::set(int64_t source) 671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char str[MAX_DIGITS+2]; // Leave room for sign and trailing nul. 673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) formatBase10(source, str); 674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(uprv_strlen(str) < sizeof(str)); 675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberFromString(fDecNumber, str, &fContext); 677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDouble = (double)source; 678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = TRUE; 679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Set the DigitList from a decimal number string. 685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The incoming string _must_ be nul terminated, even though it is arriving 687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * as a StringPiece because that is what the decNumber library wants. 688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * We can get away with this for an internal function; it would not 689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * be acceptable for a public API. 690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::set(const StringPiece &source, UErrorCode &status) { 693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Figure out a max number of digits to use during the conversion, and 698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // resize the number up if necessary. 699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t numDigits = source.length(); 700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (numDigits > fContext.digits) { 701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // fContext.digits == fStorage.getCapacity() 702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity()); 703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (t == NULL) { 704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber = t; 708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = numDigits; 709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.status = 0; 712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberFromString(fDecNumber, source.data(), &fContext); 713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if ((fContext.status & DEC_Conversion_syntax) != 0) { 714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_DECIMAL_NUMBER_SYNTAX_ERROR; 715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Set the digit list to a representation of the given double value. 721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This method supports both fixed-point and exponential notation. 722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param source Value to be converted. 723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::set(double source) 726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // for now, simple implementation; later, do proper IEEE stuff 728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough) 729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Generate a representation of the form /[+-][0-9]+e[+-][0-9]+/ 731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source); 732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(uprv_strlen(rep) < sizeof(rep)); 733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // uprv_decNumberFromString() will parse the string expecting '.' as a 735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // decimal separator, however sprintf() can use ',' in certain locales. 736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Overwrite a different decimal separator with '.' here before proceeding. 737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) loadDecimalChar(); 738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (gDecimal != '.') { 739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char *decimalPt = strchr(rep, gDecimal); 740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (decimalPt != NULL) { 741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *decimalPt = '.'; 742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Create a decNumber from the string. 746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberFromString(fDecNumber, rep, &fContext); 747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberTrim(fDecNumber); 748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDouble = source; 749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = TRUE; 750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Multiply 756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The number will be expanded if need be to retain full precision. 757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * In practice, for formatting, multiply is by 10, 100 or 1000, so more digits 758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * will not be required for this use. 759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::mult(const DigitList &other, UErrorCode &status) { 762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.status = 0; 763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t requiredDigits = this->digits() + other.digits(); 764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (requiredDigits > fContext.digits) { 765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) reduce(); // Remove any trailing zeros 766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t requiredDigits = this->digits() + other.digits(); 767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ensureCapacity(requiredDigits, status); 768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext); 770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Divide 777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The number will _not_ be expanded for inexact results. 778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * TODO: probably should expand some, for rounding increments that 779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * could add a few digits, e.g. .25, but not expand arbitrarily. 780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::div(const DigitList &other, UErrorCode &status) { 783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext); 787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ensureCapacity. Grow the digit storage for the number if it's less than the requested 794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * amount. Never reduce it. Available size is kept in fContext.digits. 795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) { 798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (requestedCapacity <= 0) { 802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_ILLEGAL_ARGUMENT_ERROR; 803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (requestedCapacity > DEC_MAX_DIGITS) { 806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Don't report an error for requesting too much. 807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Arithemetic Results will be rounded to what can be supported. 808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // At 999,999,999 max digits, exceeding the limit is not too likely! 809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) requestedCapacity = DEC_MAX_DIGITS; 810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (requestedCapacity > fContext.digits) { 812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity()); 813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (newBuffer == NULL) { 814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = requestedCapacity; 818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fDecNumber = newBuffer; 819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Round the representation to the given number of digits. 826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param maximumDigits The maximum number of digits to be shown. 827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Upon return, count will be less than or equal to maximumDigits. 828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::round(int32_t maximumDigits) 831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t savedDigits = fContext.digits; 833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = maximumDigits; 834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext); 835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fContext.digits = savedDigits; 836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberTrim(fDecNumber); 837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::roundFixedPoint(int32_t maximumFractionDigits) { 843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trim(); // Remove trailing zeros. 844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (fDecNumber->exponent >= -maximumFractionDigits) { 845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) decNumber scale; // Dummy decimal number, but with the desired number of 848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberZero(&scale); // fraction digits. 849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) scale.exponent = -maximumFractionDigits; 850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) scale.lsu[0] = 1; 851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext); 853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trim(); 854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fHaveDouble = FALSE; 855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void 860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::toIntegralValue() { 861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext); 862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ------------------------------------- 866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool 867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DigitList::isZero() const 868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return decNumberIsZero(fDecNumber); 870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_END 874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif // #if !UCONFIG_NO_FORMATTING 875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//eof 877