Skip to content

Commit

Permalink
wio
Browse files Browse the repository at this point in the history
  • Loading branch information
wirew0rm committed Oct 6, 2023
1 parent 6c142b8 commit 143e0f1
Show file tree
Hide file tree
Showing 43 changed files with 196 additions and 124 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,6 @@ endif ()
add_subdirectory(bench) # custom ut addon for microbenchmarking

add_subdirectory(core)
add_subdirectory(meta)
add_subdirectory(algorithm)
add_subdirectory(blocks)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![License](https://img.shields.io/badge/License-LGPL%203.0-blue.svg)](https://opensource.org/licenses/LGPL-3.0)
![CMake](https://github.com/fair-acc/graph-prototype/workflows/CMake/badge.svg)
# Graph Prototype
# GNURadio 4.0 prototype
A small proof-of-concept for evaluating efficient [directed graph](https://en.wikipedia.org/wiki/Directed_graph)-based
algorithms, notably required node structures, scheduling interfaces, and partial compile-time merging of
[directed acyclic](https://en.wikipedia.org/wiki/Directed_acyclic_graph) as well as
Expand Down
7 changes: 7 additions & 0 deletions algorithm/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_library(gnuradio-algorithm INTERFACE)
target_include_directories(gnuradio-algorithm INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/> $<INSTALL_INTERFACE:include/>)
target_link_libraries(gnuradio-algorithm INTERFACE gnuradio-options gnuradio-meta vir fftw)

if (ENABLE_TESTING)
add_subdirectory(test)
endif ()
6 changes: 6 additions & 0 deletions algorithm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# gnuradio-algorithm

A math support library with math primitives to be used by different block types.

Included algorithms:
- Fast Fourier Transform
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

#include <ranges>

#include <gnuradio-4.0/node.hpp>

#include "fft_types.hpp"
#include "window.hpp"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <cmath>
#include <vector>

#include <fmt/format.h>

#include "fft_types.hpp"

namespace gr::algorithm {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#ifndef GRAPH_PROTOTYPE_ALGORITHM_FFT_TYPES_HPP
#define GRAPH_PROTOTYPE_ALGORITHM_FFT_TYPES_HPP

#include <gnuradio-4.0/node.hpp>
#include <type_traits>
#include <complex>

namespace gr::algorithm {
template<typename T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@

#include <fftw3.h>

#include <gnuradio-4.0/dataset.hpp>
#include <gnuradio-4.0/history_buffer.hpp>
#include <gnuradio-4.0/node.hpp>

#include "fft_types.hpp"
#include "window.hpp"

namespace gr::algorithm {

using namespace fair::graph;

template<typename T>
concept FFTwDoubleType = std::is_same_v<T, std::complex<double>> || std::is_same_v<T, double>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#include <string_view>
#include <vector>

#include <gnuradio-4.0/utils.hpp>

#include <fmt/format.h>

#include <gnuradio-4.0/meta/utils.hpp>

namespace gr::algorithm::window {

/**
Expand Down
2 changes: 2 additions & 0 deletions algorithm/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_ut_test(qa_algorithm_fourier)
target_link_libraries(qa_algorithm_fourier PRIVATE gnuradio-algorithm)
100 changes: 100 additions & 0 deletions algorithm/test/qa_algorithm_fourier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <numbers>

#include <boost/ut.hpp>

#include <fmt/format.h>

#include <gnuradio-4.0/algorithm/fourier/fft.hpp>
#include <gnuradio-4.0/algorithm/fourier/fftw.hpp>

template<typename T, typename U = T>
bool
equalVectors(const std::vector<T> &v1, const std::vector<U> &v2, double tolerance = std::is_same_v<T, double> ? 1.e-5 : 1e-4) {
if (v1.size() != v2.size()) {
return false;
}
if constexpr (gr::algorithm::ComplexType<T>) {
return std::equal(v1.begin(), v1.end(), v2.begin(), [&tolerance](const auto &l, const auto &r) {
return std::abs(l.real() - r.real()) < static_cast<typename T::value_type>(tolerance) && std::abs(l.imag() - r.imag()) < static_cast<typename T::value_type>(tolerance);
});
} else {
return std::equal(v1.begin(), v1.end(), v2.begin(), [&tolerance](const auto &l, const auto &r) { return std::abs(static_cast<double>(l) - static_cast<double>(r)) < tolerance; });
}
}

const boost::ut::suite<"window functions"> windowTests = [] {
using namespace boost::ut;
using namespace boost::ut::reflection;
using gr::algorithm::window::create;

"window pre-computed array tests"_test = []<typename T>() { // this tests regression w.r.t. changed implementations
// Expected value for size 8
std::vector<T> Rectangular8{ 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f };
std::vector<T> Hamming8{ 0.07672f, 0.2119312255f, 0.53836f, 0.8647887745f, 1.0f, 0.8647887745f, 0.53836f, 0.2119312255f };
std::vector<T> Hann8{ 0.f, 0.1882550991f, 0.611260467f, 0.950484434f, 0.950484434f, 0.611260467f, 0.1882550991f, 0.f };
std::vector<T> Blackman8{ 0.f, 0.09045342435f, 0.4591829575f, 0.9203636181f, 0.9203636181f, 0.4591829575f, 0.09045342435f, 0.f };
std::vector<T> BlackmanHarris8{ 0.00006f, 0.03339172348f, 0.3328335043f, 0.8893697722f, 0.8893697722f, 0.3328335043f, 0.03339172348f, 0.00006f };
std::vector<T> BlackmanNuttall8{ 0.0003628f, 0.03777576895f, 0.34272762f, 0.8918518611f, 0.8918518611f, 0.34272762f, 0.03777576895f, 0.0003628f };
std::vector<T> Exponential8{ 1.f, 1.042546905f, 1.08690405f, 1.133148453f, 1.181360413f, 1.231623642f, 1.284025417f, 1.338656724f };
std::vector<T> FlatTop8{ 0.004f, -0.1696424054f, 0.04525319348f, 3.622389212f, 3.622389212f, 0.04525319348f, -0.1696424054f, 0.004f };
std::vector<T> HannExp8{ 0.f, 0.611260467f, 0.950484434f, 0.1882550991f, 0.1882550991f, 0.950484434f, 0.611260467f, 0.f };
std::vector<T> Nuttall8{ 0.f, 0.0311427368f, 0.3264168059f, 0.8876284573f, 0.8876284573f, 0.3264168059f, 0.0311427368f, 0.f };
std::vector<T> Kaiser8{ 0.5714348848f, 0.7650986027f, 0.9113132365f, 0.9899091685f, 0.9899091685f, 0.9113132365f, 0.7650986027f, 0.5714348848f };

// check all windows for unwanted changes
using enum gr::algorithm::window::Type;
expect(equalVectors<T>(create<T>(None, 8), Rectangular8)) << fmt::format("<{}> equal Rectangular8[8] vector {} vs. ref: {}", type_name<T>(), create<T>(None, 8), Rectangular8);
expect(equalVectors<T>(create<T>(Rectangular, 8), Rectangular8)) << fmt::format("<{}> equal Rectangular[8]vector {} vs. ref: {}", type_name<T>(), create<T>(Rectangular, 8), Rectangular8);
expect(equalVectors<T>(create<T>(Hamming, 8), Hamming8)) << fmt::format("<{}> equal Hamming[8] vector {} vs. ref: {}", type_name<T>(), create<T>(Hamming, 8), Hamming8);
expect(equalVectors<T>(create<T>(Hann, 8), Hann8)) << fmt::format("<{}> equal Hann[8] vector {} vs. ref: {}", type_name<T>(), create<T>(Hann, 8), Hann8);
expect(equalVectors<T>(create<T>(Blackman, 8), Blackman8)) << fmt::format("<{}> equal Blackman[8] vvector {} vs. ref: {}", type_name<T>(), create<T>(Blackman, 8), Blackman8);
expect(equalVectors<T>(create<T>(BlackmanHarris, 8), BlackmanHarris8))
<< fmt::format("<{}> equal BlackmanHarris[8] vector {} vs. ref: {}", type_name<T>(), create<T>(BlackmanHarris, 8), BlackmanHarris8);
expect(equalVectors<T>(create<T>(BlackmanNuttall, 8), BlackmanNuttall8))
<< fmt::format("<{}> equal BlackmanNuttall[8] vector {} vs. ref: {}", type_name<T>(), create<T>(BlackmanNuttall, 8), BlackmanNuttall8);
expect(equalVectors<T>(create<T>(Exponential, 8), Exponential8)) << fmt::format("<{}> equal Exponential[8] vector {} vs. ref: {}", type_name<T>(), create<T>(Exponential, 8), Exponential8);
expect(equalVectors<T>(create<T>(FlatTop, 8), FlatTop8)) << fmt::format("<{}> equal FlatTop[8] vector {} vs. ref: {}", type_name<T>(), create<T>(FlatTop, 8), FlatTop8);
expect(equalVectors<T>(create<T>(HannExp, 8), HannExp8)) << fmt::format("<{}> equal HannExp[8] vector {} vs. ref: {}", type_name<T>(), create<T>(HannExp, 8), HannExp8);
expect(equalVectors<T>(create<T>(Nuttall, 8), Nuttall8)) << fmt::format("<{}> equal Nuttall[8] vector {} vs. ref: {}", type_name<T>(), create<T>(Nuttall, 8), Nuttall8);
expect(equalVectors<T>(create<T>(Kaiser, 8), Kaiser8)) << fmt::format("<{}> equal Kaiser[8] vector {} vs. ref: {}", type_name<T>(), create<T>(Kaiser, 8), Kaiser8);

// test zero length
expect(eq(create<T>(None, 0).size(), 0u)) << fmt::format("<{}> zero size None[8] vectors", type_name<T>());
expect(eq(create<T>(Rectangular, 0).size(), 0u)) << fmt::format("<{}> zero size Rectangular[8] vectors", type_name<T>());
expect(eq(create<T>(Hamming, 0).size(), 0u)) << fmt::format("<{}> zero size Hamming[8] vectors", type_name<T>());
expect(eq(create<T>(Hann, 0).size(), 0u)) << fmt::format("<{}> zero size Hann[8] vectors", type_name<T>());
expect(eq(create<T>(Blackman, 0).size(), 0u)) << fmt::format("<{}> zero size Blackman[8] vectors", type_name<T>());
expect(eq(create<T>(BlackmanHarris, 0).size(), 0u)) << fmt::format("<{}> zero size BlackmanHarris[8] vectors", type_name<T>());
expect(eq(create<T>(BlackmanNuttall, 0).size(), 0u)) << fmt::format("<{}> zero size BlackmanNuttall[8] vectors", type_name<T>());
expect(eq(create<T>(Exponential, 0).size(), 0u)) << fmt::format("<{}> zero size Exponential[8] vectors", type_name<T>());
expect(eq(create<T>(FlatTop, 0).size(), 0u)) << fmt::format("<{}> zero size FlatTop[8] vectors", type_name<T>());
expect(eq(create<T>(HannExp, 0).size(), 0u)) << fmt::format("<{}> zero size HannExp[8] vectors", type_name<T>());
expect(eq(create<T>(Nuttall, 0).size(), 0u)) << fmt::format("<{}> zero size Nuttall[8] vectors", type_name<T>());
expect(eq(create<T>(Kaiser, 0).size(), 0u)) << fmt::format("<{}> zero size Kaiser[8] vectors", type_name<T>());
} | std::tuple<float, double>();

"basic window tests"_test = [](gr::algorithm::window::Type window) {
using enum gr::algorithm::window::Type;
expect(gr::algorithm::window::parse(gr::algorithm::window::to_string(window)) == window) << fmt::format("window {} parse(to_string) identity\n", gr::algorithm::window::to_string(window));

const auto w = create(window, 1024U);
expect(eq(w.size(), 1024U));

if (window == Exponential || window == FlatTop || window == Blackman || window == Nuttall) {
return; // min max out of [0, 1] by design and/or numerical corner cases
}
const auto [min, max] = std::ranges::minmax_element(w);
expect(ge(*min, 0.f)) << fmt::format("window {} min value\n", gr::algorithm::window::to_string(window));
expect(le(*max, 1.f)) << fmt::format("window {} max value\n", gr::algorithm::window::to_string(window));
} | gr::algorithm::window::TypeList;

"window corner cases"_test = []<typename T>() {
expect(throws<std::invalid_argument>([] { std::ignore = gr::algorithm::window::parse("UnknownWindow"); })) << "invalid window name";
expect(throws<std::invalid_argument>([] { std::ignore = create(gr::algorithm::window::Type::Kaiser, 1); })) << "invalid Kaiser window size";
expect(throws<std::invalid_argument>([] { std::ignore = create(gr::algorithm::window::Type::Kaiser, 2, -1.f); })) << "invalid Kaiser window beta";
} | std::tuple<float, double>();
};

int
main() { /* not needed for UT */
}
2 changes: 0 additions & 2 deletions blocks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
add_subdirectory(basic)
add_subdirectory(filter)
add_subdirectory(fourier)
add_subdirectory(math)

if (ENABLE_TESTING)
add_subdirectory(testing)
add_subdirectory(demo)
endif ()
15 changes: 15 additions & 0 deletions blocks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# gnuradio blocks

This directory contains collections of blocks by topic.

Structure of a block, entries in square brackets are optional:

- <library_name>
- include/gnuradio-4.0/<library_name>/
- one or more headers which each can contain one or more block definitions
- test
- qa_<blockname> - tests for a block
- CMakeLists.txt
- README.md - a short description of the block library
- [src] - containing optional samples
- [assets] - additional block documentation
3 changes: 2 additions & 1 deletion blocks/basic/include/gnuradio-4.0/basic/selector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#define GRAPH_PROTOTYPE_SELECTOR_HPP

#include <gnuradio-4.0/node.hpp>
#include <gnuradio-4.0/utils.hpp>

#include <gnuradio-4.0/meta/utils.hpp>

namespace gr::blocks::basic {
using namespace fair::graph;
Expand Down
3 changes: 2 additions & 1 deletion blocks/basic/test/qa_selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

#include <boost/ut.hpp>

#include <gnuradio-4.0/meta/utils.hpp>

#include <gnuradio-4.0/graph.hpp>
#include <gnuradio-4.0/node.hpp>
#include <gnuradio-4.0/utils.hpp>

#include <gnuradio-4.0/basic/selector.hpp>

Expand Down
3 changes: 0 additions & 3 deletions blocks/demo/CMakeLists.txt

This file was deleted.

1 change: 1 addition & 0 deletions blocks/filter/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
add_ut_test(qa_filter)
target_link_libraries(qa_filter PRIVATE gr-filter)
2 changes: 1 addition & 1 deletion blocks/fourier/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
add_library(gr-fourier INTERFACE)
target_link_libraries(gr-fourier INTERFACE gnuradio-core)
target_link_libraries(gr-fourier INTERFACE gnuradio-core gnuradio-algorithm)
target_include_directories(gr-fourier INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/> $<INSTALL_INTERFACE:include/>)

if (ENABLE_TESTING)
Expand Down
10 changes: 5 additions & 5 deletions blocks/fourier/include/gnuradio-4.0/fourier/fft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
#include <gnuradio-4.0/history_buffer.hpp>
#include <gnuradio-4.0/node.hpp>

#include <gnuradio-4.0/algorithm/fft/fft.hpp>
#include <gnuradio-4.0/algorithm/fft/fft_common.hpp>
#include <gnuradio-4.0/algorithm/fft/fft_types.hpp>
#include <gnuradio-4.0/algorithm/fft/fftw.hpp>
#include <gnuradio-4.0/algorithm/fft/window.hpp>
#include <gnuradio-4.0/algorithm/fourier/fft.hpp>
#include <gnuradio-4.0/algorithm/fourier/fft_common.hpp>
#include <gnuradio-4.0/algorithm/fourier/fft_types.hpp>
#include <gnuradio-4.0/algorithm/fourier/fftw.hpp>
#include <gnuradio-4.0/algorithm/fourier/window.hpp>

namespace gr::blocks::fft {

Expand Down
1 change: 1 addition & 0 deletions blocks/fourier/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
add_ut_test(qa_fourier)
target_link_libraries(qa_fourier PRIVATE gr-fourier)
Loading

0 comments on commit 143e0f1

Please sign in to comment.