diff options
| author | Vasile Vilvoiu <vasi.vilvoiu@gmail.com> | 2020-12-29 19:33:03 +0200 |
|---|---|---|
| committer | Vasile Vilvoiu <vasi.vilvoiu@gmail.com> | 2020-12-29 19:33:03 +0200 |
| commit | 26293db40f8ac62f3971e0e9dbbc0bf3439e61c0 (patch) | |
| tree | 218c93aba851c3c3123e9e72d25c974aa65cfd52 /src/input-parser.cpp | |
Initial commit
Diffstat (limited to 'src/input-parser.cpp')
| -rw-r--r-- | src/input-parser.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/input-parser.cpp b/src/input-parser.cpp new file mode 100644 index 0000000..d55661b --- /dev/null +++ b/src/input-parser.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020-2021 Vasile Vilvoiu <vasi.vilvoiu@gmail.com> + * + * specgram is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ +#include "input-parser.hpp" + +#include <cassert> + +InputParser::InputParser(double prescale, bool is_complex) : prescale_factor_(prescale), is_complex_(is_complex) +{ +} + +std::size_t +InputParser::GetBufferedValueCount() const +{ + return values_.size(); +} + +std::vector<Complex> +InputParser::PeekValues(std::size_t count) const +{ + count = std::min<std::size_t>(count, this->values_.size()); + if (count == 0) { + return std::vector<Complex>(); + } + return std::vector<Complex> (this->values_.begin(), this->values_.begin() + count); +} + +void +InputParser::RemoveValues(std::size_t count) +{ + count = std::min<std::size_t>(count, this->values_.size()); + if (count > 0) { + this->values_.erase(this->values_.begin(), this->values_.begin() + count); + } +} + +std::unique_ptr<InputParser> +InputParser::FromDataType(DataType dtype, double prescale, bool is_complex) +{ + if (dtype == DataType::kSignedInt8) { + return std::make_unique<IntegerInputParser<char>>(prescale, is_complex); + } else if (dtype == DataType::kSignedInt16) { + return std::make_unique<IntegerInputParser<short>>(prescale, is_complex); + } else if (dtype == DataType::kSignedInt32) { + return std::make_unique<IntegerInputParser<int>>(prescale, is_complex); + } else if (dtype == DataType::kSignedInt64) { + return std::make_unique<IntegerInputParser<long long>>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt8) { + return std::make_unique<IntegerInputParser<unsigned char>>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt16) { + return std::make_unique<IntegerInputParser<unsigned short>>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt32) { + return std::make_unique<IntegerInputParser<unsigned int>>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt64) { + return std::make_unique<IntegerInputParser<unsigned long long>>(prescale, is_complex); + } else if (dtype == DataType::kFloat32) { + return std::make_unique<FloatInputParser<float>>(prescale, is_complex); + } else if (dtype == DataType::kFloat64) { + return std::make_unique<FloatInputParser<double>>(prescale, is_complex); + } else { + throw std::runtime_error("unknown datatype"); + } +} + +template <class T> +IntegerInputParser<T>::IntegerInputParser(double prescale, bool is_complex) : InputParser(prescale, is_complex) +{ +} + +template <class T> +std::size_t +IntegerInputParser<T>::GetDataTypeSize() const +{ + return sizeof(T) * (this->is_complex_ ? 2 : 1); +} + +template <class T> +std::size_t +IntegerInputParser<T>::ParseBlock(const std::vector<char> &block) +{ + /* this function assumes well structured blocks */ + std::size_t item_size = (this->is_complex_ ? 2 : 1) * sizeof(T); + if (block.size() % item_size != 0) { + throw std::runtime_error("block size must be a multiple of sizeof(datatype)"); + } + + std::size_t count = block.size() / item_size; + const T *start = reinterpret_cast<const T *>(block.data()); + + /* parse one value at a time into complex target */ + for (std::size_t i = 0; i < count; i ++) { + Complex value; + if (this->is_complex_) { + value = Complex(start[i * 2], start[i * 2 + 1]); + } else { + value = Complex(start[i], 0.0f); + } + + /* normalize to domain limit */ + value /= (double)std::numeric_limits<T>::max(); + value *= this->prescale_factor_; + this->values_.emplace_back(value); + } + + return count; +} + +template <class T> +FloatInputParser<T>::FloatInputParser(double prescale, bool is_complex) : InputParser(prescale, is_complex) +{ +} + +template <class T> +std::size_t +FloatInputParser<T>::GetDataTypeSize() const +{ + return sizeof(T) * (this->is_complex_ ? 2 : 1); +} + +template <class T> +std::size_t +FloatInputParser<T>::ParseBlock(const std::vector<char> &block) +{ + /* this function assumes well structured blocks */ + std::size_t item_size = (this->is_complex_ ? 2 : 1) * sizeof(T); + if (block.size() % item_size != 0) { + throw std::runtime_error("block size must be a multiple of sizeof(datatype)"); + } + + std::size_t count = block.size() / item_size; + const T *start = reinterpret_cast<const T *>(block.data()); + + /* parse one value at a time into complex target */ + for (std::size_t i = 0; i < count; i ++) { + Complex value; + /* remove NaNs */ + if (this->is_complex_) { + value = Complex(std::isnan(start[i * 2]) ? 0.0f : start[i * 2], + std::isnan(start[i * 2 + 1]) ? 0.0f : start[i * 2 + 1]); + } else { + value = Complex(std::isnan(start[i]) ? 0.0f : start[i], 0.0f); + } + + /* prescale */ + value *= this->prescale_factor_; + this->values_.emplace_back(value); + } + + return count; +}
\ No newline at end of file |
