-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathVector8.cs
395 lines (309 loc) · 14 KB
/
Vector8.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using System.Runtime.Serialization;
using static System.Runtime.CompilerServices.MethodImplOptions;
namespace Plato
{
/// <summary>
/// This is a wrapper around Vector256<float> that provides a more user-friendly API.
/// Note that the Vector256 class can be found in the Runtime.Intrinsics namespace, and
/// has some design difference from Vector2, Vector3, and Vector4. One of the more notable
/// differences is that a Vector8 is sometimes intended to be used as a bit-mask
/// and there are a number of bit-oriented functions around them. The intent of the
/// Vector256 type was as a wrapper around SIMD operations, and less as a general-purpose vector type.
/// In the end, we decided to put it in the same namespace, and expose a similar API as Vector4.
/// </summary>
[DataContract]
public partial struct Vector8
{
[DataMember] public readonly Vector256<float> Value;
//-------------------------------------------------------------------------------------
// Constructors
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public Vector8(Vector256<float> value) => Value = value;
[MethodImpl(AggressiveInlining)]
public Vector8(Number scalar) => Value = Vector256.Create(scalar.Value);
[MethodImpl(AggressiveInlining)]
public Vector8(Number f0, Number f1, Number f2, Number f3, Number f4, Number f5, Number f6, Number f7)
=> Value = Vector256.Create(f0, f1, f2, f3, f4, f5, f6, f7);
[MethodImpl(AggressiveInlining)]
public Vector8(Vector4 lower, Vector4 upper) => Value = Vector256.Create(lower, upper);
//-------------------------------------------------------------------------------------
// Implicit operators
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public static implicit operator Vector256<float>(Vector8 value) => value.Value;
[MethodImpl(AggressiveInlining)]
public static implicit operator Vector8(Vector256<float> value) => new(value);
//-------------------------------------------------------------------------------------
// Properties
//-------------------------------------------------------------------------------------
public Number X0
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(0);
}
public Number X1
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(1);
}
public Number X2
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(2);
}
public Number X3
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(3);
}
public Number X4
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(4);
}
public Number X5
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(5);
}
public Number X6
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(6);
}
public Number X7
{
[MethodImpl(AggressiveInlining)] get => Value.GetElement(7);
}
public Vector4 Lower
{
[MethodImpl(AggressiveInlining)] get => Value.GetLower();
}
public Vector4 Upper
{
[MethodImpl(AggressiveInlining)] get => Value.GetUpper();
}
[MethodImpl(AggressiveInlining)]
public Vector8 WithLower(Vector4 lower)
=> new(lower, Upper);
[MethodImpl(AggressiveInlining)]
public Vector8 WithUpper(Vector4 upper)
=> new(Lower, upper);
//-------------------------------------------------------------------------------------
// Operator Overloads
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public static Vector8 operator +(Vector8 left, Vector8 right) => Vector256.Add(left.Value, right.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator -(Vector8 left, Vector8 right) => Vector256.Subtract(left.Value, right.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator *(Vector8 left, Vector8 right) => Vector256.Multiply(left.Value, right.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator *(Vector8 left, Number scalar) => Vector256.Multiply(left.Value, scalar);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator *(Number scalar, Vector8 right) => Vector256.Multiply(scalar, right.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator /(Vector8 left, Vector8 right) => Vector256.Divide(left.Value, right.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator /(Vector8 left, Number scalar) => Vector256.Divide(left.Value, scalar);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator %(Vector8 left, Vector8 right)
=> left - right * (left / right).Truncate;
[MethodImpl(AggressiveInlining)]
public static Vector8 operator %(Vector8 left, Number scalar) => left % new Vector8(scalar);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator /(Number scalar, Vector8 right) =>
Vector256.Divide(new Vector8(scalar), right.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator -(Vector8 value) => Vector256.Negate(value.Value);
//-------------------------------------------------------------------------------------
// Bitwise functions
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public static Vector8 AndNot(Vector8 a, Vector8 b) => Vector256.AndNot(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator &(Vector8 a, Vector8 b) => Vector256.BitwiseAnd(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator |(Vector8 a, Vector8 b) => Vector256.BitwiseOr(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator ~(Vector8 a) => Vector256.OnesComplement(a.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator ^(Vector8 a, Vector8 b) => Vector256.Xor(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 ConditionalSelect(Vector8 condition, Vector8 a, Vector8 b) =>
Vector256.ConditionalSelect(condition.Value, a.Value, b.Value);
//-------------------------------------------------------------------------------------
// Comparison operators
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public static Vector8 operator <(Vector8 a, Vector8 b) => Vector256.LessThan(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator <=(Vector8 a, Vector8 b) => Vector256.LessThanOrEqual(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator >(Vector8 a, Vector8 b) => Vector256.GreaterThan(a.Value, b.Value);
[MethodImpl(AggressiveInlining)]
public static Vector8 operator >=(Vector8 a, Vector8 b) => Vector256.GreaterThanOrEqual(a.Value, b.Value);
//-------------------------------------------------------------------------------------
// Comparison functions
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public Vector8 Max(Vector8 other) => Vector256.Max(Value, other.Value);
[MethodImpl(AggressiveInlining)]
public Vector8 Min(Vector8 other) => Vector256.Min(Value, other.Value);
//-------------------------------------------------------------------------------------
// Basic math functions
//-------------------------------------------------------------------------------------
public Vector8 Sin
{
[MethodImpl(AggressiveInlining)] get => Vector256.Sin(Value);
}
public Vector8 Cos
{
[MethodImpl(AggressiveInlining)] get => Vector256.Cos(Value);
}
public (Vector8, Vector8) SinCos
{
[MethodImpl(AggressiveInlining)] get => Vector256.SinCos(Value);
}
public Vector8 Abs
{
[MethodImpl(AggressiveInlining)] get => Vector256.Abs(Value);
}
public Vector8 Ceiling
{
[MethodImpl(AggressiveInlining)] get => Vector256.Ceiling(Value);
}
[MethodImpl(AggressiveInlining)]
public Vector8 Clamp(Vector8 min, Vector8 max) => Vector256.Clamp(Value, min.Value, max.Value);
public Vector8 DegreesToRadians
{
[MethodImpl(AggressiveInlining)] get => Vector256.DegreesToRadians(Value);
}
[MethodImpl(AggressiveInlining)]
public Vector8 CopySign(Vector8 sign) => Vector256.CopySign(Value, sign.Value);
[MethodImpl(AggressiveInlining)]
public Number Dot(Vector8 other) => Vector256.Dot(Value, other.Value);
public Vector8 Exp
{
[MethodImpl(AggressiveInlining)] get => Vector256.Exp(Value);
}
public Vector8 Floor
{
[MethodImpl(AggressiveInlining)] get => Vector256.Floor(Value);
}
[MethodImpl(AggressiveInlining)]
public Vector8 Hypot(Vector8 other) => Vector256.Hypot(Value, other.Value);
public Vector8 IsNaN
{
[MethodImpl(AggressiveInlining)] get => Vector256.IsNaN(Value);
}
public Vector8 IsNegative
{
[MethodImpl(AggressiveInlining)] get => Vector256.IsNegative(Value);
}
public Vector8 IsPositive
{
[MethodImpl(AggressiveInlining)] get => Vector256.IsPositive(Value);
}
public Vector8 IsPositiveInfinity
{
[MethodImpl(AggressiveInlining)] get => Vector256.IsPositiveInfinity(Value);
}
public Vector8 IsZero
{
[MethodImpl(AggressiveInlining)] get => Vector256.IsZero(Value);
}
[MethodImpl(AggressiveInlining)]
public Vector8 Lerp(Vector8 b, Vector8 t)
=> Vector256.Lerp(Value, b.Value, t.Value);
public Vector8 Log
{
[MethodImpl(AggressiveInlining)] get => Vector256.Log(Value);
}
public Vector8 Log2
{
[MethodImpl(AggressiveInlining)] get => Vector256.Log2(Value);
}
public Vector8 RadiansToDegrees
{
[MethodImpl(AggressiveInlining)] get => Vector256.RadiansToDegrees(Value);
}
/// <summary>Reciprocal (1/x) of each element</summary>
public Vector8 Reciprocal
{
[MethodImpl(AggressiveInlining)] get => Avx.Reciprocal(Value);
}
/// <summary>Approximate reciprocal of the square root of each element: 1 / sqrt(x)</summary>
public Vector8 ReciprocalSqrt
{
[MethodImpl(AggressiveInlining)] get => Avx.ReciprocalSqrt(Value);
}
public Vector8 Round
{
[MethodImpl(AggressiveInlining)] get => Vector256.Round(Value);
}
public Vector8 Sign
{
[MethodImpl(AggressiveInlining)] get => Vector256.CopySign(new Vector8(1), Value);
}
public Vector8 Sqrt
{
[MethodImpl(AggressiveInlining)] get => Vector256.Sqrt(Value);
}
/// <summary>Square each element</summary>
public Vector8 Sqr
{
[MethodImpl(AggressiveInlining)] get => this * this;
}
public Number Sum
{
[MethodImpl(AggressiveInlining)] get => Vector256.Sum(Value);
}
public Vector8 Tan
{
[MethodImpl(AggressiveInlining)]
get
{
var (a, b) = SinCos;
return a / b;
}
}
public Number FirstElement
{
[MethodImpl(AggressiveInlining)] get => Vector256.ToScalar(Value);
}
public Vector8 Truncate
{
[MethodImpl(AggressiveInlining)] get => Vector256.Truncate(Value);
}
//-------------------------------------------------------------------------------------
// Pseudo-mutation operators
//-------------------------------------------------------------------------------------
[MethodImpl(AggressiveInlining)]
public Vector8 WithElement(Integer i, Number f) => Vector256.WithElement(Value, i, f);
//-------------------------------------------------------------------------------------
// Minimum and maximum elements
//-------------------------------------------------------------------------------------
public Number MinElement
{
[MethodImpl(AggressiveInlining)]
get
{
var minHalf = Lower.Min(Upper);
var shuffled = minHalf.ZWXY;
var reduced = minHalf.Min(shuffled);
reduced = reduced.Min(reduced.YXWZ);
return reduced[0];
}
}
public Number MaxElement
{
[MethodImpl(AggressiveInlining)]
get
{
var maxHalf = Lower.Max(Upper);
var shuffled = maxHalf.ZWXY;
var reduced = maxHalf.Max(shuffled);
reduced = reduced.Max(reduced.YXWZ);
return reduced[0];
}
}
}
}