SSE2 shift by vector
<p>I've been trying to implement shift by vector in SSE2 intrinsics, but from experimentation and <a href="https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE2&amp;text=_mm_sll&amp;expand=4829,4859" rel="nofollow">the intel intrinsic guide</a>, it appears to only use the least-significant part of the vector.</p>

<p>To reword my question, given a vector {v1, v2, ..., vn} and a set of shifts {s1, s2, ..., sn}, how do I calculate a result {r1, r2, ..., rn} such that:</p>

<pre><code>r1 = v1 &lt;&lt; s1
r2 = v2 &lt;&lt; s2
...
rn = vn &lt;&lt; sn
</code></pre>

<p>since it appears that _mm_sll_epi* performs this:</p>

<pre><code>r1 = v1 &lt;&lt; s1
r2 = v2 &lt;&lt; s1
...
rn = vn &lt;&lt; s1
</code></pre>

<p>Thanks in advance.</p>

<p>EDIT:</p>

<p>Here's the code I have:</p>

<pre><code>#include &lt;iostream&gt;

#include &lt;cstdint&gt;

#include &lt;mmintrin.h&gt;
#include &lt;emmintrin.h&gt;

namespace SIMD {

    using namespace std;

    class SSE2 {
    public:
        // flipped operands due to function arguments
        SSE2(uint64_t a, uint64_t b, uint64_t c, uint64_t d) { low = _mm_set_epi64x(b, a); high = _mm_set_epi64x(d, c); }

        uint64_t&amp; operator[](int idx)
        {
            switch (idx) {
            case 0:
                _mm_storel_epi64((__m128i*)result, low);
                return result[0];
            case 1:
                _mm_store_si128((__m128i*)result, low);
                return result[1];
            case 2:
                _mm_storel_epi64((__m128i*)result, high);
                return result[0];
            case 3:
                _mm_store_si128((__m128i*)result, high);
                return result[1];
            }

            /* Undefined behaviour */
            return 0;
        }

        SSE2&amp; operator&lt;&lt;=(const SSE2&amp; rhs)
        {
            low  = _mm_sll_epi64(low,  rhs.getlow());
            high = _mm_sll_epi64(high, rhs.gethigh());

            return *this;
        }

        void print()
        {
            uint64_t a[2];
            _mm_store_si128((__m128i*)a, low);

            cout &lt;&lt; hex;
            cout &lt;&lt; a[0] &lt;&lt; ' ' &lt;&lt; a[1] &lt;&lt; ' ';

            _mm_store_si128((__m128i*)a, high);

            cout &lt;&lt; a[0] &lt;&lt; ' ' &lt;&lt; a[1] &lt;&lt; ' ';
            cout &lt;&lt; dec;
        }

        __m128i getlow() const
        {
            return low;
        }

        __m128i gethigh() const
        {
            return high;
        }
    private:
        __m128i low, high;
        uint64_t result[2];
    };
}

int main()
{
    cout &lt;&lt; "operator&lt;&lt;= test: vector &lt;&lt; vector: ";
    {
        auto x = SIMD::SSE2(7, 8, 15, 10);
        auto y = SIMD::SSE2(4, 5,  6,  7);

        x.print();
        y.print();

        x &lt;&lt;= y;

        if (x[0] != 112 || x[1] != 256 || x[2] != 960 || x[3] != 1280) {
            cout &lt;&lt; "FAILED: ";
            x.print();
            cout &lt;&lt; endl;
        } else {
            cout &lt;&lt; "PASSED" &lt;&lt; endl;
        }
    }

    return 0;
}
</code></pre>

<p>What should be happening gets results of {7 &lt;&lt; 4 = 112, 8 &lt;&lt; 5 = 256, 15 &lt;&lt; 6 = 960, 10 &lt;&lt; 7 = 1280}. The results seem to be {7 &lt;&lt; 4 = 112, 8 &lt;&lt; 4 = 128, 15 &lt;&lt; 6 = 960, 15 &lt;&lt; 6 = 640}, which isn't what I want.</p>

<p>Hope this helps, Jens.</p>