// Copyright (C) 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 * Copyright (C) 2016, International Business Machines
 * Corporation and others.  All Rights Reserved.
 *
 * file name: visibledigits.cpp
 */

#include <math.h>

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "cstring.h"
#include "decNumber.h"
#include "digitlst.h"
#include "uassert.h"
#include "visibledigits.h"

static const int32_t kNegative = 1;
static const int32_t kInfinite = 2;
static const int32_t kNaN = 4;

U_NAMESPACE_BEGIN

void VisibleDigits::setNegative() {
    fFlags |= kNegative;
}

void VisibleDigits::setNaN() {
    fFlags |= kNaN;
}

void VisibleDigits::setInfinite() {
    fFlags |= kInfinite;
}

void VisibleDigits::clear() {
    fInterval.clear();
    fDigits.clear();
    fExponent = 0;
    fFlags = 0;
    fAbsIntValue = 0LL;
    fAbsIntValueSet = FALSE;
    fAbsDoubleValue = 0.0;
    fAbsDoubleValueSet = FALSE;
}

UBool VisibleDigits::isNegative() const {
    return (fFlags & kNegative);
}

UBool VisibleDigits::isNaN() const {
    return (fFlags & kNaN);
}

UBool VisibleDigits::isInfinite() const {
    return (fFlags & kInfinite);
}

int32_t VisibleDigits::getDigitByExponent(int32_t digitPos) const {
    if (digitPos < fExponent || digitPos >= fExponent + fDigits.length()) {
        return 0;
    }
    const char *ptr = fDigits.data();
    return ptr[digitPos - fExponent];
}

UBool VisibleDigits::isOverMaxDigits() const {
    return (fExponent + fDigits.length() > fInterval.getMostSignificantExclusive());
}

UBool VisibleDigits::isNaNOrInfinity() const {
    return (fFlags & (kInfinite | kNaN)) != 0;
}

double VisibleDigits::computeAbsDoubleValue() const {
    // Take care of NaN and infinity
    if (isNaN()) {
        return uprv_getNaN();
    }
    if (isInfinite()) {
        return uprv_getInfinity();
    }

    // stack allocate a decNumber to hold MAX_DBL_DIGITS+3 significant digits
    struct {
        decNumber  decNum;
        char       digits[MAX_DBL_DIGITS+3];
    } decNumberWithStorage;
    decNumber *numberPtr = &decNumberWithStorage.decNum;

    int32_t mostSig = fInterval.getMostSignificantExclusive();
    int32_t mostSigNonZero = fExponent + fDigits.length();
    int32_t end = mostSig > mostSigNonZero ? mostSigNonZero : mostSig;
    int32_t leastSig = fInterval.getLeastSignificantInclusive();
    int32_t start = leastSig > fExponent ? leastSig : fExponent;
    if (end <= start) {
        return 0.0;
    }
    if (start < end - (MAX_DBL_DIGITS+3)) {
        start = end - (MAX_DBL_DIGITS+3);
    }
    uint8_t *pos = numberPtr->lsu;
    const char *src = &(fDigits.data()[start - fExponent]);
    for (int32_t i = start; i < end; ++i) {
        *pos++ = (uint8_t) (*src++);
    }
    numberPtr->exponent = start;
    numberPtr->bits = 0;
    numberPtr->digits = end - start;
    char str[MAX_DBL_DIGITS+18];
    uprv_decNumberToString(numberPtr, str);
    U_ASSERT(uprv_strlen(str) < MAX_DBL_DIGITS+18);
    char *unused = NULL;
    return DigitList::decimalStrToDouble(str, &unused);
}

void VisibleDigits::getFixedDecimal(
    double &source, int64_t &intValue, int64_t &f, int64_t &t, int32_t &v, UBool &hasIntValue) const {
    source = 0.0;
    intValue = 0;
    f = 0;
    t = 0;
    v = 0;
    hasIntValue = FALSE;
    if (isNaNOrInfinity()) {
        return;
    }

    // source
    if (fAbsDoubleValueSet) {
        source = fAbsDoubleValue;
    } else {
        source = computeAbsDoubleValue();
    }

    // visible decimal digits
    v = fInterval.getFracDigitCount();

    // intValue

    // If we initialized from an int64 just use that instead of
    // calculating
    if (fAbsIntValueSet) {
        intValue = fAbsIntValue;
    } else {
        int32_t startPos = fInterval.getMostSignificantExclusive();
        if (startPos > 18) {
            startPos = 18;
        }
        // process the integer digits
        for (int32_t i = startPos - 1; i >= 0; --i) {
            intValue = intValue * 10LL + getDigitByExponent(i);
        }
        if (intValue == 0LL && startPos > 0) {
            intValue = 100000000000000000LL;
        }
    }

    // f (decimal digits)
    // skip over any leading 0's in fraction digits.
    int32_t idx = -1;
    for (; idx >= -v && getDigitByExponent(idx) == 0; --idx)
      ;

    // Only process up to first 18 non zero fraction digits for decimalDigits
    // since that is all we can fit into an int64.
    for (int32_t i = idx; i >= -v && i > idx - 18; --i) {
        f = f * 10LL + getDigitByExponent(i);
    }

    // If we have no decimal digits, we don't have an integer value
    hasIntValue = (f == 0LL);

    // t (decimal digits without trailing zeros)
   t = f;
    while (t > 0 && t % 10LL == 0) {
        t /= 10;
    }
}

U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
