OGLplus  (0.59.0) a C++ wrapper for rendering APIs

detail.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_UNITS_DETAIL_HPP
10 #define EAGINE_UNITS_DETAIL_HPP
11 
12 #include "../mp_arithmetic.hpp"
13 #include "../type_identity.hpp"
14 #include "base_dim.hpp"
15 #include "fwd.hpp"
16 #include "scales.hpp"
17 
18 namespace eagine::units::bits {
19 
20 // collapse_tail
21 template <typename X>
22 struct collapse_tail : type_identity<X> {};
23 
24 template <typename X>
25 using collapse_tail_t = typename collapse_tail<X>::type;
26 
27 // dim_pow
28 template <typename Dim, int Pow>
29 struct dim_pow {
30  using dim = Dim;
31  using pow = int_constant<Pow>;
32 };
33 
34 // dims
35 template <typename Head, typename Tail>
36 struct dims {
37  using type = dims;
38 };
39 
40 using dimless = dims<nothing_t, nothing_t>;
41 
42 template <>
43 struct collapse_tail<dims<nothing_t, nothing_t>> : nothing_t {};
44 
45 // pow_of_dim
46 template <typename D, typename Dims>
47 struct pow_of_dim;
48 
49 template <typename D, typename Dims>
50 constexpr int pow_of_dim_v = pow_of_dim<D, Dims>::value;
51 
52 template <typename D>
53 struct pow_of_dim<D, nothing_t> : int_constant<0> {};
54 
55 template <typename D>
56 struct pow_of_dim<D, dimless> : int_constant<0> {};
57 
58 template <typename D, int P, typename T>
59 struct pow_of_dim<D, dims<dim_pow<D, P>, T>> : int_constant<P> {};
60 
61 template <typename D1, typename D2, int P, typename T>
62 struct pow_of_dim<D1, dims<dim_pow<D2, P>, T>> : pow_of_dim<D1, T> {};
63 
64 // get_pow_of_dim
65 template <typename D, typename H, typename T>
66 static constexpr auto get_pow_of_dim(base::dimension<D>, dims<H, T>) noexcept
67  -> int {
68  return pow_of_dim_v<D, dims<H, T>>;
69 }
70 
71 // dim_add
72 template <typename Dims1, typename Dims2>
73 struct dim_add;
74 
75 template <typename Dims1, typename Dims2>
76 using dim_add_t = typename dim_add<Dims1, Dims2>::type;
77 
78 template <>
79 struct dim_add<nothing_t, nothing_t> : nothing_t {};
80 
81 template <typename H, typename T>
82 struct dim_add<nothing_t, dims<H, T>> : dims<H, T> {};
83 
84 template <typename H, typename T>
85 struct dim_add<dims<H, T>, nothing_t> : dims<H, T> {};
86 
87 template <>
88 struct dim_add<dimless, dimless> : dimless {};
89 
90 template <typename H, typename T>
91 struct dim_add<dims<H, T>, dimless> : dims<H, T> {};
92 
93 template <typename H, typename T>
94 struct dim_add<dimless, dims<H, T>> : dims<H, T> {};
95 
96 template <typename Dim, int Pow1, typename Tail1, int Pow2, typename Tail2>
97 struct dim_add<dims<dim_pow<Dim, Pow1>, Tail1>, dims<dim_pow<Dim, Pow2>, Tail2>>
98  : std::conditional_t<
99  (Pow1 + Pow2 == 0),
100  dim_add_t<Tail1, Tail2>,
101  dims<dim_pow<Dim, Pow1 + Pow2>, collapse_tail_t<dim_add_t<Tail1, Tail2>>>> {
102 };
103 
104 template <
105  typename Dim1,
106  int Pow1,
107  typename Tail1,
108  typename Dim2,
109  int Pow2,
110  typename Tail2>
111 struct dim_add<dims<dim_pow<Dim1, Pow1>, Tail1>, dims<dim_pow<Dim2, Pow2>, Tail2>>
112  : std::conditional_t<
113  (base::dim_num_v<Dim1> < base::dim_num_v<Dim2>),
114  dims<
115  dim_pow<Dim1, Pow1>,
116  collapse_tail_t<dim_add_t<Tail1, dims<dim_pow<Dim2, Pow2>, Tail2>>>>,
117  dims<
118  dim_pow<Dim2, Pow2>,
119  collapse_tail_t<dim_add_t<dims<dim_pow<Dim1, Pow1>, Tail1>, Tail2>>>> {
120 };
121 
122 // dim_sub
123 template <typename Dims1, typename Dims2>
124 struct dim_sub;
125 
126 template <typename Dims1, typename Dims2>
127 using dim_sub_t = typename dim_sub<Dims1, Dims2>::type;
128 
129 template <>
130 struct dim_sub<nothing_t, nothing_t> : dimless {};
131 
132 template <>
133 struct dim_sub<nothing_t, dimless> : dimless {};
134 
135 template <typename H, typename T>
136 struct dim_sub<dims<H, T>, nothing_t> : dims<H, T> {};
137 
138 template <typename D, int P, typename T>
139 struct dim_sub<nothing_t, dims<dim_pow<D, P>, T>>
140  : dims<dim_pow<D, -P>, collapse_tail_t<dim_sub_t<nothing_t, T>>> {};
141 
142 template <>
143 struct dim_sub<dimless, dimless> : dimless {};
144 
145 template <typename H, typename T>
146 struct dim_sub<dims<H, T>, dimless> : dims<H, T> {};
147 
148 template <typename D, int P, typename T>
149 struct dim_sub<dimless, dims<dim_pow<D, P>, T>>
150  : dims<dim_pow<D, -P>, collapse_tail_t<dim_sub_t<nothing_t, T>>> {};
151 
152 template <typename Dim, int Pow1, typename Tail1, int Pow2, typename Tail2>
153 struct dim_sub<dims<dim_pow<Dim, Pow1>, Tail1>, dims<dim_pow<Dim, Pow2>, Tail2>>
154  : std::conditional_t<
155  (Pow1 - Pow2 == 0),
156  dim_sub_t<Tail1, Tail2>,
157  dims<dim_pow<Dim, Pow1 - Pow2>, collapse_tail_t<dim_sub_t<Tail1, Tail2>>>> {
158 };
159 
160 template <
161  typename Dim1,
162  int Pow1,
163  typename Tail1,
164  typename Dim2,
165  int Pow2,
166  typename Tail2>
167 struct dim_sub<dims<dim_pow<Dim1, Pow1>, Tail1>, dims<dim_pow<Dim2, Pow2>, Tail2>>
168  : std::conditional_t<
169  (base::dim_num_v<Dim1> < base::dim_num_v<Dim2>),
170  dims<
171  dim_pow<Dim1, Pow1>,
172  collapse_tail_t<dim_sub_t<Tail1, dims<dim_pow<Dim2, Pow2>, Tail2>>>>,
173  dims<
174  dim_pow<Dim2, -Pow2>,
175  collapse_tail_t<dim_sub_t<dims<dim_pow<Dim1, Pow1>, Tail1>, Tail2>>>> {
176 };
177 
178 // get_pow
179 template <typename Dims, typename Dim>
180 struct get_pow;
181 
182 // get_pow
183 template <typename Dim>
184 struct get_pow<nothing_t, Dim> : int_constant<0> {};
185 
186 // get_pow
187 template <typename Dim>
188 struct get_pow<dimless, Dim> : int_constant<0> {};
189 
190 // get_pow
191 template <typename H, typename T, typename Dim>
192 struct get_pow<dims<H, T>, Dim> : get_pow<T, Dim> {};
193 
194 // get_pow
195 template <typename Dim, int Pow, typename T>
196 struct get_pow<dims<dim_pow<Dim, Pow>, T>, Dim> : int_constant<Pow> {};
197 
198 // uni_sca
199 template <typename Unit, typename Scale>
200 struct uni_sca;
201 
202 template <typename Head, typename Tail>
203 struct unit_scales {
204  using type = unit_scales;
205 };
206 
207 template <>
208 struct collapse_tail<unit_scales<nothing_t, nothing_t>> : nothing_t {};
209 
210 // insert
211 template <typename UnitScales, typename Unit, typename Scale>
212 struct insert;
213 
214 template <typename UnitScales, typename Unit, typename Scale>
215 using insert_t = typename insert<UnitScales, Unit, Scale>::type;
216 
217 template <typename U, typename S>
218 struct insert<nothing_t, U, S> : unit_scales<uni_sca<U, S>, nothing_t> {};
219 
220 template <typename U, typename S>
221 struct insert<unit_scales<nothing_t, nothing_t>, U, S>
222  : unit_scales<uni_sca<U, S>, nothing_t> {};
223 
224 template <typename U, typename SO, typename SN, typename T>
225 struct insert<unit_scales<uni_sca<U, SO>, T>, U, SN>
226  : unit_scales<uni_sca<U, SN>, T> {};
227 
228 template <typename H, typename T, typename U, typename S>
229 struct insert<unit_scales<H, T>, U, S> : unit_scales<H, insert_t<T, U, S>> {};
230 
231 // get_scale
232 template <typename UnitScales, typename Unit, typename Fallback>
233 struct get_scale;
234 
235 template <typename UnitScales, typename Unit, typename Fallback>
236 using get_scale_t = typename get_scale<UnitScales, Unit, Fallback>::type;
237 
238 template <typename U, typename Fallback>
239 struct get_scale<nothing_t, U, Fallback> : Fallback {};
240 
241 template <typename U, typename Fallback>
242 struct get_scale<unit_scales<nothing_t, nothing_t>, U, Fallback> : Fallback {};
243 
244 template <typename U, typename Scale, typename T, typename F>
245 struct get_scale<unit_scales<uni_sca<U, Scale>, T>, U, F> : Scale {};
246 
247 template <typename U, typename S1, typename S2, typename T, typename F>
248 struct get_scale<unit_scales<uni_sca<U, S1>, T>, base::scaled_unit<S2, U>, F>
249  : scales::divided<S1, S2> {};
250 
251 template <typename H, typename T, typename U, typename F>
252 struct get_scale<unit_scales<H, T>, U, F> : get_scale<T, U, F> {};
253 
254 // get_dim_unit
255 template <typename UnitScales, typename BaseDim, typename Fallback>
256 struct get_dim_unit;
257 
258 template <typename BD, typename Fallback>
259 struct get_dim_unit<nothing_t, BD, Fallback> : Fallback {};
260 
261 template <typename BD, typename Fallback>
262 struct get_dim_unit<unit_scales<nothing_t, nothing_t>, BD, Fallback>
263  : Fallback {};
264 
265 template <typename U, typename S, typename T, typename BD, typename F>
266 struct get_dim_unit<unit_scales<uni_sca<U, S>, T>, BD, F>
267  : std::conditional_t<
268  std::is_same_v<dimension_of_t<U>, BD>,
269  base::scaled_unit<S, U>,
270  typename get_dim_unit<T, BD, F>::type> {};
271 
272 // merge
273 template <typename UnitConv1, typename UnitConv2>
274 struct merge;
275 
276 template <typename UnitConv1, typename UnitConv2>
277 using merge_t = typename merge<UnitConv1, UnitConv2>::type;
278 
279 template <>
280 struct merge<nothing_t, nothing_t> : unit_scales<nothing_t, nothing_t> {};
281 
282 template <>
283 struct merge<unit_scales<nothing_t, nothing_t>, unit_scales<nothing_t, nothing_t>>
284  : unit_scales<nothing_t, nothing_t> {};
285 
286 template <typename H, typename T>
287 struct merge<unit_scales<H, T>, nothing_t> : unit_scales<H, T> {};
288 
289 template <typename H, typename T>
290 struct merge<nothing_t, unit_scales<H, T>> : unit_scales<H, T> {};
291 
292 template <typename H, typename T>
293 struct merge<unit_scales<H, T>, unit_scales<nothing_t, nothing_t>>
294  : unit_scales<H, T> {};
295 
296 template <typename H, typename T>
297 struct merge<unit_scales<nothing_t, nothing_t>, unit_scales<H, T>>
298  : unit_scales<H, T> {};
299 
300 template <typename U, typename S1, typename S2, typename T1, typename T2>
301 struct merge<unit_scales<uni_sca<U, S1>, T1>, unit_scales<uni_sca<U, S2>, T2>>
302  : unit_scales<uni_sca<U, S1>, collapse_tail_t<merge_t<T1, T2>>> {};
303 
304 template <
305  typename U1,
306  typename U2,
307  typename S1,
308  typename S2,
309  typename T1,
310  typename T2>
311 struct merge<unit_scales<uni_sca<U1, S1>, T1>, unit_scales<uni_sca<U2, S2>, T2>>
312  : std::conditional_t<
313  (base::dim_num_v<dimension_of_t<U1>> <
314  base::dim_num_v<dimension_of_t<U2>>),
315  unit_scales<
316  uni_sca<U1, S1>,
317  collapse_tail_t<merge_t<T1, unit_scales<uni_sca<U2, S2>, T2>>>>,
318  unit_scales<
319  uni_sca<U2, S2>,
320  collapse_tail_t<merge_t<unit_scales<uni_sca<U1, S1>, T1>, T2>>>> {};
321 
322 // _sc_unit_sc_hlp
323 template <typename Scales, typename System>
324 struct _sc_unit_sc_hlp {
325 
326  template <typename T, typename SV>
327  static constexpr auto _pow(T v, SV, int_constant<0>) {
328  return v;
329  }
330 
331  template <typename T, typename S, int E>
332  static constexpr auto _pow(T v, S s, int_constant<E>) {
333  return _pow(
334  (E > 0) ? S::to_base(v) : S::from_base(v),
335  s,
336  int_constant<E + ((E > 0) ? -1 : 1)>());
337  }
338 
339  template <typename Dir, typename T>
340  static constexpr auto _hlp(Dir, T v) noexcept -> T {
341  return v;
342  }
343 
344  template <typename Dir, typename T>
345  static constexpr auto _hlp(Dir d, T v, nothing_t) noexcept -> T {
346  return _hlp(d, v);
347  }
348 
349  template <typename Dir, typename T>
350  static constexpr auto _hlp(Dir d, T v, dimless) noexcept -> T {
351  return _hlp(d, v);
352  }
353 
354  template <typename Dir, typename T, typename D, int E>
355  static constexpr auto _hlp2(Dir, T v, dim_pow<D, E>) noexcept {
356  using SBU = typename System ::template base_unit<D>::type;
357  using BS = scales::scale_of_t<SBU>;
358 
359  return _pow(
360  v,
361  get_scale_t<Scales, SBU, BS>(),
362  int_constant<(Dir::value ? E : -E)>());
363  }
364 
365  template <typename Dir, typename T, typename D, int P, typename Dims>
366  static constexpr auto
367  _hlp(Dir dir, T v, dims<dim_pow<D, P>, Dims>) noexcept {
368  return _hlp(dir, _hlp2(dir, v, dim_pow<D, P>()), Dims());
369  }
370 };
371 
372 } // namespace eagine::units::bits
373 
374 #endif // EAGINE_UNITS_DETAIL_HPP
std::integral_constant< int, I > int_constant
Alias for signed int constant type.
Definition: int_constant.hpp:25

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).