Introduction


1. Prerequisites

KFR is a header-only so just #include <kfr/math.hpp> to start using it

1.1 Tests and Examples

The following tools are required to build the examples:

To build the tests:

2. Installation

To obtain the full code, including examples and tests, you can clone the git repository:

git clone https://github.com/kfrlib/kfr.git

To be able to run the tests and examples install the following python modules:

pip install matplotlib # or download prebuilt package for windows
pip install numpy # or download prebuilt package for windows
pip install scipy # or download prebuilt package for windows

Install dspplot using python setup.py install inside dspplot directory

3. Tests

Execute build.py or build-cl.py (Visual Studio version) to run the tests or run tests manually from the tests directory

Tested on the following systems:

Note: clang 3.8 has incompatibility with Visual Studio 2015 update 2 so install latest Clang from trunk.

4. Basics

4.1 Data types

KFR supports all standard C/C++ types:

i8 (char), u8 (unsigned char),

i16 (short), u16 (unsigned short),

i32 (int), u32 (unsigned int),

i64 (long long), u64 (unsigned long long),

f32 (float), f64 (double)

Complex types are also supported

4.2 univector class

univector class is a base of all containers in KFR. univector can have both static and dynamic size and can even hold only reference to an external data (just like array_view or string_view)

univector<float> behaves like an instance of std::vector<float> You can call all vector's member functions and constructors

univector<float, 10> behaves like std::array<float, 10>

On the other hand, univector<float, 0> is only reference to data and doesn't contain any values

Example:

float data[4];
univector<float, 0> v3(data, 4);

You can get subrange of an array using slice function univector<float, 0> v4 = v2.slice(2, 5);

v4 now contains subrange of s2 starting from 2 with length 5

5. Expressions

Almost every thing in KFR is an expression. Input expressions can be read from and output expressions can be written to. Class can be an input and output expression at same time. univector is an example of such class.

Data type of an input expressions can be determined by calling value_type_of. However, not all expressions have their types specified. In such cases value_type_of will return special type generic.

Size (length) of an expression also can be specified or not. counter is an example of generic (untyped) expression without the size.

5.1 Calling functions

Passing an expression into a function doesn't calculate value immediately. Instead, new expression will be created.

Example:

auto a = counter();      // a is an expression without type
auto b = a * 2 + 1;      // b is an expression without type
univector<int, 5> c = b; // fill c with values 1, 3, 5, 7, 9

In the example above, only the last line does actual calculations. This is similar to concept of lazy evaluation.

univector<int, 6> d = sqr(counter());
print(d); // prints 0, 1, 4, 9, 16, 25

const double w = c_pi<double> * 0.125;
univector<int, 6> e = sin(counter() * w);
print(e); // prints  0  0.382683  0.707107   0.92388         1   0.92388

6. DSP Algorithms

6.1 Fast Fourier Transform (FFT)

Header kfr/dft/fft.hpp

KFR contains C++ implementation‎of the Cooley–Tukey FFT algorithm both inplace and out-of-place variants. As all of our algorithms FFT is tuned for speed and provides fast way to transform your data from time to frequence domain and vice-versa.

No need to create two plans to do both direct and inverse tranform.

Example:

#include <kfr/math.hpp>
#include <kfr/dft/fft.hpp>
...

void func()
{
    dft_plan dft(size);                      // initialize plan
    univector<u8> temp(dft.temp_size);       // allocate work buffer
    dft.execute(freq, samples, temp);        // do the actual transform
    // work with freq
    dft.execute(samples, freq, temp, true);  // do the inverse transform
}

Read the function reference