#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_affine_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;
const wf_offset_t* const i1_ext = wavefront_set->in_i1wavefront_ext->offsets;
const wf_offset_t* const d1_ext = wavefront_set->in_d1wavefront_ext->offsets;
wf_offset_t* const out_m = wavefront_set->out_mwavefront->offsets;
wf_offset_t* const out_i1 = wavefront_set->out_i1wavefront->offsets;
wf_offset_t* const out_d1 = wavefront_set->out_d1wavefront->offsets;
int k;
PRAGMA_LOOP_VECTORIZE
for (k=lo;k<=hi;++k) {
const wf_offset_t ins1_o = m_open1[k-1];
const wf_offset_t ins1_e = i1_ext[k-1];
const wf_offset_t ins1 = MAX(ins1_o,ins1_e) + 1;
out_i1[k] = ins1;
const wf_offset_t del1_o = m_open1[k+1];
const wf_offset_t del1_e = d1_ext[k+1];
const wf_offset_t del1 = MAX(del1_o,del1_e);
out_d1[k] = del1;
const wf_offset_t misms = m_misms[k] + 1;
wf_offset_t max = MAX(del1,MAX(misms,ins1));
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_affine_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 wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets;
const wf_offset_t* const i1_ext = wavefront_set->in_i1wavefront_ext->offsets;
const wf_offset_t* const d1_ext = wavefront_set->in_d1wavefront_ext->offsets;
wf_offset_t* const out_m = wavefront_set->out_mwavefront->offsets;
wf_offset_t* const out_i1 = wavefront_set->out_i1wavefront->offsets;
wf_offset_t* const out_d1 = wavefront_set->out_d1wavefront->offsets;
const pcigar_t* const m_misms_bt_pcigar = wavefront_set->in_mwavefront_misms->bt_pcigar;
const pcigar_t* const m_open1_bt_pcigar = wavefront_set->in_mwavefront_open1->bt_pcigar;
const pcigar_t* const i1_ext_bt_pcigar = wavefront_set->in_i1wavefront_ext->bt_pcigar;
const pcigar_t* const d1_ext_bt_pcigar = wavefront_set->in_d1wavefront_ext->bt_pcigar;
const bt_block_idx_t* const m_misms_bt_prev = wavefront_set->in_mwavefront_misms->bt_prev;
const bt_block_idx_t* const m_open1_bt_prev = wavefront_set->in_mwavefront_open1->bt_prev;
const bt_block_idx_t* const i1_ext_bt_prev = wavefront_set->in_i1wavefront_ext->bt_prev;
const bt_block_idx_t* const d1_ext_bt_prev = wavefront_set->in_d1wavefront_ext->bt_prev;
pcigar_t* const out_m_bt_pcigar = wavefront_set->out_mwavefront->bt_pcigar;
pcigar_t* const out_i1_bt_pcigar = wavefront_set->out_i1wavefront->bt_pcigar;
pcigar_t* const out_d1_bt_pcigar = wavefront_set->out_d1wavefront->bt_pcigar;
bt_block_idx_t* const out_m_bt_prev = wavefront_set->out_mwavefront->bt_prev;
bt_block_idx_t* const out_i1_bt_prev = wavefront_set->out_i1wavefront->bt_prev;
bt_block_idx_t* const out_d1_bt_prev = wavefront_set->out_d1wavefront->bt_prev;
int k;
PRAGMA_LOOP_VECTORIZE for (k=lo;k<=hi;++k) {
const wf_offset_t ins1_o = m_open1[k-1];
const wf_offset_t ins1_e = i1_ext[k-1];
wf_offset_t ins1;
pcigar_t ins1_pcigar;
bt_block_idx_t ins1_block_idx;
if (ins1_e >= ins1_o) {
ins1 = ins1_e;
ins1_pcigar = i1_ext_bt_pcigar[k-1];
ins1_block_idx = i1_ext_bt_prev[k-1];
} else {
ins1 = ins1_o;
ins1_pcigar = m_open1_bt_pcigar[k-1];
ins1_block_idx = m_open1_bt_prev[k-1];
}
out_i1_bt_pcigar[k] = PCIGAR_PUSH_BACK_INS(ins1_pcigar);
out_i1_bt_prev[k] = ins1_block_idx;
out_i1[k] = ++ins1;
const wf_offset_t del1_o = m_open1[k+1];
const wf_offset_t del1_e = d1_ext[k+1];
wf_offset_t del1;
pcigar_t del1_pcigar;
bt_block_idx_t del1_block_idx;
if (del1_e >= del1_o) {
del1 = del1_e;
del1_pcigar = d1_ext_bt_pcigar[k+1];
del1_block_idx = d1_ext_bt_prev[k+1];
} else {
del1 = del1_o;
del1_pcigar = m_open1_bt_pcigar[k+1];
del1_block_idx = m_open1_bt_prev[k+1];
}
out_d1_bt_pcigar[k] = PCIGAR_PUSH_BACK_DEL(del1_pcigar);
out_d1_bt_prev[k] = del1_block_idx;
out_d1[k] = del1;
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] = out_i1_bt_pcigar[k];
out_m_bt_prev[k] = out_i1_bt_prev[k];
}
if (max == del1) {
out_m_bt_pcigar[k] = out_d1_bt_pcigar[k];
out_m_bt_prev[k] = out_d1_bt_prev[k];
}
if (max == misms) {
out_m_bt_pcigar[k] = m_misms_bt_pcigar[k];
out_m_bt_prev[k] = m_misms_bt_prev[k];
}
out_m_bt_pcigar[k] = PCIGAR_PUSH_BACK_MISMS(out_m_bt_pcigar[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_affine_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_affine_idm_piggyback(wf_aligner,wavefront_set,lo,hi);
} else {
wavefront_compute_affine_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_affine_idm_piggyback(wf_aligner,wavefront_set,t_lo,t_hi);
} else {
wavefront_compute_affine_idm(wf_aligner,wavefront_set,t_lo,t_hi);
}
}
#endif
}
}
void wavefront_compute_affine(
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 &&
wavefront_set.in_i1wavefront_ext->null &&
wavefront_set.in_d1wavefront_ext->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_affine_dispatcher(wf_aligner,&wavefront_set,lo,hi);
if (wf_aligner->wf_components.bt_piggyback) {
wavefront_backtrace_offload_affine(wf_aligner,&wavefront_set,lo,hi);
}
wavefront_compute_process_ends(wf_aligner,&wavefront_set,score);
}