packages feed

sdr 0.1.0.0 → 0.1.0.1

raw patch · 3 files changed

+279/−2 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

+ c_sources/common.h view
@@ -0,0 +1,276 @@+/*+ * Common functions used by filters, decimators and resamplers. + * Includes real and complex dot products and SIMD horizontal additions.+ * TODO: better performance might be possible by avoiding unaligned memory accesses.+ */++#include <x86intrin.h>++/*+ * Real horizontal addition+ */+static inline __m128 sse_hadd_R(__m128 in){+    __m128 accum;+    accum = _mm_hadd_ps(in, in);+    return _mm_hadd_ps(accum, accum);+}++static inline __m128 avx_hadd_R(__m256 in){+    __m128 res1 = _mm256_extractf128_ps(in, 0);+    __m128 res2 = _mm256_extractf128_ps(in, 1);++    res1 = _mm_hadd_ps(res1, res1);+    res1 = _mm_hadd_ps(res1, res1);++    res2 = _mm_hadd_ps(res2, res2);+    res2 = _mm_hadd_ps(res2, res2);++    return _mm_add_ss(res1, res2);+}++/*+ * Real dot products+ */+static inline float dotprod_R(int num, float *a, float *b){+    int i;+    float accum = 0;+    for(i=0; i<num; i++){+        accum += a[i] * b[i];+    }+    return accum;+}++static inline __m128 sse_dotprod_R(int num, float *a, float *b){+    int i;+    __m128 accum = _mm_setzero_ps();++    for(i=0; i<num; i+=4){+        //Load the needed vectors+        __m128 coeff = _mm_loadu_ps(a + i);+        __m128 val   = _mm_loadu_ps(b + i);++        //Multiply and acumulate+        accum = _mm_add_ps(accum, _mm_mul_ps(coeff, val));+    }+    return accum;+}++static inline __m256 avx_dotprod_R(int num, float *a, float *b){+    int i;+    __m256 accum = _mm256_setzero_ps();++    for(i=0; i<num; i+=8){++        //Load the needed vectors+        __m256 coeff = _mm256_loadu_ps(a + i);+        __m256 val   = _mm256_loadu_ps(b + i);++        //Multiply and acumulate+        accum = _mm256_add_ps(accum, _mm256_mul_ps(coeff, val));+    }+    return accum;+}++/*+ * Complex horizontal addition+ */+static inline __m128 sse_hadd_C(__m128 in) {+    __m128 accum = _mm_shuffle_ps(in, in, 0b11011000);+    return _mm_hadd_ps(accum, accum);+}++static inline __m128 avx_hadd_C(__m256 in) {+    __m256 accum    = _mm256_permute_ps(in, _MM_SHUFFLE(3, 1, 2, 0));+    __m128 accum_hi = _mm256_extractf128_ps(accum, 1);+    __m128 accum_lo = _mm256_extractf128_ps(accum, 0);+    __m128 added    = _mm_hadd_ps(accum_lo, accum_hi);+    added           = _mm_permute_ps(added, _MM_SHUFFLE(3, 1, 2, 0));+    added           = _mm_hadd_ps(added, added);+    return added;+}++/*+ * Complex dot products+ */+static inline float dotprod_C(int num, float *a, float *b, float *result){+    int i;+    float real = 0;+    float imag = 0;+    for(i=0; i<num; i++){+        real += b[2*i] * a[i];+        imag += b[2*i+1] * a[i];+    }+    result[0] = real;+    result[1] = imag;+}++static inline __m128 sse_dotprod_C(int num, float *coeffs, float *startPtr){+    int i;+    __m128 accum1 = _mm_setzero_ps();+    __m128 accum2 = _mm_setzero_ps();++    for(i=0; i<num; i+=4){++        //Load the needed vectors+        __m128 coeff  = _mm_loadu_ps(coeffs + i);+        __m128 coeff1 = _mm_shuffle_ps(coeff, coeff, 0x50);+        __m128 coeff2 = _mm_shuffle_ps(coeff, coeff, 0xfa);+        __m128 val1   = _mm_loadu_ps(startPtr + 2 * i);+        __m128 val2   = _mm_loadu_ps(startPtr + 2 * i + 4);++        //Multiply and acumulate+        accum1 = _mm_add_ps(accum1, _mm_mul_ps(coeff1, val1));+        accum2 = _mm_add_ps(accum2, _mm_mul_ps(coeff2, val2));+    }+    __m128 accum = _mm_add_ps(accum1, accum2);+    return accum;+}++static inline __m256 avx_dotprod_C(int num, float *a, float *b){+    int i;+    __m256 accum1 = _mm256_setzero_ps();+    __m256 accum2 = _mm256_setzero_ps();++    float *startPtr = a;+    for(i=0; i<num; i+=8){++        //Load the needed vectors+        __m256 coeff  = _mm256_loadu_ps(a + i);++        __m256 coeffa = _mm256_shuffle_ps(coeff, coeff, 0x50);+        __m256 coeffb = _mm256_shuffle_ps(coeff, coeff, 0xfa);++        __m256 coeff1 = _mm256_permute2f128_ps(coeffa, coeffb, 0x20);+        __m256 coeff2 = _mm256_permute2f128_ps(coeffa, coeffb, 0x31);++        __m256 val1   = _mm256_loadu_ps(b + 2 * i);+        __m256 val2   = _mm256_loadu_ps(b + 2 * i + 8);++        //Multiply and acumulate+        accum1 = _mm256_add_ps(accum1, _mm256_mul_ps(coeff1, val1));+        accum2 = _mm256_add_ps(accum2, _mm256_mul_ps(coeff2, val2));+    }++    return _mm256_add_ps(accum1, accum2);+}++/*+ * Real symmetric dot products+ */+static inline __m128 sse_sym_dotprod_R(int num, float *a, float *b){+    int i;+    __m128 accum = _mm_setzero_ps();++    float *startPtr = b;+    float *endPtr = b + num * 2 - 4;+    for(i=0; i<num; i+=4){++        //Load the needed vectors+        __m128 coeff = _mm_loadu_ps(a + i);+        __m128 val1  = _mm_loadu_ps(startPtr + i);+        __m128 val2  = _mm_loadu_ps(endPtr   - i);+        val2         = _mm_permute_ps(val2, _MM_SHUFFLE(0, 1, 2, 3));++        //Multiply and acumulate+        accum = _mm_add_ps(accum, _mm_mul_ps(coeff, _mm_add_ps(val1, val2)));+    }++    return accum;+}++static inline __m256 avx_sym_dotprod_R(int num, float *a, float *b){+    int i;+    __m256 accum = _mm256_setzero_ps();++    float *startPtr = b;+    float *endPtr   = b + num * 2 - 8;+    for(i=0; i<num; i+=8){++        //Load the needed vectors+        __m256 coeff = _mm256_loadu_ps(a + i);+        __m256 val1  = _mm256_loadu_ps(startPtr + i);+        __m256 val2  = _mm256_loadu_ps(endPtr   - i);+        val2         = _mm256_permute2f128_ps(val2, val2, 0x01);+        val2         = _mm256_permute_ps(val2, _MM_SHUFFLE(0, 1, 2, 3));++        //Multiply and acumulate+        accum = _mm256_add_ps(accum, _mm256_mul_ps(coeff, _mm256_add_ps(val1, val2)));+    }++    return accum;+}++/*+ * Complex symmetric dot products+ */+static inline __m128 sse_sym_dotprod_C(int num, float *a, float *b){+    int i;+    __m128 accum1 = _mm_setzero_ps();+    __m128 accum2 = _mm_setzero_ps();++    float *startPtr = b;+    float *endPtr   = b + num * 4 - 4;+    for(i=0; i<num; i+=4){++        //Load the needed vectors+        __m128 coeff  = _mm_loadu_ps(a + i);+        __m128 coeff1 = _mm_shuffle_ps(coeff, coeff, 0x50);+        __m128 coeff2 = _mm_shuffle_ps(coeff, coeff, 0xfa);++        __m128 val1   = _mm_loadu_ps(startPtr + 2*i);+        __m128 val2   = _mm_loadu_ps(startPtr + 2*i + 4);+        __m128 val3   = _mm_loadu_ps(endPtr   - 2*i - 4);+        val3          = _mm_shuffle_ps(val3, val3, _MM_SHUFFLE(1, 0, 3, 2));+        __m128 val4   = _mm_loadu_ps(endPtr   - 2*i);+        val4          = _mm_shuffle_ps(val4, val4, _MM_SHUFFLE(1, 0, 3, 2));++        //Multiply and acumulate+        accum1 = _mm_add_ps(accum1, _mm_mul_ps(coeff1, _mm_add_ps(val1, val4)));+        accum2 = _mm_add_ps(accum2, _mm_mul_ps(coeff2, _mm_add_ps(val2, val3)));+    }++    return _mm_add_ps(accum1, accum2);+}++static inline __m256 avx_sym_dotprod_C(int num, float *a, float *b){+    int i;+    __m256 accum1 = _mm256_setzero_ps();+    __m256 accum2 = _mm256_setzero_ps();++    float *startPtr = b;+    float *endPtr   = b + num * 4 - 8;+    for(i=0; i<num; i+=8){+        //+        //Load the needed vectors+        __m256 coeff  = _mm256_loadu_ps(a + i);+        __m256 coeffa = _mm256_shuffle_ps(coeff, coeff, 0x50);+        __m256 coeffb = _mm256_shuffle_ps(coeff, coeff, 0xfa);+        __m256 coeff1 = _mm256_permute2f128_ps(coeffa, coeffb, 0x20);+        __m256 coeff2 = _mm256_permute2f128_ps(coeffa, coeffb, 0x31);++        __m256 val1  = _mm256_loadu_ps(startPtr + 2*i);+        __m256 val2  = _mm256_loadu_ps(startPtr + 2*i + 8);+        __m256 val3  = _mm256_loadu_ps(endPtr   - 2*i - 8);+        val3         = _mm256_permute_ps(val3, _MM_SHUFFLE(1, 0, 3, 2));+        val3         = _mm256_permute2f128_ps(val3, val3, 0x01);+        __m256 val4  = _mm256_loadu_ps(endPtr   - 2*i);+        val4         = _mm256_permute_ps(val4, _MM_SHUFFLE(1, 0, 3, 2));+        val4         = _mm256_permute2f128_ps(val4, val4, 0x01);++        //Multiply and acumulate+        accum1 = _mm256_add_ps(accum1, _mm256_mul_ps(coeff1, _mm256_add_ps(val1, val4)));+        accum2 = _mm256_add_ps(accum2, _mm256_mul_ps(coeff2, _mm256_add_ps(val2, val3)));+    }++    return _mm256_add_ps(accum1, accum2);+}++/*+ * Storing complex numbers+ */+static inline void store_complex(float *loc, __m128 val){+    _mm_store_ss(loc, val);+    val = _mm_shuffle_ps(val, val, 0b00000001);+    _mm_store_ss(loc + 1, val);+}+
hs_sources/SDR/PipeUtils.hs view
@@ -20,7 +20,7 @@         lift $ yield res         lift $ lift $ yield res --- | Combime two consumers into a single consumer+-- | Combine two consumers into a single consumer combine :: Monad m => Consumer a m r -> Consumer a m r -> Consumer a m r combine x y = runEffect $ runEffect (fork func >-> hoist (lift . lift) x) >-> hoist lift y     where
sdr.cabal view
@@ -1,5 +1,5 @@ name:                sdr-version:             0.1.0.0+version:             0.1.0.1 synopsis:            A software defined radio library description:              Write software defined radio applications in Haskell.@@ -95,6 +95,7 @@     default-language:    Haskell2010     ghc-options:         -O2     includes:            c_sources/common.h+    install-includes:    c_sources/common.h     c-sources:                    c_sources/filter.c,          c_sources/decimate.c,