Line | Branch | Exec | Source |
---|---|---|---|
1 | // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de> | ||
2 | // SPDX-License-Identifier: MIT | ||
3 | /*! | ||
4 | * \file | ||
5 | * \ingroup Common | ||
6 | * \brief Types to represent different precisions. | ||
7 | */ | ||
8 | #ifndef GRIDFORMAT_COMMON_PRECISION_HPP_ | ||
9 | #define GRIDFORMAT_COMMON_PRECISION_HPP_ | ||
10 | |||
11 | #include <cstdint> | ||
12 | #include <variant> | ||
13 | #include <utility> | ||
14 | #include <type_traits> | ||
15 | #include <concepts> | ||
16 | #include <ostream> | ||
17 | |||
18 | #include <gridformat/common/type_traits.hpp> | ||
19 | #include <gridformat/common/concepts.hpp> | ||
20 | |||
21 | namespace GridFormat { | ||
22 | |||
23 | /*! | ||
24 | * \ingroup Common | ||
25 | * \brief Represents a precision known at compile-time | ||
26 | */ | ||
27 | template<Concepts::Scalar _T> | ||
28 | struct Precision { using T = _T; }; | ||
29 | |||
30 | using Float32 = Precision<float>; | ||
31 | using Float64 = Precision<double>; | ||
32 | inline constexpr Float32 float32; | ||
33 | inline constexpr Float64 float64; | ||
34 | |||
35 | using Int8 = Precision<std::int_least8_t>; | ||
36 | using Int16 = Precision<std::int_least16_t>; | ||
37 | using Int32 = Precision<std::int_least32_t>; | ||
38 | using Int64 = Precision<std::int_least64_t>; | ||
39 | inline constexpr Int8 int8; | ||
40 | inline constexpr Int16 int16; | ||
41 | inline constexpr Int32 int32; | ||
42 | inline constexpr Int64 int64; | ||
43 | |||
44 | using UInt8 = Precision<std::uint_least8_t>; | ||
45 | using UInt16 = Precision<std::uint_least16_t>; | ||
46 | using UInt32 = Precision<std::uint_least32_t>; | ||
47 | using UInt64 = Precision<std::uint_least64_t>; | ||
48 | inline constexpr UInt8 uint8; | ||
49 | inline constexpr UInt16 uint16; | ||
50 | inline constexpr UInt32 uint32; | ||
51 | inline constexpr UInt64 uint64; | ||
52 | |||
53 | /*! | ||
54 | * \ingroup Common | ||
55 | * \brief Represents a dynamic precision. | ||
56 | * \note This can only represent the precisions predefined in this header. | ||
57 | */ | ||
58 | class DynamicPrecision { | ||
59 | public: | ||
60 | 159852 | DynamicPrecision() = default; | |
61 | |||
62 | template<typename T> | ||
63 | 1023582 | DynamicPrecision(Precision<T> prec) | |
64 | 1023582 | : _precision{std::move(prec)} | |
65 | 1023582 | {} | |
66 | |||
67 | 139170 | bool is_integral() const { | |
68 | 417510 | return std::visit([] <typename T> (const Precision<T>&) { | |
69 | 278340 | return std::is_integral_v<T>; | |
70 |
1/2✓ Branch 1 taken 139170 times.
✗ Branch 2 not taken.
|
278340 | }, _precision); |
71 | } | ||
72 | |||
73 | 18811 | bool is_signed() const { | |
74 | 56433 | return std::visit([] <typename T> (const Precision<T>&) { | |
75 | 37622 | return std::is_signed_v<T>; | |
76 |
1/2✓ Branch 1 taken 18811 times.
✗ Branch 2 not taken.
|
37622 | }, _precision); |
77 | } | ||
78 | |||
79 | 326458 | std::size_t size_in_bytes() const { | |
80 | 979374 | return std::visit([] <typename T> (const Precision<T>&) { | |
81 | 652916 | return sizeof(T); | |
82 |
1/2✓ Branch 1 taken 326458 times.
✗ Branch 2 not taken.
|
652916 | }, _precision); |
83 | } | ||
84 | |||
85 | template<typename T> | ||
86 | 21482 | bool is() const { | |
87 | 64446 | return std::visit([] <typename _T> (const Precision<_T>&) { | |
88 | 21482 | return std::is_same_v<_T, T>; | |
89 |
1/2✓ Branch 1 taken 21482 times.
✗ Branch 2 not taken.
|
42964 | }, _precision); |
90 | } | ||
91 | |||
92 | template<typename Visitor> | ||
93 | 223462 | decltype(auto) visit(Visitor&& visitor) const { | |
94 | 223462 | return std::visit(std::forward<Visitor>(visitor), _precision); | |
95 | } | ||
96 | |||
97 | 1125 | bool operator==(const DynamicPrecision& other) const { | |
98 | 1125 | return _precision.index() == other._precision.index(); | |
99 | } | ||
100 | |||
101 | 10 | friend std::ostream& operator<<(std::ostream& s, const DynamicPrecision& prec) { | |
102 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
30 | prec.visit([&] <typename T> (Precision<T>) { |
103 | if constexpr (std::is_same_v<T, char>) | ||
104 | ✗ | s << "char"; | |
105 | else if constexpr (std::signed_integral<T>) | ||
106 | 8 | s << "int" << sizeof(T)*8; | |
107 | else if constexpr (std::unsigned_integral<T>) | ||
108 | 8 | s << "uint" << sizeof(T)*8; | |
109 | else | ||
110 | 4 | s << "float" << sizeof(T)*8; | |
111 | 20 | }); | |
112 | 10 | return s; | |
113 | } | ||
114 | |||
115 | private: | ||
116 | UniqueVariant< | ||
117 | Precision<float>, | ||
118 | Precision<double>, | ||
119 | Precision<std::int8_t>, | ||
120 | Precision<std::int16_t>, | ||
121 | Precision<std::int32_t>, | ||
122 | Precision<std::int64_t>, | ||
123 | Precision<std::uint8_t>, | ||
124 | Precision<std::uint16_t>, | ||
125 | Precision<std::uint32_t>, | ||
126 | Precision<std::uint64_t>, | ||
127 | Precision<std::size_t>, | ||
128 | Precision<char> | ||
129 | > _precision; | ||
130 | }; | ||
131 | |||
132 | } // namespace GridFormat | ||
133 | |||
134 | #endif // GRIDFORMAT_COMMON_PRECISION_HPP_ | ||
135 |