4d38c40bc8e2ef98d6056421545329ee51f0a5c4
[mono.git] / mcs / class / Mono.Simd / Mono.Simd / Vector4f.cs
1 // Vector4f.cs
2 //
3 // Author:
4 //   Rodrigo Kumpera (rkumpera@novell.com)
5 //
6 // (C) 2008 Novell, Inc. (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 //
27
28 using System;\r
29 using System.Runtime.InteropServices;\r
30 \r
31 namespace Mono.Simd\r
32 {\r
33         public enum ShuffleSel\r
34         {
35                 XFromX,
36                 XFromY,
37                 XFromZ,
38                 XFromW,
39
40                 YFromX = 0x00,
41                 YFromY = 0x04,
42                 YFromZ = 0x08,
43                 YFromW = 0x0C,
44
45                 ZFromX = 0x00,
46                 ZFromY = 0x10,
47                 ZFromZ = 0x20,
48                 ZFromW = 0x30,
49
50                 WFromX = 0x00,
51                 WFromY = 0x40,
52                 WFromZ = 0x80,
53                 WFromW = 0xC0,\r
54
55                 /*Expand a single element into all elements*/
56                 ExpandX = XFromX | YFromX | ZFromX | WFromX,
57                 ExpandY = XFromY | YFromY | ZFromY | WFromY,
58                 ExpandZ = XFromZ | YFromZ | ZFromZ | WFromZ,
59                 ExpandW = XFromW | YFromW | ZFromW | WFromW,
60
61                 /*Expand a pair of elements (x,y,z,w) -> (x,x,y,y)*/
62                 ExpandXY = XFromX | YFromX | ZFromY | WFromY,
63                 ExpandZW = XFromZ | YFromZ | ZFromW | WFromW,
64
65                 /*Expand interleaving elements (x,y,z,w) -> (x,y,x,y)*/
66                 ExpandInterleavedXY = XFromX | YFromY | ZFromX | WFromY,
67                 ExpandInterleavedZW = XFromZ | YFromW | ZFromZ | WFromW,
68
69                 /*Rotate elements*/
70                 RotateRight = XFromY | YFromZ | ZFromW | WFromX,
71                 RotateLeft = XFromW | YFromX | ZFromY | WFromZ,
72
73                 /*Swap order*/
74                 Swap = XFromW | YFromZ | ZFromY | WFromX,
75         };\r
76
77 /*
78         TODO:
79         Unary - (implemented as mulps [-1,-1,-1,-1])
80         Abs (implemented as pand [7fffffff,...] )
81         Comparison functions
82         Mask extraction function
83         Setters
84         vector x float ops
85         Single float constructor (expand it to the 4 positions)
86                 Replace Shuffle with less bug prone methods
87 */
88 \r
89         [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 16)]\r
90         public struct Vector4f\r
91         {\r
92                 private float x;\r
93                 private float y;\r
94                 private float z;\r
95                 private float w;\r
96 \r
97                 public float X { get { return x; } set { x = value; } }\r
98                 public float Y { get { return y; } set { y = value; } }\r
99                 public float Z { get { return z; } set { z = value; } }\r
100                 public float W { get { return w; } set { w = value; } }\r
101 \r
102                 public Vector4f (float x, float y, float z, float w)\r
103                 {\r
104                         this.x = x;\r
105                         this.y = y;\r
106                         this.z = z;\r
107                         this.w = w;\r
108                 }
109
110                 [Acceleration (AccelMode.SSE1)]
111                 public static unsafe Vector4f operator & (Vector4f v1, Vector4f v2)\r
112                 {\r
113                         Vector4f res = new Vector4f ();
114                         int *a = (int*)&v1;\r
115                         int *b = (int*)&v2;\r
116                         int *c = (int*)&res;
117                         *c++ = *a++ & *b++;\r
118                         *c++ = *a++ & *b++;\r
119                         *c++ = *a++ & *b++;\r
120                         *c = *a & *b;
121                         return res;\r
122                 }\r
123
124                 [Acceleration (AccelMode.SSE1)]
125                 public static unsafe Vector4f operator | (Vector4f v1, Vector4f v2)\r
126                 {\r
127                         Vector4f res = new Vector4f ();
128                         int *a = (int*)&v1;\r
129                         int *b = (int*)&v2;\r
130                         int *c = (int*)&res;
131                         *c++ = *a++ | *b++;\r
132                         *c++ = *a++ | *b++;\r
133                         *c++ = *a++ | *b++;\r
134                         *c = *a | *b;
135                         return res;\r
136                 }\r
137
138                 [Acceleration (AccelMode.SSE1)]
139                 public static unsafe Vector4f operator ^ (Vector4f v1, Vector4f v2)\r
140                 {\r
141                         Vector4f res = new Vector4f ();
142                         int *a = (int*)&v1;\r
143                         int *b = (int*)&v2;\r
144                         int *c = (int*)&res;
145                         *c++ = *a++ ^ *b++;\r
146                         *c++ = *a++ ^ *b++;\r
147                         *c++ = *a++ ^ *b++;\r
148                         *c = *a ^ *b;
149                         return res;\r
150                 }\r
151 \r
152                 [Acceleration (AccelMode.SSE1)]
153                 public static Vector4f operator + (Vector4f v1, Vector4f v2)\r
154                 {\r
155                         return new Vector4f (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);\r
156                 }\r
157 \r
158                 [Acceleration (AccelMode.SSE1)]
159                 public static Vector4f operator - (Vector4f v1, Vector4f v2)\r
160                 {\r
161                         return new Vector4f (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);\r
162                 }\r
163 \r
164                 [Acceleration (AccelMode.SSE1)]
165                 public static Vector4f operator * (Vector4f v1, Vector4f v2)\r
166                 {\r
167                         return new Vector4f (v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w);\r
168                 }\r
169 \r
170                 [Acceleration (AccelMode.SSE1)]
171                 public static Vector4f operator / (Vector4f v1, Vector4f v2)\r
172                 {\r
173                         return new Vector4f (v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w);\r
174                 }\r
175
176                 [Acceleration (AccelMode.SSE1)]
177                 public static unsafe Vector4f AndNot (Vector4f v1, Vector4f v2)\r
178                 {\r
179                         Vector4f res = new Vector4f ();
180                         int *a = (int*)&v1;\r
181                         int *b = (int*)&v2;\r
182                         int *c = (int*)&res;
183                         *c++ = ~*a++ & *b++;\r
184                         *c++ = ~*a++ & *b++;\r
185                         *c++ = ~*a++ & *b++;\r
186                         *c = ~*a & *b;
187                         return res;\r
188                 }
189 \r
190                 [Acceleration (AccelMode.SSE1)]
191                 public static Vector4f Sqrt (Vector4f v1)\r
192                 {\r
193                         return new Vector4f ((float)System.Math.Sqrt ((float)v1.x),\r
194                                                                 (float)System.Math.Sqrt ((float)v1.y),\r
195                                                                 (float)System.Math.Sqrt ((float)v1.z),\r
196                                                                 (float)System.Math.Sqrt ((float)v1.w));\r
197                 }\r
198 \r
199                 [Acceleration (AccelMode.SSE1)]
200                 public static Vector4f InvSqrt (Vector4f v1)\r
201                 {\r
202                         return new Vector4f ((float)(1.0 / System.Math.Sqrt ((float)v1.x)),\r
203                                                                 (float)(1.0 / System.Math.Sqrt ((float)v1.y)),\r
204                                                                 (float)(1.0 / System.Math.Sqrt ((float)v1.z)),\r
205                                                                 (float)(1.0 / System.Math.Sqrt ((float)v1.w)));\r
206                 }\r
207
208                 [Acceleration (AccelMode.SSE1)]
209                 public static Vector4f Reciprocal (Vector4f v1)\r
210                 {\r
211                         return new Vector4f (1.0f / v1.x, 1.0f / v1.y, 1.0f / v1.z, 1.0f / v1.w);\r
212                 }
213 \r
214                 [Acceleration (AccelMode.SSE1)]
215                 public static Vector4f Max (Vector4f v1, Vector4f v2)\r
216                 {\r
217                         return new Vector4f (System.Math.Max (v1.x, v2.x),\r
218                                                                 System.Math.Max (v1.y, v2.y),\r
219                                                                 System.Math.Max (v1.z, v2.z),\r
220                                                                 System.Math.Max (v1.w, v2.w));\r
221                 }\r
222 \r
223                 [Acceleration (AccelMode.SSE1)]
224                 public static Vector4f Min (Vector4f v1, Vector4f v2)\r
225                 {\r
226                         return new Vector4f (System.Math.Min (v1.x, v2.x),\r
227                                                                 System.Math.Min (v1.y, v2.y),\r
228                                                                 System.Math.Min (v1.z, v2.z),\r
229                                                                 System.Math.Min (v1.w, v2.w));\r
230                 }\r
231 \r
232                 [Acceleration (AccelMode.SSE3)]
233                 public static Vector4f HorizontalAdd (Vector4f v1, Vector4f v2)\r
234                 {\r
235                         return new Vector4f (v1.x + v1.y, v1.z + v1.w, v2.x + v2.y, v2.z + v2.w);\r
236                 }\r
237
238                 [Acceleration (AccelMode.SSE3)]
239                 public static Vector4f AddSub (Vector4f v1, Vector4f v2)\r
240                 {\r
241                         return new Vector4f (v1.x - v2.x, v1.y + v2.y, v1.z - v2.z, v1.w + v2.w);\r
242                 }\r
243 \r
244                 [Acceleration (AccelMode.SSE3)]
245                 public static Vector4f HorizontalSub (Vector4f v1, Vector4f v2)\r
246                 {\r
247                         return new Vector4f (v1.x - v1.y, v1.z - v1.w, v2.x - v2.y, v2.z - v2.w);\r
248                 }\r
249 \r
250                 [Acceleration (AccelMode.SSE1)]
251                 public static Vector4f InterleaveHigh (Vector4f v1, Vector4f v2)\r
252                 {\r
253                         return new Vector4f (v1.z, v2.z, v1.w, v2.w);\r
254                 }\r
255
256                 [Acceleration (AccelMode.SSE1)]
257                 public static Vector4f InterleaveLow (Vector4f v1, Vector4f v2)\r
258                 {\r
259                         return new Vector4f (v1.x, v2.x, v1.y, v2.y);\r
260                 }
261
262                 /*Same as a == b. */
263                 [Acceleration (AccelMode.SSE1)]
264                 public unsafe static Vector4f CompareEqual (Vector4f v1, Vector4f v2)
265                 {
266                         Vector4f res = new Vector4f ();
267                         int *c = (int*)&res;
268                         *c++ = v1.x == v2.x ? -1 : 0;\r
269                         *c++ = v1.y == v2.y ? -1 : 0;\r
270                         *c++ = v1.z == v2.z ? -1 : 0;\r
271                         *c = v1.w == v2.w ? -1 : 0;
272                         return res;\r            }
273
274                 /*Same as a < b. */
275                 [Acceleration (AccelMode.SSE1)]
276                 public unsafe static Vector4f CompareLessThan (Vector4f v1, Vector4f v2)
277                 {
278                         Vector4f res = new Vector4f ();
279                         int *c = (int*)&res;
280                         *c++ = v1.x < v2.x ? -1 : 0;\r
281                         *c++ = v1.y < v2.y ? -1 : 0;\r
282                         *c++ = v1.z < v2.z ? -1 : 0;\r
283                         *c = v1.w < v2.w ? -1 : 0;
284                         return res;
285                 }
286
287                 /*Same as a <= b. */
288                 [Acceleration (AccelMode.SSE1)]
289                 public unsafe static Vector4f CompareLessEqual (Vector4f v1, Vector4f v2)
290                 {
291                         Vector4f res = new Vector4f ();
292                         int *c = (int*)&res;
293                         *c++ = v1.x <= v2.x ? -1 : 0;\r
294                         *c++ = v1.y <= v2.y ? -1 : 0;\r
295                         *c++ = v1.z <= v2.z ? -1 : 0;\r
296                         *c = v1.w <= v2.w ? -1 : 0;
297                         return res;\r            }
298
299                 /*Same float.IsNaN (a) || float.IsNaN (b). */
300                 [Acceleration (AccelMode.SSE1)]
301                 public unsafe static Vector4f CompareUnordered (Vector4f v1, Vector4f v2)
302                 {
303                         Vector4f res = new Vector4f ();
304                         int *c = (int*)&res;
305                         *c++ = float.IsNaN (v1.x) || float.IsNaN (v2.x) ? -1 : 0;\r
306                         *c++ = float.IsNaN (v1.y) || float.IsNaN (v2.y) ? -1 : 0;\r
307                         *c++ = float.IsNaN (v1.z) || float.IsNaN (v2.z) ? -1 : 0;\r
308                         *c = float.IsNaN (v1.w) || float.IsNaN (v2.w) ? -1 : 0;
309                         return res;\r            }
310
311                 /*Same as a != b. */
312                 [Acceleration (AccelMode.SSE1)]
313                 public unsafe static Vector4f CompareNotEqual (Vector4f v1, Vector4f v2)
314                 {
315                         Vector4f res = new Vector4f ();
316                         int *c = (int*)&res;
317                         *c++ = v1.x != v2.x ? -1 : 0;\r
318                         *c++ = v1.y != v2.y ? -1 : 0;\r
319                         *c++ = v1.z != v2.z ? -1 : 0;\r
320                         *c = v1.w != v2.w ? -1 : 0;
321                         return res;
322                 }
323
324                 /*Same as !(a < b). */
325                 [Acceleration (AccelMode.SSE1)]
326                 public unsafe static Vector4f CompareNotLessThan (Vector4f v1, Vector4f v2)
327                 {
328                         Vector4f res = new Vector4f ();
329                         int *c = (int*)&res;
330                         *c++ = v1.x < v2.x ? 0 : -1;\r
331                         *c++ = v1.y < v2.y ? 0 : -1;\r
332                         *c++ = v1.z < v2.z ? 0 : -1;\r
333                         *c = v1.w < v2.w ? 0 : -1;
334                         return res;
335                 }
336
337                 /*Same as !(a <= b). */
338                 [Acceleration (AccelMode.SSE1)]
339                 public unsafe static Vector4f CompareNotLessEqual (Vector4f v1, Vector4f v2)
340                 {
341                         Vector4f res = new Vector4f ();
342                         int *c = (int*)&res;
343                         *c++ = v1.x <= v2.x ? 0 : -1;\r
344                         *c++ = v1.y <= v2.y ? 0 : -1;\r
345                         *c++ = v1.z <= v2.z ? 0 : -1;\r
346                         *c = v1.w <= v2.w ? 0 : -1;
347                         return res;
348                 }
349
350                 /*Same !float.IsNaN (a) && !float.IsNaN (b). */
351                 [Acceleration (AccelMode.SSE1)]
352                 public unsafe static Vector4f CompareOrdered (Vector4f v1, Vector4f v2)
353                 {
354                         Vector4f res = new Vector4f ();
355                         int *c = (int*)&res;
356                         *c++ = !float.IsNaN (v1.x) && !float.IsNaN (v2.x) ? -1 : 0;\r
357                         *c++ = !float.IsNaN (v1.y) && !float.IsNaN (v2.y) ? -1 : 0;\r
358                         *c++ = !float.IsNaN (v1.z) && !float.IsNaN (v2.z) ? -1 : 0;\r
359                         *c = !float.IsNaN (v1.w) && !float.IsNaN (v2.w) ? -1 : 0;
360                         return res;\r            }
361
362                 [Acceleration (AccelMode.SSE3)]
363                 public static Vector4f DuplicateLow (Vector4f v1)
364                 {
365                         return new Vector4f (v1.x, v1.x, v1.z, v1.z);
366                 }
367
368                 [Acceleration (AccelMode.SSE3)]
369                 public static Vector4f DuplicateHigh (Vector4f v1)
370                 {
371                         return new Vector4f (v1.y, v1.y, v1.w, v1.w);
372                 }
373
374                 /*
375                 The sel argument must be a value combination of ShuffleSel flags.
376                 */\r
377                 [Acceleration (AccelMode.SSE2)]
378                 public static unsafe Vector4f Shuffle (Vector4f v1, ShuffleSel sel)\r
379                 {
380                         float *ptr = (float*)&v1;
381                         int idx = (int)sel;\r
382                         return new Vector4f (*(ptr + ((idx >> 0) & 0x3)),*(ptr + ((idx >> 2) & 0x3)),*(ptr + ((idx >> 4) & 0x3)),*(ptr + ((idx >> 6) & 0x3)));\r
383                 }\r
384
385                 [CLSCompliant(false)]\r
386                 [Acceleration (AccelMode.SSE1)]
387                 public static unsafe explicit operator Vector4ui(Vector4f v)\r
388                 {\r
389                         Vector4ui* p = (Vector4ui*)&v;\r
390                         return *p;\r
391                 }\r
392
393                 [CLSCompliant(false)]\r
394                 [Acceleration (AccelMode.SSE1)]
395                 public static unsafe explicit operator Vector8us(Vector4f v)\r
396                 {\r
397                         Vector8us* p = (Vector8us*)&v;\r
398                         return *p;\r
399                 }\r
400
401                 [CLSCompliant(false)]\r
402                 [Acceleration (AccelMode.SSE1)]
403                 public static unsafe explicit operator Vector16b(Vector4f v)\r
404                 {\r
405                         Vector16b* p = (Vector16b*)&v;\r
406                         return *p;\r
407                 }\r
408
409                 [Acceleration (AccelMode.SSE1)]
410                 public static Vector4f LoadAligned (ref Vector4f v)\r
411                 {\r
412                         return v;\r
413                 }\r
414 \r
415                 [Acceleration (AccelMode.SSE1)]
416                 public static void StoreAligned (ref Vector4f res, Vector4f val)\r
417                 {\r
418                         res = val;\r
419                 }\r
420
421                 [CLSCompliant(false)]\r
422                 [Acceleration (AccelMode.SSE1)]
423                 public static unsafe Vector4f LoadAligned (Vector4f *v)\r
424                 {\r
425                         return *v;\r
426                 }\r
427 \r
428                 [CLSCompliant(false)]\r
429                 [Acceleration (AccelMode.SSE1)]
430                 public static unsafe void StoreAligned (Vector4f *res, Vector4f val)\r
431                 {\r
432                         *res = val;\r
433                 }\r
434 \r
435         }\r
436 }\r