1/* Copyright (C) 2014 Povilas Kanapickas <povilas@radix.lt>
2
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*/
7
8#ifndef LIBSIMDPP_SIMDPP_CORE_DETAIL_GET_EXPR_BITWISE_H
9#define LIBSIMDPP_SIMDPP_CORE_DETAIL_GET_EXPR_BITWISE_H
10
11#include <simdpp/detail/get_expr.h>
12
13namespace simdpp {
14namespace SIMDPP_ARCH_NAMESPACE {
15namespace detail {
16
17
18/* We want to reduce the number of overloads that need to be created in order
19 to match a specific case of an expression tree containing 'bit_and',
20 or 'bit_andnot'. nodes. The following "optimizations"
21 are performed:
22
23 * If the parameters are types have different element sizes then both
24 expression arguments have the same type as the expression itself, except
25 that signed vectors are converted to unsigned vectors.
26 * Otherwise if the expression is of a mask type then both types are the
27 same as the expression itself.
28 * Otherwise both types have the same type as the expression itself, except
29 that signed vectors are converted to unsigned vectors and if the second
30 type is a mask type then it is converted to floating-point mask if the
31 expression is floating-point expression and to integer mask otherwise.
32
33 So, as a result, the following tuples of types will appear as the arguments
34 of the returned expression:
35
36 * mask_int8, mask_int8
37 * uint8, mask_int8
38 * uint8, uint8
39 * mask_int16, mask_int16
40 * uint16, mask_int16
41 * uint16, uint16
42 * mask_int32, mask_int32
43 * uint32, mask_int32
44 * uint32, uint32
45 * mask_int64, mask_int64
46 * uint64, mask_int64
47 * uint64, uint64
48 * mask_float32, mask_float32
49 * float32, mask_float32
50 * float32, float32
51 * mask_float64, mask_float64
52 * float64, mask_float64
53 * float64, float64
54
55 The type of the returned expression is governed by the usual rules
56 (see simdpp/types/tag.h)
57*/
58
59template<class V1, class V2>
60struct get_expr_bitwise2_and_impl {
61 using tags = expr2_maybe_scalar_tags<V1, V2>;
62
63 // (size_tag) get the size tag of the resulting expression
64 static const unsigned size_tag = tags::v1_size_tag > tags::v2_size_tag
65 ? tags::v1_size_tag : tags::v2_size_tag;
66
67 // (type_tag) get the type tag of the expression. We compute it in the same
68 // way get_expr2 computes them, i.e.
69 // type_tag == get_expr2<V1,V2>::type::type_tag
70 static const unsigned type_tag_t1 = tags::v1_type_tag > tags::v2_type_tag
71 ? tags::v1_type_tag : tags::v2_type_tag;
72 static const bool is_mask_op1 = type_tag_t1 == SIMDPP_TAG_MASK_INT ||
73 type_tag_t1 == SIMDPP_TAG_MASK_FLOAT;
74 static const unsigned type_tag = (is_mask_op1 && tags::v1_size_tag != tags::v2_size_tag)
75 ? SIMDPP_TAG_UINT : type_tag_t1;
76
77 // strip signed integer types
78 static const unsigned v1_type_tag = type_tag == SIMDPP_TAG_INT ? SIMDPP_TAG_UINT : type_tag;
79
80
81 static const bool is_v2_mask = tags::v2_type_tag == SIMDPP_TAG_MASK_INT ||
82 tags::v2_type_tag == SIMDPP_TAG_MASK_FLOAT;
83 static const bool is_v1_float = type_tag == SIMDPP_TAG_FLOAT ||
84 type_tag == SIMDPP_TAG_MASK_FLOAT;
85
86 // if second parameter is a mask, then:
87 // - convert the mask to float mask if the expression is float
88 // - convert the mask to integer mask otherwise
89 static const unsigned v2_type_tag = (!is_v2_mask) ? v1_type_tag :
90 is_v1_float ? SIMDPP_TAG_MASK_FLOAT :
91 SIMDPP_TAG_MASK_INT;
92
93 using v1_final_type = typename type_of_tag<v1_type_tag + size_tag,
94 tags::length_bytes, void>::type;
95 using v2_final_type = typename type_of_tag<v2_type_tag + size_tag,
96 tags::length_bytes, void>::type;
97};
98
99template<template<class, class> class E, class V1, class V2>
100struct get_expr_bitwise2_and {
101 using impl = get_expr_bitwise2_and_impl<V1, V2>;
102 using type = typename type_of_tag<impl::type_tag + impl::size_tag,
103 impl::tags::length_bytes,
104 E<V1, V2>>::type;
105};
106
107
108/* The case with bit_or is similar to bit_and and bit_andnot except that the
109 expression types are either leave two masks or none.
110
111 * Both expression arguments have the same type as the expression itself,
112 except that signed vectors are converted to unsigned vectors.
113
114 So, as a result, the following tuples of types will appear as the arguments
115 of the returned expression:
116
117 * mask_int8, mask_int8
118 * uint8, uint8
119 * mask_int16, mask_int16
120 * uint16, uint16
121 * mask_int32, mask_int32
122 * uint32, uint32
123 * mask_int64, mask_int64
124 * uint64, uint64
125 * mask_float32, mask_float32
126 * float32, float32
127 * mask_float64, mask_float64
128 * float64, float64
129
130 The type of the returned expression is governed by the usual rules
131 (see simdpp/types/tag.h)
132*/
133
134template<class V1, class V2>
135class get_expr_bit_or {
136
137 // (size_tag) get the size tag of the resulting expression
138 static const unsigned size_tag = V1::size_tag > V2::size_tag ? V1::size_tag : V2::size_tag;
139
140 // (type_tag) get the type tag of the expression. We compute it in the same
141 // way get_expr2 computes them, i.e.
142 // type_tag == get_expr2<V1,V2>::type::type_tag
143 static const unsigned type_tag_t1 = V1::type_tag > V2::type_tag ? V1::type_tag : V2::type_tag;
144 static const bool is_mask_op1 = type_tag_t1 == SIMDPP_TAG_MASK_INT ||
145 type_tag_t1 == SIMDPP_TAG_MASK_FLOAT;
146 static const unsigned type_tag = (is_mask_op1 && V1::size_tag != V2::size_tag)
147 ? SIMDPP_TAG_UINT : type_tag_t1;
148
149 // strip signed integer types
150 static const unsigned v12_type_tag = type_tag == SIMDPP_TAG_INT ? SIMDPP_TAG_UINT : type_tag;
151
152
153public:
154 using v1_final_type = typename type_of_tag<v12_type_tag + size_tag,
155 V1::length_bytes, void>::type;
156 using v2_final_type = typename type_of_tag<v12_type_tag + size_tag,
157 V1::length_bytes, void>::type;
158
159 using type = typename type_of_tag<type_tag + size_tag, V1::length_bytes,
160 expr_bit_or<V1, V2>>::type;
161};
162
163
164
165} // namespace detail
166} // namespace SIMDPP_ARCH_NAMESPACE
167} // namespace simdpp
168
169#endif
170