2010-03-12 Jb Evain <jbevain@novell.com>
[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;
29 using System.Runtime.InteropServices;
30
31 namespace Mono.Simd
32 {
33         public enum ShuffleSel
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,
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         };
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
89         [StructLayout(LayoutKind.Explicit, Pack = 0, Size = 16)]
90         public struct Vector4f
91         {
92                 [ FieldOffset(0) ]
93                 internal float x;
94                 [ FieldOffset(4) ]
95                 internal float y;
96                 [ FieldOffset(8) ]
97                 internal float z;
98                 [ FieldOffset(12) ]
99                 internal float w;
100
101                 public float X { get { return x; } set { x = value; } }
102                 public float Y { get { return y; } set { y = value; } }
103                 public float Z { get { return z; } set { z = value; } }
104                 public float W { get { return w; } set { w = value; } }
105
106                 public static Vector4f Pi 
107                 {
108                         get { return new Vector4f ((float)System.Math.PI); }
109                 }
110
111                 public static Vector4f E 
112                 {
113                         get { return new Vector4f ((float)System.Math.E); }
114                 }
115
116                 public  static Vector4f One 
117                 {
118                         get { return new Vector4f (1); }
119                 }
120
121                 public  static Vector4f Zero 
122                 {
123                         get { return new Vector4f (0); }
124                 }
125
126                 public  static Vector4f MinusOne 
127                 {
128                         get { return new Vector4f (-1); }
129                 }
130
131                 [System.Runtime.CompilerServices.IndexerName ("Component")]
132                 public unsafe float this [int index]
133                 {
134                         get {
135                                 if ((index | 0x3) != 0x3) //index < 0 || index > 3
136                                         throw new ArgumentOutOfRangeException ("index");
137                                 fixed (float *v = &x) {
138                                         return * (v + index);
139                                 }
140                         }
141                         set {
142                                 if ( (index | 0x3) != 0x3) //index < 0 || index > 3
143                                         throw new ArgumentOutOfRangeException ("index");
144                                 fixed (float *v = &x) {
145                                         * (v + index) = value;
146                                 }
147                         }
148                 }
149
150                 public Vector4f (float x, float y, float z, float w)
151                 {
152                         this.x = x;
153                         this.y = y;
154                         this.z = z;
155                         this.w = w;
156                 }
157                 
158                 public Vector4f (float f)
159                 {
160                         this.x = f;
161                         this.y = f;
162                         this.z = f;
163                         this.w = f;
164                 }
165
166                 [Acceleration (AccelMode.SSE1)]
167                 public static unsafe Vector4f operator & (Vector4f v1, Vector4f v2)
168                 {
169                         Vector4f res = new Vector4f ();
170                         int *a = (int*)&v1;
171                         int *b = (int*)&v2;
172                         int *c = (int*)&res;
173                         *c++ = *a++ & *b++;
174                         *c++ = *a++ & *b++;
175                         *c++ = *a++ & *b++;
176                         *c = *a & *b;
177                         return res;
178                 }
179
180                 [Acceleration (AccelMode.SSE1)]
181                 public static unsafe Vector4f operator | (Vector4f v1, Vector4f v2)
182                 {
183                         Vector4f res = new Vector4f ();
184                         int *a = (int*)&v1;
185                         int *b = (int*)&v2;
186                         int *c = (int*)&res;
187                         *c++ = *a++ | *b++;
188                         *c++ = *a++ | *b++;
189                         *c++ = *a++ | *b++;
190                         *c = *a | *b;
191                         return res;
192                 }
193
194                 [Acceleration (AccelMode.SSE1)]
195                 public static unsafe Vector4f operator ^ (Vector4f v1, Vector4f v2)
196                 {
197                         Vector4f res = new Vector4f ();
198                         int *a = (int*)&v1;
199                         int *b = (int*)&v2;
200                         int *c = (int*)&res;
201                         *c++ = *a++ ^ *b++;
202                         *c++ = *a++ ^ *b++;
203                         *c++ = *a++ ^ *b++;
204                         *c = *a ^ *b;
205                         return res;
206                 }
207
208                 [Acceleration (AccelMode.SSE1)]
209                 public static Vector4f operator + (Vector4f v1, Vector4f v2)
210                 {
211                         return new Vector4f (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
212                 }
213
214                 [Acceleration (AccelMode.SSE1)]
215                 public static Vector4f operator - (Vector4f v1, Vector4f v2)
216                 {
217                         return new Vector4f (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);
218                 }
219
220                 [Acceleration (AccelMode.SSE1)]
221                 public static Vector4f operator * (Vector4f v1, Vector4f v2)
222                 {
223                         return new Vector4f (v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w);
224                 }
225
226                 [Acceleration (AccelMode.SSE1)]
227                 public static Vector4f operator / (Vector4f v1, Vector4f v2)
228                 {
229                         return new Vector4f (v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w);
230                 }
231
232                 [Acceleration (AccelMode.SSE2)]
233                 public static bool operator ==(Vector4f v1, Vector4f v2)
234                 {
235                         return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w;
236                 }
237
238                 [Acceleration (AccelMode.SSE2)]
239                 public static bool operator !=(Vector4f v1, Vector4f v2)
240                 {
241                         return v1.x != v2.x || v1.y != v2.y || v1.z != v2.z || v1.w != v2.w;
242                 }
243
244                 [Acceleration (AccelMode.SSE1)]
245                 public static unsafe explicit operator Vector2d (Vector4f v)
246                 {
247                         Vector2d* p = (Vector2d*)&v;
248                         return *p;
249                 }
250
251                 [Acceleration (AccelMode.SSE1)]
252                 public static unsafe explicit operator Vector2l (Vector4f v)
253                 {
254                         Vector2l* p = (Vector2l*)&v;
255                         return *p;
256                 }
257
258                 [Acceleration (AccelMode.SSE1)]
259                 [CLSCompliant(false)]
260                 public static unsafe explicit operator Vector2ul (Vector4f v)
261                 {
262                         Vector2ul* p = (Vector2ul*)&v;
263                         return *p;
264                 }
265
266                 [Acceleration (AccelMode.SSE1)]
267                 public static unsafe explicit operator Vector4i (Vector4f v)
268                 {
269                         Vector4i* p = (Vector4i*)&v;
270                         return *p;
271                 }
272
273                 [Acceleration (AccelMode.SSE1)]
274                 [CLSCompliant(false)]
275                 public static unsafe explicit operator Vector4ui (Vector4f v)
276                 {
277                         Vector4ui* p = (Vector4ui*)&v;
278                         return *p;
279                 }
280
281                 [Acceleration (AccelMode.SSE1)]
282                 public static unsafe explicit operator Vector8s (Vector4f v)
283                 {
284                         Vector8s* p = (Vector8s*)&v;
285                         return *p;
286                 }
287
288                 [Acceleration (AccelMode.SSE1)]
289                 [CLSCompliant(false)]
290                 public static unsafe explicit operator Vector8us (Vector4f v)
291                 {
292                         Vector8us* p = (Vector8us*)&v;
293                         return *p;
294                 }
295
296                 [Acceleration (AccelMode.SSE1)]
297                 [CLSCompliant(false)]
298                 public static unsafe explicit operator Vector16sb (Vector4f v)
299                 {
300                         Vector16sb* p = (Vector16sb*)&v;
301                         return *p;
302                 }
303
304                 [Acceleration (AccelMode.SSE1)]
305                 public static unsafe explicit operator Vector16b (Vector4f v)
306                 {
307                         Vector16b* p = (Vector16b*)&v;
308                         return *p;
309                 }
310
311                 [Acceleration (AccelMode.SSE1)]
312                 public static Vector4f LoadAligned (ref Vector4f v)
313                 {
314                         return v;
315                 }
316
317                 [Acceleration (AccelMode.SSE1)]
318                 public static void StoreAligned (ref Vector4f res, Vector4f val)
319                 {
320                         res = val;
321                 }
322
323                 [CLSCompliant(false)]
324                 [Acceleration (AccelMode.SSE1)]
325                 public static unsafe Vector4f LoadAligned (Vector4f *v)
326                 {
327                         return *v;
328                 }
329
330                 [CLSCompliant(false)]
331                 [Acceleration (AccelMode.SSE1)]
332                 public static unsafe void StoreAligned (Vector4f *res, Vector4f val)
333                 {
334                         *res = val;
335                 }
336
337                 [Acceleration (AccelMode.SSE1)]
338                 [CLSCompliant(false)]
339                 public static void PrefetchTemporalAllCacheLevels (ref Vector4f res)
340                 {
341                 }
342
343                 [Acceleration (AccelMode.SSE1)]
344                 [CLSCompliant(false)]
345                 public static void PrefetchTemporal1stLevelCache (ref Vector4f res)
346                 {
347                 }
348
349                 [Acceleration (AccelMode.SSE1)]
350                 [CLSCompliant(false)]
351                 public static void PrefetchTemporal2ndLevelCache (ref Vector4f res)
352                 {
353                 }
354
355                 [Acceleration (AccelMode.SSE1)]
356                 [CLSCompliant(false)]
357                 public static void PrefetchNonTemporal (ref Vector4f res)
358                 {
359                 }
360
361                 [Acceleration (AccelMode.SSE1)]
362                 [CLSCompliant(false)]
363                 public static unsafe void PrefetchTemporalAllCacheLevels (Vector4f *res)
364                 {
365                 }
366
367                 [Acceleration (AccelMode.SSE1)]
368                 [CLSCompliant(false)]
369                 public static unsafe void PrefetchTemporal1stLevelCache (Vector4f *res)
370                 {
371                 }
372
373                 [Acceleration (AccelMode.SSE1)]
374                 [CLSCompliant(false)]
375                 public static unsafe void PrefetchTemporal2ndLevelCache (Vector4f *res)
376                 {
377                 }
378
379                 [Acceleration (AccelMode.SSE1)]
380                 [CLSCompliant(false)]
381                 public static unsafe void PrefetchNonTemporal (Vector4f *res)
382                 {
383                 }
384                 
385                 public override string ToString()
386                 {
387                         return "<" + x + ", " + y + ", " + z + ", " + w + ">"; 
388                 }
389         }
390 }