Boost logo

Boost Users :

Subject: Re: [Boost-users] [Multiprecision] Runtime assertion failure with clang++3.6.0 but not g++4.9.2
From: mbw_bst_at_[hidden]
Date: 2016-02-08 19:43:56


Hello again and thanks for your replies!

Taking the following two statements into account:

> For type int, the values are computed recursively at compile time, for a
> user-defined-type the values are computed at runtime and you hit
> initialization-order issues.

> Seems to be that Multiprecision relies on static data that haven't
> (necessarily) been initialized before your own static members. Works
> fine
> if the members are made non-static:

Does that mean that, since
a) boost::multiprecision::number<gmp_int> is not constexpr enabled, and
b) static initialization can't happen at compile-time for user-defined
types,

that there is no way for me to initialize a variable of this type at
compile-time?
Does b) follow logically from a) ?

I (believe to have) confirmed runtime-initialization by running valgrind,
which showed the presence of dynamic memory allocations (and also jumps
depending on uninitialized variables, which probably corresponds to the
assertion failure). I am mentioning this because initially my little test
program looked somewhat like this:

#include <iostream>
#include <vector>
#include <boost/multiprecision/gmp.hpp>

namespace bm = boost::multiprecision;

template<std::size_t N>
struct factorial
{
    static const bm::mpz_int value;
    static void add_values(std::vector<bm::mpz_int>& vec)
    {
        factorial<N-1>::add_values(vec);
        vec.push_back(value);
    }
};
template<std::size_t N>
const bm::mpz_int factorial<N>::value = N * factorial<N-1>::value;

template<>
struct factorial<std::size_t{0}>
{
    static const bm::mpz_int value;
    static void add_values(std::vector<bm::mpz_int>& vec)
    {
        vec.push_back(value);
    }
};
const bm::mpz_int factorial<0>::value = 1;

    int
main ()
{
    std::vector<bm::mpz_int> fac_table{};
    factorial<10'000>::add_values(fac_table);
    std::cout << "Enter a number between 0 and 10'000 to calculate
factorial:";
    std::size_t number;
    std::cin >> number;
    std::cout << '\n' << number << "! == " << fac_table[number] << '\n';

    return 0;
}

This still includes the "unsafe" static initialization of a user-defined
type. However it compiles and runs via

g++ -ansi -std=c++14 -O3 -Wall -Wextra -pedantic -static -save-temps
-ftemplate-depth-50000 -DNDEBUG -o main main.cpp -lgmp -pthread

This was what made me believe in the compile-time computation of the
factorials in the first place, since using this version, valgrind does not
show any dynamic memory allocation at all. On the other hand, I don't
understand what's going on here really, especially since std::vector<> is
supposed to allocate memory at run-time.

Now I'm not sure whether the last example has anything to do with
Boost.Multiprecision anymore, so while it would really make my day if you
could help me better understand this, I will understand if this is not the
right place to ask these questions.

Thanks again for your replies so far, they have been of great help!

Cheers,

Max


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net