CNL  2.0.2 (development)
Compositional Numeric Library
op.h
Go to the documentation of this file.
1 
2 // Copyright John McFarlane 2019.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file ../LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
9 
10 #if !defined(CNL_IMPL_OPERATORS_OPERATORS_H)
11 #define CNL_IMPL_OPERATORS_OPERATORS_H
12 
13 #include "../config.h"
14 
15 #include <type_traits>
16 
18 namespace cnl {
19  namespace _impl {
21  // operation tags
22 
23  struct convert_op {
24  template<class Destination, class Source>
25  [[nodiscard]] constexpr auto operator()(Source const& source) const
26  {
27  return static_cast<Destination>(source);
28  }
29  };
30 
31  struct minus_op {
32  template<class Rhs>
33  [[nodiscard]] constexpr auto operator()(Rhs const& rhs) const
34  {
35  return -rhs;
36  }
37  };
38 
39  struct plus_op {
40  template<class Rhs>
41  [[nodiscard]] constexpr auto operator()(Rhs const& rhs) const
42  {
43  return +rhs;
44  }
45  };
46 
47  struct bitwise_not_op {
48  template<class Rhs>
49  [[nodiscard]] constexpr auto operator()(Rhs const& rhs) const
50  {
51  return ~rhs;
52  }
53  };
54 
55  struct add_op {
56  template<class Lhs, class Rhs>
57  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
58  {
59  return lhs + rhs;
60  }
61  };
62 
63  struct subtract_op {
64  template<class Lhs, class Rhs>
65  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
66  {
67  return lhs - rhs;
68  }
69  };
70 
71  struct multiply_op {
72  template<class Lhs, class Rhs>
73  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
74  {
75  return lhs * rhs;
76  }
77  };
78 
79  struct divide_op {
80  template<class Lhs, class Rhs>
81  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
82  {
83  return lhs / rhs;
84  }
85  };
86 
87  struct modulo_op {
88  template<class Lhs, class Rhs>
89  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
90  {
91  return lhs % rhs;
92  }
93  };
94 
95  struct bitwise_or_op {
96  template<class Lhs, class Rhs>
97  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
98  {
99  return lhs | rhs;
100  }
101  };
102 
103  struct bitwise_and_op {
104  template<class Lhs, class Rhs>
105  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
106  {
107  return lhs & rhs;
108  }
109  };
110 
111  struct bitwise_xor_op {
112  template<class Lhs, class Rhs>
113  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
114  {
115  return lhs ^ rhs;
116  }
117  };
118 
119  struct shift_left_op {
120  template<class Lhs, class Rhs>
121  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
122  {
123  return lhs << rhs;
124  }
125  };
126 
127  struct shift_right_op {
128  template<class Lhs, class Rhs>
129  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
130  {
131  return lhs >> rhs;
132  }
133  };
134 
135  struct equal_op {
136  template<class Lhs, class Rhs>
137  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
138  {
139  return lhs == rhs;
140  }
141  };
142 
143  struct not_equal_op {
144  template<class Lhs, class Rhs>
145  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
146  {
147  return lhs != rhs;
148  }
149  };
150 
151  struct less_than_op {
152  template<class Lhs, class Rhs>
153  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
154  {
155  return lhs < rhs; // NOLINT(hicpp-use-nullptr,modernize-use-nullptr)
156  }
157  };
158 
159  struct greater_than_op {
160  template<class Lhs, class Rhs>
161  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
162  {
163  return lhs > rhs; // NOLINT(hicpp-use-nullptr,modernize-use-nullptr)
164  }
165  };
166 
167  struct less_than_or_equal_op {
168  template<class Lhs, class Rhs>
169  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
170  {
171  return lhs <= rhs; // NOLINT(hicpp-use-nullptr,modernize-use-nullptr)
172  }
173  };
174 
175  struct greater_than_or_equal_op {
176  template<class Lhs, class Rhs>
177  [[nodiscard]] constexpr auto operator()(Lhs const& lhs, Rhs const& rhs) const
178  {
179  return lhs >= rhs; // NOLINT(hicpp-use-nullptr,modernize-use-nullptr)
180  }
181  };
182 
183  struct pre_increment_op {
184  template<class Rhs>
185  constexpr auto operator()(Rhs& rhs) const
186  {
187  return ++rhs;
188  }
189  };
190 
191  struct pre_decrement_op {
192  template<class Rhs>
193  constexpr auto operator()(Rhs& rhs) const
194  {
195  return --rhs;
196  }
197  };
198 
199  struct post_increment_op {
200  template<class Lhs>
201  constexpr auto operator()(Lhs& lhs) const
202  {
203  return lhs++;
204  }
205  };
206 
207  struct post_decrement_op {
208  template<class Lhs>
209  constexpr auto operator()(Lhs& lhs) const
210  {
211  return lhs--;
212  }
213  };
214 
215 #if defined(__GNUC__)
216 // GCC warns against short+=short and short-=short
217 #pragma GCC diagnostic push
218 #pragma GCC diagnostic ignored "-Wconversion"
219 #elif defined(_MSC_VER)
220 #pragma warning(push)
221 #pragma warning(disable : 4244)
222 #endif
223  struct assign_add_op {
224  using binary = add_op;
225 
226  template<class Lhs, class Rhs>
227  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
228  {
229  return lhs += rhs;
230  }
231  };
232 
233  struct assign_subtract_op {
234  using binary = subtract_op;
235 
236  template<class Lhs, class Rhs>
237  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
238  {
239  return lhs -= rhs;
240  }
241  };
242 #if defined(__GNUC__)
243 #pragma GCC diagnostic pop
244 #elif defined(_MSC_VER)
245 #pragma warning(pop)
246 #endif
247 
248  struct assign_multiply_op {
249  using binary = multiply_op;
250 
251  template<class Lhs, class Rhs>
252  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
253  {
254  return lhs *= rhs;
255  }
256  };
257 
258  struct assign_divide_op {
259  using binary = divide_op;
260 
261  template<class Lhs, class Rhs>
262  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
263  {
264  return lhs /= rhs;
265  }
266  };
267 
268  struct assign_modulo_op {
269  using binary = modulo_op;
270 
271  template<class Lhs, class Rhs>
272  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
273  {
274  return lhs %= rhs;
275  }
276  };
277 
278  struct assign_bitwise_or_op {
279  using binary = bitwise_or_op;
280 
281  template<class Lhs, class Rhs>
282  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
283  {
284  return lhs |= rhs;
285  }
286  };
287 
288  struct assign_bitwise_and_op {
289  using binary = bitwise_and_op;
290 
291  template<class Lhs, class Rhs>
292  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
293  {
294  return lhs &= rhs;
295  }
296  };
297 
298  struct assign_bitwise_xor_op {
299  using binary = bitwise_xor_op;
300 
301  template<class Lhs, class Rhs>
302  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
303  {
304  return lhs ^= rhs;
305  }
306  };
307 
308  struct assign_shift_left_op {
309  using binary = shift_left_op;
310 
311  template<class Lhs, class Rhs>
312  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
313  {
314  return lhs <<= rhs;
315  }
316  };
317 
318  struct assign_shift_right_op {
319  using binary = shift_right_op;
320 
321  template<class Lhs, class Rhs>
322  constexpr auto operator()(Lhs& lhs, Rhs const& rhs) const
323  {
324  return lhs >>= rhs;
325  }
326  };
327 
329  // operator trait/concept
330 
331  template<class T>
332  inline constexpr auto is_unary_arithmetic_op = false;
333  template<>
334  inline constexpr auto is_unary_arithmetic_op<minus_op> = true;
335  template<>
336  inline constexpr auto is_unary_arithmetic_op<plus_op> = true;
337  template<>
338  inline constexpr auto is_unary_arithmetic_op<bitwise_not_op> = true;
339 
340  template<class T>
341  inline constexpr auto is_binary_arithmetic_op = false;
342  template<>
343  inline constexpr auto is_binary_arithmetic_op<add_op> = true;
344  template<>
345  inline constexpr auto is_binary_arithmetic_op<subtract_op> = true;
346  template<>
347  inline constexpr auto is_binary_arithmetic_op<multiply_op> = true;
348  template<>
349  inline constexpr auto is_binary_arithmetic_op<divide_op> = true;
350  template<>
351  inline constexpr auto is_binary_arithmetic_op<modulo_op> = true;
352  template<>
353  inline constexpr auto is_binary_arithmetic_op<bitwise_or_op> = true;
354  template<>
355  inline constexpr auto is_binary_arithmetic_op<bitwise_and_op> = true;
356  template<>
357  inline constexpr auto is_binary_arithmetic_op<bitwise_xor_op> = true;
358 
359  template<class T>
360  inline constexpr auto is_shift_op = false;
361  template<>
362  inline constexpr auto is_shift_op<shift_left_op> = true;
363  template<>
364  inline constexpr auto is_shift_op<shift_right_op> = true;
365 
366  template<class T>
367  inline constexpr auto is_comparison_op = false;
368  template<>
369  inline constexpr auto is_comparison_op<equal_op> = true;
370  template<>
371  inline constexpr auto is_comparison_op<not_equal_op> = true;
372  template<>
373  inline constexpr auto is_comparison_op<less_than_op> = true;
374  template<>
375  inline constexpr auto is_comparison_op<greater_than_op> = true;
376  template<>
377  inline constexpr auto is_comparison_op<less_than_or_equal_op> = true;
378  template<>
379  inline constexpr auto is_comparison_op<greater_than_or_equal_op> = true;
380 
381  template<class T>
382  inline constexpr auto is_binary_op = is_binary_arithmetic_op<T> || is_shift_op<T> || is_comparison_op<T>;
383 
384  template<class T>
385  inline constexpr auto is_prefix_op = false;
386  template<>
387  inline constexpr auto is_prefix_op<pre_increment_op> = true;
388  template<>
389  inline constexpr auto is_prefix_op<pre_decrement_op> = true;
390 
391  template<class T>
392  inline constexpr auto is_postfix_op = false;
393  template<>
394  inline constexpr auto is_postfix_op<post_increment_op> = true;
395  template<>
396  inline constexpr auto is_postfix_op<post_decrement_op> = true;
397 
398  template<class T>
399  inline constexpr auto is_compound_assign_op = false;
400  template<>
401  inline constexpr auto is_compound_assign_op<assign_add_op> = true;
402  template<>
403  inline constexpr auto is_compound_assign_op<assign_subtract_op> = true;
404  template<>
405  inline constexpr auto is_compound_assign_op<assign_multiply_op> = true;
406  template<>
407  inline constexpr auto is_compound_assign_op<assign_divide_op> = true;
408  template<>
409  inline constexpr auto is_compound_assign_op<assign_modulo_op> = true;
410  template<>
411  inline constexpr auto is_compound_assign_op<assign_bitwise_or_op> = true;
412  template<>
413  inline constexpr auto is_compound_assign_op<assign_bitwise_and_op> = true;
414  template<>
415  inline constexpr auto is_compound_assign_op<assign_bitwise_xor_op> = true;
416  template<>
417  inline constexpr auto is_compound_assign_op<assign_shift_left_op> = true;
418  template<>
419  inline constexpr auto is_compound_assign_op<assign_shift_right_op> = true;
420 
421  template<class T>
422  inline constexpr auto is_op = is_unary_arithmetic_op<T> || is_binary_arithmetic_op<T> || is_shift_op<T> || is_comparison_op<T> || is_prefix_op<T> || is_postfix_op<T> || is_compound_assign_op<T>;
423  template<>
424  inline constexpr auto is_op<convert_op> = true;
425 
426  template<class T>
427  concept unary_arithmetic_op = is_unary_arithmetic_op<T>;
428  template<class T>
429  concept binary_arithmetic_op = is_binary_arithmetic_op<T>;
430  template<class T>
431  concept shift_op = is_shift_op<T>;
432  template<class T>
433  concept comparison_op = is_comparison_op<T>;
434  template<class T>
435  concept binary_op = is_binary_op<T>;
436  template<class T>
437  concept prefix_op = is_prefix_op<T>;
438  template<class T>
439  concept postfix_op = is_postfix_op<T>;
440  template<class T>
441  concept compound_assign_op = is_compound_assign_op<T>;
442  template<typename T>
443  concept op = is_op<T>;
444 
446  // cnl::_impl::op_result
447 
448  template<op Operator, class... Operands>
449  using op_result = decltype(Operator()(std::declval<Operands>()...));
450 
452  // type transformations from increment/decrement to compound add/subtract
453 
454  template<prefix_op Operator>
455  struct pre_to_assign;
456 
457  template<>
458  struct pre_to_assign<pre_increment_op> : std::type_identity<assign_add_op> {
459  };
460 
461  template<>
462  struct pre_to_assign<pre_decrement_op> : std::type_identity<assign_subtract_op> {
463  };
464 
465  template<postfix_op Operator>
466  struct post_to_assign;
467 
468  template<>
469  struct post_to_assign<post_increment_op> : std::type_identity<assign_add_op> {
470  };
471 
472  template<>
473  struct post_to_assign<post_decrement_op> : std::type_identity<assign_subtract_op> {
474  };
475  }
476 }
477 
478 #endif // CNL_IMPL_OPERATORS_OPERATORS_H
cnl
compositional numeric library
Definition: abort.h:15