Skip to content

Commit

Permalink
Add implementation of ostream formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Naoki Shibata committed Jun 14, 2024
1 parent 331a538 commit 97b7a08
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 15 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Below is a simple C++ source code utilizing TLFloat.

```
#include <iostream>
#include <iomanip>
#include <tlfloat/tlmath.hpp>
using namespace tlfloat;
Expand All @@ -107,7 +108,7 @@ Octuple machin() {
}
int main(int argc, char **argv) {
std::cout << to_string(machin(), 70) << std::endl;
std::cout << std::setprecision(70) << machin() << std::endl;
}
```

Expand Down
25 changes: 23 additions & 2 deletions src/include/tlfloat/bigint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,7 @@ namespace tlfloat {
#if defined(TLFLOAT_DOXYGEN) || !defined(TLFLOAT_NO_LIBSTDCXX)

#include <iostream>
#include <ios>
#include <vector>
#include <string>

Expand Down Expand Up @@ -1334,7 +1335,17 @@ namespace tlfloat {
return std::string(s.data());
}

template<int N> static std::ostream& operator<<(std::ostream &os, const BigUInt<N>& u) { return os << to_string(u); }
template<int N> static std::ostream& operator<<(std::ostream &os, const BigUInt<N>& u) {
std::vector<char> buf(1000);
std::ios_base::fmtflags f = os.flags();
char typespec = 'u';
int base = 10;
if ((f & os.hex) != 0) { typespec = 'x'; base = 16; }
if ((f & os.oct) != 0) { typespec = 'o'; base = 8; }
BigInt<N>::snprint(buf.data(), buf.size(), BigInt<N>(u), typespec, os.width(), os.precision(), base, 1 << N,
false, false, false, (f & std::ios::left) != 0, false, (f & std::ios::uppercase) != 0);
return os << buf.data();
}

template<int N>
std::string to_string(const BigInt<N>& i) {
Expand All @@ -1343,7 +1354,17 @@ namespace tlfloat {
return std::string(s.data());
}

template<int N> static std::ostream& operator<<(std::ostream &os, const BigInt<N>& u) { return os << to_string(u); }
template<int N> static std::ostream& operator<<(std::ostream &os, const BigInt<N>& d) {
std::vector<char> buf(1000);
std::ios_base::fmtflags f = os.flags();
char typespec = 'd';
int base = 10;
if ((f & os.hex) != 0) { typespec = 'x'; base = 16; }
if ((f & os.oct) != 0) { typespec = 'o'; base = 8; }
BigInt<N>::snprint(buf.data(), buf.size(), d, typespec, os.width(), os.precision(), base, 1 << N,
false, false, false, (f & std::ios::left) != 0, false, (f & std::ios::uppercase) != 0);
return os << buf.data();
}
}
#endif // #if defined(TLFLOAT_DOXYGEN) || !defined(TLFLOAT_NO_LIBSTDCXX)
#endif // #ifndef __BIGINT_HPP_INCLUDED__
Expand Down
18 changes: 15 additions & 3 deletions src/include/tlfloat/tlfloat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1685,22 +1685,34 @@ namespace tlfloat {

template<typename Unpacked_t>
static std::string to_string(Unpacked_t u, int d=6) {
typedef decltype(Unpacked_t::xUnpackedFloat()) xUnpacked_t;
std::vector<char> buf(1000);
snprint(buf.data(), buf.size(), u, 'g', 0, d, false, false, false, false, false, false);
snprint(buf.data(), buf.size(), u.cast((xUnpacked_t *)0), 'g', 0, d, false, false, false, false, false, false);
return std::string(buf.data());
}
#endif

/** This works like sprintf(str, "%.6g", *this) where the precision can be specified with d */
template<typename Unpacked_t>
static std::string to_string(TLFloat<Unpacked_t> a, int d=6) {
typedef decltype(Unpacked_t::xUnpackedFloat()) xUnpacked_t;
std::vector<char> buf(1000);
snprint(buf.data(), buf.size(), a.getUnpacked(), 'g', 0, d, false, false, false, false, false, false);
snprint(buf.data(), buf.size(), a.getUnpacked().cast((xUnpacked_t *)0), 'g', 0, d, false, false, false, false, false, false);
return std::string(buf.data());
}

template<typename Unpacked_t>
static std::ostream& operator<<(std::ostream &os, const TLFloat<Unpacked_t>& u) { return os << to_string(u); }
static std::ostream& operator<<(std::ostream &os, const TLFloat<Unpacked_t>& a) {
typedef decltype(Unpacked_t::xUnpackedFloat()) xUnpacked_t;
std::vector<char> buf(1000);
std::ios_base::fmtflags f = os.flags();
char typespec = 'g';
if ((f & os.fixed) != 0) typespec = 'f';
if ((f & os.hex) != 0) typespec = 'a';
snprint(buf.data(), buf.size(), a.getUnpacked().cast((xUnpacked_t *)0), typespec, os.width(), os.precision(),
false, false, false, (f & std::ios::left) != 0, false, (f & std::ios::uppercase) != 0);
return os << buf.data();
}
#endif // #if defined(TLFLOAT_DOXYGEN) || !defined(TLFLOAT_NO_LIBSTDCXX)

//
Expand Down
68 changes: 59 additions & 9 deletions src/tester/test_bigint3.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
#include <iostream>
#include <sstream>
#include <vector>
#include <thread>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <cmath>
#include <signal.h>
#include <iomanip>

#include "suppress.hpp"

Expand Down Expand Up @@ -145,6 +137,27 @@ void checks(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double
if (!equal(i1 -= i0, b1 -= b0)) e("-=");
if (!equal(i1 *= i0, b1 *= b0)) e("*=");
//if (!equal(i1 /= i0, b1 /= b0)) e("/=");

{
stringstream ssc, sst;
ssc << (int64_t)low0 << endl;
sst << BigInt<7>((int64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 0s c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << (int64_t)low0 << endl;
sst << setw(20) << BigInt<7>((int64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 1s c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << right << (int64_t)low0 << endl;
sst << setw(20) << right << BigInt<7>((int64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 2s c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}
}

void checku(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double d) {
Expand Down Expand Up @@ -269,6 +282,43 @@ void checku(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double
if (!equal(i1 -= i0, b1 -= b0)) e("-=");
if (!equal(i1 *= i0, b1 *= b0)) e("*=");
if (!equal(i1 /= i0, b1 /= b0)) e("/=");

//

{
stringstream ssc, sst;
ssc << (uint64_t)low0 << endl;
sst << BigUInt<7>((uint64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 0u c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << (uint64_t)low0 << endl;
sst << setw(20) << BigUInt<7>((uint64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 1u c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << hex << (uint64_t)low0 << endl;
sst << setw(20) << hex << BigUInt<7>((uint64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 2u c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << oct << (uint64_t)low0 << endl;
sst << setw(20) << oct << BigUInt<7>((uint64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 3u c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << right << (uint64_t)low0 << endl;
sst << setw(20) << right << BigUInt<7>((uint64_t)low0) << endl;
if (ssc.str() != sst.str()) { cout << "NG 4u c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}
}

int main(int argc, char **argv) {
Expand Down
32 changes: 32 additions & 0 deletions src/tester/tester1.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>

#include <tlfloat/detect.h>
Expand Down Expand Up @@ -455,6 +457,36 @@ int main(int argc, char **argv) {
doTest<Octuple, fma_, mpfr_fma>("Octuple fma", ovalues[index0], ovalues[index1], ovalues[index2], mr, ma1, ma2, ma3);
}
}

//

{
stringstream ssc, sst;
ssc << (double)dvalues[index0] << endl;
sst << dvalues[index0] << endl;
if (ssc.str() != sst.str()) { cout << "NG 0 c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << (double)dvalues[index0] << endl;
sst << setw(20) << dvalues[index0] << endl;
if (ssc.str() != sst.str()) { cout << "NG 1 c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setprecision(14) << (double)dvalues[index0] << endl;
sst << setprecision(14) << dvalues[index0] << endl;
if (ssc.str() != sst.str()) { cout << "NG 2 c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}

{
stringstream ssc, sst;
ssc << setw(20) << right << (double)dvalues[index0] << endl;
sst << setw(20) << right << dvalues[index0] << endl;
if (ssc.str() != sst.str()) { cout << "NG 3 c = <" << ssc.str() << ">, t = <" << sst.str() << ">" << endl; exit(-1); }
}
}

mpfr_clears(mr, ma1, ma2, ma3, NULL);
Expand Down

0 comments on commit 97b7a08

Please sign in to comment.