0

I have the following code that computes the Stirling number of the second kind for a given n and k,

#include <cstdint>
#include <map>

#include <boost/multiprecision/cpp_int.hpp>

namespace mp = boost::multiprecision;


mp::cpp_int stirlingS2(unsigned n, unsigned k)
{
    if (n == 0 && k == 0) {
        return 1;
    }

    if (n == 0 || k == 0) {
        return 0;
    }

    static auto memo = std::map<std::pair<unsigned, unsigned>, mp::cpp_int>();
    auto nKPair = std::pair<unsigned, unsigned>(n, k);

    if (memo.count(nKPair) > 0) {
        return memo[nKPair];
    }

    auto val = k * stirlingS2(n - 1, k) + stirlingS2(n - 1, k - 1);

    memo[nKPair] = val;

    return val;
}

Unfortunately, when this code is running, it segfaults. It seems to run fine for the first 87795 values inserted into memo, but then crashes shortly thereafter. Specifically, the segfault happens at map::count, in the line if (memo.count(nKPair) > 0) {. I thought maybe this was a matter of memo running out of size, so I added the following caveat to the assignment to memo,

if (memo.size() < memo.max_size()) {
    memo[nKPair] = val;
}

But that didn't help. I've also noticed that the 87795 value is not indicative of when this crashes. With some minor modifications, changing the first if statement to,

if (n <= k) {
    return 1;
}

changes that value to 66453.

Does anyone know what's going on here?

1 Answers1

1

Ok, so after hours of confusion, I narrowed this down to an expression templates issue. I don't really fully understand why, but it all had to do with that little auto in the line

auto val = k * stirlingS2(n - 1, k) + stirlingS2(n - 1, k - 1)

Basically, change that auto to mp::cpp_int and suddenly, no segfault.