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_INT16_H
9 #define LIBSIMDPP_SIMDPP_CORE_TO_INT16_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/detail/insn/conv_extend_to_int16.h>
17 #include <simdpp/detail/insn/conv_shrink_to_int16.h>
18 #include <simdpp/detail/insn/conv_float_to_int16.h>
19 
20 namespace simdpp {
21 namespace SIMDPP_ARCH_NAMESPACE {
22 
23 
24 /** Converts elements within a vector to 16-bit signed values.
25 
26     The conversion rules are as follows:
27     8-bit signed integers are sign-extended to 16 bits.
28     8-bit unsigned integers are zero-extended to 16 bits.
29     32-bit and wider integers are truncated.
30     floating-point numbers are converted to integer values and truncated.
31     If floating-point value can not be represented in 16-bit signed integer,
32     the behavior is different for different instruction sets.
33 
34     @code
35     r0 = (int16_t) a0
36     ...
37     rN = (int16_t) aN
38     @endcode
39 */
40 template<unsigned N, class E> SIMDPP_INL
to_int16(const int8<N,E> & a)41 int16<N,expr_empty> to_int16(const int8<N,E>& a)
42 {
43     return detail::insn::i_to_int16(a.eval());
44 }
45 template<unsigned N, class E> SIMDPP_INL
to_int16(const uint8<N,E> & a)46 int16<N,expr_empty> to_int16(const uint8<N,E>& a)
47 {
48     return (int16<N>) detail::insn::i_to_uint16(a.eval());
49 }
50 template<unsigned N, class E> SIMDPP_INL
to_int16(const int16<N,E> & a)51 int16<N,expr_empty> to_int16(const int16<N,E>& a)
52 {
53     return a.eval();
54 }
55 template<unsigned N, class E> SIMDPP_INL
to_int16(const uint16<N,E> & a)56 int16<N,expr_empty> to_int16(const uint16<N,E>& a)
57 {
58     return int16<N>(a.eval());
59 }
60 template<unsigned N, class E> SIMDPP_INL
to_int16(const int32<N,E> & a)61 int16<N,expr_empty> to_int16(const int32<N,E>& a)
62 {
63     return detail::insn::i_to_uint16(uint32<N>(a.eval()));
64 }
65 template<unsigned N, class E> SIMDPP_INL
to_int16(const uint32<N,E> & a)66 int16<N,expr_empty> to_int16(const uint32<N,E>& a)
67 {
68     return detail::insn::i_to_uint16(a.eval());
69 }
70 template<unsigned N, class E> SIMDPP_INL
to_int16(const int64<N,E> & a)71 int16<N,expr_empty> to_int16(const int64<N,E>& a)
72 {
73     return detail::insn::i_to_uint16(uint64<N>(a.eval()));
74 }
75 template<unsigned N, class E> SIMDPP_INL
to_int16(const uint64<N,E> & a)76 int16<N,expr_empty> to_int16(const uint64<N,E>& a)
77 {
78     return detail::insn::i_to_uint16(a.eval());
79 }
80 template<unsigned N, class E> SIMDPP_INL
to_int16(const float32<N,E> & a)81 int16<N,expr_empty> to_int16(const float32<N,E>& a)
82 {
83     return detail::insn::i_to_int16(a.eval());
84 }
85 template<unsigned N, class E> SIMDPP_INL
to_int16(const float64<N,E> & a)86 int16<N,expr_empty> to_int16(const float64<N,E>& a)
87 {
88     return detail::insn::i_to_int16(a.eval());
89 }
90 
91 /** Converts elements within a vector to 16-bit unsigned values.
92 
93     The conversion rules are as follows:
94     8-bit signed integers are sign-extended to 16 bits.
95     8-bit unsigned integers are zero-extended to 16 bits.
96     32-bit and wider integers are truncated.
97     If floating-point value can not be represented in 16-bit unsigned integer,
98     the behavior is different for different instruction sets.
99 
100     @code
101     r0 = (uint16_t) a0
102     ...
103     rN = (uint16_t) aN
104     @endcode
105 */
106 template<unsigned N, class E> SIMDPP_INL
to_uint16(const int8<N,E> & a)107 uint16<N,expr_empty> to_uint16(const int8<N,E>& a)
108 {
109     return (uint16<N>) detail::insn::i_to_int16(a.eval());
110 }
111 template<unsigned N, class E> SIMDPP_INL
to_uint16(const uint8<N,E> & a)112 uint16<N,expr_empty> to_uint16(const uint8<N,E>& a)
113 {
114     return detail::insn::i_to_uint16(a.eval());
115 }
116 template<unsigned N, class E> SIMDPP_INL
to_uint16(const int16<N,E> & a)117 uint16<N,expr_empty> to_uint16(const int16<N,E>& a)
118 {
119     return uint16<N>(a.eval());
120 }
121 template<unsigned N, class E> SIMDPP_INL
to_uint16(const uint16<N,E> & a)122 uint16<N,expr_empty> to_uint16(const uint16<N,E>& a)
123 {
124     return a.eval();
125 }
126 template<unsigned N, class E> SIMDPP_INL
to_uint16(const int32<N,E> & a)127 uint16<N,expr_empty> to_uint16(const int32<N,E>& a)
128 {
129     return detail::insn::i_to_uint16(uint32<N>(a.eval()));
130 }
131 template<unsigned N, class E> SIMDPP_INL
to_uint16(const uint32<N,E> & a)132 uint16<N,expr_empty> to_uint16(const uint32<N,E>& a)
133 {
134     return detail::insn::i_to_uint16(a.eval());
135 }
136 template<unsigned N, class E> SIMDPP_INL
to_uint16(const int64<N,E> & a)137 uint16<N,expr_empty> to_uint16(const int64<N,E>& a)
138 {
139     return detail::insn::i_to_uint16(uint64<N>(a.eval()));
140 }
141 template<unsigned N, class E> SIMDPP_INL
to_uint16(const uint64<N,E> & a)142 uint16<N,expr_empty> to_uint16(const uint64<N,E>& a)
143 {
144     return detail::insn::i_to_uint16(a.eval());
145 }
146 template<unsigned N, class E> SIMDPP_INL
to_uint16(const float32<N,E> & a)147 uint16<N,expr_empty> to_uint16(const float32<N,E>& a)
148 {
149     return detail::insn::i_to_uint16(a.eval());
150 }
151 template<unsigned N, class E> SIMDPP_INL
to_uint16(const float64<N,E> & a)152 uint16<N,expr_empty> to_uint16(const float64<N,E>& a)
153 {
154     return detail::insn::i_to_uint16(a.eval());
155 }
156 
157 } // namespace SIMDPP_ARCH_NAMESPACE
158 } // namespace simdpp
159 
160 #endif
161 
162