<commit_before>#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "decode.h"
#include "util.h"

#define NBASE 4


float decode_transducer(const scrappie_matrix logpost, float skip_pen, int * seq, bool use_slip){
	assert(NULL != logpost);
	assert(skip_pen >= 0.0);
	assert(NULL != seq);
	const int nev = logpost->nc;
	const int nstate = logpost->nr;
	const int ldp = logpost->nrq * 4;
	const int nhistory = nstate - 1;
	assert((nhistory %4) == 0);
	const int32_t nhistoryq = nhistory / 4;
	const __m128i nhistoryqv = _mm_set1_epi32(nhistoryq);
	assert((nhistoryq % 4) == 0);
	const int32_t nhistoryqq = nhistoryq / 4;
	const __m128i nhistoryqqv = _mm_set1_epi32(nhistoryqq);
	assert((nhistoryqq % 4) == 0);
	const int32_t nhistoryqqq = nhistoryqq / 4;
	const __m128i nhistoryqqqv = _mm_set1_epi32(nhistoryqqq);
	assert((nhistoryqqq % 4) == 0);
	const int nhistoryqqqq = nhistoryqqq / 4;

	//  Forwards memory + traceback
	scrappie_matrix score = make_scrappie_matrix(nhistory, 1);
	scrappie_matrix prev_score = make_scrappie_matrix(nhistory, 1);
	scrappie_matrix tmp = make_scrappie_matrix(nhistory, 1);
	scrappie_imatrix itmp = make_scrappie_imatrix(nhistory, nev);
	scrappie_imatrix traceback = make_scrappie_imatrix(nhistory, nev);

	//  Initialise
	for( int i=0 ; i < nhistoryq ; i++){
		score->data.v[i] = logpost->data.v[i];
	}

	//  Forwards Viterbi iteration
	for(int ev=1 ; ev < nev ; ev++){
		const size_t offsetTq = ev * nhistoryq;
		const size_t offsetP = ev * ldp;
		const size_t offsetPq = ev * logpost->nrq;
		// Swap score and previous score
		{
			scrappie_matrix tmptr = score;
			score = prev_score;
			prev_score = tmptr;
		}

		// Stay
		const __m128 stay_m128 = _mm_set1_ps(logpost->data.f[offsetP + nhistory]);
		const __m128i negone_m128i = _mm_set1_epi32(-1);
		for(int i=0 ; i < nhistoryq ; i++){
			// Traceback for stay is negative
			score->data.v[i] = prev_score->data.v[i] + stay_m128;
			traceback->data.v[offsetTq + i] = negone_m128i;
		}

		// Step
		// Following three loops find maximum over suffix and record index
		for(int i=0 ; i<nhistoryqq ; i++){
			tmp->data.v[i] = prev_score->data.v[i];
			itmp->data.v[i] = _mm_setzero_si128();
		}
		for(int r=1 ; r<NBASE ; r++){
			const size_t offset = r * nhistoryqq;
			const __m128i itmp_fill = _mm_set1_epi32(r);
			for(int i=0 ; i<nhistoryqq ; i++){
				__m128i mask = _mm_castps_si128(_mm_cmplt_ps(tmp->data.v[i], prev_score->data.v[offset + i]));
				tmp->data.v[i] = _mm_max_ps(tmp->data.v[i], prev_score->data.v[offset + i]);
				itmp->data.v[i] = _mm_or_si128(_mm_andnot_si128(mask, itmp->data.v[i]),
					                       _mm_and_si128(mask, itmp_fill));
			}
		}
		const __m128i c0123_m128i = _mm_setr_epi32(0, 1, 2, 3);
		for(int i=0 ; i<nhistoryqq ; i++){
			itmp->data.v[i] = _mm_add_epi32(
							_mm_mullo_epi32(itmp->data.v[i], nhistoryqv),
							_mm_add_epi32(c0123_m128i, _mm_set1_epi32(i * 4)));
		}

		for(int pref=0 ; pref < nhistoryq ; pref++){
			const size_t i = pref;
			const __m128 step_score = logpost->data.v[offsetPq + i] + _mm_set1_ps(tmp->data.f[pref]);
			__m128i mask = _mm_castps_si128(_mm_cmplt_ps(score->data.v[i], step_score));
			score->data.v[i] = _mm_max_ps(score->data.v[i], step_score);
			traceback->data.v[offsetTq + i] = _mm_or_si128(_mm_andnot_si128(mask, traceback->data.v[offsetTq + i]),
								       _mm_and_si128(mask, _mm_set1_epi32(itmp->data.f[pref])));
		}



		// Skip
		const __m128 skip_penv = _mm_set1_ps(skip_pen);
		for(int i=0 ; i<nhistoryqqq ; i++){
			tmp->data.v[i] = prev_score->data.v[i];
			itmp->data.v[i] = _mm_setzero_si128();
		}
		for(int r=1 ; r<NBASE * NBASE ; r++){
			const size_t offset = r * nhistoryqqq;
			const __m128i itmp_fill = _mm_set1_epi32(r);
			for(int i=0 ; i<nhistoryqqq ; i++){
				__m128i mask = _mm_castps_si128(_mm_cmplt_ps(tmp->data.v[i], prev_score->data.v[offset + i]));
				tmp->data.v[i] = _mm_max_ps(tmp->data.v[i], prev_score->data.v[offset + i]);
				itmp->data.v[i] = _mm_or_si128(_mm_andnot_si128(mask, itmp->data.v[i]),
					                       _mm_and_si128(mask, itmp_fill));
			}
		}
		for(int i=0 ; i<nhistoryqqq ; i++){
			itmp->data.v[i] = _mm_add_epi32(
							_mm_mullo_epi32(itmp->data.v[i], nhistoryqqv),
							_mm_add_epi32(c0123_m128i, _mm_set1_epi32(i * 4)));
		}
		for(int pref=0 ; pref < nhistoryqq ; pref++){
			for(int i=0 ; i < NBASE ; i++){
				const size_t oi = pref * NBASE + i;
				// This cycling through prefixes
				const __m128 skip_score = logpost->data.v[offsetPq + oi]
	                                                + _mm_set1_ps(tmp->data.f[pref])
							- skip_penv;
				__m128i mask = _mm_castps_si128(_mm_cmplt_ps(score->data.v[oi], skip_score));
				score->data.v[oi] = _mm_max_ps(score->data.v[oi], skip_score);
				traceback->data.v[offsetTq + oi] = _mm_or_si128(_mm_andnot_si128(mask, traceback->data.v[offsetTq + oi]),
									        _mm_and_si128(mask, _mm_set1_epi32(itmp->data.f[pref])));
			}
		}

		// Slip
		if(use_slip){
			const __m128 slip_penv = _mm_set1_ps(2.0 * skip_pen);
			for(int i=0 ; i<nhistoryqqqq ; i++){
				tmp->data.v[i] = prev_score->data.v[i];
				itmp->data.v[i] = _mm_setzero_si128();
			}
			for(int r=1 ; r<NBASE * NBASE * NBASE; r++){
				const size_t offset = r * nhistoryqqqq;
				const __m128i itmp_fill = _mm_set1_epi32(r);
				for(int i=0 ; i<nhistoryqqqq ; i++){
					__m128i mask = _mm_castps_si128(_mm_cmplt_ps(tmp->data.v[i], prev_score->data.v[offset + i]));
					tmp->data.v[i] = _mm_max_ps(tmp->data.v[i], prev_score->data.v[offset + i]);
					itmp->data.v[i] = _mm_or_si128(_mm_andnot_si128(mask, itmp->data.v[i]),
								       _mm_and_si128(mask, itmp_fill));
				}
			}
			for(int i=0 ; i<nhistoryqqqq ; i++){
				itmp->data.v[i] = _mm_add_epi32(
								_mm_mullo_epi32(itmp->data.v[i],  nhistoryqqqv),
								_mm_add_epi32(c0123_m128i, _mm_set1_epi32(i * 4)));
			}
			for(int pref=0 ; pref < nhistoryqqq ; pref++){
				for(int i=0 ; i < NBASE * NBASE; i++){
					const size_t oi = pref * NBASE * NBASE + i;<commit_msg>Fixes #26. Avoid assertion for small basis and slips.<commit_after>#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "decode.h"
#include "util.h"

#define NBASE 4


float decode_transducer(const scrappie_matrix logpost, float skip_pen, int * seq, bool use_slip){
	assert(NULL != logpost);
	assert(skip_pen >= 0.0);
	assert(NULL != seq);
	const int nev = logpost->nc;
	const int nstate = logpost->nr;
	const int ldp = logpost->nrq * 4;
	const int nhistory = nstate - 1;
	assert((nhistory % 4) == 0);
	const int32_t nhistoryq = nhistory / 4;
	const __m128i nhistoryqv = _mm_set1_epi32(nhistoryq);
	assert((nhistoryq % 4) == 0);
	const int32_t nhistoryqq = nhistoryq / 4;
	const __m128i nhistoryqqv = _mm_set1_epi32(nhistoryqq);
	assert((nhistoryqq % 4) == 0);
	const int32_t nhistoryqqq = nhistoryqq / 4;
	const __m128i nhistoryqqqv = _mm_set1_epi32(nhistoryqqq);
	if(use_slip){
	   	assert((nhistoryqqq % 4) == 0);
	}


	//  Forwards memory + traceback
	scrappie_matrix score = make_scrappie_matrix(nhistory, 1);
	scrappie_matrix prev_score = make_scrappie_matrix(nhistory, 1);
	scrappie_matrix tmp = make_scrappie_matrix(nhistory, 1);
	scrappie_imatrix itmp = make_scrappie_imatrix(nhistory, nev);
	scrappie_imatrix traceback = make_scrappie_imatrix(nhistory, nev);

	//  Initialise
	for( int i=0 ; i < nhistoryq ; i++){
		score->data.v[i] = logpost->data.v[i];
	}

	//  Forwards Viterbi iteration
	for(int ev=1 ; ev < nev ; ev++){
		const size_t offsetTq = ev * nhistoryq;
		const size_t offsetP = ev * ldp;
		const size_t offsetPq = ev * logpost->nrq;
		// Swap score and previous score
		{
			scrappie_matrix tmptr = score;
			score = prev_score;
			prev_score = tmptr;
		}

		// Stay
		const __m128 stay_m128 = _mm_set1_ps(logpost->data.f[offsetP + nhistory]);
		const __m128i negone_m128i = _mm_set1_epi32(-1);
		for(int i=0 ; i < nhistoryq ; i++){
			// Traceback for stay is negative
			score->data.v[i] = prev_score->data.v[i] + stay_m128;
			traceback->data.v[offsetTq + i] = negone_m128i;
		}

		// Step
		// Following three loops find maximum over suffix and record index
		for(int i=0 ; i<nhistoryqq ; i++){
			tmp->data.v[i] = prev_score->data.v[i];
			itmp->data.v[i] = _mm_setzero_si128();
		}
		for(int r=1 ; r<NBASE ; r++){
			const size_t offset = r * nhistoryqq;
			const __m128i itmp_fill = _mm_set1_epi32(r);
			for(int i=0 ; i<nhistoryqq ; i++){
				__m128i mask = _mm_castps_si128(_mm_cmplt_ps(tmp->data.v[i], prev_score->data.v[offset + i]));
				tmp->data.v[i] = _mm_max_ps(tmp->data.v[i], prev_score->data.v[offset + i]);
				itmp->data.v[i] = _mm_or_si128(_mm_andnot_si128(mask, itmp->data.v[i]),
					                       _mm_and_si128(mask, itmp_fill));
			}
		}
		const __m128i c0123_m128i = _mm_setr_epi32(0, 1, 2, 3);
		for(int i=0 ; i<nhistoryqq ; i++){
			itmp->data.v[i] = _mm_add_epi32(
							_mm_mullo_epi32(itmp->data.v[i], nhistoryqv),
							_mm_add_epi32(c0123_m128i, _mm_set1_epi32(i * 4)));
		}

		for(int pref=0 ; pref < nhistoryq ; pref++){
			const size_t i = pref;
			const __m128 step_score = logpost->data.v[offsetPq + i] + _mm_set1_ps(tmp->data.f[pref]);
			__m128i mask = _mm_castps_si128(_mm_cmplt_ps(score->data.v[i], step_score));
			score->data.v[i] = _mm_max_ps(score->data.v[i], step_score);
			traceback->data.v[offsetTq + i] = _mm_or_si128(_mm_andnot_si128(mask, traceback->data.v[offsetTq + i]),
								       _mm_and_si128(mask, _mm_set1_epi32(itmp->data.f[pref])));
		}



		// Skip
		const __m128 skip_penv = _mm_set1_ps(skip_pen);
		for(int i=0 ; i<nhistoryqqq ; i++){
			tmp->data.v[i] = prev_score->data.v[i];
			itmp->data.v[i] = _mm_setzero_si128();
		}
		for(int r=1 ; r<NBASE * NBASE ; r++){
			const size_t offset = r * nhistoryqqq;
			const __m128i itmp_fill = _mm_set1_epi32(r);
			for(int i=0 ; i<nhistoryqqq ; i++){
				__m128i mask = _mm_castps_si128(_mm_cmplt_ps(tmp->data.v[i], prev_score->data.v[offset + i]));
				tmp->data.v[i] = _mm_max_ps(tmp->data.v[i], prev_score->data.v[offset + i]);
				itmp->data.v[i] = _mm_or_si128(_mm_andnot_si128(mask, itmp->data.v[i]),
					                       _mm_and_si128(mask, itmp_fill));
			}
		}
		for(int i=0 ; i<nhistoryqqq ; i++){
			itmp->data.v[i] = _mm_add_epi32(
							_mm_mullo_epi32(itmp->data.v[i], nhistoryqqv),
							_mm_add_epi32(c0123_m128i, _mm_set1_epi32(i * 4)));
		}
		for(int pref=0 ; pref < nhistoryqq ; pref++){
			for(int i=0 ; i < NBASE ; i++){
				const size_t oi = pref * NBASE + i;
				// This cycling through prefixes
				const __m128 skip_score = logpost->data.v[offsetPq + oi]
	                                                + _mm_set1_ps(tmp->data.f[pref])
							- skip_penv;
				__m128i mask = _mm_castps_si128(_mm_cmplt_ps(score->data.v[oi], skip_score));
				score->data.v[oi] = _mm_max_ps(score->data.v[oi], skip_score);
				traceback->data.v[offsetTq + oi] = _mm_or_si128(_mm_andnot_si128(mask, traceback->data.v[offsetTq + oi]),
									        _mm_and_si128(mask, _mm_set1_epi32(itmp->data.f[pref])));
			}
		}

		// Slip
		if(use_slip){
			const int32_t nhistoryqqqq = nhistoryqqq / 4;
			const __m128 slip_penv = _mm_set1_ps(2.0 * skip_pen);
			for(int i=0 ; i<nhistoryqqqq ; i++){
				tmp->data.v[i] = prev_score->data.v[i];
				itmp->data.v[i] = _mm_setzero_si128();
			}
			for(int r=1 ; r<NBASE * NBASE * NBASE; r++){
				const size_t offset = r * nhistoryqqqq;
				const __m128i itmp_fill = _mm_set1_epi32(r);
				for(int i=0 ; i<nhistoryqqqq ; i++){
					__m128i mask = _mm_castps_si128(_mm_cmplt_ps(tmp->data.v[i], prev_score->data.v[offset + i]));
					tmp->data.v[i] = _mm_max_ps(tmp->data.v[i], prev_score->data.v[offset + i]);
					itmp->data.v[i] = _mm_or_si128(_mm_andnot_si128(mask, itmp->data.v[i]),
								       _mm_and_si128(mask, itmp_fill));
				}
			}
			for(int i=0 ; i<nhistoryqqqq ; i++){
				itmp->data.v[i] = _mm_add_epi32(
								_mm_mullo_epi32(itmp->data.v[i],  nhistoryqqqv),
								_mm_add_epi32(c0123_m128i, _mm_set1_epi32(i * 4)));
			}
			for(int pref=0 ; pref < nhistoryqqq ; pref++){
				for(int i=0 ; i < NBASE * NBASE; i++){
					const size_t oi = pref * NBASE * NBASE + i;
{'fraction_non_alphanumeric': 0.1571639829116004, 'fraction_numerical': 0.04633585277686494, 'mean_word_length': 3.526961695797694, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 137, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1399364', 'n_tokens_mistral': 6133, 'n_tokens_neox': 5246, 'n_words': 922}