/**
 * \file main_sse2_signatures.c
 * \brief TODO
 *
 * \date Aug 30, 2009
 * \author alexander
 */

#include <stdint.h>
#include <stdio.h>
#include <xmmintrin.h>


#define PROCESS_DATA(X)                                         \
	data = _mm_set1_epi16 ((uint16_t)datamem[X - 1]);    		\
	pat = _mm_load_si128((__m128i *)pattern##X##1);				\
	pat = _mm_mullo_epi16(data, pat);							\
	acc1 = _mm_add_epi16(acc1, pat);							\
																\
	pat = _mm_load_si128((__m128i *)pattern12);					\
	pat = _mm_mullo_epi16(data, pat);							\
	acc2 = _mm_add_epi16(acc2, pat);


int main (void)
{
	uint32_t datamem[16] = {156, 242, 234, 123,
			             565, 234, 45, 78,
			             62, 23, 984 , 234,
			             23, 1, 65, 3 };

	int16_t pattern0_1[8] __attribute__((aligned(16))) = {1, 1, 0, 1, 1, 1, 0, 1};
	int16_t pattern0_2[8] __attribute__((aligned(16))) = {1, 1, 0, 0, 0, 0, 0};
	int16_t pattern1_1[8] __attribute__((aligned(16))) = {1, -1, 0, 1, 1, -1, 0, 1};
	int16_t pattern1_2[8] __attribute__((aligned(16))) = {1, -1, 0, 0, 0, 0, 0};
	int16_t pattern2_1[8] __attribute__((aligned(16))) = {-1, 0, 1, 1, -1, 0, 1, 1};
	int16_t pattern2_2[8] __attribute__((aligned(16))) = {-1, 0, 1, 0, 0, 0, 0};
	int16_t pattern3_1[8] __attribute__((aligned(16))) = {-1, 0, -1, 1, -1, 0, -1, 1};
	int16_t pattern3_2[8] __attribute__((aligned(16))) = {-1, 0, -1, 0, 0, 0, 0};
	int16_t pattern4_1[8] __attribute__((aligned(16))) = {1, 1, 0, 1, 1, 1, 0, -1};
	int16_t pattern4_2[8] __attribute__((aligned(16))) = {-1, -1, 0, 0, 0, 0, 0};
	int16_t pattern5_1[8] __attribute__((aligned(16))) = {1, -1, 0, 1, 1, -1, 0, -1};
	int16_t pattern5_2[8] __attribute__((aligned(16))) = {-1, 1, 0, 0, 0, 0, 0};
	int16_t pattern6_1[8] __attribute__((aligned(16))) = {-1, 0, 1, 1, -1, 0, 1, -1};
	int16_t pattern6_2[8] __attribute__((aligned(16))) = {1, 0, -1, 0, 0, 0, 0};
	int16_t pattern7_1[8] __attribute__((aligned(16))) = {-1, 0, -1, 1, -1, 0, -1, -1};
	int16_t pattern7_2[8] __attribute__((aligned(16))) = {1, 0, 1, 0, 0, 0, 0};
	int16_t pattern8_1[8] __attribute__((aligned(16))) = {1, 1, 0, -1, -1, -1, 0, 0};
	int16_t pattern8_2[8] __attribute__((aligned(16))) = {0, 0, 0, 1, 1, 1, 0};
	int16_t pattern9_1[8] __attribute__((aligned(16))) = {1, -1, 0, -1, -1, 1, 0, 0};
	int16_t pattern9_2[8] __attribute__((aligned(16))) = {0, 0, 0, 1, 1, -1, 0};
	int16_t pattern10_1[8] __attribute__((aligned(16))) = {-1, 0, 1, -1, 1, 0, -1, 0};
	int16_t pattern10_2[8] __attribute__((aligned(16))) = {0, 0, 0, 1, -1, 0, 1};
	int16_t pattern11_1[8] __attribute__((aligned(16))) = {-1, 0, -1, -1, 1, 0, 1, 0};
	int16_t pattern11_2[8] __attribute__((aligned(16))) = {0, 0, 0, 1, -1, 0, -1};
	int16_t pattern12_1[8] __attribute__((aligned(16))) = {1, 1, 0, -1, -1, -1, 0, 0};
	int16_t pattern12_2[8] __attribute__((aligned(16))) = {0, 0, 0, -1, -1, -1, 0};
	int16_t pattern13_1[8] __attribute__((aligned(16))) = {1, -1, 0, -1, -1, 1, 0, 0};
	int16_t pattern13_2[8] __attribute__((aligned(16))) = {0, 0, 0, -1, -1, 1, 0};
	int16_t pattern14_1[8] __attribute__((aligned(16))) = {-1, 0, 1, -1, 1, 0, -1, 0};
	int16_t pattern14_2[8] __attribute__((aligned(16))) = {0, 0, 0, -1, 1, 0, -1};
	int16_t pattern15_1[8] __attribute__((aligned(16))) = {-1, 0, -1, -1, 1, 0, 1, 0};
	int16_t pattern15_2[8] __attribute__((aligned(16))) = {0, 0, 0, -1, 1, 0, 1};
	int16_t acc1mem[8] __attribute__((aligned(16)));
	int16_t acc2mem[8] __attribute__((aligned(16)));
	__m128i data;
	__m128i pat;
	__m128i acc1 = _mm_set1_epi16 (0);
	__m128i acc2 = _mm_set1_epi16 (0);

	data = _mm_set1_epi16 ((uint16_t)datamem[0]);
	pat = _mm_load_si128((__m128i *)pattern0_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern0_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[1]);
	pat = _mm_load_si128((__m128i *)pattern1_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern1_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[2]);
	pat = _mm_load_si128((__m128i *)pattern2_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern2_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[3]);
	pat = _mm_load_si128((__m128i *)pattern3_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern3_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[4]);
	pat = _mm_load_si128((__m128i *)pattern4_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern4_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[5]);
	pat = _mm_load_si128((__m128i *)pattern5_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern5_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[6]);
	pat = _mm_load_si128((__m128i *)pattern6_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern6_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[7]);
	pat = _mm_load_si128((__m128i *)pattern7_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern7_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[8]);
	pat = _mm_load_si128((__m128i *)pattern8_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern8_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[9]);
	pat = _mm_load_si128((__m128i *)pattern9_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern9_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[10]);
	pat = _mm_load_si128((__m128i *)pattern10_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern10_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[11]);
	pat = _mm_load_si128((__m128i *)pattern11_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern11_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[12]);
	pat = _mm_load_si128((__m128i *)pattern12_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern12_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[13]);
	pat = _mm_load_si128((__m128i *)pattern13_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern13_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[14]);
	pat = _mm_load_si128((__m128i *)pattern14_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern14_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	data = _mm_set1_epi16 ((uint16_t)datamem[15]);
	pat = _mm_load_si128((__m128i *)pattern15_1);
	pat = _mm_mullo_epi16(data, pat);
	acc1 = _mm_add_epi16(acc1, pat);

	pat = _mm_load_si128((__m128i *)pattern15_2);
	pat = _mm_mullo_epi16(data, pat);
	acc2 = _mm_add_epi16(acc2, pat);

	_mm_store_si128((__m128i *)acc1mem, acc1);
	_mm_store_si128((__m128i *)acc2mem, acc2);



	int i;
	for (i = 0; i < 8; i++)
	{
	  printf("%d, ", acc1mem[i]);
	}
	for (i = 0; i < 8; i++)
	{
	  printf("%d , ", acc2mem[i]);
	}
	printf("\n");

	  /*__asm__ ("movl %eax, %ebx\n\t"
	           "movl $56, %esi\n\t"
	           "movl %ecx, $label(%edx,%ebx,$4)\n\t"
	           "movb %ah, (%ebx)");*/


	  return 0;
}

