<tb@panthema.net>
<http://www.gnu.org/licenses/>
namespace sacheck
{
template < class InputSA >
class tuplize_sa_index
{
typedef typename InputSA::value_type offset_type;
typedef tuples::pair<offset_type, offset_type> tuple_type;
InputSA& m_input;
size_t m_counter;
bool m_finished;
tuple_type m_result;
public:
typedef tuple_type value_type;
tuplize_sa_index(InputSA& input)
: m_input(input), m_counter(0), m_finished(false)
{
assert(!m_input.empty());
m_result = value_type(m_counter, *m_input);
}
const value_type & operator*() const
{
return m_result;
}
tuplize_sa_index & operator++()
{
assert(!m_input.empty());
++m_input;
++m_counter;
if (!m_input.empty())
m_result = value_type(m_counter, *m_input);
else
m_finished = true;
return *this;
}
bool empty()
{
return m_finished;
}
};
template <typename InputT, typename InputSA, typename SizeType>
bool check_sa(InputT& inputT, InputSA& inputSA)
{
using namespace stxxl;
using namespace tuples;
typedef typename InputT::value_type alphabet_type;
typedef typename InputSA::value_type offset_type;
typedef SizeType size_type;
typedef tuples::pair<offset_type, offset_type> pair_type;
typedef tuples::triple<offset_type,alphabet_type,offset_type> triple_type;
typedef pair_less2nd<pair_type> pair_less_type;
typedef tuplize_sa_index<InputSA> tuplize_sa_index_type;
typedef typename stream::sort<tuplize_sa_index_type, pair_less_type, block_size> build_isa_type;
tuplize_sa_index_type tuplize_sa_index(inputSA);
build_isa_type build_isa(tuplize_sa_index, pair_less_type(), ram_use / 3);
typedef triple_less1st<triple_type> triple_less_type;
typedef typename stream::use_push<triple_type> triple_push_type;
typedef typename stream::runs_creator<triple_push_type, triple_less_type, block_size, RC> triple_rc_type;
typedef typename stream::runs_merger<typename triple_rc_type::sorted_runs_type, triple_less_type> triple_rm_type;
triple_rc_type triple_rc(triple_less_type(), ram_use / 3);
size_type totalSize;
{
offset_type prev_isa = (*build_isa).first;
offset_type counter = 0;
while (!build_isa.empty())
{
if ((*build_isa).second != counter) {
std::cout << "Error: suffix array is not a permutation of 0..n-1.\n";
return false;
}
++counter;
++build_isa;
if (!build_isa.empty())
{
triple_rc.push( triple_type(prev_isa, *inputT, (*build_isa).first) );
prev_isa = (*build_isa).first;
}
++inputT;
}
totalSize = counter;
}
if (totalSize == 1) return true;
triple_rm_type triple_rm(triple_rc.result(), triple_less_type(), ram_use / 3);
{
triple_type prev_triple = *triple_rm;
size_type counter = 0;
++triple_rm;
while (!triple_rm.empty())
{
const triple_type& this_triple = *triple_rm;
if (prev_triple.second > this_triple.second)
{
std::cout << "Error: suffix array position " << counter << " ordered incorrectly.\n";
return false;
}
else if (prev_triple.second == this_triple.second)
{
if ( this_triple.third == (offset_type)totalSize ) {
std::cout << "Error: suffix array position " << counter << " ordered incorrectly.\n";
return false;
}
if ( prev_triple.third != (offset_type)totalSize &&
prev_triple.third > this_triple.third )
{
std::cout << "Error: suffix array position " << counter << " ordered incorrectly.\n";
return false;
}
}
prev_triple = this_triple;
++triple_rm;
++counter;
}
}
return true;
}
template <typename InputT, typename InputSA>
bool check_sa_vectors(InputT& inputT, InputSA& inputSA)
{
using namespace tuples;
typedef it_rg<typename InputT::iterator> InputT_it_rg;
InputT_it_rg string_input = create_ls(inputT.begin(), inputT.end());
typedef it_rg<typename InputSA::iterator> InputSA_it_rg;
InputSA_it_rg sa_input = create_ls(inputSA.begin(), inputSA.end());
return check_sa<InputT_it_rg, InputSA_it_rg, typename InputSA::size_type>(string_input, sa_input);
}
}