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
21namespace simdpp {
22namespace 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*/
43template<unsigned N, class E> SIMDPP_INL
44int64<N,expr_empty> to_int64(const int8<N,E>& a)
45{
46 return detail::insn::i_to_int64(a.eval());
47}
48template<unsigned N, class E> SIMDPP_INL
49int64<N,expr_empty> to_int64(const uint8<N,E>& a)
50{
51 return (int64<N>) detail::insn::i_to_uint64(a.eval());
52}
53template<unsigned N, class E> SIMDPP_INL
54int64<N,expr_empty> to_int64(const int16<N,E>& a)
55{
56 return detail::insn::i_to_int64(a.eval());
57}
58template<unsigned N, class E> SIMDPP_INL
59int64<N,expr_empty> to_int64(const uint16<N,E>& a)
60{
61 return (int64<N>) detail::insn::i_to_uint64(a.eval());
62}
63template<unsigned N, class E> SIMDPP_INL
64int64<N,expr_empty> to_int64(const int32<N,E>& a)
65{
66 return detail::insn::i_to_int64(a.eval());
67}
68template<unsigned N, class E> SIMDPP_INL
69int64<N,expr_empty> to_int64(const uint32<N,E>& a)
70{
71 return (int64<N>) detail::insn::i_to_uint64(a.eval());
72}
73template<unsigned N, class E> SIMDPP_INL
74int64<N,expr_empty> to_int64(const int64<N,E>& a)
75{
76 return a;
77}
78template<unsigned N, class E> SIMDPP_INL
79int64<N,expr_empty> to_int64(const uint64<N,E>& a)
80{
81 return int64<N>(a.eval());
82}
83template<unsigned N, class E> SIMDPP_INL
84int64<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}
92template<unsigned N, class E> SIMDPP_INL
93int64<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*/
121template<unsigned N, class E> SIMDPP_INL
122uint64<N,expr_empty> to_uint64(const int8<N,E>& a)
123{
124 return (uint64<N>) detail::insn::i_to_int64(a.eval());
125}
126template<unsigned N, class E> SIMDPP_INL
127uint64<N,expr_empty> to_uint64(const uint8<N,E>& a)
128{
129 return detail::insn::i_to_uint64(a.eval());
130}
131template<unsigned N, class E> SIMDPP_INL
132uint64<N,expr_empty> to_uint64(const int16<N,E>& a)
133{
134 return (uint64<N>) detail::insn::i_to_int64(a.eval());
135}
136template<unsigned N, class E> SIMDPP_INL
137uint64<N,expr_empty> to_uint64(const uint16<N,E>& a)
138{
139 return detail::insn::i_to_uint64(a.eval());
140}
141template<unsigned N, class E> SIMDPP_INL
142uint64<N,expr_empty> to_uint64(const int32<N,E>& a)
143{
144 return (uint64<N>) detail::insn::i_to_int64(a.eval());
145}
146template<unsigned N, class E> SIMDPP_INL
147uint64<N,expr_empty> to_uint64(const uint32<N,E>& a)
148{
149 return detail::insn::i_to_uint64(a.eval());
150}
151template<unsigned N, class E> SIMDPP_INL
152uint64<N,expr_empty> to_uint64(const int64<N,E>& a)
153{
154 return uint64<N>(a.eval());
155}
156template<unsigned N, class E> SIMDPP_INL
157uint64<N,expr_empty> to_uint64(const uint64<N,E>& a)
158{
159 return a.eval();
160}
161template<unsigned N, class E> SIMDPP_INL
162uint64<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}
170template<unsigned N, class E> SIMDPP_INL
171uint64<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