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 | using Boolean = Precision<bool>; | ||
54 | inline constexpr Boolean boolean; | ||
55 | |||
56 | /*! | ||
57 | * \ingroup Common | ||
58 | * \brief Represents a dynamic precision. | ||
59 | * \note This can only represent the precisions predefined in this header. | ||
60 | */ | ||
61 | class DynamicPrecision { | ||
62 | public: | ||
63 | 160064 | DynamicPrecision() = default; | |
64 | |||
65 | template<typename T> | ||
66 | 1024594 | DynamicPrecision(Precision<T> prec) | |
67 | 1024594 | : _precision{std::move(prec)} | |
68 | 1024594 | {} | |
69 | |||
70 | 139220 | bool is_integral() const { | |
71 | 417660 | return std::visit([] <typename T> (const Precision<T>&) { | |
72 | 278440 | return std::is_integral_v<T>; | |
73 |
1/2✓ Branch 1 taken 139220 times.
✗ Branch 2 not taken.
|
278440 | }, _precision); |
74 | } | ||
75 | |||
76 | 18834 | bool is_signed() const { | |
77 | 56502 | return std::visit([] <typename T> (const Precision<T>&) { | |
78 | 37668 | return std::is_signed_v<T>; | |
79 |
1/2✓ Branch 1 taken 18834 times.
✗ Branch 2 not taken.
|
37668 | }, _precision); |
80 | } | ||
81 | |||
82 | 326721 | std::size_t size_in_bytes() const { | |
83 | 980163 | return std::visit([] <typename T> (const Precision<T>&) { | |
84 | 653442 | return sizeof(T); | |
85 |
1/2✓ Branch 1 taken 326721 times.
✗ Branch 2 not taken.
|
653442 | }, _precision); |
86 | } | ||
87 | |||
88 | template<typename T> | ||
89 | 21488 | bool is() const { | |
90 | 64464 | return std::visit([] <typename _T> (const Precision<_T>&) { | |
91 | 21488 | return std::is_same_v<_T, T>; | |
92 |
1/2✓ Branch 1 taken 21488 times.
✗ Branch 2 not taken.
|
42976 | }, _precision); |
93 | } | ||
94 | |||
95 | template<typename Visitor> | ||
96 | 223801 | decltype(auto) visit(Visitor&& visitor) const { | |
97 | 223801 | return std::visit(std::forward<Visitor>(visitor), _precision); | |
98 | } | ||
99 | |||
100 | 1127 | bool operator==(const DynamicPrecision& other) const { | |
101 | 1127 | return _precision.index() == other._precision.index(); | |
102 | } | ||
103 | |||
104 | 11 | friend std::ostream& operator<<(std::ostream& s, const DynamicPrecision& prec) { | |
105 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
33 | prec.visit([&] <typename T> (Precision<T>) { |
106 | if constexpr (std::is_same_v<T, char>) | ||
107 | ✗ | s << "char"; | |
108 | else if constexpr (std::signed_integral<T>) | ||
109 | 8 | s << "int" << sizeof(T)*8; | |
110 | else if constexpr (std::unsigned_integral<T>) | ||
111 | 10 | s << "uint" << sizeof(T)*8; | |
112 | else | ||
113 | 4 | s << "float" << sizeof(T)*8; | |
114 | 22 | }); | |
115 | 11 | return s; | |
116 | } | ||
117 | |||
118 | private: | ||
119 | UniqueVariant< | ||
120 | Precision<float>, | ||
121 | Precision<double>, | ||
122 | Precision<std::int8_t>, | ||
123 | Precision<std::int16_t>, | ||
124 | Precision<std::int32_t>, | ||
125 | Precision<std::int64_t>, | ||
126 | Precision<std::uint8_t>, | ||
127 | Precision<std::uint16_t>, | ||
128 | Precision<std::uint32_t>, | ||
129 | Precision<std::uint64_t>, | ||
130 | Precision<std::size_t>, | ||
131 | Precision<char>, | ||
132 | Precision<bool> | ||
133 | > _precision; | ||
134 | }; | ||
135 | |||
136 | } // namespace GridFormat | ||
137 | |||
138 | #endif // GRIDFORMAT_COMMON_PRECISION_HPP_ | ||
139 |