#/*
#==============================================================================
#
# simd_avx.h
#
#------------------------------------------------------------------------------
#
# Copyright (C) 2012-2017 Hinnerk Stueben
#
# This file is part of BQCD -- Berlin Quantum ChromoDynamics program
#
# BQCD is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BQCD is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BQCD.  If not, see <http://www.gnu.org/licenses/>.
#
#------------------------------------------------------------------------------
#*/

# include <immintrin.h>

# define SIMD_WIDTH_R4 8
# define SIMD_WIDTH_R8 4

# define SIMD_VECTOR_R4 __m256
# define SIMD_VECTOR_R8 __m256d

# define SIMD_ALIGNMENT_VALUE 32

# define LoadS_r4(a)    _mm256_broadcast_ss((float*) &(a))
# define LoadS_r8(a)    _mm256_broadcast_sd((double*) &(a))

#if defined (INTEL) && defined(ALIGNMENT_VALUE)

# if ALIGNMENT_VALUE != SIMD_ALIGNMENT_VALUE
# error alignment values do not match 
# endif

# define Load_r4(a)     _mm256_load_ps((float*) &(a))
# define Load_r8(a)     _mm256_load_pd((double*) &(a))

# define Store_r4(a, b) _mm256_store_ps((float*) &(a), b)
# define Store_r8(a, b) _mm256_store_pd((double*) &(a), b)

#else

# define Load_r4(a)     _mm256_loadu_ps((float*) &(a))
# define Load_r8(a)     _mm256_loadu_pd((double*) &(a))

# define Store_r4(a, b) _mm256_storeu_ps((float*) &(a), b)
# define Store_r8(a, b) _mm256_storeu_pd((double*) &(a), b)

#endif

# define Sum_r4(a, b)   _mm256_add_ps(a, b)
# define Sum_r8(a, b)   _mm256_add_pd(a, b)

# define Diff_r4(a, b)  _mm256_sub_ps(a, b)
# define Diff_r8(a, b)  _mm256_sub_pd(a, b)

# define Prod_r4(a, b)  _mm256_mul_ps(a, b)
# define Prod_r8(a, b)  _mm256_mul_pd(a, b)

# define Fmadd_r4(a, b, c) _mm256_add_ps(_mm256_mul_ps(a, b), c)
# define Fmadd_r8(a, b, c) _mm256_add_pd(_mm256_mul_pd(a, b), c)

# define Fmsub_r4(a, b, c) _mm256_sub_ps(_mm256_mul_ps(a, b), c)
# define Fmsub_r8(a, b, c) _mm256_sub_pd(_mm256_mul_pd(a, b), c)

# define LoadU_r4(a)    _mm256_loadu_ps((float*) &(a))
# define LoadU_r8(a)    _mm256_loadu_pd((double*) &(a))
