fast_muls.c
void mul_va3232_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;
//	assert(vcols <= 32);
//	assert(arows == vcols);


	for (int j = 0; j < vrows; j++)
	{
//		uint64_t v = mzd_read_bits(V, j, 0, vcols);
		uint64_t v = *(V->rows[j]); // FIXME: always correct?

		__m256i m2, rr;
		__m256i acc = _mm256_setzero_si256();
		__m256i m1  = _mm256_set_epi32(1, 2, 4, 8, 16, 32, 64, 128);
		__m256i vv  = _mm256_set1_epi32(v);

		/* main loop */
		int i;
		for (i = 0; i < (int)(vcols-8); i+=8)
		{
//			rr  = _mm256_set_epi32(mzd_read_bits(A, i, 0, acols), mzd_read_bits(A, i+1, 0, acols), mzd_read_bits(A, i+2, 0, acols), mzd_read_bits(A, i+3, 0, acols),
//					mzd_read_bits(A, i+4, 0, acols), mzd_read_bits(A, i+5, 0, acols), mzd_read_bits(A, i+6, 0, acols), mzd_read_bits(A, i+7, 0, acols));
			rr  = _mm256_set_epi32(*(A->rows[i]), *(A->rows[i+1]), *(A->rows[i+2]), *(A->rows[i+3]), *(A->rows[i+4]), *(A->rows[i+5]), *(A->rows[i+6]), *(A->rows[i+7])); // FIXME: always correct?
			m2  = _mm256_and_si256(vv, m1);
			m2  = _mm256_cmpeq_epi32(m1, m2);
			rr  = _mm256_and_si256(rr, m2);
			acc = _mm256_xor_si256(acc, rr);
			m1  = _mm256_slli_epi32(m1, 8);
		}
		/* footer */
//		uint32_t r0 = mzd_read_bits(A, i, 0, acols);
//		uint32_t r1 = i+1 >= arows ? 0 : mzd_read_bits(A, i+1, 0, acols);
//		uint32_t r2 = i+2 >= arows ? 0 : mzd_read_bits(A, i+2, 0, acols);
//		uint32_t r3 = i+3 >= arows ? 0 : mzd_read_bits(A, i+3, 0, acols);
//		uint32_t r4 = i+4 >= arows ? 0 : mzd_read_bits(A, i+4, 0, acols);
//		uint32_t r5 = i+5 >= arows ? 0 : mzd_read_bits(A, i+5, 0, acols);
//		uint32_t r6 = i+6 >= arows ? 0 : mzd_read_bits(A, i+6, 0, acols);
//		uint32_t r7 = i+7 >= arows ? 0 : mzd_read_bits(A, i+7, 0, acols);
		uint32_t r0 = *(A->rows[i]); // FIXME: always correct?
		uint32_t r1 = i+1 >= arows ? 0 : *(A->rows[i+1]); // FIXME: always correct?
		uint32_t r2 = i+2 >= arows ? 0 : *(A->rows[i+2]); // FIXME: always correct?
		uint32_t r3 = i+3 >= arows ? 0 : *(A->rows[i+3]); // FIXME: always correct?
		uint32_t r4 = i+4 >= arows ? 0 : *(A->rows[i+4]); // FIXME: always correct?
		uint32_t r5 = i+5 >= arows ? 0 : *(A->rows[i+5]); // FIXME: always correct?
		uint32_t r6 = i+6 >= arows ? 0 : *(A->rows[i+6]); // FIXME: always correct?
		uint32_t r7 = i+7 >= arows ? 0 : *(A->rows[i+7]); // FIXME: always correct?
		rr  = _mm256_set_epi32(r0, r1, r2, r3, r4, r5, r6, r7);
		m2  = _mm256_and_si256(vv, m1);
		m2  = _mm256_cmpeq_epi32(m1, m2);
		rr  = _mm256_and_si256(rr, m2);
		acc = _mm256_xor_si256(acc, rr);

		if (clear)
		{
			mzd_and_bits(res, j, 0, acols, 0);
		}
		uint32_t tmpacc1 = _mm256_extract_epi32(acc, 0) ^ _mm256_extract_epi32(acc, 1);
		uint32_t tmpacc2 = _mm256_extract_epi32(acc, 2) ^ _mm256_extract_epi32(acc, 3);
		uint32_t tmpacc3 = _mm256_extract_epi32(acc, 4) ^ _mm256_extract_epi32(acc, 5);
		uint32_t tmpacc4 = _mm256_extract_epi32(acc, 6) ^ _mm256_extract_epi32(acc, 7);
		tmpacc1 ^= tmpacc2;
		tmpacc3 ^= tmpacc4;
		tmpacc1 ^= tmpacc3;
		mzd_xor_bits(res, j, 0, acols, tmpacc1);
	}

	return;
}
/*
 * Same as above, but using AVX2
 */
Same as above, but using AVX2
Same as above but using AVX2
void mul_va3232_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;
	for (int j = 0; j < vrows; j++)
	{
		uint64_t v = *(V->rows[j]); 
		__m256i m2, rr;
		__m256i acc = _mm256_setzero_si256();
		__m256i m1  = _mm256_set_epi32(1, 2, 4, 8, 16, 32, 64, 128);
		__m256i vv  = _mm256_set1_epi32(v);
		int i;
		for (i = 0; i < (int)(vcols-8); i+=8)
		{
			rr  = _mm256_set_epi32(*(A->rows[i]), *(A->rows[i+1]), *(A->rows[i+2]), *(A->rows[i+3]), *(A->rows[i+4]), *(A->rows[i+5]), *(A->rows[i+6]), *(A->rows[i+7])); 
			m2  = _mm256_and_si256(vv, m1);
			m2  = _mm256_cmpeq_epi32(m1, m2);
			rr  = _mm256_and_si256(rr, m2);
			acc = _mm256_xor_si256(acc, rr);
			m1  = _mm256_slli_epi32(m1, 8);
		}
		uint32_t r0 = *(A->rows[i]); 
		uint32_t r1 = i+1 >= arows ? 0 : *(A->rows[i+1]); 
		uint32_t r2 = i+2 >= arows ? 0 : *(A->rows[i+2]); 
		uint32_t r3 = i+3 >= arows ? 0 : *(A->rows[i+3]); 
		uint32_t r4 = i+4 >= arows ? 0 : *(A->rows[i+4]); 
		uint32_t r5 = i+5 >= arows ? 0 : *(A->rows[i+5]); 
		uint32_t r6 = i+6 >= arows ? 0 : *(A->rows[i+6]); 
		uint32_t r7 = i+7 >= arows ? 0 : *(A->rows[i+7]); 
		rr  = _mm256_set_epi32(r0, r1, r2, r3, r4, r5, r6, r7);
		m2  = _mm256_and_si256(vv, m1);
		m2  = _mm256_cmpeq_epi32(m1, m2);
		rr  = _mm256_and_si256(rr, m2);
		acc = _mm256_xor_si256(acc, rr);
		if (clear)
		{
			mzd_and_bits(res, j, 0, acols, 0);
		}
		uint32_t tmpacc1 = _mm256_extract_epi32(acc, 0) ^ _mm256_extract_epi32(acc, 1);
		uint32_t tmpacc2 = _mm256_extract_epi32(acc, 2) ^ _mm256_extract_epi32(acc, 3);
		uint32_t tmpacc3 = _mm256_extract_epi32(acc, 4) ^ _mm256_extract_epi32(acc, 5);
		uint32_t tmpacc4 = _mm256_extract_epi32(acc, 6) ^ _mm256_extract_epi32(acc, 7);
		tmpacc1 ^= tmpacc2;
		tmpacc3 ^= tmpacc4;
		tmpacc1 ^= tmpacc3;
		mzd_xor_bits(res, j, 0, acols, tmpacc1);
	}
	return;
}
void mul_va3232_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 ; for ( int j = 0 ; j < vrows ; j ++ ) { uint64_t v = * ( V -> rows [ j ] ) ; __m256i m2 , rr ; __m256i acc = _mm256_setzero_si256 ( ) ; __m256i m1 = _mm256_set_epi32 ( 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 ) ; __m256i vv = _mm256_set1_epi32 ( v ) ; int i ; for ( i = 0 ; i < ( int ) ( vcols - 8 ) ; i += 8 ) { rr = _mm256_set_epi32 ( * ( A -> rows [ i ] ) , * ( A -> rows [ i + 1 ] ) , * ( A -> rows [ i + 2 ] ) , * ( A -> rows [ i + 3 ] ) , * ( A -> rows [ i + 4 ] ) , * ( A -> rows [ i + 5 ] ) , * ( A -> rows [ i + 6 ] ) , * ( A -> rows [ i + 7 ] ) ) ; m2 = _mm256_and_si256 ( vv , m1 ) ; m2 = _mm256_cmpeq_epi32 ( m1 , m2 ) ; rr = _mm256_and_si256 ( rr , m2 ) ; acc = _mm256_xor_si256 ( acc , rr ) ; m1 = _mm256_slli_epi32 ( m1 , 8 ) ; } uint32_t r0 = * ( A -> rows [ i ] ) ; uint32_t r1 = i + 1 >= arows ? 0 : * ( A -> rows [ i + 1 ] ) ; uint32_t r2 = i + 2 >= arows ? 0 : * ( A -> rows [ i + 2 ] ) ; uint32_t r3 = i + 3 >= arows ? 0 : * ( A -> rows [ i + 3 ] ) ; uint32_t r4 = i + 4 >= arows ? 0 : * ( A -> rows [ i + 4 ] ) ; uint32_t r5 = i + 5 >= arows ? 0 : * ( A -> rows [ i + 5 ] ) ; uint32_t r6 = i + 6 >= arows ? 0 : * ( A -> rows [ i + 6 ] ) ; uint32_t r7 = i + 7 >= arows ? 0 : * ( A -> rows [ i + 7 ] ) ; rr = _mm256_set_epi32 ( r0 , r1 , r2 , r3 , r4 , r5 , r6 , r7 ) ; m2 = _mm256_and_si256 ( vv , m1 ) ; m2 = _mm256_cmpeq_epi32 ( m1 , m2 ) ; rr = _mm256_and_si256 ( rr , m2 ) ; acc = _mm256_xor_si256 ( acc , rr ) ; if ( clear ) { mzd_and_bits ( res , j , 0 , acols , 0 ) ; } uint32_t tmpacc1 = _mm256_extract_epi32 ( acc , 0 ) ^ _mm256_extract_epi32 ( acc , 1 ) ; uint32_t tmpacc2 = _mm256_extract_epi32 ( acc , 2 ) ^ _mm256_extract_epi32 ( acc , 3 ) ; uint32_t tmpacc3 = _mm256_extract_epi32 ( acc , 4 ) ^ _mm256_extract_epi32 ( acc , 5 ) ; uint32_t tmpacc4 = _mm256_extract_epi32 ( acc , 6 ) ^ _mm256_extract_epi32 ( acc , 7 ) ; tmpacc1 ^= tmpacc2 ; tmpacc3 ^= tmpacc4 ; tmpacc1 ^= tmpacc3 ; mzd_xor_bits ( res , j , 0 , acols , tmpacc1 ) ; } return ; }
Same as above, but using AVX2
Same as above but using AVX2
//	assert(vcols <= 32); //	assert(arows == vcols); //		uint64_t v = mzd_read_bits(V, j, 0, vcols); // FIXME: always correct? /* main loop */ //			rr  = _mm256_set_epi32(mzd_read_bits(A, i, 0, acols), mzd_read_bits(A, i+1, 0, acols), mzd_read_bits(A, i+2, 0, acols), mzd_read_bits(A, i+3, 0, acols), //					mzd_read_bits(A, i+4, 0, acols), mzd_read_bits(A, i+5, 0, acols), mzd_read_bits(A, i+6, 0, acols), mzd_read_bits(A, i+7, 0, acols)); // FIXME: always correct? /* footer */ //		uint32_t r0 = mzd_read_bits(A, i, 0, acols); //		uint32_t r1 = i+1 >= arows ? 0 : mzd_read_bits(A, i+1, 0, acols); //		uint32_t r2 = i+2 >= arows ? 0 : mzd_read_bits(A, i+2, 0, acols); //		uint32_t r3 = i+3 >= arows ? 0 : mzd_read_bits(A, i+3, 0, acols); //		uint32_t r4 = i+4 >= arows ? 0 : mzd_read_bits(A, i+4, 0, acols); //		uint32_t r5 = i+5 >= arows ? 0 : mzd_read_bits(A, i+5, 0, acols); //		uint32_t r6 = i+6 >= arows ? 0 : mzd_read_bits(A, i+6, 0, acols); //		uint32_t r7 = i+7 >= arows ? 0 : mzd_read_bits(A, i+7, 0, acols); // FIXME: always correct? // FIXME: always correct? // FIXME: always correct? // FIXME: always correct? // FIXME: always correct? // FIXME: always correct? // FIXME: always correct? // FIXME: always correct?