3309a2584e979d818704ad1a9dd6b6322b74f1e7
[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                 public static unsafe Vector4f operator & (Vector4f v1, Vector4f v2)\r
111                 {\r
112                         Vector4f res = new Vector4f ();
113                         int *a = (int*)&v1;\r
114                         int *b = (int*)&v2;\r
115                         int *c = (int*)&res;
116                         *c++ = *a++ & *b++;\r
117                         *c++ = *a++ & *b++;\r
118                         *c++ = *a++ & *b++;\r
119                         *c = *a & *b;
120                         return res;\r
121                 }\r
122
123                 public static unsafe Vector4f operator | (Vector4f v1, Vector4f v2)\r
124                 {\r
125                         Vector4f res = new Vector4f ();
126                         int *a = (int*)&v1;\r
127                         int *b = (int*)&v2;\r
128                         int *c = (int*)&res;
129                         *c++ = *a++ | *b++;\r
130                         *c++ = *a++ | *b++;\r
131                         *c++ = *a++ | *b++;\r
132                         *c = *a | *b;
133                         return res;\r
134                 }\r
135
136                 public static unsafe Vector4f operator ^ (Vector4f v1, Vector4f v2)\r
137                 {\r
138                         Vector4f res = new Vector4f ();
139                         int *a = (int*)&v1;\r
140                         int *b = (int*)&v2;\r
141                         int *c = (int*)&res;
142                         *c++ = *a++ ^ *b++;\r
143                         *c++ = *a++ ^ *b++;\r
144                         *c++ = *a++ ^ *b++;\r
145                         *c = *a ^ *b;
146                         return res;\r
147                 }\r
148 \r
149                 public static Vector4f operator + (Vector4f v1, Vector4f v2)\r
150                 {\r
151                         return new Vector4f (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);\r
152                 }\r
153 \r
154                 public static Vector4f operator - (Vector4f v1, Vector4f v2)\r
155                 {\r
156                         return new Vector4f (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);\r
157                 }\r
158 \r
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                 public static Vector4f operator / (Vector4f v1, Vector4f v2)\r
165                 {\r
166                         return new Vector4f (v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w);\r
167                 }\r
168
169                 public static unsafe Vector4f AndNot (Vector4f v1, Vector4f v2)\r
170                 {\r
171                         Vector4f res = new Vector4f ();
172                         int *a = (int*)&v1;\r
173                         int *b = (int*)&v2;\r
174                         int *c = (int*)&res;
175                         *c++ = ~*a++ & *b++;\r
176                         *c++ = ~*a++ & *b++;\r
177                         *c++ = ~*a++ & *b++;\r
178                         *c = ~*a & *b;
179                         return res;\r
180                 }
181 \r
182                 public static Vector4f Sqrt (Vector4f v1)\r
183                 {\r
184                         return new Vector4f ((float)System.Math.Sqrt ((float)v1.x),\r
185                                                                 (float)System.Math.Sqrt ((float)v1.y),\r
186                                                                 (float)System.Math.Sqrt ((float)v1.z),\r
187                                                                 (float)System.Math.Sqrt ((float)v1.w));\r
188                 }\r
189 \r
190                 public static Vector4f InvSqrt (Vector4f v1)\r
191                 {\r
192                         return new Vector4f ((float)(1.0 / System.Math.Sqrt ((float)v1.x)),\r
193                                                                 (float)(1.0 / System.Math.Sqrt ((float)v1.y)),\r
194                                                                 (float)(1.0 / System.Math.Sqrt ((float)v1.z)),\r
195                                                                 (float)(1.0 / System.Math.Sqrt ((float)v1.w)));\r
196                 }\r
197
198                 public static Vector4f Reciprocal (Vector4f v1)\r
199                 {\r
200                         return new Vector4f (1.0f / v1.x, 1.0f / v1.y, 1.0f / v1.z, 1.0f / v1.w);\r
201                 }
202 \r
203                 public static Vector4f Max (Vector4f v1, Vector4f v2)\r
204                 {\r
205                         return new Vector4f (System.Math.Max (v1.x, v2.x),\r
206                                                                 System.Math.Max (v1.y, v2.y),\r
207                                                                 System.Math.Max (v1.z, v2.z),\r
208                                                                 System.Math.Max (v1.w, v2.w));\r
209                 }\r
210 \r
211                 public static Vector4f Min (Vector4f v1, Vector4f v2)\r
212                 {\r
213                         return new Vector4f (System.Math.Min (v1.x, v2.x),\r
214                                                                 System.Math.Min (v1.y, v2.y),\r
215                                                                 System.Math.Min (v1.z, v2.z),\r
216                                                                 System.Math.Min (v1.w, v2.w));\r
217                 }\r
218 \r
219                 public static Vector4f HorizontalAdd (Vector4f v1, Vector4f v2)\r
220                 {\r
221                         return new Vector4f (v1.x + v1.y, v1.z + v1.w, v2.x + v2.y, v2.z + v2.w);\r
222                 }\r
223
224                 public static Vector4f AddSub (Vector4f v1, Vector4f v2)\r
225                 {\r
226                         return new Vector4f (v1.x - v2.x, v1.y + v2.y, v1.z - v2.z, v1.w + v2.w);\r
227                 }\r
228 \r
229                 public static Vector4f HorizontalSub (Vector4f v1, Vector4f v2)\r
230                 {\r
231                         return new Vector4f (v1.x - v1.y, v1.z - v1.w, v2.x - v2.y, v2.z - v2.w);\r
232                 }\r
233 \r
234                 public static Vector4f InterleaveHigh (Vector4f v1, Vector4f v2)\r
235                 {\r
236                         return new Vector4f (v1.z, v2.z, v1.w, v2.w);\r
237                 }\r
238
239                 public static Vector4f InterleaveLow (Vector4f v1, Vector4f v2)\r
240                 {\r
241                         return new Vector4f (v1.x, v2.x, v1.y, v2.y);\r
242                 }
243
244                 /*Same as a == b. */
245                 public unsafe static Vector4f CompareEquals (Vector4f v1, Vector4f v2)
246                 {
247                         Vector4f res = new Vector4f ();
248                         int *c = (int*)&res;
249                         *c++ = v1.x == v2.x ? -1 : 0;\r
250                         *c++ = v1.y == v2.y ? -1 : 0;\r
251                         *c++ = v1.z == v2.z ? -1 : 0;\r
252                         *c = v1.w == v2.w ? -1 : 0;
253                         return res;\r            }
254
255                 /*Same as a < b. */
256                 public unsafe static Vector4f CompareLessThan (Vector4f v1, Vector4f v2)
257                 {
258                         Vector4f res = new Vector4f ();
259                         int *c = (int*)&res;
260                         *c++ = v1.x < v2.x ? -1 : 0;\r
261                         *c++ = v1.y < v2.y ? -1 : 0;\r
262                         *c++ = v1.z < v2.z ? -1 : 0;\r
263                         *c = v1.w < v2.w ? -1 : 0;
264                         return res;
265                 }
266
267                 /*Same as a <= b. */
268                 public unsafe static Vector4f CompareLessEqual (Vector4f v1, Vector4f v2)
269                 {
270                         Vector4f res = new Vector4f ();
271                         int *c = (int*)&res;
272                         *c++ = v1.x <= v2.x ? -1 : 0;\r
273                         *c++ = v1.y <= v2.y ? -1 : 0;\r
274                         *c++ = v1.z <= v2.z ? -1 : 0;\r
275                         *c = v1.w <= v2.w ? -1 : 0;
276                         return res;\r            }
277
278                 /*Same float.IsNaN (a) || float.IsNaN (b). */
279                 public unsafe static Vector4f CompareUnordered (Vector4f v1, Vector4f v2)
280                 {
281                         Vector4f res = new Vector4f ();
282                         int *c = (int*)&res;
283                         *c++ = float.IsNaN (v1.x) || float.IsNaN (v2.x) ? -1 : 0;\r
284                         *c++ = float.IsNaN (v1.y) || float.IsNaN (v2.y) ? -1 : 0;\r
285                         *c++ = float.IsNaN (v1.z) || float.IsNaN (v2.z) ? -1 : 0;\r
286                         *c = float.IsNaN (v1.w) || float.IsNaN (v2.w) ? -1 : 0;
287                         return res;\r            }
288
289                 /*Same as a != b. */
290                 public unsafe static Vector4f CompareNotEqual (Vector4f v1, Vector4f v2)
291                 {
292                         Vector4f res = new Vector4f ();
293                         int *c = (int*)&res;
294                         *c++ = v1.x != v2.x ? -1 : 0;\r
295                         *c++ = v1.y != v2.y ? -1 : 0;\r
296                         *c++ = v1.z != v2.z ? -1 : 0;\r
297                         *c = v1.w != v2.w ? -1 : 0;
298                         return res;
299                 }
300
301                 /*Same as !(a < b). */
302                 public unsafe static Vector4f CompareNotLessThan (Vector4f v1, Vector4f v2)
303                 {
304                         Vector4f res = new Vector4f ();
305                         int *c = (int*)&res;
306                         *c++ = v1.x < v2.x ? 0 : -1;\r
307                         *c++ = v1.y < v2.y ? 0 : -1;\r
308                         *c++ = v1.z < v2.z ? 0 : -1;\r
309                         *c = v1.w < v2.w ? 0 : -1;
310                         return res;
311                 }
312
313                 /*Same as !(a <= b). */
314                 public unsafe static Vector4f CompareNotLessEqual (Vector4f v1, Vector4f v2)
315                 {
316                         Vector4f res = new Vector4f ();
317                         int *c = (int*)&res;
318                         *c++ = v1.x <= v2.x ? 0 : -1;\r
319                         *c++ = v1.y <= v2.y ? 0 : -1;\r
320                         *c++ = v1.z <= v2.z ? 0 : -1;\r
321                         *c = v1.w <= v2.w ? 0 : -1;
322                         return res;
323                 }
324
325                 /*Same !float.IsNaN (a) && !float.IsNaN (b). */
326                 public unsafe static Vector4f CompareOrdered (Vector4f v1, Vector4f v2)
327                 {
328                         Vector4f res = new Vector4f ();
329                         int *c = (int*)&res;
330                         *c++ = !float.IsNaN (v1.x) && !float.IsNaN (v2.x) ? -1 : 0;\r
331                         *c++ = !float.IsNaN (v1.y) && !float.IsNaN (v2.y) ? -1 : 0;\r
332                         *c++ = !float.IsNaN (v1.z) && !float.IsNaN (v2.z) ? -1 : 0;\r
333                         *c = !float.IsNaN (v1.w) && !float.IsNaN (v2.w) ? -1 : 0;
334                         return res;\r            }
335
336                 public static Vector4f DuplicateLow (Vector4f v1)
337                 {
338                         return new Vector4f (v1.x, v1.x, v1.z, v1.z);
339                 }
340
341                 public static Vector4f DuplicateHigh (Vector4f v1)
342                 {
343                         return new Vector4f (v1.y, v1.y, v1.w, v1.w);
344                 }
345
346                 /*
347                 The sel argument must be a value combination of ShuffleSel flags.
348                 */\r
349                 public static unsafe Vector4f Shuffle (Vector4f v1, ShuffleSel sel)\r
350                 {
351                         float *ptr = (float*)&v1;
352                         int idx = (int)sel;\r
353                         return new Vector4f (*(ptr + ((idx >> 0) & 0x3)),*(ptr + ((idx >> 2) & 0x3)),*(ptr + ((idx >> 4) & 0x3)),*(ptr + ((idx >> 6) & 0x3)));\r
354                 }\r
355
356                 [CLSCompliant(false)]\r
357                 public static unsafe explicit operator Vector4ui(Vector4f v)\r
358                 {\r
359                         Vector4ui* p = (Vector4ui*)&v;\r
360                         return *p;\r
361                 }\r
362
363                 [CLSCompliant(false)]\r
364                 public static unsafe explicit operator Vector8us(Vector4f v)\r
365                 {\r
366                         Vector8us* p = (Vector8us*)&v;\r
367                         return *p;\r
368                 }\r
369
370                 [CLSCompliant(false)]\r
371                 public static unsafe explicit operator Vector16b(Vector4f v)\r
372                 {\r
373                         Vector16b* p = (Vector16b*)&v;\r
374                         return *p;\r
375                 }\r
376
377                 public static Vector4f LoadAligned (ref Vector4f v)\r
378                 {\r
379                         return v;\r
380                 }\r
381 \r
382                 public static void StoreAligned (ref Vector4f res, Vector4f val)\r
383                 {\r
384                         res = val;\r
385                 }\r
386 \r
387         }\r
388 }\r