8
8
using System . Tests ;
9
9
using Xunit ;
10
10
11
- namespace System . Runtime . Intrinsics . Tests . PackedSimd
11
+ namespace System . Runtime . Intrinsics . Wasm . Tests
12
12
{
13
13
[ PlatformSpecific ( TestPlatforms . Browser ) ]
14
14
public sealed class PackedSimdTests
@@ -167,15 +167,14 @@ public unsafe void LoadScalarAndSplatTest()
167
167
int value = 42 ;
168
168
float fValue = 3.14f ;
169
169
170
- fixed ( int * intPtr = & value )
171
- fixed ( float * floatPtr = & fValue )
172
- {
173
- var intSplat = PackedSimd . LoadScalarAndSplatVector128 ( intPtr ) ;
174
- var floatSplat = PackedSimd . LoadScalarAndSplatVector128 ( floatPtr ) ;
170
+ int * intPtr = & value ;
171
+ float * floatPtr = & fValue ;
175
172
176
- Assert . Equal ( Vector128 . Create ( 42 , 42 , 42 , 42 ) , intSplat ) ;
177
- Assert . Equal ( Vector128 . Create ( 3.14f , 3.14f , 3.14f , 3.14f ) , floatSplat ) ;
178
- }
173
+ var intSplat = PackedSimd . LoadScalarAndSplatVector128 ( intPtr ) ;
174
+ var floatSplat = PackedSimd . LoadScalarAndSplatVector128 ( floatPtr ) ;
175
+
176
+ Assert . Equal ( Vector128 . Create ( 42 , 42 , 42 , 42 ) , intSplat ) ;
177
+ Assert . Equal ( Vector128 . Create ( 3.14f , 3.14f , 3.14f , 3.14f ) , floatSplat ) ;
179
178
}
180
179
181
180
[ Fact ]
@@ -195,25 +194,21 @@ public unsafe void StoreSelectedScalarTest()
195
194
{
196
195
var v = Vector128 . Create ( 1 , 2 , 3 , 4 ) ;
197
196
int value = 0 ;
197
+ int * ptr = & value ;
198
198
199
- fixed ( int * ptr = & value )
200
- {
201
- PackedSimd . StoreSelectedScalar ( ptr , v , 2 ) ;
202
- Assert . Equal ( 3 , value ) ;
203
- }
199
+ PackedSimd . StoreSelectedScalar ( ptr , v , 2 ) ;
200
+ Assert . Equal ( 3 , value ) ;
204
201
}
205
202
206
203
[ Fact ]
207
204
public unsafe void LoadScalarAndInsertTest ( )
208
205
{
209
206
var v = Vector128 . Create ( 1 , 2 , 3 , 4 ) ;
210
207
int newValue = 42 ;
208
+ int * ptr = & newValue ;
211
209
212
- fixed ( int * ptr = & newValue )
213
- {
214
- var result = PackedSimd . LoadScalarAndInsert ( ptr , v , 2 ) ;
215
- Assert . Equal ( Vector128 . Create ( 1 , 2 , 42 , 4 ) , result ) ;
216
- }
210
+ var result = PackedSimd . LoadScalarAndInsert ( ptr , v , 2 ) ;
211
+ Assert . Equal ( Vector128 . Create ( 1 , 2 , 42 , 4 ) , result ) ;
217
212
}
218
213
219
214
[ Fact ]
@@ -259,18 +254,6 @@ public unsafe void MultiplyWideningTest()
259
254
Assert . Equal ( Vector128 . Create ( 100 , 120 , 140 , 160 ) , upperResult ) ;
260
255
}
261
256
262
- [ Fact ]
263
- public unsafe void ConvertNarrowingTest ( )
264
- {
265
- var lower = Vector128 . Create ( 1 , 2 , 3 , 4 ) ;
266
- var upper = Vector128 . Create ( 5 , 6 , 7 , 8 ) ;
267
-
268
- var narrowed = PackedSimd . ConvertNarrowingSaturate ( lower , upper ) ;
269
-
270
- Assert . Equal ( Vector128 . Create ( ( short ) 1 , ( short ) 2 , ( short ) 3 , ( short ) 4 ,
271
- ( short ) 5 , ( short ) 6 , ( short ) 7 , ( short ) 8 ) , narrowed ) ;
272
- }
273
-
274
257
[ Fact ]
275
258
public unsafe void DotProductTest ( )
276
259
{
@@ -393,16 +376,47 @@ public unsafe void MultiplyRoundedSaturateQ15Test()
393
376
{
394
377
// Q15 format represents values in [-1, 1) using 16-bit integers
395
378
// Maximum positive value is 0x7FFF (32767) representing approximately 0.99997
396
- // Test with values that should saturate when multiplied
397
- var shorts1 = Vector128 . Create ( ( short ) 32767 , ( short ) - 32768 , ( short ) 32700 , ( short ) - 32700 ) ;
398
- var shorts2 = Vector128 . Create ( ( short ) 100 , ( short ) - 100 , ( short ) 100 , ( short ) - 100 ) ;
399
-
400
- var addSat = PackedSimd . AddSaturate ( shorts1 , shorts2 ) ;
401
- var subSat = PackedSimd . SubtractSaturate ( shorts1 , shorts2 ) ;
402
-
403
- // Verify saturation at max/min values
404
- Assert . Equal ( Vector128 . Create ( ( short ) 32767 , ( short ) - 32768 , ( short ) 32767 , ( short ) - 32768 ) , addSat ) ;
405
- Assert . Equal ( Vector128 . Create ( ( short ) 32767 , ( short ) - 32768 , ( short ) 32767 , ( short ) - 32768 ) , subSat ) ;
379
+ // Minimum negative value is 0x8000 (-32768) representing -1.0
380
+ var v1 = Vector128 . Create (
381
+ ( short ) 32767 , // ~1.0 (max positive)
382
+ ( short ) - 32768 , // -1.0 (min negative)
383
+ ( short ) 16384 , // 0.5
384
+ ( short ) - 16384 , // -0.5
385
+ ( short ) 8192 , // 0.25
386
+ ( short ) - 8192 , // -0.25
387
+ ( short ) 0 , // 0
388
+ ( short ) 16384 // 0.5
389
+ ) ;
390
+ var v2 = Vector128 . Create (
391
+ ( short ) 32767 , // ~1.0 (max positive)
392
+ ( short ) - 32768 , // -1.0 (min negative)
393
+ ( short ) 16384 , // 0.5
394
+ ( short ) 16384 , // 0.5
395
+ ( short ) - 16384 , // -0.5
396
+ ( short ) 16384 , // 0.5
397
+ ( short ) 32767 , // ~1.0
398
+ ( short ) - 32768 // -1.0
399
+ ) ;
400
+
401
+ var result = PackedSimd . MultiplyRoundedSaturateQ15 ( v1 , v2 ) ;
402
+
403
+ // Verify results:
404
+ // 1.0 * 1.0 ≈ 1.0 (saturates to max positive)
405
+ Assert . Equal ( ( short ) 32767 , result . GetElement ( 0 ) ) ;
406
+ // -1.0 * -1.0 = 1.0 (saturates to max positive)
407
+ Assert . Equal ( ( short ) 32767 , result . GetElement ( 1 ) ) ;
408
+ // 0.5 * 0.5 = 0.25 (rounded)
409
+ Assert . Equal ( ( short ) 8192 , result . GetElement ( 2 ) ) ;
410
+ // -0.5 * 0.5 = -0.25 (rounded)
411
+ Assert . Equal ( ( short ) - 8192 , result . GetElement ( 3 ) ) ;
412
+ // 0.25 * -0.5 = -0.125 (rounded)
413
+ Assert . Equal ( ( short ) - 4096 , result . GetElement ( 4 ) ) ;
414
+ // -0.25 * 0.5 = -0.125 (rounded)
415
+ Assert . Equal ( ( short ) - 4096 , result . GetElement ( 5 ) ) ;
416
+ // 0 * 1.0 = 0
417
+ Assert . Equal ( ( short ) 0 , result . GetElement ( 6 ) ) ;
418
+ // 0.5 * -1.0 = -0.5
419
+ Assert . Equal ( ( short ) - 16384 , result . GetElement ( 7 ) ) ;
406
420
}
407
421
408
422
[ Fact ]
@@ -432,21 +446,20 @@ public unsafe void LoadScalarAndSplatInfinityTest()
432
446
float fInf = float . PositiveInfinity ;
433
447
double dInf = double . PositiveInfinity ;
434
448
435
- fixed ( float * fPtr = & fInf )
436
- fixed ( double * dPtr = & dInf )
437
- {
438
- var floatSplat = PackedSimd . LoadScalarAndSplatVector128 ( fPtr ) ;
439
- var doubleSplat = PackedSimd . LoadScalarAndSplatVector128 ( dPtr ) ;
449
+ float * fPtr = & fInf ;
450
+ double * dPtr = & dInf ;
440
451
441
- for ( int i = 0 ; i < 4 ; i ++ )
442
- {
443
- Assert . True ( float . IsPositiveInfinity ( floatSplat . GetElement ( i ) ) ) ;
444
- }
452
+ var floatSplat = PackedSimd . LoadScalarAndSplatVector128 ( fPtr ) ;
453
+ var doubleSplat = PackedSimd . LoadScalarAndSplatVector128 ( dPtr ) ;
445
454
446
- for ( int i = 0 ; i < 2 ; i ++ )
447
- {
448
- Assert . True ( double . IsPositiveInfinity ( doubleSplat . GetElement ( i ) ) ) ;
449
- }
455
+ for ( int i = 0 ; i < 4 ; i ++ )
456
+ {
457
+ Assert . True ( float . IsPositiveInfinity ( floatSplat . GetElement ( i ) ) ) ;
458
+ }
459
+
460
+ for ( int i = 0 ; i < 2 ; i ++ )
461
+ {
462
+ Assert . True ( double . IsPositiveInfinity ( doubleSplat . GetElement ( i ) ) ) ;
450
463
}
451
464
}
452
465
@@ -482,45 +495,75 @@ public unsafe void ComparisonWithNaNTest()
482
495
[ Fact ]
483
496
public unsafe void SignedSaturatedArithmeticTest ( )
484
497
{
485
- var shorts1 = Vector128 . Create ( ( short ) 32767 , ( short ) - 32768 , ( short ) 32700 , ( short ) - 32700 ) ;
486
- var shorts2 = Vector128 . Create ( ( short ) 100 , ( short ) - 100 , ( short ) 100 , ( short ) - 100 ) ;
487
-
488
- var addSat = PackedSimd . AddSaturate ( shorts1 , shorts2 ) ;
489
- var subSat = PackedSimd . SubtractSaturate ( shorts1 , shorts2 ) ;
490
-
491
- // Verify saturation at max/min values
492
- Assert . Equal ( Vector128 . Create ( ( short ) 32767 , ( short ) - 32768 , ( short ) 32767 , ( short ) - 32768 ) , addSat ) ;
493
- Assert . Equal ( Vector128 . Create ( ( short ) 32767 , ( short ) - 32768 , ( short ) 32767 , ( short ) - 32768 ) , subSat ) ;
498
+ // Test saturation for various edge cases in signed 16-bit arithmetic
499
+ var v1 = Vector128 . Create (
500
+ ( short ) 32767 , ( short ) - 32768 , ( short ) 30000 , ( short ) - 30000 ,
501
+ ( short ) 20000 , ( short ) - 20000 , ( short ) 10000 , ( short ) - 10000 ) ;
502
+ var v2 = Vector128 . Create (
503
+ ( short ) 10 , ( short ) - 10 , ( short ) 5000 , ( short ) - 5000 ,
504
+ ( short ) 20000 , ( short ) - 20000 , ( short ) 5000 , ( short ) - 5000 ) ;
505
+
506
+ var addResult = PackedSimd . AddSaturate ( v1 , v2 ) ;
507
+ var subResult = PackedSimd . SubtractSaturate ( v1 , v2 ) ;
508
+
509
+ // Adding to max positive should saturate at max
510
+ Assert . Equal ( ( short ) 32767 , addResult . GetElement ( 0 ) ) ;
511
+ // Adding to min negative should saturate at min
512
+ Assert . Equal ( ( short ) - 32768 , addResult . GetElement ( 1 ) ) ;
513
+ // Large positive additions should saturate
514
+ Assert . Equal ( ( short ) 32767 , addResult . GetElement ( 2 ) ) ;
515
+ // Large negative additions should saturate
516
+ Assert . Equal ( ( short ) - 32768 , addResult . GetElement ( 3 ) ) ;
517
+ // More saturation cases with higher values
518
+ Assert . Equal ( ( short ) 32767 , addResult . GetElement ( 4 ) ) ;
519
+ Assert . Equal ( ( short ) - 32768 , addResult . GetElement ( 5 ) ) ;
520
+ // Regular addition within range
521
+ Assert . Equal ( ( short ) 15000 , addResult . GetElement ( 6 ) ) ;
522
+ Assert . Equal ( ( short ) - 15000 , addResult . GetElement ( 7 ) ) ;
523
+
524
+ // Subtracting negative from max positive should saturate at max
525
+ Assert . Equal ( ( short ) 32767 , subResult . GetElement ( 0 ) ) ;
526
+ // Subtracting positive from min negative should saturate at min
527
+ Assert . Equal ( ( short ) - 32768 , subResult . GetElement ( 1 ) ) ;
528
+ // Regular subtraction within range shouldn't saturate
529
+ Assert . Equal ( ( short ) 25000 , subResult . GetElement ( 2 ) ) ;
530
+ Assert . Equal ( ( short ) - 25000 , subResult . GetElement ( 3 ) ) ;
531
+ // Perfect zero result
532
+ Assert . Equal ( ( short ) 0 , subResult . GetElement ( 4 ) ) ;
533
+ Assert . Equal ( ( short ) 0 , subResult . GetElement ( 5 ) ) ;
534
+ // More regular subtraction
535
+ Assert . Equal ( ( short ) 5000 , subResult . GetElement ( 6 ) ) ;
536
+ Assert . Equal ( ( short ) - 5000 , subResult . GetElement ( 7 ) ) ;
494
537
}
495
538
496
539
[ Fact ]
497
540
public unsafe void NativeIntegerArithmeticTest ( )
498
541
{
499
- var v1 = Vector128 . Create ( ( nint ) 1 , ( nint ) 2 , ( nint ) 3 , ( nint ) 4 ) ;
500
- var v2 = Vector128 . Create ( ( nint ) 5 , ( nint ) 6 , ( nint ) 7 , ( nint ) 8 ) ;
542
+ var v1 = Vector128 . Create ( [ ( nint ) 1 , ( nint ) 2 , ( nint ) 3 , ( nint ) 4 ] ) ;
543
+ var v2 = Vector128 . Create ( [ ( nint ) 5 , ( nint ) 6 , ( nint ) 7 , ( nint ) 8 ] ) ;
501
544
502
545
var addResult = PackedSimd . Add ( v1 , v2 ) ;
503
546
var subResult = PackedSimd . Subtract ( v1 , v2 ) ;
504
547
var mulResult = PackedSimd . Multiply ( v1 , v2 ) ;
505
548
506
- Assert . Equal ( Vector128 . Create ( ( nint ) 6 , ( nint ) 8 , ( nint ) 10 , ( nint ) 12 ) , addResult ) ;
507
- Assert . Equal ( Vector128 . Create ( ( nint ) ( - 4 ) , ( nint ) ( - 4 ) , ( nint ) ( - 4 ) , ( nint ) ( - 4 ) ) , subResult ) ;
508
- Assert . Equal ( Vector128 . Create ( ( nint ) 5 , ( nint ) 12 , ( nint ) 21 , ( nint ) 32 ) , mulResult ) ;
549
+ Assert . Equal ( Vector128 . Create ( [ ( nint ) 6 , ( nint ) 8 , ( nint ) 10 , ( nint ) 12 ] ) , addResult ) ;
550
+ Assert . Equal ( Vector128 . Create ( [ ( nint ) ( - 4 ) , ( nint ) ( - 4 ) , ( nint ) ( - 4 ) , ( nint ) ( - 4 ) ] ) , subResult ) ;
551
+ Assert . Equal ( Vector128 . Create ( [ ( nint ) 5 , ( nint ) 12 , ( nint ) 21 , ( nint ) 32 ] ) , mulResult ) ;
509
552
}
510
553
511
554
[ Fact ]
512
555
public unsafe void NativeUnsignedIntegerArithmeticTest ( )
513
556
{
514
- var v1 = Vector128 . Create ( ( nuint ) 1 , ( nuint ) 2 , ( nuint ) 3 , ( nuint ) 4 ) ;
515
- var v2 = Vector128 . Create ( ( nuint ) 5 , ( nuint ) 6 , ( nuint ) 7 , ( nuint ) 8 ) ;
557
+ var v1 = Vector128 . Create ( [ ( nuint ) 1 , ( nuint ) 2 , ( nuint ) 3 , ( nuint ) 4 ] ) ;
558
+ var v2 = Vector128 . Create ( [ ( nuint ) 5 , ( nuint ) 6 , ( nuint ) 7 , ( nuint ) 8 ] ) ;
516
559
517
560
var addResult = PackedSimd . Add ( v1 , v2 ) ;
518
561
var subResult = PackedSimd . Subtract ( v1 , v2 ) ;
519
562
var mulResult = PackedSimd . Multiply ( v1 , v2 ) ;
520
563
521
- Assert . Equal ( Vector128 . Create ( ( nuint ) 6 , ( nuint ) 8 , ( nuint ) 10 , ( nuint ) 12 ) , addResult ) ;
522
- Assert . Equal ( Vector128 . Create ( unchecked ( ( nuint ) - 4 ) , unchecked ( ( nuint ) - 4 ) , unchecked ( ( nuint ) - 4 ) , unchecked ( ( nuint ) - 4 ) ) , subResult ) ;
523
- Assert . Equal ( Vector128 . Create ( ( nuint ) 5 , ( nuint ) 12 , ( nuint ) 21 , ( nuint ) 32 ) , mulResult ) ;
564
+ Assert . Equal ( Vector128 . Create ( [ ( nuint ) 6 , ( nuint ) 8 , ( nuint ) 10 , ( nuint ) 12 ] ) , addResult ) ;
565
+ Assert . Equal ( Vector128 . Create ( [ unchecked ( ( nuint ) ( - 4 ) ) , unchecked ( ( nuint ) ( - 4 ) ) , unchecked ( ( nuint ) ( - 4 ) ) , unchecked ( ( nuint ) ( - 4 ) ) ] ) , subResult ) ;
566
+ Assert . Equal ( Vector128 . Create ( [ ( nuint ) 5 , ( nuint ) 12 , ( nuint ) 21 , ( nuint ) 32 ] ) , mulResult ) ;
524
567
}
525
568
526
569
[ Fact ]
@@ -530,7 +573,7 @@ public unsafe void NativeIntegerLoadStoreTest()
530
573
fixed ( nint * ptr = values )
531
574
{
532
575
var loaded = PackedSimd . LoadVector128 ( ptr ) ;
533
- Assert . Equal ( Vector128 . Create ( ( nint ) 1 , ( nint ) 2 , ( nint ) 3 , ( nint ) 4 ) , loaded ) ;
576
+ Assert . Equal ( Vector128 . Create ( values . AsSpan ( ) ) , loaded ) ;
534
577
535
578
nint [ ] storeTarget = new nint [ 4 ] ;
536
579
fixed ( nint * storePtr = storeTarget )
@@ -548,7 +591,7 @@ public unsafe void NativeUnsignedIntegerLoadStoreTest()
548
591
fixed ( nuint * ptr = values )
549
592
{
550
593
var loaded = PackedSimd . LoadVector128 ( ptr ) ;
551
- Assert . Equal ( Vector128 . Create ( ( nuint ) 1 , ( nuint ) 2 , ( nuint ) 3 , ( nuint ) 4 ) , loaded ) ;
594
+ Assert . Equal ( Vector128 . Create ( values . AsSpan ( ) ) , loaded ) ;
552
595
553
596
nuint [ ] storeTarget = new nuint [ 4 ] ;
554
597
fixed ( nuint * storePtr = storeTarget )
@@ -562,27 +605,27 @@ public unsafe void NativeUnsignedIntegerLoadStoreTest()
562
605
[ Fact ]
563
606
public void NativeIntegerShiftTest ( )
564
607
{
565
- var v = Vector128 . Create ( ( nint ) 16 , ( nint ) - 16 , ( nint ) 32 , ( nint ) - 32 ) ;
608
+ var v = Vector128 . Create ( [ ( nint ) 16 , ( nint ) ( - 16 ) , ( nint ) 32 , ( nint ) ( - 32 ) ] ) ;
566
609
567
610
var leftShift = PackedSimd . ShiftLeft ( v , 2 ) ;
568
611
var rightShiftArith = PackedSimd . ShiftRightArithmetic ( v , 2 ) ;
569
612
var rightShiftLogical = PackedSimd . ShiftRightLogical ( v , 2 ) ;
570
613
571
- Assert . Equal ( Vector128 . Create ( ( nint ) 64 , ( nint ) - 64 , ( nint ) 128 , ( nint ) - 128 ) , leftShift ) ;
572
- Assert . Equal ( Vector128 . Create ( ( nint ) 4 , ( nint ) - 4 , ( nint ) 8 , ( nint ) - 8 ) , rightShiftArith ) ;
573
- Assert . Equal ( Vector128 . Create ( ( nint ) 4 , ( nint ) 1073741820 , ( nint ) 8 , ( nint ) 1073741816 ) , rightShiftLogical ) ;
614
+ Assert . Equal ( Vector128 . Create ( [ ( nint ) 64 , ( nint ) ( - 64 ) , ( nint ) 128 , ( nint ) ( - 128 ) ] ) , leftShift ) ;
615
+ Assert . Equal ( Vector128 . Create ( [ ( nint ) 4 , ( nint ) ( - 4 ) , ( nint ) 8 , ( nint ) ( - 8 ) ] ) , rightShiftArith ) ;
616
+ Assert . Equal ( Vector128 . Create ( [ ( nint ) 4 , ( nint ) 1073741820 , ( nint ) 8 , ( nint ) 1073741816 ] ) , rightShiftLogical ) ;
574
617
}
575
618
576
619
[ Fact ]
577
620
public void NativeUnsignedIntegerShiftTest ( )
578
621
{
579
- var v = Vector128 . Create ( ( nuint ) 16 , ( nuint ) unchecked ( - 16 ) , ( nuint ) 32 , ( nuint ) unchecked ( - 32 ) ) ;
622
+ var v = Vector128 . Create ( [ ( nuint ) 16 , unchecked ( ( nuint ) ( - 16 ) ) , ( nuint ) 32 , unchecked ( ( nuint ) ( - 32 ) ) ] ) ;
580
623
581
624
var leftShift = PackedSimd . ShiftLeft ( v , 2 ) ;
582
625
var rightShiftLogical = PackedSimd . ShiftRightLogical ( v , 2 ) ;
583
626
584
- Assert . Equal ( Vector128 . Create ( ( nuint ) 64 , unchecked ( ( nuint ) - 64 ) , ( nuint ) 128 , unchecked ( ( nuint ) - 128 ) ) , leftShift ) ;
585
- Assert . Equal ( Vector128 . Create ( ( nuint ) 4 , ( nuint ) 1073741820 , ( nuint ) 8 , ( nuint ) 1073741816 ) , rightShiftLogical ) ;
627
+ Assert . Equal ( Vector128 . Create ( [ ( nuint ) 64 , unchecked ( ( nuint ) ( - 64 ) ) , ( nuint ) 128 , unchecked ( ( nuint ) ( - 128 ) ) ] ) , leftShift ) ;
628
+ Assert . Equal ( Vector128 . Create ( [ ( nuint ) 4 , ( nuint ) 1073741820 , ( nuint ) 8 , ( nuint ) 1073741816 ] ) , rightShiftLogical ) ;
586
629
}
587
630
}
588
631
}
0 commit comments