1 /** @addtogroup cometa
2  *  @{
3  */
4 #pragma once
5 
6 #include "../cometa.hpp"
7 
8 namespace cometa
9 {
10 
11 /// @brief Short names for common types
12 using b8   = bool;
13 using f32  = float;
14 using f64  = double;
15 using i8   = int8_t;
16 using i16  = int16_t;
17 using i32  = int32_t;
18 using i64  = int64_t;
19 using u8   = uint8_t;
20 using u16  = uint16_t;
21 using u32  = uint32_t;
22 using u64  = uint64_t;
23 using umax = uint64_t;
24 using imax = int64_t;
25 using fmax = double;
26 using f80  = long double;
27 
28 #if defined(CMT_BASETYPE_F32) || defined(CMT_NO_NATIVE_F64)
29 using fbase = float;
30 #else
31 using fbase = double;
32 #endif
33 
34 namespace details
35 {
36 template <typename T>
37 struct fix_type_impl
38 {
39     using type = T;
40 };
41 
42 template <>
43 struct fix_type_impl<char>
44 {
45     using type = i8;
46 };
47 
48 template <>
49 struct fix_type_impl<unsigned long>
50 {
51 #if ULONG_MAX == ULLONG_MAX
52     using type = u64;
53 #else
54     using type = u32;
55 #endif
56 };
57 
58 template <>
59 struct fix_type_impl<signed long>
60 {
61 #if LONG_MAX == LLONG_MAX
62     using type = i64;
63 #else
64     using type = i32;
65 #endif
66 };
67 
68 template <>
69 struct fix_type_impl<unsigned long long>
70 {
71     using type = u64;
72 };
73 
74 template <>
75 struct fix_type_impl<signed long long>
76 {
77     using type = i64;
78 };
79 
80 } // namespace details
81 
82 template <typename T>
83 using fix_type = typename details::fix_type_impl<T>::type;
84 
85 /// @brief An enumeration representing data type
86 enum class datatype : int
87 {
88     typebits_mask  = 0xFF,
89     f              = 0x100, // floating point
90     i              = 0x200, // signed integer
91     u              = 0x300, // unsigned integer
92     c              = 0x400, // complex floating point
93     b              = 0x500, // boolean
94     typeclass_mask = 0xF00,
95     f16            = static_cast<int>(f) | 16,
96     f32            = static_cast<int>(f) | 32,
97     f64            = static_cast<int>(f) | 64,
98     f80            = static_cast<int>(f) | 80,
99     i8             = static_cast<int>(i) | 8,
100     i16            = static_cast<int>(i) | 16,
101     i24            = static_cast<int>(i) | 24,
102     i32            = static_cast<int>(i) | 32,
103     i64            = static_cast<int>(i) | 64,
104     u8             = static_cast<int>(u) | 8,
105     u16            = static_cast<int>(u) | 16,
106     u24            = static_cast<int>(u) | 24,
107     u32            = static_cast<int>(u) | 32,
108     u64            = static_cast<int>(u) | 64,
109     c32            = static_cast<int>(c) | 32,
110     c64            = static_cast<int>(c) | 64,
111     b8             = static_cast<int>(b) | 8
112 };
113 
operator |(datatype x,datatype y)114 constexpr inline datatype operator|(datatype x, datatype y)
115 {
116     using type = underlying_type<datatype>;
117     return static_cast<datatype>(static_cast<type>(x) | static_cast<type>(y));
118 }
119 
operator &(datatype x,datatype y)120 constexpr inline datatype operator&(datatype x, datatype y)
121 {
122     using type = underlying_type<datatype>;
123     return static_cast<datatype>(static_cast<type>(x) & static_cast<type>(y));
124 }
125 
126 template <typename T>
127 constexpr inline datatype typeclass = is_floating_point<typename compound_type_traits<T>::subtype>
128                                           ? datatype::f
129                                           : is_integral<typename compound_type_traits<T>::subtype>
130                                                 ? (is_unsigned<typename compound_type_traits<T>::subtype>
131                                                        ? datatype::u
132                                                        : datatype::i)
133                                                 : datatype();
134 
135 template <typename T>
136 constexpr inline bool is_f_class = typeclass<T> == datatype::f;
137 template <typename T>
138 constexpr inline bool is_u_class = typeclass<T> == datatype::u;
139 template <typename T>
140 constexpr inline bool is_i_class = typeclass<T> == datatype::i;
141 
142 template <typename T>
143 struct typebits
144 {
145     constexpr static size_t bits  = sizeof(typename compound_type_traits<T>::subtype) * 8;
146     constexpr static size_t width = compound_type_traits<T>::is_scalar ? 0 : compound_type_traits<T>::width;
147     using subtype                 = typename compound_type_traits<T>::subtype;
148 };
149 
150 template <typename T>
151 using ftype =
152     typename compound_type_traits<T>::template deep_rebind<float_type<typebits<deep_subtype<T>>::bits>>;
153 template <typename T>
154 using itype =
155     typename compound_type_traits<T>::template deep_rebind<int_type<typebits<deep_subtype<T>>::bits>>;
156 template <typename T>
157 using utype =
158     typename compound_type_traits<T>::template deep_rebind<unsigned_type<typebits<deep_subtype<T>>::bits>>;
159 
160 template <typename T>
161 using uitype = conditional<is_i_class<deep_subtype<T>>, T, utype<T>>;
162 
163 template <typename T>
164 using fsubtype = ftype<subtype<T>>;
165 template <typename T>
166 using isubtype = itype<subtype<T>>;
167 template <typename T>
168 using usubtype = utype<subtype<T>>;
169 namespace details
170 {
171 template <typename T>
172 struct flt_type_impl
173 {
174     using type = conditional<sizeof(T) <= 2, float, fbase>;
175 };
176 
177 template <>
178 struct flt_type_impl<float>
179 {
180     using type = float;
181 };
182 template <>
183 struct flt_type_impl<double>
184 {
185     using type = double;
186 };
187 } // namespace details
188 
189 template <typename T>
190 using flt_type = typename cometa::compound_type_traits<T>::template deep_rebind<
191     typename details::flt_type_impl<deep_subtype<T>>::type>;
192 
193 } // namespace cometa
194