Print __float128, without using quadmath_snprintf
Asked Answered
C

4

6

In my question about Analysis of float/double precision in 32 decimal digits, one answer said to take a look at __float128.

I used it and the compiler could find it, but I can not print it, since the complier can not find the header quadmath.h.

So my questions are:

  1. __float128 is standard, correct?
  2. How to print it?
  3. Isn't quadmath.h standard?

These answers did not help:

  1. Use extern C
  2. Precision in C++
  3. Printing

The ref also did not help.

Note that I do not want to use any non standard library.

[EDIT]

It would be also useful, if that question had an answer, even if the answer was a negative one.

Complexity answered 14/5, 2014 at 12:25 Comment(2)
As the leading underscores indicate: do not use itBlasting
Did you check the link I provided to the analysis? The answer says that it would be an option. No?Complexity
A
2

__float128 is a vendor extension.


In C23, _FloatN for N = 16, 32, 64, 128 or multiples of 32 greater than 128 are standardised extensions that a compiler can provide. So _Float128 would be the standard type. To print the type, you use strfromfN to turn it into a string:

void print(_Float128 fp) {
    char buf[32 + sizeof(".e+99999")];
    int sz = strfromf128(buf, sizeof buf, "%.32g", fp);
    fwrite(buf, 1, sz, stdout);
}

https://godbolt.org/z/E7W6a4r8d


In C++23, as well as _FloatN probably being provided as well by your compilers as an extension, std::float128_t is provided as the standard 128-bit float type.

It is implementation defined if there is an overload for operator<< so you can simply use std::cout, but there will be a std::formatter specialization, so std::format can be used to create a string:

void print(std::float128_t fp) {
    std::println("{:.32g}", fp);  // std::println is C++26
    // C++23: `std::cout << std::format("{:.32g}\n", fp);`
}

https://godbolt.org/z/5sahahn4P


Before C23/C++23, there was no standard type for 128 bit float. Sometimes long double is 128 bits, but that is rare (it is more likely to be 80 bits or the same 64 bits as a regular double). So you had to use compiler extensions or a software emulation library.

Algia answered 21/3 at 12:43 Comment(0)
I
2

Using the boost library was the best answer for me:

#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions/gamma.hpp>

using namespace boost::multiprecision;  

float128 su1= 0.33333333333333333q;
cout << "su1=" << su1 << endl;

Remember to link this library:

-lquadmath
Incertitude answered 25/9, 2020 at 7:9 Comment(1)
And for those who insist on perfect precision, try this BCD library: github.com/edwig/bcd It's MS Windows specific but I hacked up my personal copy to remove the Windows dependencies.Incertitude
A
2

__float128 is a vendor extension.


In C23, _FloatN for N = 16, 32, 64, 128 or multiples of 32 greater than 128 are standardised extensions that a compiler can provide. So _Float128 would be the standard type. To print the type, you use strfromfN to turn it into a string:

void print(_Float128 fp) {
    char buf[32 + sizeof(".e+99999")];
    int sz = strfromf128(buf, sizeof buf, "%.32g", fp);
    fwrite(buf, 1, sz, stdout);
}

https://godbolt.org/z/E7W6a4r8d


In C++23, as well as _FloatN probably being provided as well by your compilers as an extension, std::float128_t is provided as the standard 128-bit float type.

It is implementation defined if there is an overload for operator<< so you can simply use std::cout, but there will be a std::formatter specialization, so std::format can be used to create a string:

void print(std::float128_t fp) {
    std::println("{:.32g}", fp);  // std::println is C++26
    // C++23: `std::cout << std::format("{:.32g}\n", fp);`
}

https://godbolt.org/z/5sahahn4P


Before C23/C++23, there was no standard type for 128 bit float. Sometimes long double is 128 bits, but that is rare (it is more likely to be 80 bits or the same 64 bits as a regular double). So you had to use compiler extensions or a software emulation library.

Algia answered 21/3 at 12:43 Comment(0)
G
1

No, it's not standard - neither the type nor the header. That's why the type has a double underscore (reserved name). Apparently, quadmath.h provides a quadmath_snprintf method. In C++ you would have used <<, of course.

Glyceric answered 14/5, 2014 at 13:13 Comment(4)
No you can't. __float128 will cause a syntax error when used with <<. Edit the answer and I will be happy to accept it, thanks. Or if you know how to make it work with <<, feel free to teach me(us).Complexity
@G.Samaras: I wrote "would" instead of "can" because it's a hypothetical - if quadmath was a C++ library, it would offer <<.Glyceric
IMHO, your syntax is misleading. However the comment clears that. You seem to have the experience whether to edit or not. Accept and +1.Complexity
Fair point, it's easy to be too subtle on the Internet. Fixed.Glyceric
V
1

Work in GNU-Fortran! It allows to run the same program in different precision: single (32 bit), double (64 bit), extended (80 bit) and quad (128 bit). You don't have to do any changes in the program, you simply write 'real' for all floating points. The size of floating points is set by compiler options -freal-4-real-8, -freal-4-real-10 and -freal-4-real-16.

Vareck answered 10/2, 2018 at 14:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.