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