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