1 /**
2 *** Copyright (C) 1985-1999 Intel Corporation.  All rights reserved.
3 ***
4 *** The information and source code contained herein is the exclusive
5 *** property of Intel Corporation and may not be disclosed, examined
6 *** or reproduced in whole or in part without explicit written authorization
7 *** from the company.
8 ***
9 **/
10
11 /*
12  *  Definition of a C++ class interface to MMX(TM) instruction intrinsics.
13  *
14  */
15
16 #ifndef _IVEC_H_INCLUDED
17 #define _IVEC_H_INCLUDED
18 #ifndef RC_INVOKED
19
20 #if !defined __cplusplus
21     #error ERROR: This file is only supported in C++ compilations!
22 #endif /* !__cplusplus */
23
24 #if defined(_M_CEE_PURE)
25     #error ERROR: This file is not supported in the pure mode!
26 #else
27
28 #include <mmintrin.h>
29 #include <assert.h>
30
31 /*
32  * Define _SILENCE_IVEC_C4799 to disable warning C4799 inside this header.
33  * Be careful that any code that uses these functions properly executes EMMS
34  * or _m_empty() after using any MMX instruction and before using the x87 NDP.
35  */
36 #if defined(_SILENCE_IVEC_C4799)
37     #pragma warning(push)
38     #pragma warning(disable: 4799)
39 #endif
40
41 /*
42  * Define _ENABLE_VEC_DEBUG to enable std::ostream inserters for debug output
43  */
44 #if defined(_ENABLE_VEC_DEBUG)
45     #include <iostream>
46 #endif
47
48 #define EXPLICIT explicit
49
50 class I8vec8;            /* 8 elements, each element a signed or unsigned char data type */
51 class Is8vec8;            /* 8 elements, each element a signed char data type */
52 class Iu8vec8;            /* 8 elements, each element an unsigned char data type */
53 class I16vec4;            /* 4 elements, each element a signed or unsigned short */
54 class Is16vec4;            /* 4 elements, each element a signed short */
55 class Iu16vec4;            /* 4 elements, each element an unsigned short */
56 class I32vec2;            /* 2 elements, each element a signed or unsigned long */
57 class Is32vec2;            /* 2 elements, each element a signed long */
58 class Iu32vec2;            /* 2 elements, each element a unsigned long */
59 class I64vec1;            /* 1 element, a __m64 data type - Base I64vec1 class  */
60
61 #define _MM_8UB(element,vector) (*((unsigned char*)&##vector + ##element))
62 #define _MM_8B(element,vector) (*((signed char*)&##vector + ##element))
63
64 #define _MM_4UW(element,vector) (*((unsigned short*)&##vector + ##element))
65 #define _MM_4W(element,vector) (*((short*)&##vector + ##element))
66
67 #define _MM_2UDW(element,vector) (*((unsigned int*)&##vector + ##element))
68 #define _MM_2DW(element,vector) (*((int*)&##vector + ##element))
69
70 #define _MM_QW (*((__int64*)&vec))
71
72 /* M64 Class:
73  * 1 element, a __m64 data type
74  * Contructors & Logical Operations
75  */
76 class M64
77 {
78 protected:
79         __m64 vec;
80
81 public:
82     M64()                                    { }
83     M64(__m64 mm)                            { vec = mm; }
84     M64(__int64 mm)                            { _MM_QW = mm; }
85     M64(int i)                                { vec = _m_from_int(i); }
86
87     operator __m64() const                    { return vec; }
88
89     /* Logical Operations */
90     M64& operator&=(const M64 &a)                    { return *this = (M64) _m_pand(vec,a); }
91     M64& operator|=(const M64 &a)                    { return *this = (M64) _m_por(vec,a); }
92     M64& operator^=(const M64 &a)                    { return *this = (M64) _m_pxor(vec,a); }
93
94 };
95
96 inline M64 operator&(const M64 &a, const M64 &b)    { return _m_pand( a,b); }
97 inline M64 operator|(const M64 &a, const M64 &b)    { return _m_por(a,b); }
98 inline M64 operator^(const M64 &a, const M64 &b)    { return _m_pxor(a,b); }
99 inline M64 andnot(const M64 &a, const M64 &b)        { return _m_pandn(a,b); }
100
101 /* I64vec1 Class:
102  * 1 element, a __m64 data type
103  * Contains Operations which can operate on any __m64 data type
104  */
105
106 class I64vec1 : public M64
107 {
108 public:
109     I64vec1()                                { }
110     I64vec1(__m64 mm) : M64(mm)                { }
111     EXPLICIT I64vec1(int i) : M64(i)        { }
112     EXPLICIT I64vec1(__int64 mm) : M64(mm)    { }
113
114     I64vec1& operator= (const M64 &a) { return *this = (I64vec1) a; }
115     I64vec1& operator&=(const M64 &a) { return *this = (I64vec1) _m_pand(vec,a); }
116     I64vec1& operator|=(const M64 &a) { return *this = (I64vec1) _m_por(vec,a); }
117     I64vec1& operator^=(const M64 &a) { return *this = (I64vec1) _m_pxor(vec,a); }
118
119     /* Shift Logical Operations */
120     I64vec1 operator<<(const M64 &a)                { return _m_psllq(vec, a); }
121     I64vec1 operator<<(int count)                       { return _m_psllqi(vec, count); }
122     I64vec1& operator<<=(const M64 &a)                { return *this = (I64vec1) _m_psllq(vec, a); }
123     I64vec1& operator<<=(int count)                 { return *this = (I64vec1) _m_psllqi(vec, count); }
124     I64vec1 operator>>(const M64 &a)                { return _m_psrlq(vec, a); }
125     I64vec1 operator>>(int count)                     { return _m_psrlqi(vec, count); }
126     I64vec1& operator>>=(const M64 &a)                { return *this = (I64vec1) _m_psrlq(vec, a); }
127     I64vec1& operator>>=(int count)                 { return *this = (I64vec1) _m_psrlqi(vec, count); }
128 };
129
130 /* I32vec2 Class:
131  * 2 elements, each element either a signed or unsigned int
132  */
133 class I32vec2 : public M64
134 {
135 public:
136     I32vec2() { }
137     I32vec2(__m64 mm) : M64(mm) { }
138     EXPLICIT I32vec2(int i) : M64 (i) { }
139     EXPLICIT I32vec2(__int64 i): M64(i) {}
140
141     /* Assignment Operator */
142     I32vec2& operator= (const M64 &a) { return *this = (I32vec2) a; }
143
144     /* Logical Assignment Operators */
145     I32vec2& operator&=(const M64 &a) { return *this = (I32vec2) _m_pand(vec,a); }
146     I32vec2& operator|=(const M64 &a) { return *this = (I32vec2) _m_por(vec,a); }
147     I32vec2& operator^=(const M64 &a) { return *this = (I32vec2) _m_pxor(vec,a); }
148
149     /* Addition & Subtraction Assignment Operators */
150     I32vec2& operator +=(const I32vec2 &a)            { return *this = (I32vec2) _m_paddd(vec,a); }
151     I32vec2& operator -=(const I32vec2 &a)            { return *this = (I32vec2) _m_psubd(vec,a); }
152
153     /* Shift Logical Operators */
154     I32vec2 operator<<(const I32vec2 &a)             { return _m_pslld(vec,a); }
155     I32vec2 operator<<(int count)                       { return _m_pslldi(vec,count); }
156     I32vec2& operator<<=(const I32vec2 &a)            { return *this = (I32vec2) _m_pslld(vec,a); }
157     I32vec2& operator<<=(int count)                 { return *this = (I32vec2) _m_pslldi(vec,count); }
158
159 };
160
161 /* Compare For Equality */
162 inline I32vec2 cmpeq(const I32vec2 &a, const I32vec2 &b)           { return _m_pcmpeqd(a,b); }
163 inline I32vec2 cmpneq(const I32vec2 &a, const I32vec2 &b)           { return _m_pandn(_m_pcmpeqd(a,b), M64(0xffffffffffffffffi64)); }
164 /* Unpacks */
165 inline I32vec2 unpack_low(const I32vec2 &a, const I32vec2 &b)     {return _m_punpckldq(a,b); }
166 inline I32vec2 unpack_high(const I32vec2 &a, const I32vec2 &b)     {return _m_punpckhdq(a,b); }
167
168 /* Is32vec2 Class:
169  * 2 elements, each element a signed int
170  */
171 class Is32vec2 : public I32vec2
172 {
173 public:
174     Is32vec2() { }
175     Is32vec2(__m64 mm) : I32vec2(mm) { }
176     Is32vec2(signed int i0, signed int i1)
177     {
178         _MM_2DW(0,vec) = i1;
179         _MM_2DW(1,vec) = i0;
180     }
181     EXPLICIT Is32vec2(int i) : I32vec2 (i)        {}
182     EXPLICIT Is32vec2(__int64 i): I32vec2(i)    {}
183
184     /* Assignment Operator */
185     Is32vec2& operator= (const M64 &a)        { return *this = (Is32vec2) a; }
186
187     /* Logical Assignment Operators */
188     Is32vec2& operator&=(const M64 &a)        { return *this = (Is32vec2) _m_pand(vec,a); }
189     Is32vec2& operator|=(const M64 &a)        { return *this = (Is32vec2) _m_por(vec,a); }
190     Is32vec2& operator^=(const M64 &a)        { return *this = (Is32vec2) _m_pxor(vec,a); }
191
192     /* Addition & Subtraction Assignment Operators */
193     Is32vec2& operator +=(const I32vec2 &a)    { return *this = (Is32vec2) _m_paddd(vec,a); }
194     Is32vec2& operator -=(const I32vec2 &a)    { return *this = (Is32vec2) _m_psubd(vec,a); }
195
196     /* Shift Logical Operators */
197     Is32vec2 operator<<(const M64 &a)         { return _m_pslld(vec,a); }
198     Is32vec2 operator<<(int count)             { return _m_pslldi(vec,count); }
199     Is32vec2& operator<<=(const M64 &a)        { return *this = (Is32vec2) _m_pslld(vec,a); }
200     Is32vec2& operator<<=(int count)         { return *this = (Is32vec2) _m_pslldi(vec,count); }
201     /* Shift Arithmetic Operations */
202     Is32vec2 operator>>(const M64 &a)         { return _m_psrad(vec, a); }
203     Is32vec2 operator>>(int count)               { return _m_psradi(vec, count); }
204     Is32vec2& operator>>=(const M64 &a)        { return *this = (Is32vec2) _m_psrad(vec, a); }
205     Is32vec2& operator>>=(int count)         { return *this = (Is32vec2) _m_psradi(vec, count); }
206
207 #if defined(_ENABLE_VEC_DEBUG)
208     /* Output for Debug */
209     friend std::ostream& operator<< (std::ostream &os, const Is32vec2 &a)
210     {
211         os << " [1]:" << _MM_2DW(1,a)
212         << " [0]:" << _MM_2DW(0,a);
213         return os;
214     }
215 #endif
216
217     /* Element Access for Debug, No data modified */
218     const int& operator[](int i)const
219     {
220         assert(static_cast<unsigned int>(i) < 2);    /* Only 2 elements to access */
221         return _MM_2DW(i,vec);
222     }
223
224     /* Element Access and Assignment for Debug */
225     int& operator[](int i)
226     {
227         assert(static_cast<unsigned int>(i) < 2);    /* Only 2 elements to access */
228         return _MM_2DW(i,vec);
229     }
230 };
231
232 /* Compares */
233 inline Is32vec2 cmpeq(const Is32vec2 &a, const Is32vec2 &b)           { return _m_pcmpeqd(a,b); }
234 inline Is32vec2 cmpneq(const Is32vec2 &a, const Is32vec2 &b)           { return _m_pandn(_m_pcmpeqd(a,b), M64(0xffffffffffffffffi64)); }
235 inline Is32vec2 cmpgt(const Is32vec2 &a, const Is32vec2 &b)            { return _m_pcmpgtd(a,b); }
236 inline Is32vec2 cmplt(const Is32vec2 &a, const Is32vec2 &b)            { return _m_pcmpgtd(b,a); }
237 inline Is32vec2 cmple(const Is32vec2 &a, const Is32vec2 &b)            { return _m_pandn(_m_pcmpgtd(a,b), M64(0xffffffffffffffffi64)); }
238 inline Is32vec2 cmpge(const Is32vec2 &a, const Is32vec2 &b)            { return _m_pandn(_m_pcmpgtd(b,a), M64(0xffffffffffffffffi64)); }
239 /* Unpacks & Pack */
240 inline Is32vec2 unpack_low(const Is32vec2 &a, const Is32vec2 &b)     { return _m_punpckldq(a,b); }
241 inline Is32vec2 unpack_high(const Is32vec2 &a, const Is32vec2 &b)     { return _m_punpckhdq(a,b); }
242
243 /* Iu32vec2 Class:
244  * 2 elements, each element unsigned int
245  */
246 class Iu32vec2 : public I32vec2
247 {
248 public:
249     Iu32vec2() { }
250     Iu32vec2(__m64 mm) : I32vec2(mm) { }
251     Iu32vec2(unsigned int ui0, unsigned int ui1)
252     {
253         _MM_2UDW(0,vec) = ui1;
254         _MM_2UDW(1,vec) = ui0;
255     }
256
257     EXPLICIT Iu32vec2(int i) : I32vec2 (i)        { }
258     EXPLICIT Iu32vec2(__int64 i) : I32vec2 (i)    { }
259
260     /* Assignment Operator */
261     Iu32vec2& operator= (const M64 &a)        { return *this = (Iu32vec2) a; }
262
263     /* Logical Assignment Operators */
264     Iu32vec2& operator&=(const M64 &a)        { return *this = (Iu32vec2) _m_pand(vec,a); }
265     Iu32vec2& operator|=(const M64 &a)        { return *this = (Iu32vec2) _m_por(vec,a); }
266     Iu32vec2& operator^=(const M64 &a)        { return *this = (Iu32vec2) _m_pxor(vec,a); }
267
268     /* Addition & Subtraction Assignment Operators */
269     Iu32vec2& operator +=(const I32vec2 &a)    { return *this = (Iu32vec2) _m_paddd(vec,a); }
270     Iu32vec2& operator -=(const I32vec2 &a)    { return *this = (Iu32vec2) _m_psubd(vec,a); }
271
272     /* Shift Logical Operators */
273     Iu32vec2 operator<<(const M64 &a)         { return _m_pslld(vec,a); }
274     Iu32vec2 operator<<(int count)             { return _m_pslldi(vec,count); }
275     Iu32vec2& operator<<=(const M64 &a)        { return *this = (Iu32vec2) _m_pslld(vec,a); }
276     Iu32vec2& operator<<=(int count)         { return *this = (Iu32vec2) _m_pslldi(vec,count); }
277     Iu32vec2 operator>>(const M64 &a)         { return _m_psrld(vec,a); }
278     Iu32vec2 operator>>(int count)             { return _m_psrldi(vec,count); }
279     Iu32vec2& operator>>=(const M64 &a)        { return *this = (Iu32vec2) _m_psrld(vec,a); }
280     Iu32vec2& operator>>=(int count)         { return *this = (Iu32vec2) _m_psrldi(vec,count); }
281
282 #if defined(_ENABLE_VEC_DEBUG)
283     /* Output for Debug */
284     friend std::ostream& operator<< (std::ostream &os, const Iu32vec2 &a)
285     {
286         os << " [1]:" << _MM_2UDW(1,a)
287         << " [0]:" << _MM_2UDW(0,a);
288         return os;
289     }
290 #endif
291
292     /* Element Access for Debug, No data modified */
293     const unsigned int& operator[](int i)const
294     {
295         assert(static_cast<unsigned int>(i) < 2);    /* Only 2 elements to access */
296         return _MM_2UDW(i,vec);
297     }
298
299     /* Element Access and Assignment for Debug */
300     unsigned int& operator[](int i)
301     {
302         assert(static_cast<unsigned int>(i) < 2);    /* Only 2 elements to access */
303         return _MM_2UDW(i,vec);
304     }
305 };
306
307 /* Compares For Equality / Inequality */
308 inline Iu32vec2 cmpeq(const Iu32vec2 &a, const Iu32vec2 &b)           { return _m_pcmpeqd(a,b); }
309 inline Iu32vec2 cmpneq(const Iu32vec2 &a, const Iu32vec2 &b)           { return _m_pandn(_m_pcmpeqd(a,b), M64(0xffffffffffffffffi64)); }
310 /* Unpacks */
311 inline Iu32vec2 unpack_low(const Iu32vec2 &a, const Iu32vec2 &b)     {return _m_punpckldq(a,b); }
312 inline Iu32vec2 unpack_high(const Iu32vec2 &a, const Iu32vec2 &b)     {return _m_punpckhdq(a,b); }
313
314 /* I16vec4 Class:
315  * 4 elements, each element either a signed or unsigned short
316  */
317 class I16vec4 : public M64
318 {
319 public:
320     I16vec4() { }
321     I16vec4(__m64 mm) : M64(mm) { }
322     EXPLICIT I16vec4(__int64 i) : M64 (i) { }
323     EXPLICIT I16vec4(int i) : M64 (i) { }
324
325     /* Assignment Operator */
326     I16vec4& operator= (const M64 &a)                { return *this = (I16vec4) a; }
327
328     /* Addition & Subtraction Assignment Operators */
329     I16vec4& operator&=(const M64 &a)                { return *this = (I16vec4) _m_pand(vec,a); }
330     I16vec4& operator|=(const M64 &a)                { return *this = (I16vec4) _m_por(vec,a); }
331     I16vec4& operator^=(const M64 &a)                { return *this = (I16vec4) _m_pxor(vec,a); }
332
333     /* Addition & Subtraction Assignment Operators */
334     I16vec4& operator +=(const I16vec4 &a)            { return *this = (I16vec4)_m_paddw(vec,a); }
335     I16vec4& operator -=(const I16vec4 &a)            { return *this = (I16vec4)_m_psubw(vec,a); }
336     I16vec4& operator *=(const I16vec4 &a)            { return *this = (I16vec4)_m_pmullw(vec,a); }
337
338     /* Shift Logical Operators */
339     I16vec4 operator<<(const I16vec4 &a)             { return _m_psllw(vec,a); }
340     I16vec4 operator<<(int count)                       { return _m_psllwi(vec,count); }
341     I16vec4& operator<<=(const I16vec4 &a)            { return *this = (I16vec4)_m_psllw(vec,a); }
342     I16vec4& operator<<=(int count)                 { return *this = (I16vec4)_m_psllwi(vec,count); }
343 };
344
345 inline I16vec4 operator*(const I16vec4 &a, const I16vec4 &b)     { return _m_pmullw(a,b); }
346 inline I16vec4 cmpeq(const I16vec4 &a, const I16vec4 &b)           { return _m_pcmpeqw(a,b); }
347 inline I16vec4 cmpneq(const I16vec4 &a, const I16vec4 &b)           { return _m_pandn(_m_pcmpeqw(a,b), M64(0xffffffffffffffffi64)); }
348
349 inline I16vec4 unpack_low(const I16vec4 &a, const I16vec4 &b)     { return _m_punpcklwd(a,b); }
350 inline I16vec4 unpack_high(const I16vec4 &a, const I16vec4 &b)     { return _m_punpckhwd(a,b); }
351
352 /* Is16vec4 Class:
353  * 4 elements, each element signed short
354  */
355 class Is16vec4 : public I16vec4
356 {
357 public:
358     Is16vec4() { }
359     Is16vec4(__m64 mm) : I16vec4(mm) { }
360     Is16vec4(short i0, short i1, short i2, short i3)
361     {
362         _MM_4W(0,vec) = i3;
363         _MM_4W(1,vec) = i2;
364         _MM_4W(2,vec) = i1;
365         _MM_4W(3,vec) = i0;
366     }
367
368     EXPLICIT Is16vec4(__int64 i) : I16vec4 (i)    { }
369     EXPLICIT Is16vec4(int i) : I16vec4 (i)        { }
370
371     /* Assignment Operator */
372     Is16vec4& operator= (const M64 &a)        { return *this = (Is16vec4) a; }
373
374     /* Addition & Subtraction Assignment Operators */
375     Is16vec4& operator&=(const M64 &a)        { return *this = (Is16vec4) _m_pand(vec,a); }
376     Is16vec4& operator|=(const M64 &a)        { return *this = (Is16vec4) _m_por(vec,a); }
377     Is16vec4& operator^=(const M64 &a)        { return *this = (Is16vec4) _m_pxor(vec,a); }
378
379     /* Addition & Subtraction Assignment Operators */
380     Is16vec4& operator +=(const I16vec4 &a)    { return *this = (Is16vec4)_m_paddw(vec,a); }
381     Is16vec4& operator -=(const I16vec4 &a)    { return *this = (Is16vec4)_m_psubw(vec,a); }
382     Is16vec4& operator *=(const I16vec4 &a)    { return *this = (Is16vec4)_m_pmullw(vec,a); }
383
384     /* Shift Logical Operators */
385     Is16vec4 operator<<(const M64 &a)         { return _m_psllw(vec,a); }
386     Is16vec4 operator<<(int count)             { return _m_psllwi(vec,count); }
387     Is16vec4& operator<<=(const M64 &a)        { return *this = (Is16vec4)_m_psllw(vec,a); }
388     Is16vec4& operator<<=(int count)         { return *this = (Is16vec4)_m_psllwi(vec,count); }
389     /* Shift Arithmetic Operations */
390     Is16vec4 operator>>(const M64 &a)         { return _m_psraw(vec,a); }
391     Is16vec4 operator>>(int count)             { return _m_psrawi(vec,count); }
392     Is16vec4& operator>>=(const M64 &a)        { return *this = (Is16vec4) _m_psraw(vec,a); }
393     Is16vec4& operator>>=(int count)         { return *this = (Is16vec4) _m_psrawi(vec,count); }
394
395 #if defined(_ENABLE_VEC_DEBUG)
396     /* Output for Debug */
397     friend std::ostream& operator<< (std::ostream &os, const Is16vec4 &a)
398     {
399         os << "[3]:" << _MM_4W(3,a)
400             << " [2]:" << _MM_4W(2,a)
401             << " [1]:" << _MM_4W(1,a)
402             << " [0]:" << _MM_4W(0,a);
403         return os;
404     }
405 #endif
406
407     /* Element Access for Debug, No data modified */
408     const short& operator[](int i)const
409     {
410         assert(static_cast<unsigned int>(i) < 4);    /* Only 4 elements to access */
411         return _MM_4W(i,vec);
412     }
413
414     /* Element Access for Debug */
415     short& operator[](int i)
416     {
417         assert(static_cast<unsigned int>(i) < 4);    /* Only 4 elements to access */
418         return _MM_4W(i,vec);
419     }
420 };
421
422 inline Is16vec4 operator*(const Is16vec4 &a, const Is16vec4 &b)     { return _m_pmullw(a,b); }
423
424 /* Compares */
425 inline Is16vec4 cmpeq(const Is16vec4 &a, const Is16vec4 &b)           { return _m_pcmpeqw(a,b); }
426 inline Is16vec4 cmpneq(const Is16vec4 &a, const Is16vec4 &b)           { return _m_pandn(_m_pcmpeqw(a,b), M64(0xffffffffffffffffi64)); }
427 inline Is16vec4 cmpgt(const Is16vec4 &a, const Is16vec4 &b)            { return _m_pcmpgtw(a,b); }
428 inline Is16vec4 cmplt(const Is16vec4 &a, const Is16vec4 &b)            { return _m_pcmpgtw(b,a); }
429 inline Is16vec4 cmple(const Is16vec4 &a, const Is16vec4 &b)            { return _m_pandn(_m_pcmpgtw(a,b), M64(0xffffffffffffffffi64)); }
430 inline Is16vec4 cmpge(const Is16vec4 &a, const Is16vec4 &b)            { return _m_pandn(_m_pcmpgtw(b,a), M64(0xffffffffffffffffi64)); }
431 /* Unpacks */
432 inline Is16vec4 unpack_low(const Is16vec4 &a, const Is16vec4 &b)     { return _m_punpcklwd(a,b); }
433 inline Is16vec4 unpack_high(const Is16vec4 &a, const Is16vec4 &b)     { return _m_punpckhwd(a,b); }
434
435 inline Is16vec4 sat_add(const Is16vec4 &a, const Is16vec4 &b)        { return _m_paddsw(a,b); }
436 inline Is16vec4 sat_sub(const Is16vec4 &a, const Is16vec4 &b)        { return _m_psubsw(a,b); }
437 inline Is16vec4 mul_high(const Is16vec4 &a, const Is16vec4 &b)        { return _m_pmulhw(a,b); }
438 inline Is32vec2 mul_add(const Is16vec4 &a, const Is16vec4 &b)        { return _m_pmaddwd(a,b);}
439
440
441 /* Iu16vec4 Class:
442  * 4 elements, each element unsigned short
443  */
444 class Iu16vec4 : public I16vec4
445 {
446 public:
447     Iu16vec4() { }
448     Iu16vec4(__m64 mm) : I16vec4(mm) { }
449     Iu16vec4(unsigned short ui0, unsigned short ui1, unsigned short ui2, unsigned short ui3)
450     {
451         _MM_4UW(0,vec) = ui3;
452         _MM_4UW(1,vec) = ui2;
453         _MM_4UW(2,vec) = ui1;
454         _MM_4UW(3,vec) = ui0;
455     }
456     EXPLICIT Iu16vec4(__int64 i) : I16vec4 (i) { }
457     EXPLICIT Iu16vec4(int i) : I16vec4 (i) { }
458
459     /* Assignment Operator */
460     Iu16vec4& operator= (const M64 &a)        { return *this = (Iu16vec4) a; }
461
462     /* Logical Assignment Operators */
463     Iu16vec4& operator&=(const M64 &a)        { return *this = (Iu16vec4) _m_pand(vec,a); }
464     Iu16vec4& operator|=(const M64 &a)        { return *this = (Iu16vec4) _m_por(vec,a); }
465     Iu16vec4& operator^=(const M64 &a)        { return *this = (Iu16vec4) _m_pxor(vec,a); }
466
467     /* Addition & Subtraction Assignment Operators */
468     Iu16vec4& operator +=(const I16vec4 &a)    { return *this = (Iu16vec4)_m_paddw(vec,a); }
469     Iu16vec4& operator -=(const I16vec4 &a)    { return *this = (Iu16vec4)_m_psubw(vec,a); }
470     Iu16vec4& operator *=(const I16vec4 &a)    { return *this = (Iu16vec4)_m_pmullw(vec,a); }
471
472     /* Shift Logical Operators */
473     Iu16vec4 operator<<(const M64 &a)                 { return _m_psllw(vec,a); }
474     Iu16vec4 operator<<(int count)                       { return _m_psllwi(vec,count); }
475     Iu16vec4& operator<<=(const M64 &a)                { return *this = (Iu16vec4)_m_psllw(vec,a); }
476     Iu16vec4& operator<<=(int count)                 { return *this = (Iu16vec4)_m_psllwi(vec,count); }
477     Iu16vec4 operator>>(const M64 &a)                 { return _m_psrlw(vec,a); }
478     Iu16vec4 operator>>(int count)                       { return _m_psrlwi(vec,count); }
479     Iu16vec4& operator>>=(const M64 &a)                { return *this = (Iu16vec4) _m_psrlw(vec,a); }
480     Iu16vec4& operator>>=(int count)                 { return *this = (Iu16vec4) _m_psrlwi(vec,count); }
481
482 #if defined(_ENABLE_VEC_DEBUG)
483     /* Output for Debug */
484     friend std::ostream& operator<< (std::ostream &os, const Iu16vec4 &a)
485     {
486         os << "[3]:" << _MM_4UW(3,a)
487             << " [2]:" << _MM_4UW(2,a)
488             << " [1]:" << _MM_4UW(1,a)
489             << " [0]:" << _MM_4UW(0,a);
490         return os;
491     }
492 #endif
493
494     /* Element Access for Debug, No data modified */
495     const unsigned short& operator[](int i)const
496     {
497         assert(static_cast<unsigned int>(i) < 4);    /* Only 4 elements to access */
498         return _MM_4UW(i,vec);
499     }
500
501     /* Element Access and Assignment for Debug */
502     unsigned short& operator[](int i)
503     {
504         assert(static_cast<unsigned int>(i) < 4);    /* Only 4 elements to access */
505         return _MM_4UW(i,vec);
506     }
507 };
508
509 inline Iu16vec4 operator*(const Iu16vec4 &a, const Iu16vec4 &b)     { return _m_pmullw(a,b); }
510 inline Iu16vec4 cmpeq(const Iu16vec4 &a, const Iu16vec4 &b)           { return _m_pcmpeqw(a,b); }
511 inline Iu16vec4 cmpneq(const Iu16vec4 &a, const Iu16vec4 &b)           { return _m_pandn(_m_pcmpeqw(a,b), M64(0xffffffffffffffffi64)); }
512
513 inline Iu16vec4 sat_add(const Iu16vec4 &a, const Iu16vec4 &b)    { return _m_paddusw(a,b); }
514 inline Iu16vec4 sat_sub(const Iu16vec4 &a, const Iu16vec4 &b)    { return _m_psubusw(a,b); }
515
516 inline Iu16vec4 unpack_low(const Iu16vec4 &a, const Iu16vec4 &b)     { return _m_punpcklwd(a,b); }
517 inline Iu16vec4 unpack_high(const Iu16vec4 &a, const Iu16vec4 &b)     { return _m_punpckhwd(a,b); }
518
519 /* I8vec8 Class:
520  * 8 elements, each element either unsigned or signed char
521  */
522 class I8vec8 : public M64
523 {
524 public:
525     I8vec8() { }
526     I8vec8(__m64 mm) : M64(mm) { }
527     EXPLICIT I8vec8(__int64 i) : M64 (i) { }
528     EXPLICIT I8vec8(int i) : M64 (i) { }
529
530     /* Assignment Operator */
531     I8vec8& operator= (const M64 &a)        { return *this = (I8vec8) a; }
532
533     /* Logical Assignment Operators */
534     I8vec8& operator&=(const M64 &a)        { return *this = (I8vec8) _m_pand(vec,a); }
535     I8vec8& operator|=(const M64 &a)        { return *this = (I8vec8) _m_por(vec,a); }
536     I8vec8& operator^=(const M64 &a)        { return *this = (I8vec8) _m_pxor(vec,a); }
537
538     /* Addition & Subtraction Assignment Operators */
539     I8vec8& operator +=(const I8vec8 &a)    { return *this = (I8vec8) _m_paddb(vec,a); }
540     I8vec8& operator -=(const I8vec8 &a)    { return *this = (I8vec8) _m_psubb(vec,a); }
541 };
542
543
544 inline I8vec8 cmpeq(const I8vec8 &a, const I8vec8 &b)         { return _m_pcmpeqb(a,b); }
545 inline I8vec8 cmpneq(const I8vec8 &a, const I8vec8 &b)         { return _m_pandn(_m_pcmpeqb(a,b), M64(0xffffffffffffffffi64)); }
546
547 inline I8vec8 unpack_low(const I8vec8 &a, const I8vec8 &b)     { return _m_punpcklbw(a,b); }
548 inline I8vec8 unpack_high(const I8vec8 &a, const I8vec8 &b) { return _m_punpckhbw(a,b); }
549
550 /* Is8vec8 Class:
551  * 8 elements, each element signed char
552  */
553 class Is8vec8 : public I8vec8
554 {
555 public:
556     Is8vec8() { }
557     Is8vec8(__m64 mm) : I8vec8(mm) { }
558     Is8vec8(signed char s0,signed char s1,signed char s2,signed char s3,signed char s4,signed char s5,signed char s6,signed char s7)
559      {
560         _MM_8B(0,vec) = s7;
561         _MM_8B(1,vec) = s6;
562         _MM_8B(2,vec) = s5;
563         _MM_8B(3,vec) = s4;
564         _MM_8B(4,vec) = s3;
565         _MM_8B(5,vec) = s2;
566         _MM_8B(6,vec) = s1;
567         _MM_8B(7,vec) = s0;
568     }
569
570     EXPLICIT Is8vec8(__int64 i) : I8vec8 (i) { }
571     EXPLICIT Is8vec8(int i) : I8vec8 (i) { }
572
573     /* Assignment Operator */
574     Is8vec8& operator= (const M64 &a)        { return *this = (Is8vec8) a; }
575
576     /* Logical Assignment Operators */
577     Is8vec8& operator&=(const M64 &a)        { return *this = (Is8vec8) _m_pand(vec,a); }
578     Is8vec8& operator|=(const M64 &a)        { return *this = (Is8vec8) _m_por(vec,a); }
579     Is8vec8& operator^=(const M64 &a)        { return *this = (Is8vec8) _m_pxor(vec,a); }
580
581     /* Addition & Subtraction Assignment Operators */
582     Is8vec8& operator +=(const I8vec8 &a)    { return *this = (Is8vec8) _m_paddb(vec,a); }
583     Is8vec8& operator -=(const I8vec8 &a)    { return *this = (Is8vec8) _m_psubb(vec,a); }
584
585 #if defined(_ENABLE_VEC_DEBUG)
586     /* Output for Debug */
587     friend std::ostream& operator<< (std::ostream &os, const Is8vec8 &a)
588     {
589         os << "[7]:" << short(_MM_8B(7,a))
590             << " [6]:" << short(_MM_8B(6,a))
591             << " [5]:" << short(_MM_8B(5,a))
592             << " [4]:" << short(_MM_8B(4,a))
593             << " [3]:" << short(_MM_8B(3,a))
594             << " [2]:" << short(_MM_8B(2,a))
595             << " [1]:" << short(_MM_8B(1,a))
596             << " [0]:" << short(_MM_8B(0,a));
597         return os;
598     }
599 #endif
600
601     /* Element Access for Debug, No data modified */
602     const signed char& operator[](int i)const
603     {
604         assert(static_cast<unsigned int>(i) < 8);    /* Only 8 elements to access */
605         return _MM_8B(i,vec);
606     }
607
608     /* Element Access and Assignment for Debug */
609     signed char& operator[](int i)
610     {
611         assert(static_cast<unsigned int>(i) < 8);    /* Only 8 elements to access */
612         return _MM_8B(i,vec);
613     }
614 };
615
616 /* Additional Is8vec8 functions: compares, unpacks, sat add/sub */
617 inline Is8vec8 cmpeq(const Is8vec8 &a, const Is8vec8 &b)         { return _m_pcmpeqb(a,b); }
618 inline Is8vec8 cmpneq(const Is8vec8 &a, const Is8vec8 &b)         { return _m_pandn(_m_pcmpeqb(a,b), M64(0xffffffffffffffffi64)); }
619 inline Is8vec8 cmpgt(const Is8vec8 &a, const Is8vec8 &b)        { return _m_pcmpgtb(a,b); }
620 inline Is8vec8 cmplt(const Is8vec8 &a, const Is8vec8 &b)        { return _m_pcmpgtb(b,a); }
621 inline Is8vec8 cmple(const Is8vec8 &a, const Is8vec8 &b)        { return _m_pandn(_m_pcmpgtb(a,b), M64(0xffffffffffffffffi64)); }
622 inline Is8vec8 cmpge(const Is8vec8 &a, const Is8vec8 &b)        { return _m_pandn(_m_pcmpgtb(b,a), M64(0xffffffffffffffffi64)); }
623
624 inline Is8vec8 unpack_low(const Is8vec8 &a, const Is8vec8 &b)     { return _m_punpcklbw(a,b); }
625 inline Is8vec8 unpack_high(const Is8vec8 &a, const Is8vec8 &b)     { return _m_punpckhbw(a,b); }
626
627 inline Is8vec8 sat_add(const Is8vec8 &a, const Is8vec8 &b)        { return _m_paddsb(a,b); }
628 inline Is8vec8 sat_sub(const Is8vec8 &a, const Is8vec8 &b)        { return _m_psubsb(a,b); }
629
630 /* Iu8vec8 Class:
631  * 8 elements, each element unsigned char
632  */
633 class Iu8vec8 : public I8vec8
634 {
635 public:
636     Iu8vec8() { }
637     Iu8vec8(__m64 mm) : I8vec8(mm) { }
638     Iu8vec8(unsigned char s0,unsigned char s1,unsigned char s2,unsigned char s3,unsigned char s4,unsigned char s5,unsigned char s6,unsigned char s7)
639     {
640         _MM_8UB(0,vec) = s7;
641         _MM_8UB(1,vec) = s6;
642         _MM_8UB(2,vec) = s5;
643         _MM_8UB(3,vec) = s4;
644         _MM_8UB(4,vec) = s3;
645         _MM_8UB(5,vec) = s2;
646         _MM_8UB(6,vec) = s1;
647         _MM_8UB(7,vec) = s0;
648     }
649     EXPLICIT Iu8vec8(__int64 i) : I8vec8 (i) { }
650     EXPLICIT Iu8vec8(int i) : I8vec8 (i) { }
651
652     /* Assignment Operator */
653     Iu8vec8& operator= (const M64 &a)        { return *this = (Iu8vec8) a; }
654     /* Logical Assignment Operators */
655     Iu8vec8& operator&=(const M64 &a)        { return *this = (Iu8vec8) _m_pand(vec,a); }
656     Iu8vec8& operator|=(const M64 &a)        { return *this = (Iu8vec8) _m_por(vec,a); }
657     Iu8vec8& operator^=(const M64 &a)        { return *this = (Iu8vec8) _m_pxor(vec,a); }
658     /* Addition & Subtraction Assignment Operators */
659     Iu8vec8& operator +=(const I8vec8 &a)    { return *this = (Iu8vec8) _m_paddb(vec,a); }
660     Iu8vec8& operator -=(const I8vec8 &a)    { return *this = (Iu8vec8) _m_psubb(vec,a); }
661
662 #if defined(_ENABLE_VEC_DEBUG)
663     /* Output for Debug */
664     friend std::ostream& operator << (std::ostream &os, const Iu8vec8 &a)
665     {
666          os << "[7]:"  << unsigned short(_MM_8UB(7,a))
667             << " [6]:" << unsigned short(_MM_8UB(6,a))
668             << " [5]:" << unsigned short(_MM_8UB(5,a))
669             << " [4]:" << unsigned short(_MM_8UB(4,a))
670             << " [3]:" << unsigned short(_MM_8UB(3,a))
671             << " [2]:" << unsigned short(_MM_8UB(2,a))
672             << " [1]:" << unsigned short(_MM_8UB(1,a))
673             << " [0]:" << unsigned short(_MM_8UB(0,a));
674         return os;
675     }
676 #endif
677
678     /* Element Access for Debug, No data modified */
679     const unsigned char& operator[](int i)const
680     {
681         assert(static_cast<unsigned int>(i) < 8);    /* Only 8 elements to access */
682         return _MM_8UB(i,vec);
683     }
684
685     /* Element Access for Debug */
686     unsigned char& operator[](int i)
687     {
688         assert(static_cast<unsigned int>(i) < 8);    /* Only 8 elements to access */
689         return _MM_8UB(i,vec);
690     }
691 };
692
693 /* Additional Iu8vec8 functions: cmpeq,cmpneq, unpacks, sat add/sub */
694 inline Iu8vec8 cmpeq(const Iu8vec8 &a, const Iu8vec8 &b)         { return _m_pcmpeqb(a,b); }
695 inline Iu8vec8 cmpneq(const Iu8vec8 &a, const Iu8vec8 &b)         { return _m_pandn(_m_pcmpeqb(a,b), M64(0xffffffffffffffffi64)); }
696
697 inline Iu8vec8 unpack_low(const Iu8vec8 &a, const Iu8vec8 &b)     { return _m_punpcklbw(a,b); }
698 inline Iu8vec8 unpack_high(const Iu8vec8 &a, const Iu8vec8 &b)     { return _m_punpckhbw(a,b); }
699
700 inline Iu8vec8 sat_add(const Iu8vec8 &a, const Iu8vec8 &b)        { return _m_paddusb(a,b); }
701 inline Iu8vec8 sat_sub(const Iu8vec8 &a, const Iu8vec8 &b)        { return _m_psubusb(a,b); }
702
703 inline Is16vec4 pack_sat(const Is32vec2 &a, const Is32vec2 &b)        { return _m_packssdw(a,b); }
704 inline Is8vec8 pack_sat(const Is16vec4 &a, const Is16vec4 &b)         { return _m_packsswb(a,b); }
705 inline Iu8vec8 packu_sat(const Is16vec4 &a, const Is16vec4 &b)     { return _m_packuswb(a,b); }
706
707 /********************************* Logicals ****************************************/
708 #define IVEC_LOGICALS(vect,element) \
709 inline I##vect##vec##element operator& (const I##vect##vec##element &a, const I##vect##vec##element &b) \
710 { return _m_pand( a,b); } \
711 inline I##vect##vec##element operator| (const I##vect##vec##element &a, const I##vect##vec##element &b) \
712 { return _m_por( a,b); } \
713 inline I##vect##vec##element operator^ (const I##vect##vec##element &a, const I##vect##vec##element &b) \
714 { return _m_pxor( a,b); } \
715 inline I##vect##vec##element andnot (const I##vect##vec##element &a, const I##vect##vec##element &b) \
716 { return _m_pandn( a,b); }
717
718 IVEC_LOGICALS(8,8)
719 IVEC_LOGICALS(u8,8)
720 IVEC_LOGICALS(s8,8)
721 IVEC_LOGICALS(16,4)
722 IVEC_LOGICALS(u16,4)
723 IVEC_LOGICALS(s16,4)
724 IVEC_LOGICALS(32,2)
725 IVEC_LOGICALS(u32,2)
726 IVEC_LOGICALS(s32,2)
727 IVEC_LOGICALS(64,1)
728 #undef IVEC_LOGICALS
729
730 /********************************* Add & Sub ****************************************/
731 #define IVEC_ADD_SUB(vect,element,opsize) \
732 inline I##vect##vec##element operator+ (const I##vect##vec##element &a, const I##vect##vec##element &b) \
733 { return _m_padd##opsize( a,b); } \
734 inline I##vect##vec##element operator- (const I##vect##vec##element &a, const I##vect##vec##element &b) \
735 { return _m_psub##opsize( a,b); }
736
737 IVEC_ADD_SUB(8,8, b)
738 IVEC_ADD_SUB(u8,8, b)
739 IVEC_ADD_SUB(s8,8, b)
Lines 740 ... 749 are skipped.
750  *    Where OP is one of the possible comparision operators.                                     *
751  *    Example: r = select_eq(a,b,c,d);                                                         *
752  *    if "member at position x of the vector a" == "member at position x of vector b"          *
753  *    assign the corresponding member in r from c, else assign from d.                             *
754  ********************************* Conditional Select ****************************************/
755
756 #define IVEC_SELECT(vect12,vect34,element,selop,arg1,arg2) \
757     inline I##vect34##vec##element select_##selop (const I##vect12##vec##element &a, const I##vect12##vec##element &b, const I##vect34##vec##element &c, const I##vect34##vec##element &d)          \
758 {                                                                \
759     I##vect12##vec##element mask = cmp##selop(a,b);                        \
760     return( I##vect34##vec##element ((mask & arg1 ) | I##vect12##vec##element ((_m_pandn(mask, arg2 )))));    \
761 }
762 IVEC_SELECT(8,s8,8,eq,c,d)
763 IVEC_SELECT(8,u8,8,eq,c,d)
764 IVEC_SELECT(8,8,8,eq,c,d)
765 IVEC_SELECT(8,s8,8,neq,c,d)
766 IVEC_SELECT(8,u8,8,neq,c,d)
767 IVEC_SELECT(8,8,8,neq,c,d)
768
769 IVEC_SELECT(16,s16,4,eq,c,d)
770 IVEC_SELECT(16,u16,4,eq,c,d)
771 IVEC_SELECT(16,16,4,eq,c,d)
772 IVEC_SELECT(16,s16,4,neq,c,d)
773 IVEC_SELECT(16,u16,4,neq,c,d)
774 IVEC_SELECT(16,16,4,neq,c,d)
775
776 IVEC_SELECT(32,s32,2,eq,c,d)
777 IVEC_SELECT(32,u32,2,eq,c,d)
778 IVEC_SELECT(32,32,2,eq,c,d)
779 IVEC_SELECT(32,s32,2,neq,c,d)
780 IVEC_SELECT(32,u32,2,neq,c,d)
781 IVEC_SELECT(32,32,2,neq,c,d)
782
783
784 IVEC_SELECT(s8,s8,8,gt,c,d)
785 IVEC_SELECT(s8,u8,8,gt,c,d)
786 IVEC_SELECT(s8,8,8,gt,c,d)
787 IVEC_SELECT(s8,s8,8,lt,c,d)
788 IVEC_SELECT(s8,u8,8,lt,c,d)
789 IVEC_SELECT(s8,8,8,lt,c,d)
790 IVEC_SELECT(s8,s8,8,le,c,d)
791 IVEC_SELECT(s8,u8,8,le,c,d)
792 IVEC_SELECT(s8,8,8,le,c,d)
793 IVEC_SELECT(s8,s8,8,ge,c,d)
794 IVEC_SELECT(s8,u8,8,ge,c,d)
795 IVEC_SELECT(s8,8,8,ge,c,d)
796
797 IVEC_SELECT(s16,s16,4,gt,c,d)
798 IVEC_SELECT(s16,u16,4,gt,c,d)
799 IVEC_SELECT(s16,16,4,gt,c,d)
800 IVEC_SELECT(s16,s16,4,lt,c,d)
801 IVEC_SELECT(s16,u16,4,lt,c,d)
802 IVEC_SELECT(s16,16,4,lt,c,d)
803 IVEC_SELECT(s16,s16,4,le,c,d)
804 IVEC_SELECT(s16,u16,4,le,c,d)
805 IVEC_SELECT(s16,16,4,le,c,d)
806 IVEC_SELECT(s16,s16,4,ge,c,d)
807 IVEC_SELECT(s16,u16,4,ge,c,d)
808 IVEC_SELECT(s16,16,4,ge,c,d)
809
810 IVEC_SELECT(s32,s32,2,gt,c,d)
811 IVEC_SELECT(s32,u32,2,gt,c,d)
812 IVEC_SELECT(s32,32,2,gt,c,d)
813 IVEC_SELECT(s32,s32,2,lt,c,d)
814 IVEC_SELECT(s32,u32,2,lt,c,d)
815 IVEC_SELECT(s32,32,2,lt,c,d)
816 IVEC_SELECT(s32,s32,2,le,c,d)
817 IVEC_SELECT(s32,u32,2,le,c,d)
818 IVEC_SELECT(s32,32,2,le,c,d)
819 IVEC_SELECT(s32,s32,2,ge,c,d)
820 IVEC_SELECT(s32,u32,2,ge,c,d)
821 IVEC_SELECT(s32,32,2,ge,c,d)
822
823
824 #undef IVEC_SELECT
825
826 inline static void empty(void)         { _m_empty(); }
827
828 #if defined(_SILENCE_IVEC_C4799)
829     #pragma warning(pop)
830 #endif
831
832 #endif /* defined(_M_CEE_PURE) */
833
834 #endif /* RC_INVOKED */
835 #endif /* _IVEC_H_INCLUDED */
836