Ticket #1325: canonical-xsdouble.patch

File canonical-xsdouble.patch, 5.1 KB (added by Markus, 7 years ago)

FUStringBuilder.hpp exists twice

  • FUStringBuilder.hpp

    diff -Nur a/FUStringBuilder.hpp b/FUStringBuilder.hpp
    a b  
    2626#define SAFE_DELETE_ARRAY(ptr) if (ptr != NULL) { delete [] ptr; ptr = NULL; }
    2727#endif
    2828
    29 template <class Char, class FloatType>
    30 void FloatToString(FloatType f, Char* sz)
    31 {
    32     Char* buffer = sz + 1;
    33     static const int digitCount = 6;
    34     int decimal, sign;
    35 
    36     // ecvt rounds the string for us: http://www.datafocus.com/docs/man3/ecvt.3.asp
    37     char* end = ecvt(f, digitCount, &decimal, &sign);
    38 
    39     if (sign != 0) (*buffer++) = '-';
    40     int count = digitCount;
    41     if (decimal > digitCount)
    42     {
    43         // We use the scientific notation: P.MeX
    44         (*buffer++) = (*end++); // P is one character.
    45         (*buffer++) = '.';
    46 
    47         // Mantissa (cleaned for zeroes)
    48         for (--count; count > 0; --count) if (end[count - 1] != '0') break;
    49         for (int i = 0; i < count; ++i) (*buffer++) = (*end++);
    50         if (buffer[-1] == '.') --buffer;
    51 
    52         // Exponent
    53         (*buffer++) = 'e';
    54         uint32 exponent = decimal - 1; // X
    55         if (exponent >= 10) (*buffer++) = (Char) ('0' + (exponent / 10));
    56         (*buffer++) = (Char) ('0' + (exponent % 10));
    57         (*buffer) = 0;
    58         return;
    59     }
    60     else if (decimal > 0)
    61     {
    62         // Simple number: A.B
    63         for (int i = 0; i < decimal; ++i) (*buffer++) = (*end++);
    64         if (decimal < digitCount) (*buffer++) = '.';
    65         count = digitCount - decimal;
    66     }
    67     else if (decimal < -digitCount)
    68     {
    69         // What case is this?
    70         decimal = count = 0;
    71     }
    72     else if (decimal < 0 || (decimal == 0 && *end != '0'))
    73     {
    74         // Tiny number: 0.Me-X
    75         (*buffer++) = '0'; (*buffer++) = '.';
    76         for (int i = 0; i < -decimal; ++i) (*buffer++) = '0';
    77         count = digitCount + decimal;
    78     }
    79     for (; count > 0; --count) if (end[count - 1] != '0') break;
    80     for (int i = 0; i < count; ++i) (*buffer++) = (*end++);
    81     if (decimal == 0 && count == 0) (*buffer++) = '0';
    82     if (buffer[-1] == '.') --buffer;
    83     (*buffer) = 0;
    84 }
    85 
    8629template <class Char>
    8730FUStringBuilderT<Char>::FUStringBuilderT(const String& sz)
    8831{
     
    234177template <class Char>
    235178void FUStringBuilderT<Char>::append(float f)
    236179{
    237 #ifdef WIN32
    238     // use <float.h> _isnan method to detect the 1.#IND00 NaN.
    239     if (f != std::numeric_limits<float>::infinity() && f != -std::numeric_limits<float>::infinity() && f != std::numeric_limits<float>::quiet_NaN() && f != std::numeric_limits<float>::signaling_NaN() && !_isnan((double)f))
    240 #else
    241     if (f != std::numeric_limits<float>::infinity() && f != -std::numeric_limits<float>::infinity() && f != std::numeric_limits<float>::quiet_NaN() && f != std::numeric_limits<float>::signaling_NaN())
    242 #endif
    243     {
    244         if (IsEquivalent(f, 0.0f, std::numeric_limits<float>::epsilon())) append((Char)'0');
    245         else
    246         {
    247             Char sz[128];
    248             FloatToString(f, sz);
    249             append(sz + 1);
    250         }
    251     }
    252     else if (f == std::numeric_limits<float>::infinity())
    253     { append((Char)'I'); append((Char)'N'); append((Char)'F'); }
    254     else if (f == -std::numeric_limits<float>::infinity())
    255     { append((Char)'-'); append((Char)'I'); append((Char)'N'); append((Char)'F'); }
    256     else
    257     { append((Char)'N'); append((Char)'a'); append((Char)'N'); }
     180    append((double)f);
    258181}
    259182
    260183template <class Char>
    261184void FUStringBuilderT<Char>::append(double f)
    262185{
    263 #ifdef WIN32
    264     // use <float.h> _isnan method to detect the .#IND00 NaN.
    265     if (f != std::numeric_limits<float>::infinity() && f != -std::numeric_limits<float>::infinity() && f != std::numeric_limits<float>::quiet_NaN() && f != std::numeric_limits<float>::signaling_NaN() && !_isnan(f))
    266 #else
    267     if (f != std::numeric_limits<float>::infinity() && f != -std::numeric_limits<float>::infinity() && f != std::numeric_limits<float>::quiet_NaN() && f != std::numeric_limits<float>::signaling_NaN())
    268 #endif
    269     {
    270         if (IsEquivalent(f, 0.0, std::numeric_limits<double>::epsilon())) append((Char)'0');
    271         else
    272         {
    273             Char sz[128];
    274             FloatToString(f, sz);
    275             append(sz + 1);
    276         }
     186    if (f == -std::numeric_limits<double>::infinity()) {
     187        append("-INF");
     188        return;
     189    } else if (f == std::numeric_limits<double>::infinity()) {
     190        append("INF");
     191        return;
     192    } else if (f != f) {
     193        append("NaN");
     194        return;
     195    } else if (-std::numeric_limits<double>::epsilon() < f && f < std::numeric_limits<double>::epsilon()) {
     196        append("0.0E0");
     197        return;
     198    }
     199
     200    if (f < 0.0) {
     201        f = -f;
     202        append('-');
    277203    }
    278     else if (f == std::numeric_limits<double>::infinity())
    279     { append((Char)'I'); append((Char)'N'); append((Char)'F'); }
    280     else if (f == -std::numeric_limits<double>::infinity())
    281     { append((Char)'-'); append((Char)'I'); append((Char)'N'); append((Char)'F'); }
     204
     205    int e = 0;
     206//  e = floor(log10(f));
     207//  f = f / pow(10.0, e);
     208
     209    if (f < 1.0)
     210        for (; f < 1.0; f *= 10.0)
     211            e--;
    282212    else
    283     { append((Char)'N'); append((Char)'a'); append((Char)'N'); }
     213        for (; f >= 10.0; f /= 10.0)
     214            e++;
     215
     216    char tmp[10];
     217    sprintf(tmp, "%.6g", f);
     218    append(tmp);
     219    if (tmp[1] == 0) // only one digit, add missing part according canonical representation
     220        append(".0");
     221
     222    sprintf(tmp, "E%d", e);
     223    append(tmp);
    284224}
    285225
    286226template <class Char>