std::string count() { MessageHandler mh; mh.begin("counting") << " paths of " << typenameof(spec); std::vector<Word> tmp(stateWords + 1); Word* ptmp = tmp.data(); int const n = spec.get_root(state(ptmp)); if (n <= 0) { mh << " ..."; mh.end(0); return (n == 0) ? "0" : "1"; } uint64_t totalStorage[n / 63 + 1]; BigNumber total(totalStorage); total.store(0); size_t maxWidth = 0; //std::cerr << "\nLevel,Width\n"; std::vector<MemoryPool> pools(n + 1); MyVector<MyList<Word> > vnodeTable(n + 1); MyVector<UniqTable> uniqTable; uniqTable.reserve(n + 1); for (int i = 0; i <= n; ++i) { uniqTable.push_back(UniqTable(hasher, hasher)); } int numberWords = 1; Word* p0 = vnodeTable[n].alloc_front(stateWords + 1); spec.get_copy(state(p0), state(ptmp)); spec.destruct(state(ptmp)); number(p0).store(1); mh.setSteps(n); for (int i = n; i > 0; --i) { MyList<Word>& vnodes = vnodeTable[i]; size_t m = vnodes.size(); //std::cerr << i << "," << m << "\n"; maxWidth = std::max(maxWidth, m); MyList<Word>& nextVnodes = vnodeTable[i - 1]; UniqTable& nextUniq = uniqTable[i - 1]; int const nextWords = stateWords + numberWords + 1; Word* pp = nextVnodes.alloc_front(nextWords); //if (nextUniq.size() < m) nextUniq.rehash(m); for (; !vnodes.empty(); vnodes.pop_front()) { Word* p = vnodes.front(); if (number(p).equals(0)) { spec.destruct(state(p)); continue; } for (int b = 0; b <= 1; ++b) { spec.get_copy(state(pp), state(p)); int ii = spec.get_child(state(pp), i, b); if (ii <= 0) { spec.destruct(state(pp)); if (ii != 0) { total.add(number(p)); } } else if (ii < i - 1) { Word* qq = vnodeTable[ii].alloc_front( nextWords + (i - ii) / 63); spec.get_copy(state(qq), state(pp)); spec.destruct(state(pp)); Word* qqq = uniqTable[ii].add(qq); if (qqq == qq) { number(qqq).store(number(p)); } else { spec.destruct(state(qq)); int w = number(qqq).add(number(p)); if (numberWords < w) { numberWords = w; //FIXME might be broken at long skip } vnodeTable[ii].pop_front(); } } else { assert(ii == i - 1); Word* ppp = nextUniq.add(pp); if (ppp == pp) { number(ppp).store(number(p)); pp = nextVnodes.alloc_front(nextWords); } else { spec.destruct(state(pp)); int w = number(ppp).add(number(p)); if (numberWords < w) { numberWords = w; //FIXME might be broken at long skip } } } } spec.destruct(state(p)); } nextVnodes.pop_front(); nextUniq.clear(); pools[i].clear(); spec.destructLevel(i); mh.step(); } mh.end(maxWidth); return total; }