1 | /* Copyright (C) 2013-2017 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_TO_INT64_H |
9 | #define LIBSIMDPP_SIMDPP_CORE_TO_INT64_H |
10 | |
11 | #ifndef LIBSIMDPP_SIMD_H |
12 | #error "This file must be included through simd.h" |
13 | #endif |
14 | |
15 | #include <simdpp/types.h> |
16 | #include <simdpp/capabilities.h> |
17 | #include <simdpp/detail/insn/conv_extend_to_int64.h> |
18 | #include <simdpp/detail/insn/conv_float_to_int64.h> |
19 | #include <simdpp/detail/not_implemented.h> |
20 | |
21 | namespace simdpp { |
22 | namespace SIMDPP_ARCH_NAMESPACE { |
23 | |
24 | /** Converts elements within a vector to 64-bit signed values. |
25 | |
26 | The conversion rules are as follows: |
27 | 32-bit and narrower signed integers are sign-extended to 32 bits. |
28 | 32-bit and narrower unsigned integers are zero-extended to 32 bits. |
29 | floating-point numbers are converted to integer values and truncated. |
30 | If floating-point value can not be represented in 64-bit signed integer, |
31 | the behavior is different for different instruction sets. |
32 | |
33 | SSE specific: |
34 | If the value can not be represented by int64_t, @c 0x8000000000000000 |
35 | is returned |
36 | |
37 | @code |
38 | r0 = (int64_t) a0 |
39 | ... |
40 | rN = (int64_t) aN |
41 | @endcode |
42 | */ |
43 | template<unsigned N, class E> SIMDPP_INL |
44 | int64<N,expr_empty> to_int64(const int8<N,E>& a) |
45 | { |
46 | return detail::insn::i_to_int64(a.eval()); |
47 | } |
48 | template<unsigned N, class E> SIMDPP_INL |
49 | int64<N,expr_empty> to_int64(const uint8<N,E>& a) |
50 | { |
51 | return (int64<N>) detail::insn::i_to_uint64(a.eval()); |
52 | } |
53 | template<unsigned N, class E> SIMDPP_INL |
54 | int64<N,expr_empty> to_int64(const int16<N,E>& a) |
55 | { |
56 | return detail::insn::i_to_int64(a.eval()); |
57 | } |
58 | template<unsigned N, class E> SIMDPP_INL |
59 | int64<N,expr_empty> to_int64(const uint16<N,E>& a) |
60 | { |
61 | return (int64<N>) detail::insn::i_to_uint64(a.eval()); |
62 | } |
63 | template<unsigned N, class E> SIMDPP_INL |
64 | int64<N,expr_empty> to_int64(const int32<N,E>& a) |
65 | { |
66 | return detail::insn::i_to_int64(a.eval()); |
67 | } |
68 | template<unsigned N, class E> SIMDPP_INL |
69 | int64<N,expr_empty> to_int64(const uint32<N,E>& a) |
70 | { |
71 | return (int64<N>) detail::insn::i_to_uint64(a.eval()); |
72 | } |
73 | template<unsigned N, class E> SIMDPP_INL |
74 | int64<N,expr_empty> to_int64(const int64<N,E>& a) |
75 | { |
76 | return a; |
77 | } |
78 | template<unsigned N, class E> SIMDPP_INL |
79 | int64<N,expr_empty> to_int64(const uint64<N,E>& a) |
80 | { |
81 | return int64<N>(a.eval()); |
82 | } |
83 | template<unsigned N, class E> SIMDPP_INL |
84 | int64<N,expr_empty> to_int64(const float32<N,E>& a) |
85 | { |
86 | #if SIMDPP_HAS_FLOAT32_TO_INT64_CONVERSION |
87 | return detail::insn::i_to_int64(a.eval()); |
88 | #else |
89 | return SIMDPP_NOT_IMPLEMENTED_TEMPLATE1(E, a); |
90 | #endif |
91 | } |
92 | template<unsigned N, class E> SIMDPP_INL |
93 | int64<N,expr_empty> to_int64(const float64<N,E>& a) |
94 | { |
95 | #if SIMDPP_HAS_FLOAT64_TO_INT64_CONVERSION |
96 | return detail::insn::i_to_int64(a.eval()); |
97 | #else |
98 | return SIMDPP_NOT_IMPLEMENTED_TEMPLATE1(E, a); |
99 | #endif |
100 | } |
101 | |
102 | /** Converts elements within a vector to 64-bit unsigned values. |
103 | |
104 | The conversion rules are as follows: |
105 | 32-bit and narrower signed integers are sign-extended to 32 bits. |
106 | 32-bit and narrower unsigned integers are zero-extended to 32 bits. |
107 | If floating-point value can not be represented in 64-bit unsigned integer, |
108 | the behavior is different for different instruction sets. |
109 | |
110 | SSE specific: |
111 | If the value can not be represented by uint64_t, @c 0x8000000000000000 |
112 | is returned |
113 | @todo NaN handling |
114 | |
115 | @code |
116 | r0 = (uint64_t) a0 |
117 | ... |
118 | rN = (uint64_t) aN |
119 | @endcode |
120 | */ |
121 | template<unsigned N, class E> SIMDPP_INL |
122 | uint64<N,expr_empty> to_uint64(const int8<N,E>& a) |
123 | { |
124 | return (uint64<N>) detail::insn::i_to_int64(a.eval()); |
125 | } |
126 | template<unsigned N, class E> SIMDPP_INL |
127 | uint64<N,expr_empty> to_uint64(const uint8<N,E>& a) |
128 | { |
129 | return detail::insn::i_to_uint64(a.eval()); |
130 | } |
131 | template<unsigned N, class E> SIMDPP_INL |
132 | uint64<N,expr_empty> to_uint64(const int16<N,E>& a) |
133 | { |
134 | return (uint64<N>) detail::insn::i_to_int64(a.eval()); |
135 | } |
136 | template<unsigned N, class E> SIMDPP_INL |
137 | uint64<N,expr_empty> to_uint64(const uint16<N,E>& a) |
138 | { |
139 | return detail::insn::i_to_uint64(a.eval()); |
140 | } |
141 | template<unsigned N, class E> SIMDPP_INL |
142 | uint64<N,expr_empty> to_uint64(const int32<N,E>& a) |
143 | { |
144 | return (uint64<N>) detail::insn::i_to_int64(a.eval()); |
145 | } |
146 | template<unsigned N, class E> SIMDPP_INL |
147 | uint64<N,expr_empty> to_uint64(const uint32<N,E>& a) |
148 | { |
149 | return detail::insn::i_to_uint64(a.eval()); |
150 | } |
151 | template<unsigned N, class E> SIMDPP_INL |
152 | uint64<N,expr_empty> to_uint64(const int64<N,E>& a) |
153 | { |
154 | return uint64<N>(a.eval()); |
155 | } |
156 | template<unsigned N, class E> SIMDPP_INL |
157 | uint64<N,expr_empty> to_uint64(const uint64<N,E>& a) |
158 | { |
159 | return a.eval(); |
160 | } |
161 | template<unsigned N, class E> SIMDPP_INL |
162 | uint64<N,expr_empty> to_uint64(const float32<N,E>& a) |
163 | { |
164 | #if SIMDPP_HAS_FLOAT32_TO_UINT64_CONVERSION |
165 | return detail::insn::i_to_uint64(a.eval()); |
166 | #else |
167 | return SIMDPP_NOT_IMPLEMENTED_TEMPLATE1(E, a); |
168 | #endif |
169 | } |
170 | template<unsigned N, class E> SIMDPP_INL |
171 | uint64<N,expr_empty> to_uint64(const float64<N,E>& a) |
172 | { |
173 | #if SIMDPP_HAS_FLOAT64_TO_UINT64_CONVERSION |
174 | return detail::insn::i_to_uint64(a.eval()); |
175 | #else |
176 | return SIMDPP_NOT_IMPLEMENTED_TEMPLATE1(E, a); |
177 | #endif |
178 | } |
179 | |
180 | |
181 | } // namespace SIMDPP_ARCH_NAMESPACE |
182 | } // namespace simdpp |
183 | |
184 | #endif |
185 | |
186 | |