1

I have some code were I avoid some costly divisions by converting a boost integer to a double. For the real code I will build an fp type that's big enough to hold the maximal value (exponent). To test I am using a double. So I do this:

#define NTYPE_BITS 512
typedef number<cpp_int_backend<NTYPE_BITS, NTYPE_BITS, unsigned_magnitude, unchecked, void> > NTYPE;
NTYPE a1 = BIG_VALUE;
double a1f = (double)a1;

The code generated for that cast is quite complicated. I see it's basically looping over all the values in a1 (least significant first) scaling them by powers of two. Now in this case I guess at most the number of elements that could affect the result are the last two (64 bits for each element and the most significant element might have less that 64 bits used). Is there a better way to do this?

  • 2
    I don't think this is going to help you achieve your goal, but you should generally use `static_cast(a1);` instead of a c-style cast. https://stackoverflow.com/a/29983699/2601293 – J'e Feb 04 '21 at 12:08

1 Answers1

0

First off, NEVER use C-Style casts. (Why use static_cast<int>(x) instead of (int)x?). Second, avoid using namespace. (Third, reserve all-caps names for macros).

That said:

double a1f = a1.convert_to<double>();

Is your ticket.

Live On Coliru

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
namespace bmp = boost::multiprecision;

//0xDEADBEEFE1E104B1D00008BADF00D000ABADBABE000D15EA5E
#define BIG_VALUE "0xDEADBEEFE1E104B1D00008BADF00D000ABADBABE000D15EA5E"
#define NTYPE_BITS 512

int main() {
    using NTYPE = bmp::number<
        bmp::cpp_int_backend<
            NTYPE_BITS, NTYPE_BITS,
            bmp::unsigned_magnitude, bmp::unchecked, void>>;

    NTYPE a1(BIG_VALUE);

    std::cout << a1 << "\n";
    std::cout << std::hex << a1 << "\n";
    std::cout << a1.convert_to<double>() << "\n";
}

Prints

1397776821048146366831161011449418369017198837637750820563550
deadbeefe1e104b1d00008badf00d000abadbabe000d15ea5e
1.39778e+60
sehe
  • 374,641
  • 47
  • 450
  • 633
  • By the way, documentation: [Constructing and Interconverting Between Number Types](https://www.boost.org/doc/libs/1_75_0/libs/multiprecision/doc/html/boost_multiprecision/tut/conversions.html) – sehe Feb 04 '21 at 16:43
  • Thanks. a1.convert_to() does essentially the same thing the cast was doing. I have now decided that for the general case you really do need to process the entire number. For example if you are rounding up floating point operations then a number of the form 2^500+1 would require scanning all the libs to generate the correct value. – Neill Clift Feb 04 '21 at 18:25
  • I'm a bit confused what the problem is. You asked for the recommended/better way. Which is the documented path. If that "does the same thing" that's fine: it's what's recommended. I'm not completely sure what "rounding up floating point operations" has to do with cpp_int. – sehe Feb 04 '21 at 19:16
  • I was looking for something that performed better. For example didn't read the entire number when it didn't need to. I mention this in the question. As it turns out I think this is needed in the round up case and I give the example above. – Neill Clift Feb 06 '21 at 02:42