ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
IEEE754_SingleConverter.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#pragma once
4
6
7#include <boost/numeric/conversion/cast.hpp>
8
9#include <memory.h>
10
11#include <cfloat> // for float limits
12
13namespace ChimeraTK {
14
15 template<typename SourceType, typename DestType>
18 template<class S>
19 struct Round {
20 static S nearbyint(S s) { return round(s); }
21
22 using round_style = boost::mpl::integral_c<std::float_round_style, std::round_to_nearest>;
23 };
24
25 using converter =
26 boost::numeric::converter<DestType, SourceType, boost::numeric::conversion_traits<DestType, SourceType>,
27 boost::numeric::def_overflow_handler, Round<SourceType>>;
28 };
29
30 template<typename SourceType>
32 struct converter {
33 static Void convert(__attribute__((unused)) SourceType s) { return {}; }
34 };
35 };
36
37 template<typename DestType>
39 struct converter {
40 static DestType convert(__attribute__((unused)) Void s) { return 0.0; }
41 };
42 };
43
48 template<typename CookedType, typename RAW_ITERATOR, typename COOKED_ITERATOR>
50 const RAW_ITERATOR& raw_begin, const RAW_ITERATOR& raw_end, const COOKED_ITERATOR& cooked_begin) const {
51 // Note: IEEE754_SingleConverter must be instantiable for all raw user types but can only be used for int32_t
52 assert((std::is_same<typename std::iterator_traits<RAW_ITERATOR>::value_type, int32_t>::value));
53 static_assert(std::is_same<typename std::iterator_traits<RAW_ITERATOR>::value_type, int8_t>::value ||
54 std::is_same<typename std::iterator_traits<RAW_ITERATOR>::value_type, int16_t>::value ||
55 std::is_same<typename std::iterator_traits<RAW_ITERATOR>::value_type, int32_t>::value,
56 "RAW_ITERATOR template argument must be an iterator with value type equal to int8_t, int16_t or int32_t.");
57 static_assert(std::is_same<typename std::iterator_traits<COOKED_ITERATOR>::value_type, CookedType>::value,
58 "COOKED_ITERATOR template argument must be an iterator with value type equal to the CookedType template "
59 "argument.");
61 }
62
63 template<typename CookedType, typename RAW_ITERATOR, typename COOKED_ITERATOR>
65 static void impl(const RAW_ITERATOR& raw_begin, const RAW_ITERATOR& raw_end, COOKED_ITERATOR cooked_begin);
66 };
67
69 template<typename CookedType>
70 CookedType scalarToCooked(int32_t const& raw) const {
71 CookedType cooked;
72 vectorToCooked<CookedType>(&raw, (&raw) + 1, &cooked);
73 return cooked;
74 }
75
76 template<typename CookedType>
77 uint32_t toRaw(CookedType cookedValue) const;
78
79 explicit IEEE754_SingleConverter(const std::string& = "") {}
80
81 // all IEEE754_SingleConverters are the same
82 bool operator!=(const IEEE754_SingleConverter& /*other*/) const { return false; }
83 bool operator==(const IEEE754_SingleConverter& /*other*/) const { return true; }
84 };
85
86 template<typename CookedType, typename RAW_ITERATOR, typename COOKED_ITERATOR>
88 const RAW_ITERATOR& raw_begin, const RAW_ITERATOR& raw_end, COOKED_ITERATOR cooked_begin) {
89 for(auto it = raw_begin; it != raw_end; ++it) {
90 // Step 1: convert the raw data to the "generic" representation in the CPU: float
91 float genericRepresentation;
92 memcpy(&genericRepresentation, &(*it), sizeof(float));
93
94 // Step 2: convert the float to the cooked type
96 ++cooked_begin;
97 }
98 }
99
100 template<typename CookedType>
101 uint32_t IEEE754_SingleConverter::toRaw(CookedType cookedValue) const {
102 // step 1: convert from cooked to the generic representation in the CPU
103 // (float)
104 float genericRepresentation;
105 try {
107 }
108 catch(boost::numeric::positive_overflow&) {
109 genericRepresentation = FLT_MAX;
110 }
111 catch(boost::numeric::negative_overflow&) {
112 genericRepresentation = -FLT_MAX;
113 }
114
115 // step 2: reinterpret float to int32 to send it to the device
116 void* warningAvoider = &genericRepresentation;
117 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
118 int32_t rawValue = *(reinterpret_cast<int32_t*>(warningAvoider));
119
120 return rawValue;
121 }
122
123 template<typename RAW_ITERATOR, typename COOKED_ITERATOR>
124 struct IEEE754_SingleConverter::vectorToCooked_impl<std::string, RAW_ITERATOR, COOKED_ITERATOR> {
125 static void impl(const RAW_ITERATOR& raw_begin, const RAW_ITERATOR& raw_end, COOKED_ITERATOR cooked_begin) {
126 for(auto it = raw_begin; it != raw_end; ++it) {
127 // Step 1: convert the raw data to the "generic" representation in the CPU: float
128 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
129 float genericRepresentation = *(reinterpret_cast<const float*>(&(*it)));
130
131 // Step 2: convert the float to the cooked type
132 *cooked_begin = std::to_string(genericRepresentation);
133 ++cooked_begin;
134 }
135 }
136 };
137
138 template<>
139 [[nodiscard]] uint32_t IEEE754_SingleConverter::toRaw(std::string cookedValue) const;
140
141} // namespace ChimeraTK
Wrapper Class for void.
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
STL namespace.
std::string to_string(const std::string &v)
static void impl(const RAW_ITERATOR &raw_begin, const RAW_ITERATOR &raw_end, COOKED_ITERATOR cooked_begin)
static void impl(const RAW_ITERATOR &raw_begin, const RAW_ITERATOR &raw_end, COOKED_ITERATOR cooked_begin)
Needs to have the same interface as FixedPointConverter, except for the constructor.
IEEE754_SingleConverter(const std::string &="")
bool operator!=(const IEEE754_SingleConverter &) const
CookedType scalarToCooked(int32_t const &raw) const
Inefficient convenience function for converting a single value to cooked.
uint32_t toRaw(CookedType cookedValue) const
bool operator==(const IEEE754_SingleConverter &) const
void vectorToCooked(const RAW_ITERATOR &raw_begin, const RAW_ITERATOR &raw_end, const COOKED_ITERATOR &cooked_begin) const
define round type for the boost::numeric::converter
boost::mpl::integral_c< std::float_round_style, std::round_to_nearest > round_style
boost::numeric::converter< DestType, SourceType, boost::numeric::conversion_traits< DestType, SourceType >, boost::numeric::def_overflow_handler, Round< SourceType > > converter