From 26293db40f8ac62f3971e0e9dbbc0bf3439e61c0 Mon Sep 17 00:00:00 2001 From: Vasile Vilvoiu Date: Tue, 29 Dec 2020 19:33:03 +0200 Subject: Initial commit --- src/input-parser.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/input-parser.cpp (limited to 'src/input-parser.cpp') 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 + * + * 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 + +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 +InputParser::PeekValues(std::size_t count) const +{ + count = std::min(count, this->values_.size()); + if (count == 0) { + return std::vector(); + } + return std::vector (this->values_.begin(), this->values_.begin() + count); +} + +void +InputParser::RemoveValues(std::size_t count) +{ + count = std::min(count, this->values_.size()); + if (count > 0) { + this->values_.erase(this->values_.begin(), this->values_.begin() + count); + } +} + +std::unique_ptr +InputParser::FromDataType(DataType dtype, double prescale, bool is_complex) +{ + if (dtype == DataType::kSignedInt8) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kSignedInt16) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kSignedInt32) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kSignedInt64) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt8) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt16) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt32) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kUnsignedInt64) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kFloat32) { + return std::make_unique>(prescale, is_complex); + } else if (dtype == DataType::kFloat64) { + return std::make_unique>(prescale, is_complex); + } else { + throw std::runtime_error("unknown datatype"); + } +} + +template +IntegerInputParser::IntegerInputParser(double prescale, bool is_complex) : InputParser(prescale, is_complex) +{ +} + +template +std::size_t +IntegerInputParser::GetDataTypeSize() const +{ + return sizeof(T) * (this->is_complex_ ? 2 : 1); +} + +template +std::size_t +IntegerInputParser::ParseBlock(const std::vector &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(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::max(); + value *= this->prescale_factor_; + this->values_.emplace_back(value); + } + + return count; +} + +template +FloatInputParser::FloatInputParser(double prescale, bool is_complex) : InputParser(prescale, is_complex) +{ +} + +template +std::size_t +FloatInputParser::GetDataTypeSize() const +{ + return sizeof(T) * (this->is_complex_ ? 2 : 1); +} + +template +std::size_t +FloatInputParser::ParseBlock(const std::vector &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(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 -- cgit v1.2.3