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