commit 663dc63501c39c60f5080963fd6dad594ab11030
parent 59b08652e4e0d554d1e067a8cc93280ac23a3d4d
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Wed, 4 Dec 2019 19:29:02 +0000
Upgrade Windows CI to Clang 9, C API tests
Diffstat:
6 files changed, 262 insertions(+), 29 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -165,19 +165,6 @@ if (X86)
target_set_arch(detect_cpu PRIVATE generic)
endif ()
-if (ENABLE_TESTS)
-
- if (MSVC)
- else()
- # disable exceptions and rtti
- add_compile_options(-fno-exceptions -fno-rtti -fno-asynchronous-unwind-tables)
- endif ()
-
- add_subdirectory(examples)
- add_subdirectory(tests)
- add_subdirectory(tools)
-endif ()
-
if (ENABLE_DFT)
add_library(kfr_dft ${KFR_DFT_SRC})
target_link_libraries(kfr_dft kfr use_arch)
@@ -198,6 +185,12 @@ if (ENABLE_DFT)
endif ()
endif()
+if (ENABLE_TESTS)
+ add_subdirectory(examples)
+ add_subdirectory(tests)
+ add_subdirectory(tools)
+endif ()
+
add_library(kfr_io ${KFR_IO_SRC})
target_link_libraries(kfr_io kfr)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
@@ -25,7 +25,7 @@ jobs:
mkdir "$(Agent.TempDirectory)/sde-bin"
tar -C "$(Agent.TempDirectory)/sde-bin" -xjf "$(Agent.TempDirectory)/sde.tar.bz2" --strip 1
sudo ln -s $(Agent.TempDirectory)/sde-bin/sde64 /usr/bin/sde
- ci/run.sh build-release -DARCH_TESTS=sse2,sse3,sse41,avx,avx2,avx512 -DCPU_ARCH=detect -DUSE_SDE=ON -DCMAKE_CXX_COMPILER=clang++-8 -DCMAKE_BUILD_TYPE=Release
+ ci/run.sh build-release -DENABLE_CAPI_BUILD=ON -DARCH_TESTS=sse2,sse3,sse41,avx,avx2,avx512 -DCPU_ARCH=detect -DUSE_SDE=ON -DCMAKE_CXX_COMPILER=clang++-8 -DCMAKE_BUILD_TYPE=Release
- job: Linux_x86_64_GCC7
timeoutInMinutes: 120
@@ -133,7 +133,7 @@ jobs:
set -e
/bin/bash -c "sudo xcode-select -s /Applications/Xcode_11.2.app/Contents/Developer"
brew install ninja
- ci/run.sh build-release -DARCH_TESTS=sse2,sse3,sse41,avx -DCMAKE_BUILD_TYPE=Release
+ ci/run.sh build-release -DENABLE_CAPI_BUILD=ON -DARCH_TESTS=sse2,sse3,sse41,avx -DCMAKE_BUILD_TYPE=Release
- job: iOS_ARM_Clang_Release
timeoutInMinutes: 120
@@ -185,7 +185,7 @@ jobs:
call "%ANDROID_HOME%\tools\bin\sdkmanager.bat" "ndk-bundle" < %TMP%\always_yes
ci\run.cmd build-release -DCMAKE_TOOLCHAIN_FILE="%ANDROID_HOME%\ndk-bundle\build\cmake\android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_ARM_NEON=TRUE -DSKIP_TESTS=ON -DCMAKE_BUILD_TYPE=Release
-- job: Windows_MinGW_x86_Clang701_Release
+- job: Windows_MinGW_x86_Clang9_Release
timeoutInMinutes: 120
pool:
vmImage: 'vs2017-win2016'
@@ -194,13 +194,13 @@ jobs:
choco uninstall mingw
choco install msys2
choco install ninja
- choco install llvm --version 7.0.1
+ choco install llvm
set PATH=C:\ProgramData\Chocolatey\bin;C:\Program Files\CMake\bin;C:\tools\msys64\usr\local\bin;C:\tools\msys64\usr\bin;C:\tools\msys64\mingw32\bin;C:\windows;C:\windows\system32;C:\Windows;C:\Windows\System32\WindowsPowerShell\v1.0
call C:\tools\msys64\msys2_shell.cmd -defterm -mingw32 -no-start -full-path -here -c "pacman -S --noconfirm mingw32/mingw-w64-i686-gcc"
call C:\tools\msys64\msys2_shell.cmd -defterm -mingw32 -no-start -full-path -here -c "pacman -S --noconfirm mingw32/mingw-w64-i686-ninja"
call C:\tools\msys64\msys2_shell.cmd -defterm -mingw32 -no-start -full-path -here -c "ci/run.sh build-release -DCMAKE_CXX_COMPILER='C:/Program Files/LLVM/bin/clang++.exe' -DCPU_ARCH=detect -DCMAKE_CXX_FLAGS=--target=i686-w64-windows-gnu -DCMAKE_BUILD_TYPE=Release"
-- job: Windows_MinGW_x86_64_Clang701_Release
+- job: Windows_MinGW_x86_64_Clang9_Release
timeoutInMinutes: 120
pool:
vmImage: 'vs2017-win2016'
@@ -209,20 +209,20 @@ jobs:
choco uninstall mingw
choco install msys2
choco install ninja
- choco install llvm --version 7.0.1
+ choco install llvm
set PATH=C:\ProgramData\Chocolatey\bin;C:\Program Files\CMake\bin;C:\tools\msys64\usr\local\bin;C:\tools\msys64\usr\bin;C:\tools\msys64\mingw64\bin;C:\windows;C:\windows\system32;C:\Windows;C:\Windows\System32\WindowsPowerShell\v1.0
call C:\tools\msys64\msys2_shell.cmd -defterm -mingw64 -no-start -full-path -here -c "pacman -S --noconfirm mingw64/mingw-w64-x86_64-gcc"
call C:\tools\msys64\msys2_shell.cmd -defterm -mingw64 -no-start -full-path -here -c "pacman -S --noconfirm mingw64/mingw-w64-x86_64-ninja"
call C:\tools\msys64\msys2_shell.cmd -defterm -mingw64 -no-start -full-path -here -c "ci/run.sh build-release -DCMAKE_CXX_COMPILER='C:/Program Files/LLVM/bin/clang++.exe' -DCPU_ARCH=detect -DCMAKE_CXX_FLAGS=--target=x86_64-w64-windows-gnu -DCMAKE_BUILD_TYPE=Release"
-- job: Windows_MSVC_x86_64_AVX512_Clang701_Release
+- job: Windows_MSVC_x86_64_AVX512_Clang9_Release
timeoutInMinutes: 120
pool:
vmImage: 'vs2017-win2016'
steps:
- script: |
choco install ninja
- choco install llvm --version 7.0.1
+ choco install llvm
curl -o "$(Agent.TempDirectory)/sde.zip" -L $(SDEURL)
"C:\Program Files\7-Zip\7z.exe" x -oC:\sde "$(Agent.TempDirectory)/sde.zip"
@@ -232,16 +232,16 @@ jobs:
set PATH=%PATH:C:\Program Files\Git\mingw64\bin;=%
set PATH=%PATH:C:\Strawberry\c\bin;=%
set PATH=C:\sde;%PATH%
- ci\run.cmd build-release -DARCH_TESTS=ON -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" -DUSE_SDE=ON -DCPU_ARCH=avx512 -DCMAKE_CXX_FLAGS=-m64 -DCMAKE_BUILD_TYPE=Release
+ ci\run.cmd build-release -DENABLE_CAPI_BUILD=ON -DARCH_TESTS=ON -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" -DUSE_SDE=ON -DCPU_ARCH=avx512 -DCMAKE_CXX_FLAGS=-m64 -DCMAKE_BUILD_TYPE=Release
-- job: Windows_MSVC_x86_AVX512_Clang701_Release
+- job: Windows_MSVC_x86_AVX512_Clang9_Release
timeoutInMinutes: 120
pool:
vmImage: 'vs2017-win2016'
steps:
- script: |
choco install ninja
- choco install llvm --version 7.0.1
+ choco install llvm
curl -o "$(Agent.TempDirectory)/sde.zip" -L $(SDEURL)
"C:\Program Files\7-Zip\7z.exe" x -oC:\sde "$(Agent.TempDirectory)/sde.zip"
@@ -291,7 +291,7 @@ jobs:
set PATH=C:\sde;%PATH%
ci\run.cmd build-release -DARCH_TESTS=OFF -DUSE_SDE=ON -DCPU_ARCH=avx512 -DENABLE_DFT=OFF -DCMAKE_BUILD_TYPE=Release
-- job: Windows_MSVC2019_x86_64_Clang_Release
+- job: Windows_MSVC2019_x86_64_Clang9_Release
timeoutInMinutes: 120
pool:
vmImage: 'windows-2019'
diff --git a/capi/capi.cpp b/capi/capi.cpp
@@ -335,6 +335,9 @@ extern "C"
reinterpret_cast<filter<double>*>(plan)->apply(output, input, size);
}
+ void kfr_filter_reset_f32(KFR_FILTER_F32* plan) { reinterpret_cast<filter<float>*>(plan)->reset(); }
+ void kfr_filter_reset_f64(KFR_FILTER_F64* plan) { reinterpret_cast<filter<double>*>(plan)->reset(); }
+
void kfr_filter_delete_plan_f32(KFR_FILTER_F32* plan) { delete reinterpret_cast<filter<f32>*>(plan); }
void kfr_filter_delete_plan_f64(KFR_FILTER_F64* plan) { delete reinterpret_cast<filter<f64>*>(plan); }
}
diff --git a/include/kfr/capi.h b/include/kfr/capi.h
@@ -89,9 +89,11 @@ extern "C"
#if defined __STDC_IEC_559_COMPLEX__ && !defined KFR_NO_C_COMPLEX_TYPES
typedef float _Complex kfr_c32;
typedef double _Complex kfr_c64;
+#define KFR_COMPLEX_SIZE_MULTIPLIER 1
#else
typedef float kfr_c32;
typedef double kfr_c64;
+#define KFR_COMPLEX_SIZE_MULTIPLIER 2
#endif
typedef size_t kfr_size_t;
typedef int32_t kfr_int32_t;
@@ -236,6 +238,9 @@ typedef double kfr_c64;
size_t size);
KFR_API_SPEC void kfr_filter_process_f64(KFR_FILTER_F64* plan, kfr_f64* output, const kfr_f64* input,
size_t size);
+
+ KFR_API_SPEC void kfr_filter_reset_f32(KFR_FILTER_F32* plan);
+ KFR_API_SPEC void kfr_filter_reset_f64(KFR_FILTER_F64* plan);
KFR_API_SPEC void kfr_filter_delete_plan_f32(KFR_FILTER_F32* plan);
KFR_API_SPEC void kfr_filter_delete_plan_f64(KFR_FILTER_F64* plan);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
@@ -52,6 +52,12 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/tests/cmake/")
+if (ENABLE_CAPI_BUILD)
+ add_executable(capi_test capi_test.cpp)
+ target_include_directories(capi_test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include)
+ target_link_libraries(capi_test PUBLIC kfr_capi)
+endif ()
+
if (ENABLE_ASMTEST)
add_executable(asm_test asm_test.cpp)
target_link_libraries(asm_test kfr)
@@ -202,19 +208,23 @@ if (NOT SKIP_TESTS)
if (X86)
add_test(NAME multiarch
- COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/bin/multiarch)
+ COMMAND ${EMULATOR} multiarch)
+
+ if (ENABLE_CAPI_BUILD)
+ add_test(NAME capi_test COMMAND ${EMULATOR} capi_test)
+ endif ()
endif ()
if (ARCH_TESTS)
foreach(A IN LISTS ARCH_LIST)
if (USE_SDE)
- add_test(NAME all_tests_${A} COMMAND ${SDE} ${SDE_ARCH_${A}} -- ${PROJECT_BINARY_DIR}/bin/all_tests_${A})
+ add_test(NAME all_tests_${A} COMMAND ${SDE} ${SDE_ARCH_${A}} -- all_tests_${A})
else ()
- add_test(NAME all_tests_${A} COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/bin/all_tests_${A})
+ add_test(NAME all_tests_${A} COMMAND ${EMULATOR} all_tests_${A})
endif ()
endforeach()
else ()
add_test(NAME all_tests
- COMMAND ${EMULATOR} ${PROJECT_BINARY_DIR}/bin/all_tests)
+ COMMAND ${EMULATOR} all_tests)
endif ()
endif ()
diff --git a/tests/capi_test.cpp b/tests/capi_test.cpp
@@ -0,0 +1,222 @@
+#define KFR_NO_C_COMPLEX_TYPES 1
+
+#include <kfr/capi.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int failures = 0;
+
+#ifdef _MSC_VER
+#define CHECK(condition, message, ...) \
+ if (!(condition)) \
+ { \
+ ++failures; \
+ fprintf(stderr, "[FAILED] " message "\n", __VA_ARGS__); \
+ }
+#else
+#define CHECK(condition, message, ...) \
+ if (!(condition)) \
+ { \
+ ++failures; \
+ fprintf(stderr, "[FAILED] " message "\n", ##__VA_ARGS__); \
+ }
+#endif
+
+void test_memory()
+{
+ printf("[TEST] Memory allocation\n");
+ uint8_t* d = (uint8_t*)(kfr_allocate(256));
+ for (size_t i = 0; i < 256; i++)
+ d[i] = i;
+ CHECK(kfr_allocated_size(d) == 256, "kfr_allocated_size: wrong size: %zu", kfr_allocated_size(d));
+ d = (uint8_t*)(kfr_reallocate(d, 512));
+ CHECK(kfr_allocated_size(d) == 512, "kfr_allocated_size: wrong size: %zu", kfr_allocated_size(d));
+ for (size_t i = 0; i < 256; i++)
+ {
+ CHECK(d[i] == i, "kfr_reallocate: data lost after reallocation\n");
+ }
+ kfr_deallocate(d);
+
+ void* page = kfr_allocate_aligned(4096, 4096);
+ CHECK(((uintptr_t)page & 0xFFF) == 0, "kfr_allocate_aligned: wrong alignment: 0x%zx",
+ ((uintptr_t)page & 0xFFF));
+
+ kfr_deallocate(page);
+}
+
+#define DFT_SIZE 32
+
+void test_dft_f32()
+{
+ printf("[TEST] DFT f32\n");
+ const float eps = 0.00001f;
+ KFR_DFT_PLAN_F32* plan = kfr_dft_create_plan_f32(DFT_SIZE);
+ // kfr_dft_dump_f32(plan);
+ kfr_f32 buf[DFT_SIZE * 2];
+ for (int i = 0; i < DFT_SIZE; i++)
+ {
+ buf[i * 2 + 0] = (float)(i) / DFT_SIZE;
+ buf[i * 2 + 1] = (float)(-i) / DFT_SIZE;
+ }
+ uint8_t* tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f32(plan));
+ kfr_dft_execute_f32(plan, buf, buf, tmp);
+ kfr_dft_execute_inverse_f32(plan, buf, buf, tmp);
+ kfr_dft_delete_plan_f32(plan);
+ kfr_deallocate(tmp);
+
+ for (int i = 0; i < DFT_SIZE; i++)
+ {
+ CHECK(fabsf(buf[i * 2 + 0] - (float)(i)) < eps, "DFT: wrong result at %d: re = %f", i,
+ buf[i * 2 + 0]);
+ CHECK(fabsf(buf[i * 2 + 1] - (float)(-i)) < eps, "DFT: wrong result at %d: im = %f", i,
+ buf[i * 2 + 1]);
+ }
+}
+
+void test_dft_f64()
+{
+ printf("[TEST] DFT f64\n");
+ const float eps = 0.00000001;
+ KFR_DFT_PLAN_F64* plan = kfr_dft_create_plan_f64(DFT_SIZE);
+ // kfr_dft_dump_f64(plan);
+ kfr_f64 buf[DFT_SIZE * 2];
+ for (int i = 0; i < DFT_SIZE; i++)
+ {
+ buf[i * 2 + 0] = (double)(i) / DFT_SIZE;
+ buf[i * 2 + 1] = (double)(-i) / DFT_SIZE;
+ }
+ uint8_t* tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f64(plan));
+ kfr_dft_execute_f64(plan, buf, buf, tmp);
+ kfr_dft_execute_inverse_f64(plan, buf, buf, tmp);
+ kfr_dft_delete_plan_f64(plan);
+ kfr_deallocate(tmp);
+
+ for (int i = 0; i < DFT_SIZE; i++)
+ {
+ CHECK(fabs(buf[i * 2 + 0] - (double)(i)) < eps, "DFT: wrong result at %d: re = %f", i,
+ buf[i * 2 + 0]);
+ CHECK(fabs(buf[i * 2 + 1] - (double)(-i)) < eps, "DFT: wrong result at %d: im = %f", i,
+ buf[i * 2 + 1]);
+ }
+}
+
+#define FILTER_SIZE 256
+
+void test_fir_f32()
+{
+ printf("[TEST] FIR f32\n");
+ kfr_f32 taps[] = { 1.f, 2.f, -2.f, -1.f };
+ KFR_FILTER_F32* filter = kfr_filter_create_fir_plan_f32(taps, sizeof(taps) / sizeof(kfr_f32));
+
+ kfr_f32 buf[FILTER_SIZE];
+ for (int i = 0; i < FILTER_SIZE; i++)
+ buf[i] = i;
+
+ kfr_filter_process_f32(filter, buf, buf, FILTER_SIZE);
+ CHECK(buf[0] == 0, "FIR: wrong result at %d: %g", 0, buf[0]);
+ CHECK(buf[1] == 1, "FIR: wrong result at %d: %g", 1, buf[1]);
+ CHECK(buf[2] == 4, "FIR: wrong result at %d: %g", 2, buf[2]);
+ CHECK(buf[3] == 5, "FIR: wrong result at %d: %g", 3, buf[3]);
+ CHECK(buf[FILTER_SIZE - 1] == 5, "FIR: wrong result at %d: %g", FILTER_SIZE - 1, buf[FILTER_SIZE - 1]);
+
+ kfr_filter_delete_plan_f32(filter);
+}
+
+void test_fir_f64()
+{
+ printf("[TEST] FIR f64\n");
+ kfr_f64 taps[] = { 1.f, 2.f, -2.f, -1.f };
+ KFR_FILTER_F64* filter = kfr_filter_create_fir_plan_f64(taps, sizeof(taps) / sizeof(kfr_f64));
+
+ kfr_f64 buf[FILTER_SIZE];
+ for (int i = 0; i < FILTER_SIZE; i++)
+ buf[i] = i;
+
+ kfr_filter_process_f64(filter, buf, buf, FILTER_SIZE);
+ CHECK(buf[0] == 0, "FIR: wrong result at %d: %g", 0, buf[0]);
+ CHECK(buf[1] == 1, "FIR: wrong result at %d: %g", 1, buf[1]);
+ CHECK(buf[2] == 4, "FIR: wrong result at %d: %g", 2, buf[2]);
+ CHECK(buf[3] == 5, "FIR: wrong result at %d: %g", 3, buf[3]);
+ CHECK(buf[FILTER_SIZE - 1] == 5, "FIR: wrong result at %d: %g", FILTER_SIZE - 1, buf[FILTER_SIZE - 1]);
+
+ kfr_filter_delete_plan_f64(filter);
+}
+
+void test_iir_f32()
+{
+ const float eps = 0.00001f;
+ printf("[TEST] IIR f32\n");
+ float sos[6] = {
+ 1.,
+ -1.872871474946867,
+ 0.8809814578599688,
+ 0.002027495728275458,
+ 0.004054991456550916,
+ 0.002027495728275458,
+ };
+ KFR_FILTER_F32* filter = kfr_filter_create_iir_plan_f32(sos, 1);
+
+ kfr_f32 buf[FILTER_SIZE];
+ kfr_f32 src[4] = { 0, 1, 0, -1 };
+ for (int i = 0; i < FILTER_SIZE; i++)
+ buf[i] = src[i % 4];
+
+ kfr_filter_process_f32(filter, buf, buf, FILTER_SIZE);
+
+ CHECK(fabsf(buf[0] - 0.f) < eps, "IIR: wrong result at %d: %f", 0, buf[0]);
+ CHECK(fabsf(buf[1] - 0.002027496f) < eps, "IIR: wrong result at %d: %f", 1, buf[1]);
+ CHECK(fabsf(buf[60] - -0.001285130f) < eps, "IIR: wrong result at %d: %f", 60, buf[60]);
+
+ kfr_filter_delete_plan_f32(filter);
+}
+
+void test_iir_f64()
+{
+ const double eps = 0.0000001;
+ printf("[TEST] IIR f64\n");
+ double sos[6] = {
+ 1.,
+ -1.872871474946867,
+ 0.8809814578599688,
+ 0.002027495728275458,
+ 0.004054991456550916,
+ 0.002027495728275458,
+ };
+ KFR_FILTER_F64* filter = kfr_filter_create_iir_plan_f64(sos, 1);
+
+ kfr_f64 buf[FILTER_SIZE];
+ kfr_f64 src[4] = { 0, 1, 0, -1 };
+ for (int i = 0; i < FILTER_SIZE; i++)
+ buf[i] = src[i % 4];
+
+ kfr_filter_process_f64(filter, buf, buf, FILTER_SIZE);
+
+ CHECK(fabs(buf[0] - 0.) < eps, "IIR: wrong result at %d: %f", 0, buf[0]);
+ CHECK(fabs(buf[1] - 0.002027496) < eps, "IIR: wrong result at %d: %f", 1, buf[1]);
+ CHECK(fabs(buf[60] - -0.001285130) < eps, "IIR: wrong result at %d: %f", 60, buf[60]);
+
+ kfr_filter_delete_plan_f64(filter);
+}
+
+int main()
+{
+ CHECK(KFR_HEADERS_VERSION <= kfr_version(), "Dynamic library is too old. At least %d required",
+ KFR_HEADERS_VERSION);
+
+ printf("[INFO] %s\n", kfr_version_string());
+
+ test_memory();
+ test_dft_f32();
+ test_dft_f64();
+ test_fir_f32();
+ test_fir_f64();
+ test_iir_f32();
+ test_iir_f64();
+
+ if (failures == 0)
+ printf("[PASSED]\n");
+ else
+ printf("[FAILED] %d check(s)\n", failures);
+ return failures;
+}