     if (thread_id >= reads.size())
         return;
 
-    CountDelegate counter( count );
-
-    typedef io::ReadData::const_read_stream_type read_stream_type;
-    const read_stream_type read_stream( reads.read_stream() );
-
-    const uint32 read_begin = reads.read_index()[ thread_id ];
-    const uint32 read_end   = reads.read_index()[ thread_id+1 ];
-
-    uint4 stack[32*4];
-
-    hamming_backtrack(
-        fmi,
-        read_stream.begin() + read_begin,
-        len,
-        seed,
-        mismatches,
-        stack,
-        counter );
+    count_core( thread_id, reads, fmi, len, seed, mismatches, count );
 }
 
 //

            if (strcmp( found_str, pattern_str ) != 0)
            {
                const range_type inv = inv_psi( fmi, x );
                fprintf(stderr, "  \nerror : locating %s @ %u at SA=%u in SA(%u,%u), resulted in %s @ %u (= sa[%u] + %u)\n", pattern_str, i, x, range.x, range.y, found_str, prefix, uint32(inv.x), uint32(inv.y));
                exit(1);
            }
            /*{

            cudaEventSynchronize( stop );
            cudaEventElapsedTime( &time, start, stop );

            fprintf(stderr, "  gpu backtracking (32,1,0)... done: %.1fms, A/s: %.3f M\n", time, reads_data_cuda.size()/(time*1000.0f) );
        }
        {
            Timer timer;
            timer.start();

            uint32 counter = 0;
            for (uint32 i = 0; i < reads_data->size(); ++i)
            {
                count_core(
                    i,
                    host_reads_view,
                    host_fmindex,
                    32u,
                    0u,
                    1u,
                    &counter );
            }

            timer.stop();
            float time = timer.seconds() * 1000.0f;

            fprintf(stderr, "  cpu backtracking (32,1,0)... done: %.1fms, A/s: %.3f M\n", time, reads_data_cuda.size()/(time*1000.0f) );
        }
        // 50-mers, distance=2, seed=25
        {
