12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- #ifndef COMMONAVERAGER_H_E6A1FBFD
- #define COMMONAVERAGER_H_E6A1FBFD
- #include <iostream>
- #include <numeric>
- #include <type_traits>
- #include "CereConnBaseTypes.h"
- #include "CereConnHelpers.h"
- namespace cc
- {
-
- template<typename T, typename V = std::vector<T>>
- class CommonAverager
- {
- public:
- using ContinuousDataSampleT = T; //!< data type of samples
- using ContinuousDataSampleVT = V; //!< type of item that will be stored in RingBufferT
-
- explicit CommonAverager (const ChannelNumList_t &car_ch_map);
- explicit CommonAverager (ChannelNumList_t &&car_ch_map);
- virtual ~CommonAverager () {}
-
- void operator()(V &v);
- private:
- // this picks a type for calculation: a larger integer type for integer, or just the same for everything else (floating point)
- using TempT = typename std::conditional<std::is_integral<T>::value, smallest_larger_integral_t<typename std::conditional<std::is_integral<T>::value, T, int>::type>, T>::type;
-
- // clamp subtraction for unsigned integer sample types T. Necessary to prevent underflow if sample value is less than average
- template <typename Q = T>
- typename std::enable_if<std::is_integral<Q>::value && std::is_unsigned<Q>::value, Q>::type minus(Q x, Q y)
- {
- Q res = x - y;
- res &= -(res <= x);
- return res;
- }
- // standard subtraction for all other sample types T
- template <typename Q = T>
- typename std::enable_if<std::is_floating_point<Q>::value || std::is_signed<Q>::value, Q>::type minus(Q x, Q y)
- {
- return x - y;
- }
-
- ChannelNumList_t m_car_channel_map;
- #ifdef CC_TESTING_DEBUG
- FRIEND_TEST(CommonAverager, Constructor1);
- FRIEND_TEST(CommonAverager, Constructor2);
- #endif
- };
- template<typename T, typename V>
- CommonAverager<T, V>::CommonAverager(const ChannelNumList_t &car_ch_map)
- : m_car_channel_map(car_ch_map)
- {
- }
- template<typename T, typename V>
- CommonAverager<T, V>::CommonAverager(ChannelNumList_t &&car_ch_map)
- : m_car_channel_map(std::move(car_ch_map))
- {
- }
- template<typename T, typename V>
- void CommonAverager<T, V>::operator()(V &v)
- {
- if (m_car_channel_map.size() == 0)
- {
- return;
- }
- TempT sum = std::accumulate(m_car_channel_map.cbegin(), m_car_channel_map.cend(),
- static_cast<TempT>(0),
- [&v](TempT n, ChannelNumCont_t i){
- return n + static_cast<TempT>(v[i]);
- });
- T avg = sum / static_cast<TempT>(m_car_channel_map.size());
- for (auto &w:v)
- {
- w = minus<>(w, avg);
- }
- }
- } /* cc */
- #endif /* end of include guard: COMMONAVERAGER_H_E6A1FBFD */
|