#include "utils/commons.h"
#include "system/mm_allocator.h"
#include "wavefront_compute.h"
#include "wavefront_backtrace_offload.h"
#ifdef WFA_PARALLEL
#include <omp.h>
#endif
void wavefront_compute_linear_idm(
wavefront_aligner_t* const wf_aligner,
const wavefront_set_t* const wavefront_set,
const int lo,
const int hi) {
wavefront_sequences_t* const sequences = &wf_aligner->sequences;
const int pattern_length = sequences->pattern_length;
const int text_length = sequences->text_length;
const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets;
const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets;
wf_offset_t* const out_m = wavefront_set->out_mwavefront->offsets;
int k;
PRAGMA_LOOP_VECTORIZE
for (k=lo;k<=hi;++k) {
const wf_offset_t ins1 = m_open1[k-1];
const wf_offset_t del1 = m_open1[k+1];
const wf_offset_t misms = m_misms[k];
wf_offset_t max = MAX(del1,MAX(misms,ins1)+1);
const wf_unsigned_offset_t h = WAVEFRONT_H(k,max); const wf_unsigned_offset_t v = WAVEFRONT_V(k,max); if (h > text_length) max = WAVEFRONT_OFFSET_NULL;
if (v > pattern_length) max = WAVEFRONT_OFFSET_NULL;
out_m[k] = max;
}
}
void wavefront_compute_linear_idm_piggyback(
wavefront_aligner_t* const wf_aligner,
const wavefront_set_t* const wavefront_set,
const int lo,
const int hi) {
wavefront_sequences_t* const sequences = &wf_aligner->sequences;
const int pattern_length = sequences->pattern_length;
const int text_length = sequences->text_length;
const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets;
const pcigar_t* const m_misms_bt_pcigar = wavefront_set->in_mwavefront_misms->bt_pcigar;
const bt_block_idx_t* const m_misms_bt_prev = wavefront_set->in_mwavefront_misms->bt_prev;
const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets;
const pcigar_t* const m_open1_bt_pcigar = wavefront_set->in_mwavefront_open1->bt_pcigar;
const bt_block_idx_t* const m_open1_bt_prev = wavefront_set->in_mwavefront_open1->bt_prev;
wf_offset_t* const out_m = wavefront_set->out_mwavefront->offsets;
pcigar_t* const out_m_bt_pcigar = wavefront_set->out_mwavefront->bt_pcigar;
bt_block_idx_t* const out_m_bt_prev = wavefront_set->out_mwavefront->bt_prev;
int k;
PRAGMA_LOOP_VECTORIZE for (k=lo;k<=hi;++k) {
const wf_offset_t ins1 = m_open1[k-1] + 1;
const wf_offset_t del1 = m_open1[k+1];
const wf_offset_t misms = m_misms[k] + 1;
wf_offset_t max = MAX(del1,MAX(misms,ins1));
if (max == ins1) {
out_m_bt_pcigar[k] = PCIGAR_PUSH_BACK_INS(m_open1_bt_pcigar[k-1]);
out_m_bt_prev[k] = m_open1_bt_prev[k-1];
}
if (max == del1) {
out_m_bt_pcigar[k] = PCIGAR_PUSH_BACK_DEL(m_open1_bt_pcigar[k+1]);
out_m_bt_prev[k] = m_open1_bt_prev[k+1];
}
if (max == misms) {
out_m_bt_pcigar[k] = PCIGAR_PUSH_BACK_MISMS(m_misms_bt_pcigar[k]);
out_m_bt_prev[k] = m_misms_bt_prev[k];
}
const wf_unsigned_offset_t h = WAVEFRONT_H(k,max); const wf_unsigned_offset_t v = WAVEFRONT_V(k,max); if (h > text_length) max = WAVEFRONT_OFFSET_NULL;
if (v > pattern_length) max = WAVEFRONT_OFFSET_NULL;
out_m[k] = max;
}
}
void wavefront_compute_linear_dispatcher(
wavefront_aligner_t* const wf_aligner,
wavefront_set_t* const wavefront_set,
const int lo,
const int hi) {
const bool bt_piggyback = wf_aligner->wf_components.bt_piggyback;
const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi);
if (num_threads == 1) {
if (bt_piggyback) {
wavefront_compute_linear_idm_piggyback(wf_aligner,wavefront_set,lo,hi);
} else {
wavefront_compute_linear_idm(wf_aligner,wavefront_set,lo,hi);
}
} else {
#ifdef WFA_PARALLEL
#pragma omp parallel num_threads(num_threads)
{
int t_lo, t_hi;
const int thread_id = omp_get_thread_num();
const int thread_num = omp_get_num_threads();
wavefront_compute_thread_limits(thread_id,thread_num,lo,hi,&t_lo,&t_hi);
if (bt_piggyback) {
wavefront_compute_linear_idm_piggyback(wf_aligner,wavefront_set,t_lo,t_hi);
} else {
wavefront_compute_linear_idm(wf_aligner,wavefront_set,t_lo,t_hi);
}
}
#endif
}
}
void wavefront_compute_linear(
wavefront_aligner_t* const wf_aligner,
const int score) {
wavefront_set_t wavefront_set;
wavefront_compute_fetch_input(wf_aligner,&wavefront_set,score);
if (wavefront_set.in_mwavefront_misms->null &&
wavefront_set.in_mwavefront_open1->null) {
wf_aligner->align_status.num_null_steps++; wavefront_compute_allocate_output_null(wf_aligner,score); return;
}
wf_aligner->align_status.num_null_steps = 0;
int hi, lo;
wavefront_compute_limits_input(wf_aligner,&wavefront_set,&lo,&hi);
wavefront_compute_allocate_output(wf_aligner,&wavefront_set,score,lo,hi);
wavefront_compute_init_ends(wf_aligner,&wavefront_set,lo,hi);
wavefront_compute_linear_dispatcher(wf_aligner,&wavefront_set,lo,hi);
if (wf_aligner->wf_components.bt_piggyback) {
wavefront_backtrace_offload_linear(wf_aligner,&wavefront_set,lo,hi);
}
wavefront_compute_process_ends(wf_aligner,&wavefront_set,score);
}