kfr

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

commit d158ef1c1736136db9f21ca4326021b8a91d0383
parent eb1e2ce68272882c1f8c8b14b6b31fc8f5501f41
Author: samuriddle@gmail.com <samuriddle@gmail.com>
Date:   Sun, 31 Jul 2016 17:13:35 +0300

merge misc and base folders

Diffstat:
Mexamples/dft.cpp | 2+-
Minclude/kfr/all.hpp | 9++++-----
Ainclude/kfr/base/compiletime.hpp | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/kfr/base/random.hpp | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/kfr/base/small_buffer.hpp | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/kfr/base/sort.hpp | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/kfr/dft/fft.hpp | 2+-
Minclude/kfr/dft/ft.hpp | 2+-
Minclude/kfr/dft/reference_dft.hpp | 2+-
Dinclude/kfr/misc/compiletime.hpp | 81-------------------------------------------------------------------------------
Dinclude/kfr/misc/random.hpp | 180-------------------------------------------------------------------------------
Dinclude/kfr/misc/small_buffer.hpp | 113-------------------------------------------------------------------------------
Dinclude/kfr/misc/sort.hpp | 96-------------------------------------------------------------------------------
Msources.cmake | 8++++----
Mtests/dft_test.cpp | 2+-
15 files changed, 483 insertions(+), 484 deletions(-)

diff --git a/examples/dft.cpp b/examples/dft.cpp @@ -12,6 +12,7 @@ // print(), format() #include <kfr/cometa/string.hpp> +#include <kfr/base/random.hpp> #include <kfr/dft/fft.hpp> #include <kfr/dft/reference_dft.hpp> #include <kfr/dsp/oscillators.hpp> @@ -19,7 +20,6 @@ #include <kfr/expressions/basic.hpp> #include <kfr/expressions/reduce.hpp> #include <kfr/math.hpp> -#include <kfr/misc/random.hpp> using namespace kfr; diff --git a/include/kfr/all.hpp b/include/kfr/all.hpp @@ -27,6 +27,7 @@ #include "base/asin_acos.hpp" #include "base/atan.hpp" #include "base/clamp.hpp" +#include "base/compiletime.hpp" #include "base/complex.hpp" #include "base/constants.hpp" #include "base/digitreverse.hpp" @@ -39,12 +40,15 @@ #include "base/min_max.hpp" #include "base/modzerobessel.hpp" #include "base/operators.hpp" +#include "base/random.hpp" #include "base/read_write.hpp" #include "base/round.hpp" #include "base/saturation.hpp" #include "base/select.hpp" #include "base/shuffle.hpp" #include "base/sin_cos.hpp" +#include "base/small_buffer.hpp" +#include "base/sort.hpp" #include "base/sqrt.hpp" #include "base/tan.hpp" #include "base/types.hpp" @@ -59,11 +63,6 @@ #include "expressions/reduce.hpp" #include "version.hpp" -#include "misc/compiletime.hpp" -#include "misc/random.hpp" -#include "misc/small_buffer.hpp" -#include "misc/sort.hpp" - #include "data/bitrev.hpp" #include "data/sincos.hpp" #include "dsp/biquad.hpp" diff --git a/include/kfr/base/compiletime.hpp b/include/kfr/base/compiletime.hpp @@ -0,0 +1,81 @@ +/** + * Copyright (C) 2016 D Levin (http://www.kfrlib.com) + * This file is part of KFR + * + * KFR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KFR. + * + * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. + * Buying a commercial license is mandatory as soon as you develop commercial activities without + * disclosing the source code of your own applications. + * See http://www.kfrlib.com for details. + */ +#pragma once +#include "constants.hpp" +#include "operators.hpp" +#include "types.hpp" + +namespace kfr +{ + +namespace compiletime +{ + +template <typename T> +constexpr inline T select(bool c, T x, T y) +{ + return c ? x : y; +} +template <typename T> +constexpr inline T trunc(T x) +{ + return static_cast<T>(static_cast<long long>(x)); +} +template <typename T> +constexpr inline T abs(T x) +{ + return x < T() ? -x : x; +} +template <typename T> +constexpr inline T mulsign(T x, T y) +{ + return y < T() ? -x : x; +} +template <typename T> +constexpr inline T sin(T x) +{ + x = x - trunc(x / c_pi<T, 2>) * c_pi<T, 2>; + constexpr T c2 = -0.16665853559970855712890625; + constexpr T c4 = +8.31427983939647674560546875e-3; + constexpr T c6 = -1.85423981747590005397796630859375e-4; + + x -= c_pi<T>; + T y = abs(x); + y = select(y > c_pi<T, 1, 2>, c_pi<T> - y, y); + y = mulsign(y, -x); + + const T y2 = y * y; + T formula = c6; + const T y3 = y2 * y; + formula = fmadd(formula, y2, c4); + formula = fmadd(formula, y2, c2); + formula = formula * y3 + y; + return formula; +} +template <typename T> +constexpr inline T cos(T x) +{ + return sin(x + c_pi<T, 1, 2>); +} +} +} diff --git a/include/kfr/base/random.hpp b/include/kfr/base/random.hpp @@ -0,0 +1,180 @@ +/** + * Copyright (C) 2016 D Levin (http://www.kfrlib.com) + * This file is part of KFR + * + * KFR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KFR. + * + * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. + * Buying a commercial license is mandatory as soon as you develop commercial activities without + * disclosing the source code of your own applications. + * See http://www.kfrlib.com for details. + */ +#pragma once +#include "function.hpp" +#include "operators.hpp" +#include "shuffle.hpp" +#include "vec.hpp" + +namespace kfr +{ + +using random_state = u32x4; + +struct seed_from_rdtsc_t +{ +}; + +constexpr seed_from_rdtsc_t seed_from_rdtsc{}; + +struct random_bit_generator +{ + random_bit_generator(seed_from_rdtsc_t) noexcept + : state(bitcast<u32>(make_vector(__builtin_readcyclecounter(), + (__builtin_readcyclecounter() << 11) ^ 0x710686d615e2257bull))) + { + (void)operator()(); + } + constexpr random_bit_generator(u32 x0, u32 x1, u32 x2, u32 x3) noexcept : state(x0, x1, x2, x3) + { + (void)operator()(); + } + constexpr random_bit_generator(u64 x0, u64 x1) noexcept : state(bitcast<u32>(make_vector(x0, x1))) + { + (void)operator()(); + } + + inline random_state operator()() + { + constexpr static random_state mul{ 214013u, 17405u, 214013u, 69069u }; + constexpr static random_state add{ 2531011u, 10395331u, 13737667u, 1u }; + state = bitcast<u32>(rotateright<3>(bitcast<u8>(fmadd(state, mul, add)))); + return state; + } + +protected: + random_state state; +}; + +template <size_t N, KFR_ENABLE_IF(N <= sizeof(random_state))> +inline vec<u8, N> random_bits(random_bit_generator& gen) +{ + return narrow<N>(bitcast<u8>(gen())); +} +template <size_t N, KFR_ENABLE_IF(N > sizeof(random_state))> +inline vec<u8, N> random_bits(random_bit_generator& gen) +{ + constexpr size_t N2 = prev_poweroftwo(N - 1); + return concat(random_bits<N2>(gen), random_bits<N - N2>(gen)); +} + +template <typename T, size_t N, KFR_ENABLE_IF(std::is_integral<T>::value)> +inline vec<T, N> random_uniform(random_bit_generator& gen) +{ + return bitcast<T>(random_bits<N * sizeof(T)>(gen)); +} + +template <typename T, size_t N, KFR_ENABLE_IF(std::is_same<T, f32>::value)> +inline vec<f32, N> randommantissa(random_bit_generator& gen) +{ + return bitcast<f32>((random_uniform<u32, N>(gen) & 0x7FFFFFu) | 0x3f800000u) + 0.0f; +} + +template <typename T, size_t N, KFR_ENABLE_IF(std::is_same<T, f64>::value)> +inline vec<f64, N> randommantissa(random_bit_generator& gen) +{ + return bitcast<f64>((random_uniform<u64, N>(gen) & 0x000FFFFFFFFFFFFFull) | 0x3FF0000000000000ull) + 0.0; +} + +template <typename T, size_t N> +inline enable_if_f<vec<T, N>> random_uniform(random_bit_generator& gen) +{ + return randommantissa<T, N>(gen) - 1.f; +} + +template <size_t N, typename T> +inline enable_if_f<vec<T, N>> random_range(random_bit_generator& gen, T min, T max) +{ + return mix(random_uniform<T, N>(gen), min, max); +} + +template <size_t N, typename T> +inline enable_if_not_f<vec<T, N>> random_range(random_bit_generator& gen, T min, T max) +{ + using big_type = findinttype<sqr(std::numeric_limits<T>::min()), sqr(std::numeric_limits<T>::max())>; + + vec<T, N> u = random_uniform<T, N>(gen); + const vec<big_type, N> tmp = cast<big_type>(u); + return cast<T>((tmp * (max - min) + min) >> typebits<T>::bits); +} + +namespace internal +{ +template <typename T> +struct expression_random_uniform : input_expression +{ + using value_type = T; + constexpr expression_random_uniform(const random_bit_generator& gen) noexcept : gen(gen) {} + template <typename U, size_t N> + vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const + { + return cast<U>(random_uniform<T, N>(gen)); + } + mutable random_bit_generator gen; +}; + +template <typename T> +struct expression_random_range : input_expression +{ + using value_type = T; + constexpr expression_random_range(const random_bit_generator& gen, T min, T max) noexcept : gen(gen), + min(min), + max(max) + { + } + + template <typename U, size_t N> + vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const + { + return cast<U>(random_range<N, T>(gen, min, max)); + } + mutable random_bit_generator gen; + const T min; + const T max; +}; +} + +template <typename T> +inline internal::expression_random_uniform<T> gen_random_uniform(const random_bit_generator& gen) +{ + return internal::expression_random_uniform<T>(gen); +} + +template <typename T> +inline internal::expression_random_range<T> gen_random_range(const random_bit_generator& gen, T min, T max) +{ + return internal::expression_random_range<T>(gen, min, max); +} + +template <typename T> +inline internal::expression_random_uniform<T> gen_random_uniform() +{ + return internal::expression_random_uniform<T>(random_bit_generator(seed_from_rdtsc)); +} + +template <typename T> +inline internal::expression_random_range<T> gen_random_range(T min, T max) +{ + return internal::expression_random_range<T>(random_bit_generator(seed_from_rdtsc), min, max); +} +} diff --git a/include/kfr/base/small_buffer.hpp b/include/kfr/base/small_buffer.hpp @@ -0,0 +1,113 @@ +/** + * Copyright (C) 2016 D Levin (http://www.kfrlib.com) + * This file is part of KFR + * + * KFR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KFR. + * + * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. + * Buying a commercial license is mandatory as soon as you develop commercial activities without + * disclosing the source code of your own applications. + * See http://www.kfrlib.com for details. + */ +#pragma once + +#include "memory.hpp" +#include <algorithm> +#include <cstdint> + +namespace kfr +{ + +template <typename T, std::size_t Capacity = 16> +struct small_buffer +{ +public: + small_buffer() noexcept : m_size(0), m_data(m_preallocated) {} + + small_buffer(std::size_t size) : small_buffer() { resize(size); } + + friend void swap(small_buffer<T, Capacity>& first, small_buffer<T, Capacity>& second) noexcept + { + using std::swap; + + swap(first.m_size, second.m_size); + swap(first.m_data, second.m_data); + swap(first.m_preallocated, second.m_preallocated); + first.m_data = first.m_size <= Capacity ? first.m_preallocated : first.m_data; + second.m_data = second.m_size <= Capacity ? second.m_preallocated : second.m_data; + } + small_buffer(small_buffer<T, Capacity>&& other) : small_buffer() { swap(other, *this); } + + small_buffer(const small_buffer<T, Capacity>& other) : small_buffer() { assign(other); } + small_buffer<T, Capacity>& operator=(small_buffer<T, Capacity> other) + { + swap(other, *this); + return *this; + } + + ~small_buffer() { clear(); } + + void assign(const small_buffer<T, Capacity>& other) + { + resize(other.m_size); + std::copy_n(other.m_data, m_size, m_data); + } + + void resize(std::size_t newsize) + { + T* m_newdata; + if (newsize <= Capacity) + { + m_newdata = m_preallocated; + } + else + { + m_newdata = aligned_allocate<T>(newsize); + } + std::copy_n(std::make_move_iterator(m_data), std::min(newsize, m_size), m_newdata); + if (m_data != m_preallocated) + aligned_deallocate(m_data); + m_data = m_newdata; + m_size = newsize; + } + bool empty() const { return !size(); } + std::size_t size() const { return m_size; } + const T* begin() const { return m_data; } + const T* end() const { return m_data + m_size; } + const T* cbegin() const { return m_data; } + const T* cend() const { return m_data + m_size; } + T* begin() { return m_data; } + T* end() { return m_data + m_size; } + void clear() { resize(0); } + const T& front() const { return m_data[0]; } + const T& back() const { return m_data[m_size - 1]; } + T& front() { return m_data[0]; } + T& back() { return m_data[m_size - 1]; } + void pop_back() { resize(m_size - 1); } + T* data() { return m_data; } + const T* data() const { return m_data; } + T& operator[](std::size_t i) { return m_data[i]; } + const T& operator[](std::size_t i) const { return m_data[i]; } + void push_back(const T& value) + { + resize(m_size + 1); + m_data[m_size - 1] = value; + } + +protected: + T m_preallocated[Capacity]; + std::size_t m_size; + T* m_data; +}; +} diff --git a/include/kfr/base/sort.hpp b/include/kfr/base/sort.hpp @@ -0,0 +1,96 @@ +/** + * Copyright (C) 2016 D Levin (http://www.kfrlib.com) + * This file is part of KFR + * + * KFR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KFR. + * + * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. + * Buying a commercial license is mandatory as soon as you develop commercial activities without + * disclosing the source code of your own applications. + * See http://www.kfrlib.com for details. + */ +#pragma once + +#include "min_max.hpp" +#include "shuffle.hpp" +#include "vec.hpp" + +namespace kfr +{ +/** + * Sort the elements in the vector in ascending order + * @param x input vector + * @return sorted vector + * @code + * CHECK(sort(make_vector(1000, 1, 2, -10)) == make_vector(-10, 1, 2, 1000)); + * @endcode + */ +template <typename T, size_t N> +KFR_INLINE vec<T, N> sort(const vec<T, N>& x) +{ + constexpr size_t Nhalf = N / 2; + vec<T, Nhalf> e = low(x); + vec<T, Nhalf> o = high(x); + constexpr auto blend0 = cconcat(csizes<1>, csizeseq<Nhalf - 1, 0, 0>); + for (size_t i = 0; i < Nhalf; i++) + { + vec<T, Nhalf> t; + t = min(e, o); + o = max(e, o); + o = rotateright<1>(o); + e = t; + t = max(e, o); + o = min(e, o); + e = t; + t = blend(e, o, blend0); + o = blend(o, e, blend0); + o = rotateleft<1>(o); + e = t; + } + return interleavehalfs(concat(e, o)); +} + +/** + * Sort the elements in the vector in descending order + * @param x input vector + * @return sorted vector + * @code + * CHECK(sort(make_vector(1000, 1, 2, -10)) == make_vector(1000, 2, 1, -10)); + * @endcode + */ +template <typename T, size_t N> +KFR_INLINE vec<T, N> sortdesc(const vec<T, N>& x) +{ + constexpr size_t Nhalf = N / 2; + vec<T, Nhalf> e = low(x); + vec<T, Nhalf> o = high(x); + constexpr auto blend0 = cconcat(csizes<1>, csizeseq<Nhalf - 1, 0, 0>); + for (size_t i = 0; i < Nhalf; i++) + { + vec<T, Nhalf> t; + t = max(e, o); + o = min(e, o); + o = rotateright<1>(o); + e = t; + t = min(e, o); + o = max(e, o); + e = t; + t = blend(e, o, blend0); + o = blend(o, e, blend0); + o = rotateleft<1>(o); + e = t; + } + return interleavehalfs(concat(e, o)); +} +} diff --git a/include/kfr/dft/fft.hpp b/include/kfr/dft/fft.hpp @@ -26,8 +26,8 @@ #include "../base/constants.hpp" #include "../base/memory.hpp" #include "../base/read_write.hpp" +#include "../base/small_buffer.hpp" #include "../base/vec.hpp" -#include "../misc/small_buffer.hpp" #include "../cometa/string.hpp" diff --git a/include/kfr/dft/ft.hpp b/include/kfr/dft/ft.hpp @@ -27,9 +27,9 @@ #include "../base/digitreverse.hpp" #include "../base/read_write.hpp" #include "../base/sin_cos.hpp" +#include "../base/small_buffer.hpp" #include "../base/univector.hpp" #include "../base/vec.hpp" -#include "../misc/small_buffer.hpp" #include "../base/memory.hpp" #include "../data/sincos.hpp" diff --git a/include/kfr/dft/reference_dft.hpp b/include/kfr/dft/reference_dft.hpp @@ -26,8 +26,8 @@ #include "../base/constants.hpp" #include "../base/memory.hpp" #include "../base/read_write.hpp" +#include "../base/small_buffer.hpp" #include "../base/vec.hpp" -#include "../misc/small_buffer.hpp" #include <cmath> namespace kfr diff --git a/include/kfr/misc/compiletime.hpp b/include/kfr/misc/compiletime.hpp @@ -1,81 +0,0 @@ -/** - * Copyright (C) 2016 D Levin (http://www.kfrlib.com) - * This file is part of KFR - * - * KFR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * KFR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KFR. - * - * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. - * Buying a commercial license is mandatory as soon as you develop commercial activities without - * disclosing the source code of your own applications. - * See http://www.kfrlib.com for details. - */ -#pragma once -#include "../base/constants.hpp" -#include "../base/operators.hpp" -#include "../base/types.hpp" - -namespace kfr -{ - -namespace compiletime -{ - -template <typename T> -constexpr inline T select(bool c, T x, T y) -{ - return c ? x : y; -} -template <typename T> -constexpr inline T trunc(T x) -{ - return static_cast<T>(static_cast<long long>(x)); -} -template <typename T> -constexpr inline T abs(T x) -{ - return x < T() ? -x : x; -} -template <typename T> -constexpr inline T mulsign(T x, T y) -{ - return y < T() ? -x : x; -} -template <typename T> -constexpr inline T sin(T x) -{ - x = x - trunc(x / c_pi<T, 2>) * c_pi<T, 2>; - constexpr T c2 = -0.16665853559970855712890625; - constexpr T c4 = +8.31427983939647674560546875e-3; - constexpr T c6 = -1.85423981747590005397796630859375e-4; - - x -= c_pi<T>; - T y = abs(x); - y = select(y > c_pi<T, 1, 2>, c_pi<T> - y, y); - y = mulsign(y, -x); - - const T y2 = y * y; - T formula = c6; - const T y3 = y2 * y; - formula = fmadd(formula, y2, c4); - formula = fmadd(formula, y2, c2); - formula = formula * y3 + y; - return formula; -} -template <typename T> -constexpr inline T cos(T x) -{ - return sin(x + c_pi<T, 1, 2>); -} -} -} diff --git a/include/kfr/misc/random.hpp b/include/kfr/misc/random.hpp @@ -1,180 +0,0 @@ -/** - * Copyright (C) 2016 D Levin (http://www.kfrlib.com) - * This file is part of KFR - * - * KFR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * KFR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KFR. - * - * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. - * Buying a commercial license is mandatory as soon as you develop commercial activities without - * disclosing the source code of your own applications. - * See http://www.kfrlib.com for details. - */ -#pragma once -#include "../base/function.hpp" -#include "../base/operators.hpp" -#include "../base/shuffle.hpp" -#include "../base/vec.hpp" - -namespace kfr -{ - -using random_state = u32x4; - -struct seed_from_rdtsc_t -{ -}; - -constexpr seed_from_rdtsc_t seed_from_rdtsc{}; - -struct random_bit_generator -{ - random_bit_generator(seed_from_rdtsc_t) noexcept - : state(bitcast<u32>(make_vector(__builtin_readcyclecounter(), - (__builtin_readcyclecounter() << 11) ^ 0x710686d615e2257bull))) - { - (void)operator()(); - } - constexpr random_bit_generator(u32 x0, u32 x1, u32 x2, u32 x3) noexcept : state(x0, x1, x2, x3) - { - (void)operator()(); - } - constexpr random_bit_generator(u64 x0, u64 x1) noexcept : state(bitcast<u32>(make_vector(x0, x1))) - { - (void)operator()(); - } - - inline random_state operator()() - { - constexpr static random_state mul{ 214013u, 17405u, 214013u, 69069u }; - constexpr static random_state add{ 2531011u, 10395331u, 13737667u, 1u }; - state = bitcast<u32>(rotateright<3>(bitcast<u8>(fmadd(state, mul, add)))); - return state; - } - -protected: - random_state state; -}; - -template <size_t N, KFR_ENABLE_IF(N <= sizeof(random_state))> -inline vec<u8, N> random_bits(random_bit_generator& gen) -{ - return narrow<N>(bitcast<u8>(gen())); -} -template <size_t N, KFR_ENABLE_IF(N > sizeof(random_state))> -inline vec<u8, N> random_bits(random_bit_generator& gen) -{ - constexpr size_t N2 = prev_poweroftwo(N - 1); - return concat(random_bits<N2>(gen), random_bits<N - N2>(gen)); -} - -template <typename T, size_t N, KFR_ENABLE_IF(std::is_integral<T>::value)> -inline vec<T, N> random_uniform(random_bit_generator& gen) -{ - return bitcast<T>(random_bits<N * sizeof(T)>(gen)); -} - -template <typename T, size_t N, KFR_ENABLE_IF(std::is_same<T, f32>::value)> -inline vec<f32, N> randommantissa(random_bit_generator& gen) -{ - return bitcast<f32>((random_uniform<u32, N>(gen) & 0x7FFFFFu) | 0x3f800000u) + 0.0f; -} - -template <typename T, size_t N, KFR_ENABLE_IF(std::is_same<T, f64>::value)> -inline vec<f64, N> randommantissa(random_bit_generator& gen) -{ - return bitcast<f64>((random_uniform<u64, N>(gen) & 0x000FFFFFFFFFFFFFull) | 0x3FF0000000000000ull) + 0.0; -} - -template <typename T, size_t N> -inline enable_if_f<vec<T, N>> random_uniform(random_bit_generator& gen) -{ - return randommantissa<T, N>(gen) - 1.f; -} - -template <size_t N, typename T> -inline enable_if_f<vec<T, N>> random_range(random_bit_generator& gen, T min, T max) -{ - return mix(random_uniform<T, N>(gen), min, max); -} - -template <size_t N, typename T> -inline enable_if_not_f<vec<T, N>> random_range(random_bit_generator& gen, T min, T max) -{ - using big_type = findinttype<sqr(std::numeric_limits<T>::min()), sqr(std::numeric_limits<T>::max())>; - - vec<T, N> u = random_uniform<T, N>(gen); - const vec<big_type, N> tmp = cast<big_type>(u); - return cast<T>((tmp * (max - min) + min) >> typebits<T>::bits); -} - -namespace internal -{ -template <typename T> -struct expression_random_uniform : input_expression -{ - using value_type = T; - constexpr expression_random_uniform(const random_bit_generator& gen) noexcept : gen(gen) {} - template <typename U, size_t N> - vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const - { - return cast<U>(random_uniform<T, N>(gen)); - } - mutable random_bit_generator gen; -}; - -template <typename T> -struct expression_random_range : input_expression -{ - using value_type = T; - constexpr expression_random_range(const random_bit_generator& gen, T min, T max) noexcept : gen(gen), - min(min), - max(max) - { - } - - template <typename U, size_t N> - vec<U, N> operator()(cinput_t, size_t, vec_t<U, N>) const - { - return cast<U>(random_range<N, T>(gen, min, max)); - } - mutable random_bit_generator gen; - const T min; - const T max; -}; -} - -template <typename T> -inline internal::expression_random_uniform<T> gen_random_uniform(const random_bit_generator& gen) -{ - return internal::expression_random_uniform<T>(gen); -} - -template <typename T> -inline internal::expression_random_range<T> gen_random_range(const random_bit_generator& gen, T min, T max) -{ - return internal::expression_random_range<T>(gen, min, max); -} - -template <typename T> -inline internal::expression_random_uniform<T> gen_random_uniform() -{ - return internal::expression_random_uniform<T>(random_bit_generator(seed_from_rdtsc)); -} - -template <typename T> -inline internal::expression_random_range<T> gen_random_range(T min, T max) -{ - return internal::expression_random_range<T>(random_bit_generator(seed_from_rdtsc), min, max); -} -} diff --git a/include/kfr/misc/small_buffer.hpp b/include/kfr/misc/small_buffer.hpp @@ -1,113 +0,0 @@ -/** - * Copyright (C) 2016 D Levin (http://www.kfrlib.com) - * This file is part of KFR - * - * KFR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * KFR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KFR. - * - * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. - * Buying a commercial license is mandatory as soon as you develop commercial activities without - * disclosing the source code of your own applications. - * See http://www.kfrlib.com for details. - */ -#pragma once - -#include "../base/memory.hpp" -#include <algorithm> -#include <cstdint> - -namespace kfr -{ - -template <typename T, std::size_t Capacity = 16> -struct small_buffer -{ -public: - small_buffer() noexcept : m_size(0), m_data(m_preallocated) {} - - small_buffer(std::size_t size) : small_buffer() { resize(size); } - - friend void swap(small_buffer<T, Capacity>& first, small_buffer<T, Capacity>& second) noexcept - { - using std::swap; - - swap(first.m_size, second.m_size); - swap(first.m_data, second.m_data); - swap(first.m_preallocated, second.m_preallocated); - first.m_data = first.m_size <= Capacity ? first.m_preallocated : first.m_data; - second.m_data = second.m_size <= Capacity ? second.m_preallocated : second.m_data; - } - small_buffer(small_buffer<T, Capacity>&& other) : small_buffer() { swap(other, *this); } - - small_buffer(const small_buffer<T, Capacity>& other) : small_buffer() { assign(other); } - small_buffer<T, Capacity>& operator=(small_buffer<T, Capacity> other) - { - swap(other, *this); - return *this; - } - - ~small_buffer() { clear(); } - - void assign(const small_buffer<T, Capacity>& other) - { - resize(other.m_size); - std::copy_n(other.m_data, m_size, m_data); - } - - void resize(std::size_t newsize) - { - T* m_newdata; - if (newsize <= Capacity) - { - m_newdata = m_preallocated; - } - else - { - m_newdata = aligned_allocate<T>(newsize); - } - std::copy_n(std::make_move_iterator(m_data), std::min(newsize, m_size), m_newdata); - if (m_data != m_preallocated) - aligned_deallocate(m_data); - m_data = m_newdata; - m_size = newsize; - } - bool empty() const { return !size(); } - std::size_t size() const { return m_size; } - const T* begin() const { return m_data; } - const T* end() const { return m_data + m_size; } - const T* cbegin() const { return m_data; } - const T* cend() const { return m_data + m_size; } - T* begin() { return m_data; } - T* end() { return m_data + m_size; } - void clear() { resize(0); } - const T& front() const { return m_data[0]; } - const T& back() const { return m_data[m_size - 1]; } - T& front() { return m_data[0]; } - T& back() { return m_data[m_size - 1]; } - void pop_back() { resize(m_size - 1); } - T* data() { return m_data; } - const T* data() const { return m_data; } - T& operator[](std::size_t i) { return m_data[i]; } - const T& operator[](std::size_t i) const { return m_data[i]; } - void push_back(const T& value) - { - resize(m_size + 1); - m_data[m_size - 1] = value; - } - -protected: - T m_preallocated[Capacity]; - std::size_t m_size; - T* m_data; -}; -} diff --git a/include/kfr/misc/sort.hpp b/include/kfr/misc/sort.hpp @@ -1,96 +0,0 @@ -/** - * Copyright (C) 2016 D Levin (http://www.kfrlib.com) - * This file is part of KFR - * - * KFR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * KFR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KFR. - * - * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. - * Buying a commercial license is mandatory as soon as you develop commercial activities without - * disclosing the source code of your own applications. - * See http://www.kfrlib.com for details. - */ -#pragma once - -#include "../base/min_max.hpp" -#include "../base/shuffle.hpp" -#include "../base/vec.hpp" - -namespace kfr -{ -/** - * Sort the elements in the vector in ascending order - * @param x input vector - * @return sorted vector - * @code - * CHECK(sort(make_vector(1000, 1, 2, -10)) == make_vector(-10, 1, 2, 1000)); - * @endcode - */ -template <typename T, size_t N> -KFR_INLINE vec<T, N> sort(vec<T, N> x) -{ - constexpr size_t Nhalf = N / 2; - vec<T, Nhalf> e = low(x); - vec<T, Nhalf> o = high(x); - constexpr auto blend0 = cconcat(csizes<1>, csizeseq<Nhalf - 1, 0, 0>); - for (size_t i = 0; i < Nhalf; i++) - { - vec<T, Nhalf> t; - t = min(e, o); - o = max(e, o); - o = rotateright<1>(o); - e = t; - t = max(e, o); - o = min(e, o); - e = t; - t = blend(e, o, blend0); - o = blend(o, e, blend0); - o = rotateleft<1>(o); - e = t; - } - return interleavehalfs(concat(e, o)); -} - -/** - * Sort the elements in the vector in descending order - * @param x input vector - * @return sorted vector - * @code - * CHECK(sort(make_vector(1000, 1, 2, -10)) == make_vector(1000, 2, 1, -10)); - * @endcode - */ -template <typename T, size_t N> -KFR_INLINE vec<T, N> sortdesc(vec<T, N> x) -{ - constexpr size_t Nhalf = N / 2; - vec<T, Nhalf> e = low(x); - vec<T, Nhalf> o = high(x); - constexpr auto blend0 = cconcat(csizes<1>, csizeseq<Nhalf - 1, 0, 0>); - for (size_t i = 0; i < Nhalf; i++) - { - vec<T, Nhalf> t; - t = max(e, o); - o = min(e, o); - o = rotateright<1>(o); - e = t; - t = min(e, o); - o = max(e, o); - e = t; - t = blend(e, o, blend0); - o = blend(o, e, blend0); - o = rotateleft<1>(o); - e = t; - } - return interleavehalfs(concat(e, o)); -} -} diff --git a/sources.cmake b/sources.cmake @@ -82,10 +82,10 @@ set( ${PROJECT_SOURCE_DIR}/include/kfr/io/python_plot.hpp ${PROJECT_SOURCE_DIR}/include/kfr/io/tostring.hpp ${PROJECT_SOURCE_DIR}/include/kfr/math.hpp - ${PROJECT_SOURCE_DIR}/include/kfr/misc/compiletime.hpp - ${PROJECT_SOURCE_DIR}/include/kfr/misc/random.hpp - ${PROJECT_SOURCE_DIR}/include/kfr/misc/small_buffer.hpp - ${PROJECT_SOURCE_DIR}/include/kfr/misc/sort.hpp + ${PROJECT_SOURCE_DIR}/include/kfr/base/compiletime.hpp + ${PROJECT_SOURCE_DIR}/include/kfr/base/random.hpp + ${PROJECT_SOURCE_DIR}/include/kfr/base/small_buffer.hpp + ${PROJECT_SOURCE_DIR}/include/kfr/base/sort.hpp ${PROJECT_SOURCE_DIR}/include/kfr/version.hpp ${PROJECT_SOURCE_DIR}/include/kfr/base/kfr.h ${PROJECT_SOURCE_DIR}/include/kfr/base/intrinsics.h diff --git a/tests/dft_test.cpp b/tests/dft_test.cpp @@ -10,6 +10,7 @@ #include <tuple> #include "testo/testo.hpp" +#include <kfr/base/random.hpp> #include <kfr/cometa/string.hpp> #include <kfr/dft/fft.hpp> #include <kfr/dft/reference_dft.hpp> @@ -17,7 +18,6 @@ #include <kfr/expressions/reduce.hpp> #include <kfr/io/tostring.hpp> #include <kfr/math.hpp> -#include <kfr/misc/random.hpp> #include <kfr/version.hpp> using namespace kfr;