Skip to content

Commit f60f760

Browse files
committed
memory management bug fix in dd::to_string
1 parent 329fe2f commit f60f760

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

include/universal/number/dd/dd_impl.hpp

+38-13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <iomanip>
1818
#include <limits>
1919
#include <cmath>
20+
#include <vector>
2021

2122
// supporting types and functions
2223
#include <universal/native/ieee754.hpp>
@@ -29,6 +30,15 @@
2930

3031
namespace sw { namespace universal {
3132

33+
constexpr bool bTraceDecimalConversion = false;
34+
constexpr bool bTraceDecimalRounding = false;
35+
std::ostream& operator<<(std::ostream& ostr, const std::vector<char>& s) {
36+
for (auto c : s) {
37+
ostr << c;
38+
}
39+
return ostr;
40+
}
41+
3242
// fwd references to free functions
3343
dd operator-(const dd& lhs, const dd&);
3444
dd operator*(const dd& lhs, const dd&);
@@ -404,36 +414,44 @@ class dd {
404414
if (fixed)
405415
nrDigitsForFixedFormat = std::max(60, nrDigits); // can be much longer than the max accuracy for double-double
406416

417+
if constexpr (bTraceDecimalConversion) {
418+
std::cout << "powerOfTenScale : " << powerOfTenScale << '\n';
419+
std::cout << "integerDigits : " << integerDigits << '\n';
420+
std::cout << "nrDigits : " << nrDigits << '\n';
421+
std::cout << "nrDigitsForFixedFormat : " << nrDigitsForFixedFormat << '\n';
422+
}
423+
424+
407425
// a number in the range of [0.5, 1.0) to be printed with zero precision
408426
// must be rounded up to 1 to print correctly
409-
if (fixed && (precision == 0) && (std::abs(high()) < 1.0)) {
427+
if (fixed && (precision == 0) && (std::abs(hi) < 1.0)) {
410428
s += (std::abs(hi) >= 0.5) ? '1' : '0';
411429
return s;
412430
}
413431

414432
if (fixed && nrDigits <= 0) {
415-
// process values with negative exponents (powerOfTenScale < 0)
433+
// process values that are near zero
416434
s += '0';
417435
if (precision > 0) {
418436
s += '.';
419437
s.append(static_cast<unsigned int>(precision), '0');
420438
}
421439
}
422440
else {
423-
char* t;
441+
std::vector<char> t;
424442

425443
if (fixed) {
426-
t = new char[static_cast<size_t>(nrDigitsForFixedFormat + 1)];
444+
t.resize(nrDigitsForFixedFormat+1);
427445
to_digits(t, e, nrDigitsForFixedFormat);
428446
}
429447
else {
430-
t = new char[static_cast<size_t>(nrDigits + 1)];
448+
t.resize(nrDigits+1);
431449
to_digits(t, e, nrDigits);
432450
}
433451

434452
if (fixed) {
435453
// round the decimal string
436-
round_string(t, nrDigits, &integerDigits);
454+
round_string(t, nrDigits+1, &integerDigits);
437455

438456
if (integerDigits > 0) {
439457
int i;
@@ -457,7 +475,6 @@ class dd {
457475
s += t[i];
458476

459477
}
460-
delete[] t;
461478
}
462479
}
463480

@@ -588,11 +605,18 @@ class dd {
588605
}
589606

590607
// precondition: string s must be all digits
591-
void round_string(char* s, int precision, int* decimalPoint) const {
608+
void round_string(std::vector<char>& s, int precision, int* decimalPoint) const {
609+
if constexpr(bTraceDecimalRounding) {
610+
std::cout << "string : " << s << '\n';
611+
std::cout << "precision : " << precision << '\n';
612+
std::cout << "decimalPoint : " << *decimalPoint << '\n';
613+
}
614+
592615
int nrDigits = precision;
593616
// round decimal string and propagate carry
594617
int lastDigit = nrDigits - 1;
595618
if (s[lastDigit] >= '5') {
619+
if constexpr(bTraceDecimalRounding) std::cout << "need to round\n";
596620
int i = nrDigits - 2;
597621
s[i]++;
598622
while (i > 0 && s[i] > '9') {
@@ -603,7 +627,8 @@ class dd {
603627

604628
// if first digit is 10, shift everything.
605629
if (s[0] > '9') {
606-
for (int i = precision; i >= 2; i--) s[i] = s[i - 1];
630+
if constexpr(bTraceDecimalRounding) std::cout << "shift right to handle overflow\n";
631+
for (int i = precision; i >= 2; --i) s[i] = s[i - 1];
607632
s[0] = '1';
608633
s[1] = '0';
609634

@@ -637,12 +662,12 @@ class dd {
637662
/// <param name="s"></param>
638663
/// <param name="exponent"></param>
639664
/// <param name="precision"></param>
640-
void to_digits(char* s, int& exponent, int precision) const {
665+
//void to_digits(char* s, int& exponent, int precision) const {
666+
void to_digits(std::vector<char>& s, int& exponent, int precision) const {
641667
constexpr dd _one(1.0), _ten(10.0);
642668
constexpr double _log2(0.301029995663981);
643669

644670
if (iszero()) {
645-
std::cout << "I am zero\n";
646671
exponent = 0;
647672
for (int i = 0; i < precision; ++i) s[i] = '0';
648673
s[precision] = 0; // termination null
@@ -705,6 +730,7 @@ class dd {
705730
r *= 10.0;
706731

707732
s[i] = static_cast<char>(mostSignificantDigit + '0');
733+
if constexpr (bTraceDecimalConversion) std::cout << "to_digits digit[" << i << "] : " << s << '\n';
708734
}
709735

710736
// Fix out of range digits
@@ -857,8 +883,7 @@ inline std::string to_binary(const dd& number, bool bNibbleMarker = false) {
857883
mask >>= 1;
858884
}
859885

860-
// s << " : " << number[i];
861-
if (i < 1) s << ", ";
886+
if (i < 1) s << '\n';
862887
}
863888

864889
return s.str();

static/dd/api/api.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ namespace sw {
106106
from *= 10.0) {
107107
dd u = ulp(from);
108108
std::cout << "ulp(" << std::scientific << std::setprecision(0) << from
109-
<< ") gives " << to_binary(u) << " : "
110-
<< std::scientific << std::setprecision(6) << u
109+
<< ") gives " //<< to_binary(u) << " : "
110+
<< std::fixed << std::setprecision(6) << u
111111
<< '\n';
112112
}
113113
}

0 commit comments

Comments
 (0)