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_INT32_H
9#define LIBSIMDPP_SIMDPP_CORE_TO_INT32_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_int32.h>
18#include <simdpp/detail/insn/conv_shrink_to_int32.h>
19#include <simdpp/detail/insn/conv_float_to_int32.h>
20#include <simdpp/detail/not_implemented.h>
21
22namespace simdpp {
23namespace SIMDPP_ARCH_NAMESPACE {
24
25/** Converts elements within a vector to 32-bit signed values.
26
27 The conversion rules are as follows:
28 16-bit and narrower signed integers are sign-extended to 32 bits.
29 16-bit and narrower unsigned integers are zero-extended to 32 bits.
30 64-bit integers are truncated.
31 floating-point numbers are converted to integer values and truncated.
32 If floating-point value can not be represented in 32-bit signed integer,
33 the behavior is different for different instruction sets.
34
35 SSE specific:
36 If the value can not be represented by int32_t, @c 0x80000000 is returned
37 TODO: NaN handling
38
39 NEON, ALTIVEC specific:
40 If the value can not be represented by int32_t, either @c 0x80000000 or @c
41 0x7fffffff is returned depending on the sign of the operand (saturation
42 occurs). Conversion of NaNs results in @a 0.
43
44 @code
45 r0 = (int32_t) a0
46 ...
47 rN = (int32_t) aN
48 @endcode
49*/
50template<unsigned N, class E> SIMDPP_INL
51int32<N,expr_empty> to_int32(const int8<N,E>& a)
52{
53 return detail::insn::i_to_int32(a.eval());
54}
55template<unsigned N, class E> SIMDPP_INL
56int32<N,expr_empty> to_int32(const uint8<N,E>& a)
57{
58 return (int32<N>) detail::insn::i_to_uint32(a.eval());
59}
60template<unsigned N, class E> SIMDPP_INL
61int32<N,expr_empty> to_int32(const int16<N,E>& a)
62{
63 return detail::insn::i_to_int32(a.eval());
64}
65template<unsigned N, class E> SIMDPP_INL
66int32<N,expr_empty> to_int32(const uint16<N,E>& a)
67{
68 return (int32<N>) detail::insn::i_to_uint32(a.eval());
69}
70template<unsigned N, class E> SIMDPP_INL
71int32<N,expr_empty> to_int32(const int32<N,E>& a)
72{
73 return a;
74}
75template<unsigned N, class E> SIMDPP_INL
76int32<N,expr_empty> to_int32(const uint32<N,E>& a)
77{
78 return int32<N>(a.eval());
79}
80template<unsigned N, class E> SIMDPP_INL
81int32<N,expr_empty> to_int32(const int64<N,E>& a)
82{
83 return detail::insn::i_to_uint32(uint64<N>(a.eval()));
84}
85template<unsigned N, class E> SIMDPP_INL
86int32<N,expr_empty> to_int32(const uint64<N,E>& a)
87{
88 return detail::insn::i_to_uint32(a.eval());
89}
90template<unsigned N, class E> SIMDPP_INL
91int32<N,expr_empty> to_int32(const float32<N,E>& a)
92{
93 return detail::insn::i_to_int32(a.eval());
94}
95template<unsigned N, class E> SIMDPP_INL
96int32<N,expr_empty> to_int32(const float64<N,E>& a)
97{
98 return detail::insn::i_to_int32(a.eval());
99}
100
101/** Converts elements within a vector to 32-bit unsigned values.
102
103 The conversion rules are as follows:
104 16-bit and narrower signed integers are sign-extended to 32 bits.
105 16-bit and narrower unsigned integers are zero-extended to 32 bits.
106 64-bit integers are truncated.
107 If floating-point value can not be represented in 32-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 uint32_t, @c 0x80000000 is returned
112 @todo NaN handling
113
114 NEON VFP specific:
115 If the value can not be represented by uint32_t, either @c 0x80000000 or @c
116 0x7fffffff is returned depending on the sign of the operand. Conversion of
117 NaNs results in @a 0.
118
119 @code
120 r0 = (uint32_t) a0
121 ...
122 rN = (uint32_t) aN
123 @endcode
124*/
125template<unsigned N, class E> SIMDPP_INL
126uint32<N,expr_empty> to_uint32(const int8<N,E>& a)
127{
128 return (uint32<N>) detail::insn::i_to_int32(a.eval());
129}
130template<unsigned N, class E> SIMDPP_INL
131uint32<N,expr_empty> to_uint32(const uint8<N,E>& a)
132{
133 return detail::insn::i_to_uint32(a.eval());
134}
135template<unsigned N, class E> SIMDPP_INL
136uint32<N,expr_empty> to_uint32(const int16<N,E>& a)
137{
138 return (uint32<N>) detail::insn::i_to_int32(a.eval());
139}
140template<unsigned N, class E> SIMDPP_INL
141uint32<N,expr_empty> to_uint32(const uint16<N,E>& a)
142{
143 return detail::insn::i_to_uint32(a.eval());
144}
145template<unsigned N, class E> SIMDPP_INL
146uint32<N,expr_empty> to_uint32(const int32<N,E>& a)
147{
148 return a.eval();
149}
150template<unsigned N, class E> SIMDPP_INL
151uint32<N,expr_empty> to_uint32(const uint32<N,E>& a)
152{
153 return a;
154}
155template<unsigned N, class E> SIMDPP_INL
156uint32<N,expr_empty> to_uint32(const int64<N,E>& a)
157{
158 return detail::insn::i_to_uint32(uint64<N>(a.eval()));
159}
160template<unsigned N, class E> SIMDPP_INL
161uint32<N,expr_empty> to_uint32(const uint64<N,E>& a)
162{
163 return detail::insn::i_to_uint32(a.eval());
164}
165template<unsigned N, class E> SIMDPP_INL
166uint32<N,expr_empty> to_uint32(const float32<N,E>& a)
167{
168 return detail::insn::i_to_uint32(a.eval());
169}
170template<unsigned N, class E> SIMDPP_INL
171uint32<N,expr_empty> to_uint32(const float64<N,E>& a)
172{
173#if SIMDPP_HAS_FLOAT64_TO_UINT32_CONVERSION
174 return detail::insn::i_to_uint32(a.eval());
175#else
176 return SIMDPP_NOT_IMPLEMENTED_TEMPLATE1(E, a);
177#endif
178}
179
180} // namespace SIMDPP_ARCH_NAMESPACE
181} // namespace simdpp
182
183#endif
184
185