1/* Copyright (C) 2013-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_MOVE_R_H
9#define LIBSIMDPP_SIMDPP_CORE_MOVE_R_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/move_r.h>
17
18namespace simdpp {
19namespace SIMDPP_ARCH_NAMESPACE {
20
21/** Moves the 8-bit elements in a vector to the right by @a shift positions.
22
23 @code
24 shift: pos:| 0 1 . 14 15 |
25 0 r = [ a0 a1 . a14 a15 ]
26 1 r = [ 0 a0 . a13 a14 ]
27 2 r = [ 0 0 . a12 a13 ]
28 ... .. .. .. ... .. .. ..
29 14 r = [ 0 0 . a0 a1 ]
30 15 r = [ 0 0 . 0 a0 ]
31 16 r = [ 0 0 . 0 0 ]
32 @endcode
33
34 @par 256-bit version:
35 The lower and higher 128-bit halves are processed as if 128-bit instruction
36 was applied to each of them separately.
37
38 @icost{SSE2-AVX, NEON, ALTIVEC, 2}
39*/
40template<unsigned shift, unsigned N, class V> SIMDPP_INL
41typename detail::get_expr_nomask<V>::empty
42 move16_r(const any_vec8<N,V>& a)
43{
44 static_assert(shift <= 16, "Shift out of bounds");
45
46 typename detail::get_expr_nomask_nosign<V>::type ra;
47 ra = a.wrapped().eval();
48 return detail::insn::i_move16_r_wrapper<shift>::run(ra);
49}
50
51/** Moves the 16-bit elements in a vector to the right by @a shift positions.
52
53 @code
54 shift: pos:| 0 1 . 6 7 |
55 0 r = [ a0 a1 . a6 a7 ]
56 1 r = [ 0 a0 . a5 a6 ]
57 2 r = [ 0 0 . a4 a5 ]
58 ... .. .. .. ... .. ..
59 6 r = [ 0 0 . a0 a1 ]
60 7 r = [ 0 0 . 0 a0 ]
61 8 r = [ 0 0 . 0 0 ]
62 @endcode
63
64 @par 256-bit version:
65 The lower and higher 128-bit halves are processed as if 128-bit instruction
66 was applied to each of them separately.
67
68 @icost{SSE2-AVX, NEON, ALTIVEC, 2}
69*/
70template<unsigned shift, unsigned N, class V> SIMDPP_INL
71typename detail::get_expr_nomask<V>::empty
72 move8_r(const any_vec16<N,V>& a)
73{
74 static_assert(shift <= 8, "Shift out of bounds");
75
76 typename detail::get_expr_nomask_nosign<V>::type ra;
77 ra = a.wrapped().eval();
78 return detail::insn::i_move8_r_wrapper<shift>::run(ra);
79}
80
81/** Moves the 32-bit elements in a vector to the right by @a shift positions.
82
83 @code
84 shift: pos:| 0 1 2 3 |
85 0 r = [ a0 a1 a2 a3 ]
86 1 r = [ 0 a0 a1 a2 ]
87 2 r = [ 0 0 a0 a1 ]
88 3 r = [ 0 0 0 a0 ]
89 4 r = [ 0 0 0 0 ]
90 @endcode
91
92 @par 256-bit version:
93 The lower and higher 128-bit halves are processed as if 128-bit instruction
94 was applied to each of them separately.
95
96 @icost{SSE2-AVX, NEON, ALTIVEC, 2}
97*/
98template<unsigned shift, unsigned N, class V> SIMDPP_INL
99typename detail::get_expr_nomask<V>::empty
100 move4_r(const any_vec32<N,V>& a)
101{
102 static_assert(shift <= 4, "Shift out of bounds");
103
104 typename detail::get_expr_nomask_nosign<V>::type ra;
105 ra = a.wrapped().eval();
106 return detail::insn::i_move4_r_wrapper<shift>::run(ra);
107}
108
109
110/** Moves the 64-bit elements in a vector to the right by @a shift positions.
111
112 @code
113 shift: pos:| 0 1 |
114 0 r = [ a0 a1 ]
115 1 r = [ 0 a0 ]
116 2 r = [ 0 0 ]
117 @endcode
118
119 @par 256-bit version:
120 The lower and higher 128-bit halves are processed as if 128-bit instruction
121 was applied to each of them separately.
122
123 @icost{SSE2-AVX, NEON, ALTIVEC, 2}
124*/
125template<unsigned shift, unsigned N, class V> SIMDPP_INL
126typename detail::get_expr_nomask<V>::empty
127 move2_r(const any_vec64<N,V>& a)
128{
129 static_assert(shift <= 2, "Shift out of bounds");
130
131 typename detail::get_expr_nomask_nosign<V>::type ra;
132 ra = a.wrapped().eval();
133 return detail::insn::i_move2_r_wrapper<shift>::run(ra);
134}
135
136
137} // namespace SIMDPP_ARCH_NAMESPACE
138} // namespace simdpp
139
140#endif
141
142