17
17
#include < iomanip>
18
18
#include < limits>
19
19
#include < cmath>
20
+ #include < vector>
20
21
21
22
// supporting types and functions
22
23
#include < universal/native/ieee754.hpp>
29
30
30
31
namespace sw { namespace universal {
31
32
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
+
32
42
// fwd references to free functions
33
43
dd operator -(const dd& lhs, const dd&);
34
44
dd operator *(const dd& lhs, const dd&);
@@ -404,36 +414,44 @@ class dd {
404
414
if (fixed)
405
415
nrDigitsForFixedFormat = std::max (60 , nrDigits); // can be much longer than the max accuracy for double-double
406
416
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
+
407
425
// a number in the range of [0.5, 1.0) to be printed with zero precision
408
426
// 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 )) {
410
428
s += (std::abs (hi) >= 0.5 ) ? ' 1' : ' 0' ;
411
429
return s;
412
430
}
413
431
414
432
if (fixed && nrDigits <= 0 ) {
415
- // process values with negative exponents (powerOfTenScale < 0)
433
+ // process values that are near zero
416
434
s += ' 0' ;
417
435
if (precision > 0 ) {
418
436
s += ' .' ;
419
437
s.append (static_cast <unsigned int >(precision), ' 0' );
420
438
}
421
439
}
422
440
else {
423
- char * t;
441
+ std::vector< char > t;
424
442
425
443
if (fixed) {
426
- t = new char [ static_cast < size_t > (nrDigitsForFixedFormat + 1 )] ;
444
+ t. resize (nrDigitsForFixedFormat+ 1 ) ;
427
445
to_digits (t, e, nrDigitsForFixedFormat);
428
446
}
429
447
else {
430
- t = new char [ static_cast < size_t > (nrDigits + 1 )] ;
448
+ t. resize (nrDigits+ 1 ) ;
431
449
to_digits (t, e, nrDigits);
432
450
}
433
451
434
452
if (fixed) {
435
453
// round the decimal string
436
- round_string (t, nrDigits, &integerDigits);
454
+ round_string (t, nrDigits+ 1 , &integerDigits);
437
455
438
456
if (integerDigits > 0 ) {
439
457
int i;
@@ -457,7 +475,6 @@ class dd {
457
475
s += t[i];
458
476
459
477
}
460
- delete[] t;
461
478
}
462
479
}
463
480
@@ -588,11 +605,18 @@ class dd {
588
605
}
589
606
590
607
// 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
+
592
615
int nrDigits = precision;
593
616
// round decimal string and propagate carry
594
617
int lastDigit = nrDigits - 1 ;
595
618
if (s[lastDigit] >= ' 5' ) {
619
+ if constexpr (bTraceDecimalRounding) std::cout << " need to round\n " ;
596
620
int i = nrDigits - 2 ;
597
621
s[i]++;
598
622
while (i > 0 && s[i] > ' 9' ) {
@@ -603,7 +627,8 @@ class dd {
603
627
604
628
// if first digit is 10, shift everything.
605
629
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 ];
607
632
s[0 ] = ' 1' ;
608
633
s[1 ] = ' 0' ;
609
634
@@ -637,12 +662,12 @@ class dd {
637
662
// / <param name="s"></param>
638
663
// / <param name="exponent"></param>
639
664
// / <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 {
641
667
constexpr dd _one (1.0 ), _ten (10.0 );
642
668
constexpr double _log2 (0.301029995663981 );
643
669
644
670
if (iszero ()) {
645
- std::cout << " I am zero\n " ;
646
671
exponent = 0 ;
647
672
for (int i = 0 ; i < precision; ++i) s[i] = ' 0' ;
648
673
s[precision] = 0 ; // termination null
@@ -705,6 +730,7 @@ class dd {
705
730
r *= 10.0 ;
706
731
707
732
s[i] = static_cast <char >(mostSignificantDigit + ' 0' );
733
+ if constexpr (bTraceDecimalConversion) std::cout << " to_digits digit[" << i << " ] : " << s << ' \n ' ;
708
734
}
709
735
710
736
// Fix out of range digits
@@ -857,8 +883,7 @@ inline std::string to_binary(const dd& number, bool bNibbleMarker = false) {
857
883
mask >>= 1 ;
858
884
}
859
885
860
- // s << " : " << number[i];
861
- if (i < 1 ) s << " , " ;
886
+ if (i < 1 ) s << ' \n ' ;
862
887
}
863
888
864
889
return s.str ();
0 commit comments