fast_muls.c
void mul_va256256_avx(mzd_t *res, mzd_t *V, mzd_t *A, int clear)
{
//	unsigned arows = A->nrows;
	unsigned acols = A->ncols;
	unsigned vcols = V->ncols;
	unsigned vrows = V->nrows;
	unsigned vcmid = 0;
	unsigned vchi  = 0;
	unsigned acmid = 0;
	unsigned achi  = 0;

	if (vcols > 192)
	{
		vchi  = vcols - 192;
		vcmid = 64;
	}
	else
	{
		vcmid = vcols - 128;
	}
	if (acols > 192)
	{
		achi  = acols - 192;
		acmid = 64;
	}
	else
	{
		acmid = acols - 128;
	}

	__m256i v;

//	assert(vcols <= 256);
//	assert(arows == vcols);

	for (int j = 0; j < vrows; j++)
	{

//		v   = _mm256_set_epi64x(mzd_read_bits(V, j, 192, vchi), mzd_read_bits(V, j, 128, vcmid), mzd_read_bits(V, j, 64, 64), mzd_read_bits(V, j, 0, 64));
		v = _mm256_loadu_si256((__m256i*)V->rows[j]); // FIXME: always correct??

		__m256i m2, m3, m4, m5, rr2, rr3, rr4, rr5;
		__m256i acc = _mm256_setzero_si256();
		__m256i m1  = _mm256_set1_epi64x(1);

		for (int i = 0; i < 64; i++)
		{
//			rr2 = _mm256_set_epi64x(mzd_read_bits(A, i, 192, achi), mzd_read_bits(A, i, 128, acmid), mzd_read_bits(A, i, 64, 64), mzd_read_bits(A, i, 0, 64));
			rr2 = _mm256_loadu_si256((__m256i*)A->rows[i]); // FIXME: always correct??
			m2  = _mm256_and_si256(v, m1);
			m2  = _mm256_cmpeq_epi64(m1, m2);
//			rr3 = _mm256_set_epi64x(mzd_read_bits(A, i+64, 192, achi), mzd_read_bits(A, i+64, 128, acmid), mzd_read_bits(A, i+64, 64, 64), mzd_read_bits(A, i+64, 0, 64));
			rr3 = _mm256_loadu_si256((__m256i*)A->rows[i+64]); // FIXME: always correct??
			m3  = _mm256_permute4x64_epi64(m2, 0x55);
			rr3 = _mm256_and_si256(rr3, m3);
			acc = _mm256_xor_si256(acc, rr3);
			if (i < vcmid)
			{
//				rr4 = _mm256_set_epi64x(mzd_read_bits(A, i+128, 192, achi), mzd_read_bits(A, i+128, 128, acmid), mzd_read_bits(A, i+128, 64, 64), mzd_read_bits(A, i+128, 0, 64));
				rr4 = _mm256_loadu_si256((__m256i*)A->rows[i+128]); // FIXME: always correct??
				m4  = _mm256_permute4x64_epi64(m2, 0xAA);
				rr4 = _mm256_and_si256(rr4, m4);
				acc = _mm256_xor_si256(acc, rr4);
			}
			if (i < vchi)
			{
//				rr5 = _mm256_set_epi64x(mzd_read_bits(A, i+192, 192, achi), mzd_read_bits(A, i+192, 128, acmid), mzd_read_bits(A, i+192, 64, 64), mzd_read_bits(A, i+192, 0, 64));
				rr5 = _mm256_loadu_si256((__m256i*)A->rows[i+192]); // FIXME: always correct??
				m5  = _mm256_permute4x64_epi64(m2, 0xFF);
				rr5 = _mm256_and_si256(rr5, m5);
				acc = _mm256_xor_si256(acc, rr5);
			}
			m2  = _mm256_permute4x64_epi64(m2, 0x00);
			rr2 = _mm256_and_si256(rr2, m2);
			acc = _mm256_xor_si256(acc, rr2);
			m1  = _mm256_slli_epi64(m1, 1);
		}
		if (clear)
		{
			mzd_and_bits(res, j, 0, 64, 0);
			mzd_and_bits(res, j, 64, 64, 0);
			mzd_and_bits(res, j, 128, acmid, 0);
			if (achi)
				mzd_and_bits(res, j, 192, achi, 0);
		}
		mzd_xor_bits(res, j, 0, 64, _mm256_extract_epi64(acc, 0));
		mzd_xor_bits(res, j, 64, 64, _mm256_extract_epi64(acc, 1));
		mzd_xor_bits(res, j, 128, acmid, _mm256_extract_epi64(acc, 2));
		if (achi)
			mzd_xor_bits(res, j, 192, achi, _mm256_extract_epi64(acc, 3));
	}

	return;
}
/* Assumes that V->ncols and A->ncols > 128, otherwise a better implementation is selected */
/* FIXME Warning: also makes strong (stronger than above) assumptions about the matrix
 * format, namely that even if only 3 words are necessary (<= 192), a last one of padding
 * will always be here and we can load two 128-bit words */
Assumes that V->ncols and A->ncols > 128, otherwise a better implementation is selected
FIXME Warning: also makes strong (stronger than above) assumptions about the matrix
format, namely that even if only 3 words are necessary (<= 192), a last one of padding
will always be here and we can load two 128-bit words
Assumes that V - > ncols and A - > ncols > 128 otherwise a better implementation is selected FIXME Warning : also makes strong ( stronger than above ) assumptions about the matrix format namely that even if only 3 words are necessary ( < = 192 ) a last one of padding will always be here and we can load two 128 - bit words
void mul_va256256_avx(mzd_t *res, mzd_t *V, mzd_t *A, int clear)
{
	unsigned acols = A->ncols;
	unsigned vcols = V->ncols;
	unsigned vrows = V->nrows;
	unsigned vcmid = 0;
	unsigned vchi  = 0;
	unsigned acmid = 0;
	unsigned achi  = 0;
	if (vcols > 192)
	{
		vchi  = vcols - 192;
		vcmid = 64;
	}
	else
	{
		vcmid = vcols - 128;
	}
	if (acols > 192)
	{
		achi  = acols - 192;
		acmid = 64;
	}
	else
	{
		acmid = acols - 128;
	}
	__m256i v;
	for (int j = 0; j < vrows; j++)
	{
		v = _mm256_loadu_si256((__m256i*)V->rows[j]); 
		__m256i m2, m3, m4, m5, rr2, rr3, rr4, rr5;
		__m256i acc = _mm256_setzero_si256();
		__m256i m1  = _mm256_set1_epi64x(1);
		for (int i = 0; i < 64; i++)
		{
			rr2 = _mm256_loadu_si256((__m256i*)A->rows[i]); 
			m2  = _mm256_and_si256(v, m1);
			m2  = _mm256_cmpeq_epi64(m1, m2);
			rr3 = _mm256_loadu_si256((__m256i*)A->rows[i+64]); 
			m3  = _mm256_permute4x64_epi64(m2, 0x55);
			rr3 = _mm256_and_si256(rr3, m3);
			acc = _mm256_xor_si256(acc, rr3);
			if (i < vcmid)
			{
				rr4 = _mm256_loadu_si256((__m256i*)A->rows[i+128]); 
				m4  = _mm256_permute4x64_epi64(m2, 0xAA);
				rr4 = _mm256_and_si256(rr4, m4);
				acc = _mm256_xor_si256(acc, rr4);
			}
			if (i < vchi)
			{
				rr5 = _mm256_loadu_si256((__m256i*)A->rows[i+192]); 
				m5  = _mm256_permute4x64_epi64(m2, 0xFF);
				rr5 = _mm256_and_si256(rr5, m5);
				acc = _mm256_xor_si256(acc, rr5);
			}
			m2  = _mm256_permute4x64_epi64(m2, 0x00);
			rr2 = _mm256_and_si256(rr2, m2);
			acc = _mm256_xor_si256(acc, rr2);
			m1  = _mm256_slli_epi64(m1, 1);
		}
		if (clear)
		{
			mzd_and_bits(res, j, 0, 64, 0);
			mzd_and_bits(res, j, 64, 64, 0);
			mzd_and_bits(res, j, 128, acmid, 0);
			if (achi)
				mzd_and_bits(res, j, 192, achi, 0);
		}
		mzd_xor_bits(res, j, 0, 64, _mm256_extract_epi64(acc, 0));
		mzd_xor_bits(res, j, 64, 64, _mm256_extract_epi64(acc, 1));
		mzd_xor_bits(res, j, 128, acmid, _mm256_extract_epi64(acc, 2));
		if (achi)
			mzd_xor_bits(res, j, 192, achi, _mm256_extract_epi64(acc, 3));
	}
	return;
}
void mul_va256256_avx ( mzd_t * res , mzd_t * V , mzd_t * A , int clear ) { unsigned acols = A -> ncols ; unsigned vcols = V -> ncols ; unsigned vrows = V -> nrows ; unsigned vcmid = 0 ; unsigned vchi = 0 ; unsigned acmid = 0 ; unsigned achi = 0 ; if ( vcols > 192 ) { vchi = vcols - 192 ; vcmid = 64 ; } else { vcmid = vcols - 128 ; } if ( acols > 192 ) { achi = acols - 192 ; acmid = 64 ; } else { acmid = acols - 128 ; } __m256i v ; for ( int j = 0 ; j < vrows ; j ++ ) { v = _mm256_loadu_si256 ( ( __m256i * ) V -> rows [ j ] ) ; __m256i m2 , m3 , m4 , m5 , rr2 , rr3 , rr4 , rr5 ; __m256i acc = _mm256_setzero_si256 ( ) ; __m256i m1 = _mm256_set1_epi64x ( 1 ) ; for ( int i = 0 ; i < 64 ; i ++ ) { rr2 = _mm256_loadu_si256 ( ( __m256i * ) A -> rows [ i ] ) ; m2 = _mm256_and_si256 ( v , m1 ) ; m2 = _mm256_cmpeq_epi64 ( m1 , m2 ) ; rr3 = _mm256_loadu_si256 ( ( __m256i * ) A -> rows [ i + 64 ] ) ; m3 = _mm256_permute4x64_epi64 ( m2 , 0x55 ) ; rr3 = _mm256_and_si256 ( rr3 , m3 ) ; acc = _mm256_xor_si256 ( acc , rr3 ) ; if ( i < vcmid ) { rr4 = _mm256_loadu_si256 ( ( __m256i * ) A -> rows [ i + 128 ] ) ; m4 = _mm256_permute4x64_epi64 ( m2 , 0xAA ) ; rr4 = _mm256_and_si256 ( rr4 , m4 ) ; acc = _mm256_xor_si256 ( acc , rr4 ) ; } if ( i < vchi ) { rr5 = _mm256_loadu_si256 ( ( __m256i * ) A -> rows [ i + 192 ] ) ; m5 = _mm256_permute4x64_epi64 ( m2 , 0xFF ) ; rr5 = _mm256_and_si256 ( rr5 , m5 ) ; acc = _mm256_xor_si256 ( acc , rr5 ) ; } m2 = _mm256_permute4x64_epi64 ( m2 , 0x00 ) ; rr2 = _mm256_and_si256 ( rr2 , m2 ) ; acc = _mm256_xor_si256 ( acc , rr2 ) ; m1 = _mm256_slli_epi64 ( m1 , 1 ) ; } if ( clear ) { mzd_and_bits ( res , j , 0 , 64 , 0 ) ; mzd_and_bits ( res , j , 64 , 64 , 0 ) ; mzd_and_bits ( res , j , 128 , acmid , 0 ) ; if ( achi ) mzd_and_bits ( res , j , 192 , achi , 0 ) ; } mzd_xor_bits ( res , j , 0 , 64 , _mm256_extract_epi64 ( acc , 0 ) ) ; mzd_xor_bits ( res , j , 64 , 64 , _mm256_extract_epi64 ( acc , 1 ) ) ; mzd_xor_bits ( res , j , 128 , acmid , _mm256_extract_epi64 ( acc , 2 ) ) ; if ( achi ) mzd_xor_bits ( res , j , 192 , achi , _mm256_extract_epi64 ( acc , 3 ) ) ; } return ; }
Assumes that V->ncols and A->ncols > 128, otherwise a better implementation is selected
FIXME Warning: also makes strong (stronger than above) assumptions about the matrix
 format, namely that even if only 3 words are necessary (<= 192), a last one of padding
 will always be here and we can load two 128-bit words
Assumes that V - > ncols and A - > ncols > 128 otherwise a better implementation is selected FIXME Warning : also makes strong ( stronger than above ) assumptions about the matrix format namely that even if only 3 words are necessary ( < = 192 ) a last one of padding will always be here and we can load two 128 - bit words
//	unsigned arows = A->nrows; //	assert(vcols <= 256); //	assert(arows == vcols); //		v   = _mm256_set_epi64x(mzd_read_bits(V, j, 192, vchi), mzd_read_bits(V, j, 128, vcmid), mzd_read_bits(V, j, 64, 64), mzd_read_bits(V, j, 0, 64)); // FIXME: always correct?? //			rr2 = _mm256_set_epi64x(mzd_read_bits(A, i, 192, achi), mzd_read_bits(A, i, 128, acmid), mzd_read_bits(A, i, 64, 64), mzd_read_bits(A, i, 0, 64)); // FIXME: always correct?? //			rr3 = _mm256_set_epi64x(mzd_read_bits(A, i+64, 192, achi), mzd_read_bits(A, i+64, 128, acmid), mzd_read_bits(A, i+64, 64, 64), mzd_read_bits(A, i+64, 0, 64)); // FIXME: always correct?? //				rr4 = _mm256_set_epi64x(mzd_read_bits(A, i+128, 192, achi), mzd_read_bits(A, i+128, 128, acmid), mzd_read_bits(A, i+128, 64, 64), mzd_read_bits(A, i+128, 0, 64)); // FIXME: always correct?? //				rr5 = _mm256_set_epi64x(mzd_read_bits(A, i+192, 192, achi), mzd_read_bits(A, i+192, 128, acmid), mzd_read_bits(A, i+192, 64, 64), mzd_read_bits(A, i+192, 0, 64)); // FIXME: always correct??