kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

complex.cpp (5362B)


      1 /**
      2  * KFR (https://www.kfrlib.com)
      3  * Copyright (C) 2016-2023 Dan Cazarin
      4  * See LICENSE.txt for details
      5  */
      6 
      7 #include <kfr/simd/complex.hpp>
      8 #include <kfr/simd/read_write.hpp>
      9 
     10 namespace kfr
     11 {
     12 inline namespace CMT_ARCH_NAME
     13 {
     14 
     15 TEST(complex_convertible)
     16 {
     17     static_assert(std::is_convertible<float, complex<float>>::value, "");
     18     static_assert(std::is_convertible<float, complex<double>>::value, "");
     19     static_assert(std::is_convertible<short, complex<double>>::value, "");
     20 
     21     static_assert(std::is_convertible<complex<float>, vec<complex<float>, 4>>::value, "");
     22     static_assert(!std::is_convertible<vec<complex<float>, 1>, vec<complex<float>, 4>>::value, "");
     23 
     24     static_assert(std::is_convertible<vec<complex<float>, 2>, vec<complex<double>, 2>>::value, "");
     25     static_assert(std::is_convertible<vec<vec<float, 4>, 2>, vec<vec<double, 4>, 2>>::value, "");
     26 
     27     CHECK(static_cast<complex<float>>(10.f) == complex<float>{ 10.f, 0.f });
     28     CHECK(static_cast<complex<double>>(10.f) == complex<double>{ 10., 0. });
     29     CHECK(static_cast<complex<double>>(static_cast<short>(10)) == complex<double>{ 10., 0. });
     30 
     31     CHECK(static_cast<vec<complex<float>, 2>>(complex<float>{ 1.f, 2.f }) ==
     32           vec<complex<float>, 2>{ c32{ 1.f, 2.f }, c32{ 1.f, 2.f } });
     33 
     34     CHECK(static_cast<vec<complex<float>, 4>>(complex<float>{ 1.f, 2.f }) ==
     35           vec<complex<float>, 4>{ c32{ 1.f, 2.f }, c32{ 1.f, 2.f }, c32{ 1.f, 2.f }, c32{ 1.f, 2.f } });
     36 
     37     CHECK(static_cast<vec<complex<double>, 2>>(vec<complex<float>, 2>{ c32{ 1.f, 2.f }, c32{ 1.f, 2.f } }) ==
     38           vec<complex<double>, 2>{ c64{ 1., 2. }, c64{ 1., 2. } });
     39 }
     40 
     41 TEST(complex_static_tests)
     42 {
     43     static_assert(is_numeric<vec<complex<float>, 4>>, "");
     44     static_assert(is_numeric_args<vec<complex<float>, 4>>, "");
     45 
     46     static_assert(sizeof(vec<c32, 4>) == sizeof(vec<f32, 8>), "");
     47     static_assert(vec<f32, 4>::size() == 4, "");
     48     static_assert(vec<c32, 4>::size() == 4, "");
     49     static_assert(vec<f32, 4>::scalar_size() == 4, "");
     50     static_assert(vec<c32, 4>::scalar_size() == 8, "");
     51     testo::assert_is_same<subtype<complex<i32>>, i32>();
     52     testo::assert_is_same<vec<c32, 4>::value_type, c32>();
     53     testo::assert_is_same<vec<c32, 4>::scalar_type, f32>();
     54     testo::assert_is_same<vec<f32, 4>::value_type, f32>();
     55     testo::assert_is_same<vec<f32, 4>::scalar_type, f32>();
     56     testo::assert_is_same<vec<c32, 1>, decltype(make_vector(c32{ 0, 0 }))>();
     57     testo::assert_is_same<vec<c32, 2>, decltype(make_vector(c32{ 0, 0 }, 4))>();
     58     testo::assert_is_same<ftype<complex<i32>>, complex<f32>>();
     59     testo::assert_is_same<ftype<complex<i64>>, complex<f64>>();
     60     testo::assert_is_same<ftype<vec<complex<i32>, 4>>, vec<complex<f32>, 4>>();
     61     testo::assert_is_same<ftype<vec<complex<i64>, 8>>, vec<complex<f64>, 8>>();
     62 
     63     testo::assert_is_same<std::common_type_t<complex<int>, double>, complex<double>>();
     64 }
     65 
     66 TEST(complex_shuffle)
     67 {
     68     const vec<c32, 2> a{ c32{ 0, 1 }, c32{ 2, 3 } };
     69     CHECK(reverse(a) == make_vector(c32{ 2, 3 }, c32{ 0, 1 }));
     70 }
     71 
     72 TEST(complex_read_write)
     73 {
     74     c32 buffer[8] = { c32{ 1, 2 },  c32{ 3, 4 },   c32{ 5, 6 },   c32{ 7, 8 },
     75                       c32{ 9, 10 }, c32{ 11, 12 }, c32{ 13, 14 }, c32{ 15, 16 } };
     76 
     77     CHECK(read<4>(buffer) == make_vector(c32{ 1, 2 }, c32{ 3, 4 }, c32{ 5, 6 }, c32{ 7, 8 }));
     78     CHECK(read<3>(buffer + 1) == make_vector(c32{ 3, 4 }, c32{ 5, 6 }, c32{ 7, 8 }));
     79     write(buffer + 2, make_vector(c32{ 10, 11 }, c32{ 12, 13 }));
     80     CHECK(read<4>(buffer) == make_vector(c32{ 1, 2 }, c32{ 3, 4 }, c32{ 10, 11 }, c32{ 12, 13 }));
     81 }
     82 
     83 TEST(complex_cast)
     84 {
     85     const vec<f32, 4> v1 = bitcast<f32>(make_vector(c32{ 0, 1 }, c32{ 2, 3 }));
     86     CHECK(v1.flatten()[0] == 0.f);
     87     CHECK(v1.flatten()[1] == 1.f);
     88     CHECK(v1.flatten()[2] == 2.f);
     89     CHECK(v1.flatten()[3] == 3.f);
     90 
     91     const vec<c32, 1> v2 = bitcast<c32>(make_vector(1.f, 2.f));
     92     CHECK(v2.flatten()[0] == 1.f);
     93     CHECK(v2.flatten()[1] == 2.f);
     94 
     95     const vec<c32, 2> v3 = make_vector(1.f, 2.f);
     96     CHECK(v3.flatten()[0] == 1.f);
     97     CHECK(v3.flatten()[1] == 0.f);
     98     CHECK(v3.flatten()[2] == 2.f);
     99     CHECK(v3.flatten()[3] == 0.f);
    100 
    101     const vec<c32, 2> v4 = make_vector(1, 2);
    102     CHECK(v4.flatten()[0] == 1.f);
    103     CHECK(v4.flatten()[1] == 0.f);
    104     CHECK(v4.flatten()[2] == 2.f);
    105     CHECK(v4.flatten()[3] == 0.f);
    106 
    107     CHECK(zerovector<c32, 4>() == make_vector(c32{ 0, 0 }, c32{ 0, 0 }, c32{ 0, 0 }, c32{ 0, 0 }));
    108     CHECK(enumerate<c32, 4>() == make_vector(c32{ 0, 0 }, c32{ 1, 0 }, c32{ 2, 0 }, c32{ 3, 0 }));
    109 }
    110 
    111 TEST(complex_vector)
    112 {
    113     const vec<c32, 1> c32x1{ c32{ 0, 1 } };
    114     CHECK(c32x1.flatten()[0] == 0.0f);
    115     CHECK(c32x1.flatten()[1] == 1.0f);
    116 
    117     const vec<c32, 2> c32x2{ c32{ 0, 1 }, c32{ 2, 3 } };
    118     CHECK(c32x2.flatten()[0] == 0.0f);
    119     CHECK(c32x2.flatten()[1] == 1.0f);
    120     CHECK(c32x2.flatten()[2] == 2.0f);
    121     CHECK(c32x2.flatten()[3] == 3.0f);
    122 
    123     const vec<c32, 3> c32x3{ c32{ 0, 1 }, c32{ 2, 3 }, c32{ 4, 5 } };
    124     CHECK(c32x3.flatten()[0] == 0.0f);
    125     CHECK(c32x3.flatten()[1] == 1.0f);
    126     CHECK(c32x3.flatten()[2] == 2.0f);
    127     CHECK(c32x3.flatten()[3] == 3.0f);
    128     CHECK(c32x3.flatten()[4] == 4.0f);
    129     CHECK(c32x3.flatten()[5] == 5.0f);
    130 
    131     const vec<c32, 1> c32s = 2;
    132     CHECK(c32s.flatten()[0] == 2.f);
    133     CHECK(c32s.flatten()[1] == 0.f);
    134 }
    135 
    136 } // namespace CMT_ARCH_NAME
    137 } // namespace kfr