Skip to content

Commit 1d9821c

Browse files
committed
dd code hygiene, qd api test progression
1 parent 1313975 commit 1d9821c

File tree

5 files changed

+136
-56
lines changed

5 files changed

+136
-56
lines changed

include/universal/internal/bitblock/bitblock.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#pragma once
22
// bitblock.hpp : bitblock class
33
//
4-
// Copyright (C) 2017-2023 Stillwater Supercomputing, Inc.
4+
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
5+
// SPDX-License-Identifier: MIT
56
//
67
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
78
#include <cstdint>

include/universal/number/dd/dd_impl.hpp

+36-33
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,11 @@ class dd {
494494
std::vector<char> t;
495495

496496
if (fixed) {
497-
t.resize(nrDigitsForFixedFormat+1);
497+
t.resize(static_cast<size_t>(nrDigitsForFixedFormat+1));
498498
to_digits(t, e, nrDigitsForFixedFormat);
499499
}
500500
else {
501-
t.resize(nrDigits+1);
501+
t.resize(static_cast<size_t>(nrDigits+1));
502502
to_digits(t, e, nrDigits);
503503
}
504504

@@ -508,30 +508,32 @@ class dd {
508508

509509
if (integerDigits > 0) {
510510
int i;
511-
for (i = 0; i < integerDigits; ++i) s += t[i];
511+
for (i = 0; i < integerDigits; ++i) s += t[static_cast<unsigned>(i)];
512512
if (precision > 0) {
513513
s += '.';
514-
for (int j = 0; j < precision; ++j, ++i) s += t[i];
514+
for (int j = 0; j < precision; ++j, ++i) s += t[static_cast<unsigned>(i)];
515515
}
516516
}
517517
else {
518518
s += "0.";
519519
if (integerDigits < 0) s.append(static_cast<size_t>(-integerDigits), '0');
520-
for (int i = 0; i < nrDigits; ++i) s += t[i];
520+
for (int i = 0; i < nrDigits; ++i) s += t[static_cast<unsigned>(i)];
521521
}
522522
}
523523
else {
524-
s += t[0];
524+
s += t[0ull];
525525
if (precision > 0) s += '.';
526526

527527
for (int i = 1; i <= precision; ++i)
528-
s += t[i];
528+
s += t[static_cast<unsigned>(i)];
529529

530530
}
531531
}
532532
}
533533

534-
// trap for improper offset with large values
534+
// TBD: this is seriously broken and needs a redesign
535+
//
536+
// fix for improper offset with large values and small values
535537
// without this trap, output of values of the for 10^j - 1 fail for j > 28
536538
// and are output with the point in the wrong place, leading to a significant error
537539
if (fixed && (precision > 0)) {
@@ -546,17 +548,18 @@ class dd {
546548
for (std::string::size_type i = 1; i < s.length(); ++i) {
547549
if (s[i] == '.') {
548550
s[i] = s[i - 1];
549-
s[i - 1] = '.';
551+
s[i - 1] = '.'; // this will destroy the leading 0 when s[i==1] == '.';
550552
break;
551553
}
552554
}
553555
// BUG: the loop above, in particular s[i-1] = '.', destroys the leading 0
554556
// in the fixed point representation if the point is located at i = 1;
557+
// it also breaks the precision request as it adds a new digit to the fixed representation
555558

556559
from_string = atof(s.c_str());
557560
// if this ratio is large, then the string has not been fixed
558561
if (std::fabs(from_string / hi) > 3.0) {
559-
std::cerr << "re-rounding unsuccessful in large number fixed point trap\n";
562+
std::cerr << "re-rounding unsuccessful in fixed point fix\n";
560563
}
561564
}
562565
}
@@ -670,22 +673,22 @@ class dd {
670673
int nrDigits = precision;
671674
// round decimal string and propagate carry
672675
int lastDigit = nrDigits - 1;
673-
if (s[lastDigit] >= '5') {
676+
if (s[static_cast<unsigned>(lastDigit)] >= '5') {
674677
if constexpr(bTraceDecimalRounding) std::cout << "need to round\n";
675678
int i = nrDigits - 2;
676-
s[i]++;
677-
while (i > 0 && s[i] > '9') {
678-
s[i] -= 10;
679-
s[--i]++;
679+
s[static_cast<unsigned>(i)]++;
680+
while (i > 0 && s[static_cast<unsigned>(i)] > '9') {
681+
s[static_cast<unsigned>(i)] -= 10;
682+
s[static_cast<unsigned>(--i)]++;
680683
}
681684
}
682685

683686
// if first digit is 10, shift everything.
684687
if (s[0] > '9') {
685688
if constexpr(bTraceDecimalRounding) std::cout << "shift right to handle overflow\n";
686-
for (int i = precision; i >= 2; --i) s[i] = s[i - 1];
687-
s[0] = '1';
688-
s[1] = '0';
689+
for (int i = precision; i >= 2; --i) s[static_cast<unsigned>(i)] = s[static_cast<unsigned>(i - 1)];
690+
s[0u] = '1';
691+
s[1u] = '0';
689692

690693
(*decimalPoint)++; // increment decimal point
691694
++precision;
@@ -722,7 +725,7 @@ class dd {
722725

723726
if (iszero()) {
724727
exponent = 0;
725-
for (int i = 0; i < precision; ++i) s[i] = '0';
728+
for (int i = 0; i < precision; ++i) s[static_cast<unsigned>(i)] = '0';
726729
return;
727730
}
728731

@@ -781,20 +784,20 @@ class dd {
781784
r -= mostSignificantDigit;
782785
r *= 10.0;
783786

784-
s[i] = static_cast<char>(mostSignificantDigit + '0');
787+
s[static_cast<unsigned>(i)] = static_cast<char>(mostSignificantDigit + '0');
785788
if constexpr (bTraceDecimalConversion) std::cout << "to_digits digit[" << i << "] : " << s << '\n';
786789
}
787790

788791
// Fix out of range digits
789792
for (int i = nrDigits - 1; i > 0; --i) {
790-
if (s[i] < '0') {
791-
s[i - 1]--;
792-
s[i] += 10;
793+
if (s[static_cast<unsigned>(i)] < '0') {
794+
s[static_cast<unsigned>(i - 1)]--;
795+
s[static_cast<unsigned>(i)] += 10;
793796
}
794797
else {
795-
if (s[i] > '9') {
796-
s[i - 1]++;
797-
s[i] -= 10;
798+
if (s[static_cast<unsigned>(i)] > '9') {
799+
s[static_cast<unsigned>(i - 1)]++;
800+
s[static_cast<unsigned>(i)] -= 10;
798801
}
799802
}
800803
}
@@ -806,26 +809,26 @@ class dd {
806809

807810
// Round and propagate carry
808811
int lastDigit = nrDigits - 1;
809-
if (s[lastDigit] >= '5') {
812+
if (s[static_cast<unsigned>(lastDigit)] >= '5') {
810813
int i = nrDigits - 2;
811-
s[i]++;
812-
while (i > 0 && s[i] > '9') {
813-
s[i] -= 10;
814-
s[--i]++;
814+
s[static_cast<unsigned>(i)]++;
815+
while (i > 0 && s[static_cast<unsigned>(i)] > '9') {
816+
s[static_cast<unsigned>(i)] -= 10;
817+
s[static_cast<unsigned>(--i)]++;
815818
}
816819
}
817820

818821
// If first digit is 10, shift left and increment exponent
819822
if (s[0] > '9') {
820823
++e;
821824
for (int i = precision; i >= 2; --i) {
822-
s[i] = s[i - 1];
825+
s[static_cast<unsigned>(i)] = s[static_cast<unsigned>(i - 1)];
823826
}
824827
s[0] = '1';
825828
s[1] = '0';
826829
}
827830

828-
s[precision] = 0; // termination null
831+
s[static_cast<unsigned>(precision)] = 0; // termination null
829832
exponent = e;
830833
}
831834

include/universal/number/dd/manipulators.hpp

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
77
#include <string>
88
#include <iomanip>
9-
#include <universal/internal/blockbinary/blockbinary.hpp>
109
#include <universal/number/dd/dd_fwd.hpp>
1110
#include <universal/native/manipulators.hpp>
1211
// pull in the color printing for shells utility

static/dd/api/api.cpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ namespace sw {
7878
int expOfFirstLimb = scale(a);
7979
std::cout << to_binary(expOfFirstLimb) << " : " << expOfFirstLimb << '\n';
8080
// second limb exponent
81-
int expOfSecondLimb = expOfFirstLimb - std::log10(1ull << 53);
81+
int expOfSecondLimb = expOfFirstLimb - 15; // floor(log10(2^53)) = floor(15.9245) = 15
8282
std::cout << "exponent of the first limb : " << expOfFirstLimb << '\n';
8383
std::cout << "exponent of the second limb : " << expOfSecondLimb << '\n';
8484
// construct the second limb
@@ -115,7 +115,8 @@ namespace sw {
115115
dd u = ulp(from);
116116
std::cout << "ulp(" << std::scientific << std::setprecision(0) << from
117117
<< ") gives "
118-
<< std::fixed << std::setprecision(6) << u
118+
// << std::fixed << std::setprecision(6) << u
119+
<< " : " << std::setprecision(6) << std::defaultfloat << u
119120
<< '\n';
120121
}
121122
}
@@ -211,8 +212,6 @@ try {
211212
++d;
212213
if (isdenorm(d)) std::cout << d << " is a subnormal number\n";
213214
}
214-
215-
216215
}
217216

218217
// helper api
@@ -268,11 +267,11 @@ try {
268267
double x1{ std::pow(2.0, -53.0) };
269268

270269
// now let's walk that bit down to the ULP
271-
int precisionForRange = 16;
270+
unsigned precisionForRange = 16;
272271
std::cout << std::setprecision(precisionForRange);
273272
x0 = 1.0;
274273
dd a(x0, x1);
275-
std::cout << centered("double-double", precisionForRange + 6) << " : ";
274+
std::cout << centered("double-double", precisionForRange + 6u) << " : ";
276275
std::cout << centered("binary form of x0", 68) << " : ";
277276
std::cout << centered("real value of x0", 15) << '\n';
278277
std::cout << a << " : " << to_binary(x0) << " : " << x0 << '\n';
@@ -286,7 +285,7 @@ try {
286285
x0 = 1.0;
287286
precisionForRange = 32;
288287
std::cout << std::setprecision(precisionForRange);
289-
std::cout << centered("double-double", precisionForRange + 6) << " : ";
288+
std::cout << centered("double-double", precisionForRange + 6u) << " : ";
290289
std::cout << centered("binary form of x1", 68) << " : ";
291290
std::cout << centered("real value of x1", 15) << '\n';
292291
for (int i = 0; i < 54; ++i) {
@@ -298,7 +297,7 @@ try {
298297
std::cout << "\nvalue and binary pattern of the double-double\n";
299298
precisionForRange = 32;
300299
std::cout << std::setprecision(precisionForRange);
301-
std::cout << centered("double-double", precisionForRange + 6) << " : ";
300+
std::cout << centered("double-double", precisionForRange + 6u) << " : ";
302301
std::cout << centered("binary form of double-double", 110) << '\n';
303302
for (int i = 0; i < 54; ++i) {
304303
x1 = (std::pow(2.0, -53.0 - double(i)));
@@ -323,16 +322,18 @@ try {
323322
std::cout << std::setprecision(32);
324323
a.maxpos();
325324
std::cout << "maxpos double-double : " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
326-
a.setbits(0x0080); // positive min normal
327-
std::cout << "minnorm double-double : " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
328325
a.minpos();
329326
std::cout << "minpos double-double : " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
327+
a = std::numeric_limits<dd>::denorm_min();
328+
std::cout << "smallest double-double: " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
330329
a.zero();
331330
std::cout << "zero : " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
332331
a.minneg();
333332
std::cout << "minneg double-double : " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
334333
a.maxneg();
335334
std::cout << "maxneg double-double : " << to_binary(a) << " : " << a << " : " << scale(a) << '\n';
335+
336+
std::cout << "Notice that minpos is the smallest normal number, not the smallest number, which is a denorm\n";
336337
std::cout << std::setprecision(defaultPrecision);
337338
std::cout << "---\n";
338339
}
@@ -486,7 +487,7 @@ try {
486487

487488
std::cout << "---------- Unit in the Last Place --------+\n";
488489
{
489-
ulp_progression("\nULP progression for dd:\n", dd(10.0));
490+
ulp_progression("\nULP progression for dd:\n", dd(10.0e01));
490491

491492
for (int i = -5; i < 6; ++i) {
492493
dd a(std::pow(2.0, double(i)));

0 commit comments

Comments
 (0)