Merge pull request #2545 from ermshiperete/Xamarin-24974
[mono.git] / mcs / class / Mono.Simd / Mono.Simd / ArrayExtensions.cs
1 // Vector4ui.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 using System;
28 using System.Runtime.InteropServices;
29
30 namespace Mono.Simd
31 {
32         public static class ArrayExtensions
33         {
34                 [Acceleration (AccelMode.SSE1)]
35                 [CLSCompliant(false)]
36                 public static Vector2d GetVector (this double[] array, int offset)
37                 {
38                         return new Vector2d (array [offset], array [offset + 1]);
39                 }
40
41                 [Acceleration (AccelMode.SSE1)]
42                 [CLSCompliant(false)]
43                 public static Vector2l GetVector (this long[] array, int offset)
44                 {
45                         return new Vector2l (array [offset], array [offset + 1]);
46                 }
47
48                 [Acceleration (AccelMode.SSE1)]
49                 [CLSCompliant(false)]
50                 public static Vector2ul GetVector (this ulong[] array, int offset)
51                 {
52                         return new Vector2ul (array [offset], array [offset + 1]);
53                 }
54
55                 [Acceleration (AccelMode.SSE1)]
56                 [CLSCompliant(false)]
57                 public static Vector4f GetVector (this float[] array, int offset)
58                 {
59                         return new Vector4f (array [offset], array [offset + 1], array [offset + 2], array [offset + 3]);
60                 }
61
62                 [Acceleration (AccelMode.SSE1)]
63                 [CLSCompliant(false)]
64                 public static Vector4i GetVector (this int[] array, int offset)
65                 {
66                         return new Vector4i (array [offset], array [offset + 1], array [offset + 2], array [offset + 3]);
67                 }
68
69                 [Acceleration (AccelMode.SSE1)]
70                 [CLSCompliant(false)]
71                 public static Vector4ui GetVector (this uint[] array, int offset)
72                 {
73                         return new Vector4ui (array [offset], array [offset + 1], array [offset + 2], array [offset + 3]);
74                 }
75
76                 [Acceleration (AccelMode.SSE1)]
77                 [CLSCompliant(false)]
78                 public static Vector8s GetVector (this short[] array, int offset)
79                 {
80                         if (offset < 0 || offset > array.Length - 8)
81                                 throw new IndexOutOfRangeException ();
82                         unsafe {
83                                 fixed (void *ptr = &array[offset]) {
84                                         return *(Vector8s*)ptr;
85                                 }
86                         }
87                 }
88
89                 [Acceleration (AccelMode.SSE1)]
90                 [CLSCompliant(false)]
91                 public static Vector8us GetVector (this ushort[] array, int offset)
92                 {
93                         if (offset < 0 || offset > array.Length - 8)
94                                 throw new IndexOutOfRangeException ();
95                         unsafe {
96                                 fixed (void *ptr = &array[offset]) {
97                                         return *(Vector8us*)ptr;
98                                 }
99                         }
100                 }
101
102                 [Acceleration (AccelMode.SSE1)]
103                 [CLSCompliant(false)]
104                 public static Vector16sb GetVector (this sbyte[] array, int offset)
105                 {
106                         if (offset < 0 || offset > array.Length - 16)
107                                 throw new IndexOutOfRangeException ();
108                         unsafe {
109                                 fixed (void *ptr = &array[offset]) {
110                                         return *(Vector16sb*)ptr;
111                                 }
112                         }
113                 }
114
115                 [Acceleration (AccelMode.SSE1)]
116                 [CLSCompliant(false)]
117                 public static Vector16b GetVector (this byte[] array, int offset)
118                 {
119                         if (offset < 0 || offset > array.Length - 16)
120                                 throw new IndexOutOfRangeException ();
121                         unsafe {
122                                 fixed (void *ptr = &array[offset]) {
123                                         return *(Vector16b*)ptr;
124                                 }
125                         }
126                 }
127
128                 [Acceleration (AccelMode.SSE1)]
129                 [CLSCompliant(false)]
130                 public static void SetVector (this double[] array, Vector2d val, int offset)
131                 {
132                         array [offset + 0] = val.X;
133                         array [offset + 1] = val.Y;
134                 }
135
136                 [Acceleration (AccelMode.SSE1)]
137                 [CLSCompliant(false)]
138                 public static void SetVector (this long[] array, Vector2l val, int offset)
139                 {
140                         array [offset + 0] = val.X;
141                         array [offset + 1] = val.Y;
142                 }
143
144                 [Acceleration (AccelMode.SSE1)]
145                 [CLSCompliant(false)]
146                 public static void SetVector (this ulong[] array, Vector2ul val, int offset)
147                 {
148                         array [offset + 0] = val.X;
149                         array [offset + 1] = val.Y;
150                 }
151
152                 [Acceleration (AccelMode.SSE1)]
153                 [CLSCompliant(false)]
154                 public static void SetVector (this float[] array, Vector4f val, int offset)
155                 {
156                         array [offset + 0] = val.X;
157                         array [offset + 1] = val.Y;
158                         array [offset + 2] = val.Z;
159                         array [offset + 3] = val.W;
160                 }
161
162                 [Acceleration (AccelMode.SSE1)]
163                 [CLSCompliant(false)]
164                 public static void SetVector (this int[] array, Vector4i val, int offset)
165                 {
166                         array [offset + 0] = val.X;
167                         array [offset + 1] = val.Y;
168                         array [offset + 2] = val.Z;
169                         array [offset + 3] = val.W;
170                 }
171
172                 [Acceleration (AccelMode.SSE1)]
173                 [CLSCompliant(false)]
174                 public static void SetVector (this uint[] array, Vector4ui val, int offset)
175                 {
176                         array [offset + 0] = val.X;
177                         array [offset + 1] = val.Y;
178                         array [offset + 2] = val.Z;
179                         array [offset + 3] = val.W;
180                 }
181
182                 [Acceleration (AccelMode.SSE1)]
183                 [CLSCompliant(false)]
184                 public static void SetVector (this short[] array, Vector8s val, int offset)
185                 {
186                         array [offset + 0] = val.V0;
187                         array [offset + 1] = val.V1;
188                         array [offset + 2] = val.V2;
189                         array [offset + 3] = val.V3;
190                         array [offset + 4] = val.V4;
191                         array [offset + 5] = val.V5;
192                         array [offset + 6] = val.V6;
193                         array [offset + 7] = val.V7;
194                 }
195
196                 [Acceleration (AccelMode.SSE1)]
197                 [CLSCompliant(false)]
198                 public static void SetVector (this ushort[] array, Vector8us val, int offset)
199                 {
200                         array [offset + 0] = val.V0;
201                         array [offset + 1] = val.V1;
202                         array [offset + 2] = val.V2;
203                         array [offset + 3] = val.V3;
204                         array [offset + 4] = val.V4;
205                         array [offset + 5] = val.V5;
206                         array [offset + 6] = val.V6;
207                         array [offset + 7] = val.V7;
208                 }
209
210                 [Acceleration (AccelMode.SSE1)]
211                 [CLSCompliant(false)]
212                 public static void SetVector (this sbyte[] array, Vector16sb val, int offset)
213                 {
214                         for (int i = 0; i < 16; ++i)
215                                 array [offset + i] = val [i];
216                 }
217
218                 [Acceleration (AccelMode.SSE1)]
219                 [CLSCompliant(false)]
220                 public static void SetVector (this byte[] array, Vector16b val, int offset)
221                 {
222                         for (int i = 0; i < 16; ++i)
223                                 array [offset + i] = val [i];
224                 }
225
226
227                 [Acceleration (AccelMode.SSE1)]
228                 [CLSCompliant(false)]
229                 public static Vector2d GetVectorAligned (this double[] array, int offset)
230                 {
231                         return new Vector2d (array [offset], array [offset + 1]);
232                 }
233
234                 [Acceleration (AccelMode.SSE1)]
235                 [CLSCompliant(false)]
236                 public static Vector2l GetVectorAligned (this long[] array, int offset)
237                 {
238                         return new Vector2l (array [offset], array [offset + 1]);
239                 }
240
241                 [Acceleration (AccelMode.SSE1)]
242                 [CLSCompliant(false)]
243                 public static Vector2ul GetVectorAligned (this ulong[] array, int offset)
244                 {
245                         return new Vector2ul (array [offset], array [offset + 1]);
246                 }
247
248                 [Acceleration (AccelMode.SSE1)]
249                 [CLSCompliant(false)]
250                 public static Vector4f GetVectorAligned (this float[] array, int offset)
251                 {
252                         return new Vector4f (array [offset], array [offset + 1], array [offset + 2], array [offset + 3]);
253                 }
254
255                 [Acceleration (AccelMode.SSE1)]
256                 [CLSCompliant(false)]
257                 public static Vector4i GetVectorAligned (this int[] array, int offset)
258                 {
259                         return new Vector4i (array [offset], array [offset + 1], array [offset + 2], array [offset + 3]);
260                 }
261
262                 [Acceleration (AccelMode.SSE1)]
263                 [CLSCompliant(false)]
264                 public static Vector4ui GetVectorAligned (this uint[] array, int offset)
265                 {
266                         return new Vector4ui (array [offset], array [offset + 1], array [offset + 2], array [offset + 3]);
267                 }
268
269                 [Acceleration (AccelMode.SSE1)]
270                 [CLSCompliant(false)]
271                 public static Vector8s GetVectorAligned (this short[] array, int offset)
272                 {
273                         if (offset < 0 || offset > array.Length - 8)
274                                 throw new IndexOutOfRangeException ();
275                         unsafe {
276                                 fixed (void *ptr = &array[offset]) {
277                                         return *(Vector8s*)ptr;
278                                 }
279                         }
280                 }
281
282                 [Acceleration (AccelMode.SSE1)]
283                 [CLSCompliant(false)]
284                 public static Vector8us GetVectorAligned (this ushort[] array, int offset)
285                 {
286                         if (offset < 0 || offset > array.Length - 8)
287                                 throw new IndexOutOfRangeException ();
288                         unsafe {
289                                 fixed (void *ptr = &array[offset]) {
290                                         return *(Vector8us*)ptr;
291                                 }
292                         }
293                 }
294
295                 [Acceleration (AccelMode.SSE1)]
296                 [CLSCompliant(false)]
297                 public static Vector16sb GetVectorAligned (this sbyte[] array, int offset)
298                 {
299                         if (offset < 0 || offset > array.Length - 16)
300                                 throw new IndexOutOfRangeException ();
301                         unsafe {
302                                 fixed (void *ptr = &array[offset]) {
303                                         return *(Vector16sb*)ptr;
304                                 }
305                         }
306                 }
307
308                 [Acceleration (AccelMode.SSE1)]
309                 [CLSCompliant(false)]
310                 public static Vector16b GetVectorAligned (this byte[] array, int offset)
311                 {
312                         if (offset < 0 || offset > array.Length - 16)
313                                 throw new IndexOutOfRangeException ();
314                         unsafe {
315                                 fixed (void *ptr = &array[offset]) {
316                                         return *(Vector16b*)ptr;
317                                 }
318                         }
319                 }
320
321                 [Acceleration (AccelMode.SSE1)]
322                 [CLSCompliant(false)]
323                 public static void SetVectorAligned (this double[] array, Vector2d val, int offset)
324                 {
325                         array [offset + 0] = val.X;
326                         array [offset + 1] = val.Y;
327                 }
328
329                 [Acceleration (AccelMode.SSE1)]
330                 [CLSCompliant(false)]
331                 public static void SetVectorAligned (this long[] array, Vector2l val, int offset)
332                 {
333                         array [offset + 0] = val.X;
334                         array [offset + 1] = val.Y;
335                 }
336
337                 [Acceleration (AccelMode.SSE1)]
338                 [CLSCompliant(false)]
339                 public static void SetVectorAligned (this ulong[] array, Vector2ul val, int offset)
340                 {
341                         array [offset + 0] = val.X;
342                         array [offset + 1] = val.Y;
343                 }
344
345                 [Acceleration (AccelMode.SSE1)]
346                 [CLSCompliant(false)]
347                 public static void SetVectorAligned (this float[] array, Vector4f val, int offset)
348                 {
349                         array [offset + 0] = val.X;
350                         array [offset + 1] = val.Y;
351                         array [offset + 2] = val.Z;
352                         array [offset + 3] = val.W;
353                 }
354
355                 [Acceleration (AccelMode.SSE1)]
356                 [CLSCompliant(false)]
357                 public static void SetVectorAligned (this int[] array, Vector4i val, int offset)
358                 {
359                         array [offset + 0] = val.X;
360                         array [offset + 1] = val.Y;
361                         array [offset + 2] = val.Z;
362                         array [offset + 3] = val.W;
363                 }
364
365                 [Acceleration (AccelMode.SSE1)]
366                 [CLSCompliant(false)]
367                 public static void SetVectorAligned (this uint[] array, Vector4ui val, int offset)
368                 {
369                         array [offset + 0] = val.X;
370                         array [offset + 1] = val.Y;
371                         array [offset + 2] = val.Z;
372                         array [offset + 3] = val.W;
373                 }
374
375                 [Acceleration (AccelMode.SSE1)]
376                 [CLSCompliant(false)]
377                 public static void SetVectorAligned (this short[] array, Vector8s val, int offset)
378                 {
379                         array [offset + 0] = val.V0;
380                         array [offset + 1] = val.V1;
381                         array [offset + 2] = val.V2;
382                         array [offset + 3] = val.V3;
383                         array [offset + 4] = val.V4;
384                         array [offset + 5] = val.V5;
385                         array [offset + 6] = val.V6;
386                         array [offset + 7] = val.V7;
387                 }
388
389                 [Acceleration (AccelMode.SSE1)]
390                 [CLSCompliant(false)]
391                 public static void SetVectorAligned (this ushort[] array, Vector8us val, int offset)
392                 {
393                         array [offset + 0] = val.V0;
394                         array [offset + 1] = val.V1;
395                         array [offset + 2] = val.V2;
396                         array [offset + 3] = val.V3;
397                         array [offset + 4] = val.V4;
398                         array [offset + 5] = val.V5;
399                         array [offset + 6] = val.V6;
400                         array [offset + 7] = val.V7;
401                 }
402
403                 [Acceleration (AccelMode.SSE1)]
404                 [CLSCompliant(false)]
405                 public static void SetVectorAligned (this sbyte[] array, Vector16sb val, int offset)
406                 {
407                         for (int i = 0; i < 16; ++i)
408                                 array [offset + i] = val [i];
409                 }
410
411                 [Acceleration (AccelMode.SSE1)]
412                 [CLSCompliant(false)]
413                 public static void SetVectorAligned (this byte[] array, Vector16b val, int offset)
414                 {
415                         for (int i = 0; i < 16; ++i)
416                                 array [offset + i] = val [i];
417                 }
418
419                 public static bool IsAligned<T> (this T[] vect, int index) where T : struct
420                 {
421                         int size = Marshal.SizeOf (typeof (T));
422                         return size * index % 16 == 0;
423                 }
424         }
425 }