trueno 0.8.7

High-performance SIMD compute library with GPU support for matrix operations
Documentation
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
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
# Project Context

**Language**: rust
**Project Path**: .

## Project Structure

- **Total Files**: 28
- **Total Functions**: 90
- **Median Cyclomatic**: 2.00
- **Median Cognitive**: 1.00

## Quality Scorecard

- **Overall Health**: 81.7%
- **Maintainability Index**: 70.0
- **Complexity Score**: 90.0
- **Test Coverage**: 65.0%

## Files

### ./benches/gpu_ops.rs

**File Complexity**: 3 | **Functions**: 14

- **Function**: `generate_test_data` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_vec_add` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_dot` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_matmul` [complexity: 6] [cognitive: 13] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_relu` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_leaky_relu` [complexity: 4] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_elu` [complexity: 4] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_clip` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_sigmoid` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_tanh` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_swish` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_gelu` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_softmax` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_log_softmax` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]

### ./benches/matrix_ops.rs

**File Complexity**: 2 | **Functions**: 6

- **Function**: `bench_matmul_sizes` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_matmul_rectangular` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_transpose` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_matvec` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_convolve2d` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_convolve2d_edge_detection` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]

### ./benches/vector_ops.rs

**File Complexity**: 1 | **Functions**: 25

- **Function**: `generate_test_data` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_add` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_sub` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_mul` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_scale` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_div` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_fma` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_dot` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_sum` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_max` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_min` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_argmax` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_argmin` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_relu` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_softmax` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_log_softmax` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_clip` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_sigmoid` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_gelu` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_swish` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_tanh` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_norm_l1` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_norm_l2` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_norm_linf` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_abs` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]

### ./book/book.toml


### ./deny.toml


### ./docs/roadmaps/roadmap.yaml


### ./examples/activation_functions.rs

**File Complexity**: 1 | **Functions**: 2

- **Function**: `main` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `print_activation_row` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]

### ./examples/backend_detection.rs

**File Complexity**: 1 | **Functions**: 1

- **Function**: `main` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]

### ./examples/matrix_operations.rs

**File Complexity**: 3 | **Functions**: 3

- **Function**: `main` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `print_matrix` [complexity: 4] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `print_vector` [complexity: 3] [cognitive: 3] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]

### ./examples/ml_similarity.rs

**File Complexity**: 1 | **Functions**: 4

- **Function**: `main` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `cosine_similarity` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `l2_normalize` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `euclidean_distance` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]

### ./examples/performance_demo.rs

**File Complexity**: 5 | **Functions**: 3

- **Function**: `main` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `demo_operation` [complexity: 7] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `demo_operation_vec` [complexity: 7] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]

### ./scripts/check_regression.py

**File Complexity**: 48 | **Functions**: 5

- **Function**: `parse_time` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `parse_criterion_output` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `format_time` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `compare_benchmarks` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `main` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]

### ./src/backends/avx2.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `Avx2Backend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for Avx2Backend { # [target_feature (enable = "avx2")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_add_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "avx2")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_sub_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "avx2")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_mul_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "avx2")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_div_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "avx2" , enable = "fma")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm256_setzero_ps () ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; acc = _mm256_fmadd_ps (va , vb , acc) ; i += 8 ; } let mut result = { let sum_halves = _mm_add_ps (_mm256_castps256_ps128 (acc) , _mm256_extractf128_ps (acc , 1)) ; let temp = _mm_add_ps (sum_halves , _mm_movehl_ps (sum_halves , sum_halves)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "avx2")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm256_setzero_ps () ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; acc = _mm256_add_ps (acc , va) ; i += 8 ; } let mut result = { let sum_halves = _mm_add_ps (_mm256_castps256_ps128 (acc) , _mm256_extractf128_ps (acc , 1)) ; let temp = _mm_add_ps (sum_halves , _mm_movehl_ps (sum_halves , sum_halves)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "avx2")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = _mm256_set1_ps (a [0]) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; vmax = _mm256_max_ps (vmax , va) ; i += 8 ; } let mut result = { let max_halves = _mm_max_ps (_mm256_castps256_ps128 (vmax) , _mm256_extractf128_ps (vmax , 1)) ; let temp = _mm_max_ps (max_halves , _mm_movehl_ps (max_halves , max_halves)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "avx2")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = _mm256_set1_ps (a [0]) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; vmin = _mm256_min_ps (vmin , va) ; i += 8 ; } let mut result = { let min_halves = _mm_min_ps (_mm256_castps256_ps128 (vmin) , _mm256_extractf128_ps (vmin , 1)) ; let temp = _mm_min_ps (min_halves , _mm_movehl_ps (min_halves , min_halves)) ; let temp = _mm_min_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "avx2")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut max_value = a [0] ; let mut max_index = 0 ; let mut vmax = _mm256_set1_ps (a [0]) ; let mut vmax_idx = _mm256_set1_ps (0.0) ; let mut vidx_current = _mm256_set_ps (7.0 , 6.0 , 5.0 , 4.0 , 3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm256_set1_ps (8.0) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm256_cmp_ps :: < 30 > (va , vmax) ; vmax = _mm256_blendv_ps (vmax , va , mask) ; vmax_idx = _mm256_blendv_ps (vmax_idx , vidx_current , mask) ; vidx_current = _mm256_add_ps (vidx_current , vinc) ; i += 8 ; } let mut values = [0.0f32 ; 8] ; let mut indices = [0.0f32 ; 8] ; _mm256_storeu_ps (values . as_mut_ptr () , vmax) ; _mm256_storeu_ps (indices . as_mut_ptr () , vmax_idx) ; for lane in 0 .. 8 { if values [lane] > max_value { max_value = values [lane] ; max_index = indices [lane] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "avx2")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut min_value = a [0] ; let mut min_index = 0 ; let mut vmin = _mm256_set1_ps (a [0]) ; let mut vmin_idx = _mm256_set1_ps (0.0) ; let mut vidx_current = _mm256_set_ps (7.0 , 6.0 , 5.0 , 4.0 , 3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm256_set1_ps (8.0) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm256_cmp_ps :: < 17 > (va , vmin) ; vmin = _mm256_blendv_ps (vmin , va , mask) ; vmin_idx = _mm256_blendv_ps (vmin_idx , vidx_current , mask) ; vidx_current = _mm256_add_ps (vidx_current , vinc) ; i += 8 ; } let mut values = [0.0f32 ; 8] ; let mut indices = [0.0f32 ; 8] ; _mm256_storeu_ps (values . as_mut_ptr () , vmin) ; _mm256_storeu_ps (indices . as_mut_ptr () , vmin_idx) ; for lane in 0 .. 8 { if values [lane] < min_value { min_value = values [lane] ; min_index = indices [lane] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "avx2")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [target_feature (enable = "avx2")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = _mm256_setzero_ps () ; let sign_mask = _mm256_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm256_and_ps (va , sign_mask) ; acc = _mm256_add_ps (acc , abs_va) ; i += 8 ; } let mut result = { let sum_halves = _mm_add_ps (_mm256_castps256_ps128 (acc) , _mm256_extractf128_ps (acc , 1)) ; let temp = _mm_add_ps (sum_halves , _mm_movehl_ps (sum_halves , sum_halves)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { result += val . abs () ; } result } # [target_feature (enable = "avx2")] unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut max_vec = _mm256_setzero_ps () ; let sign_mask = _mm256_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm256_and_ps (va , sign_mask) ; max_vec = _mm256_max_ps (max_vec , abs_va) ; i += 8 ; } let mut result = { let max_halves = _mm_max_ps (_mm256_castps256_ps128 (max_vec) , _mm256_extractf128_ps (max_vec , 1) ,) ; let temp = _mm_max_ps (max_halves , _mm_movehl_ps (max_halves , max_halves)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { let abs_val = val . abs () ; if abs_val > result { result = abs_val ; } } result } # [target_feature (enable = "avx2")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = _mm256_set1_ps (scalar) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm256_mul_ps (va , scalar_vec) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sign_mask = _mm256_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm256_and_ps (va , sign_mask) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , abs_va) ; i += 8 ; } while i < len { result [i] = a [i] . abs () ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = _mm256_set1_ps (min_val) ; let max_vec = _mm256_set1_ps (max_val) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let clamped = _mm256_min_ps (_mm256_max_ps (va , min_vec) , max_vec) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , clamped) ; i += 8 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [target_feature (enable = "avx2" , enable = "fma")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = _mm256_set1_ps (t) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let diff = _mm256_sub_ps (vb , va) ; let vresult = _mm256_fmadd_ps (t_vec , diff , va) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [target_feature (enable = "avx2" , enable = "fma")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vc = _mm256_loadu_ps (c . as_ptr () . add (i)) ; let vresult = _mm256_fmadd_ps (va , vb , vc) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = _mm256_setzero_ps () ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm256_max_ps (zero , va) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let x = _mm256_max_ps (_mm256_min_ps (x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let vresult = _mm256_mul_ps (p , scale) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] . exp () ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm256_sub_ps (_mm256_setzero_ps () , x) ; let neg_x = _mm256_max_ps (_mm256_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (neg_x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (neg_x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_neg_x = _mm256_mul_ps (p , scale) ; let denom = _mm256_add_ps (one , exp_neg_x) ; let sigmoid_result = _mm256_div_ps (one , denom) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , sigmoid_result) ; i += 8 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = _mm256_set1_ps (0.797_884_6) ; let coeff = _mm256_set1_ps (0.044715) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let two = _mm256_set1_ps (2.0) ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let x2 = _mm256_mul_ps (x , x) ; let x3 = _mm256_mul_ps (x2 , x) ; let inner_sum = _mm256_fmadd_ps (coeff , x3 , x) ; let inner = _mm256_mul_ps (sqrt_2_over_pi , inner_sum) ; let two_inner = _mm256_mul_ps (two , inner) ; let two_inner = _mm256_max_ps (_mm256_min_ps (two_inner , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (two_inner , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (two_inner , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_2inner = _mm256_mul_ps (p , scale) ; let tanh_numer = _mm256_sub_ps (exp_2inner , one) ; let tanh_denom = _mm256_add_ps (exp_2inner , one) ; let tanh_result = _mm256_div_ps (tanh_numer , tanh_denom) ; let one_plus_tanh = _mm256_add_ps (one , tanh_result) ; let gelu_result = _mm256_mul_ps (half , _mm256_mul_ps (x , one_plus_tanh)) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , gelu_result) ; i += 8 ; } const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm256_sub_ps (_mm256_setzero_ps () , x) ; let neg_x = _mm256_max_ps (_mm256_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (neg_x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (neg_x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_neg_x = _mm256_mul_ps (p , scale) ; let denom = _mm256_add_ps (one , exp_neg_x) ; let swish_result = _mm256_div_ps (x , denom) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , swish_result) ; i += 8 ; } while i < len { let x = a [i] ; result [i] = if x < - 50.0 { 0.0 } else if x > 50.0 { x } else { x / (1.0 + (- x) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let two = _mm256_set1_ps (2.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let two_x = _mm256_mul_ps (two , x) ; let two_x = _mm256_max_ps (_mm256_min_ps (two_x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (two_x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (two_x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_2x = _mm256_mul_ps (p , scale) ; let tanh_numer = _mm256_sub_ps (exp_2x , one) ; let tanh_denom = _mm256_add_ps (exp_2x , one) ; let tanh_result = _mm256_div_ps (tanh_numer , tanh_denom) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , tanh_result) ; i += 8 ; } while i < len { result [i] = a [i] . tanh () ; i += 1 ; } } } . self_ty`
- **Function**: `tests::test_avx2_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_scale_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_clamp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_fma_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_lerp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sum_kahan_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_norm_l1_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_norm_l2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_dot_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_add_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sum_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_max_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]

### ./src/backends/avx512.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `Avx512Backend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for Avx512Backend { # [target_feature (enable = "avx512f")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm512_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm512_add_ps (va , vb) ; _mm512_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 16 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "avx512f")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] - b [i] ; } } # [target_feature (enable = "avx512f")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] * b [i] ; } } # [target_feature (enable = "avx512f")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] / b [i] ; } } # [target_feature (enable = "avx512f")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm512_setzero_ps () ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm512_loadu_ps (b . as_ptr () . add (i)) ; acc = _mm512_fmadd_ps (va , vb , acc) ; i += 16 ; } let mut result = _mm512_reduce_add_ps (acc) ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "avx512f")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm512_setzero_ps () ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; acc = _mm512_add_ps (acc , va) ; i += 16 ; } let mut result = _mm512_reduce_add_ps (acc) ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "avx512f")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmax = _mm512_max_ps (vmax , va) ; i += 16 ; } let mut result = _mm512_reduce_max_ps (vmax) ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "avx512f")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmin = _mm512_min_ps (vmin , va) ; i += 16 ; } let mut result = _mm512_reduce_min_ps (vmin) ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "avx512f")] unsafe fn argmax (a : & [f32]) -> usize { if a . is_empty () { return 0 ; } let len = a . len () ; let mut i = 0 ; let mut vmax = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmax = _mm512_max_ps (vmax , va) ; i += 16 ; } let mut max_val = _mm512_reduce_max_ps (vmax) ; for & val in & a [i ..] { if val > max_val { max_val = val ; } } a . iter () . position (| & x | x == max_val) . unwrap_or (0) } # [target_feature (enable = "avx512f")] unsafe fn argmin (a : & [f32]) -> usize { if a . is_empty () { return 0 ; } let len = a . len () ; let mut i = 0 ; let mut vmin = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmin = _mm512_min_ps (vmin , va) ; i += 16 ; } let mut min_val = _mm512_reduce_min_ps (vmin) ; for & val in & a [i ..] { if val < min_val { min_val = val ; } } a . iter () . position (| & x | x == min_val) . unwrap_or (0) } # [target_feature (enable = "avx512f")] unsafe fn sum_kahan (a : & [f32]) -> f32 { let mut sum = 0.0 ; let mut c = 0.0 ; for & x in a { let y = x - c ; let t = sum + y ; c = (t - sum) - y ; sum = t ; } sum } # [target_feature (enable = "avx512f")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = _mm512_setzero_ps () ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; let squared = _mm512_mul_ps (va , va) ; acc = _mm512_add_ps (acc , squared) ; i += 16 ; } let mut sum_of_squares = _mm512_reduce_add_ps (acc) ; for & val in & a [i ..] { sum_of_squares += val * val ; } sum_of_squares . sqrt () } # [target_feature (enable = "avx512f")] unsafe fn norm_l1 (a : & [f32]) -> f32 { a . iter () . map (| x | x . abs ()) . sum () } # [target_feature (enable = "avx512f")] unsafe fn norm_linf (a : & [f32]) -> f32 { a . iter () . map (| x | x . abs ()) . fold (0.0f32 , f32 :: max) } # [target_feature (enable = "avx512f")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] * scalar ; } } # [target_feature (enable = "avx512f")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . abs () ; } } # [target_feature (enable = "avx512f")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . clamp (min_val , max_val) ; } } # [target_feature (enable = "avx512f")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] + t * (b [i] - a [i]) ; } } # [target_feature (enable = "avx512f")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . mul_add (b [i] , c [i]) ; } } # [target_feature (enable = "avx512f")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . max (0.0) ; } } # [target_feature (enable = "avx512f")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . exp () ; } } # [target_feature (enable = "avx512f")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = 1.0 / (1.0 + (- a [i]) . exp ()) ; } } # [target_feature (enable = "avx512f")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; for i in 0 .. a . len () { let x = a [i] ; let cube = x * x * x ; let inner = SQRT_2_OVER_PI * (x + 0.044715 * cube) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; } } # [target_feature (enable = "avx512f")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { let sigmoid_val = 1.0 / (1.0 + (- a [i]) . exp ()) ; result [i] = a [i] * sigmoid_val ; } } # [target_feature (enable = "avx512f")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . tanh () ; } } } . self_ty`
- **Function**: `tests::avx512_test` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_special_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_remainder_correctness` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_special_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_remainder_sizes` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_orthogonal` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_remainder_sizes` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_positive_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_non_aligned_18` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_max_at_start` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_backend_equivalence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_non_aligned_18` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_positive_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_min_at_start` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_backend_equivalence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]

### ./src/backends/gpu/device.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `GpuDevice` [fields: 2]
- **Impl**: `impl GpuDevice { # [doc = " Initialize GPU device"] pub fn new () -> Result < Self , String > { pollster :: block_on (async { Self :: new_async () . await }) } async fn new_async () -> Result < Self , String > { let instance = wgpu :: Instance :: default () ; let adapter = instance . request_adapter (& wgpu :: RequestAdapterOptions { power_preference : wgpu :: PowerPreference :: HighPerformance , compatible_surface : None , force_fallback_adapter : false , }) . await . ok_or ("Failed to find GPU adapter") ? ; let (device , queue) = adapter . request_device (& wgpu :: DeviceDescriptor { label : Some ("Trueno GPU Device") , required_features : wgpu :: Features :: empty () , required_limits : wgpu :: Limits :: default () , memory_hints : wgpu :: MemoryHints :: Performance , } , None ,) . await . map_err (| e | format ! ("Failed to create device: {}" , e)) ? ; Ok (Self { device , queue }) } # [doc = " Check if GPU is available"] pub fn is_available () -> bool { pollster :: block_on (async { let instance = wgpu :: Instance :: default () ; instance . request_adapter (& wgpu :: RequestAdapterOptions { power_preference : wgpu :: PowerPreference :: HighPerformance , compatible_surface : None , force_fallback_adapter : false , }) . await . is_some () }) } # [doc = " Execute matrix multiplication on GPU"] pub fn matmul (& self , a : & [f32] , b : & [f32] , result : & mut [f32] , m : usize , k : usize , n : usize ,) -> Result < () , String > { pollster :: block_on (async { self . matmul_async (a , b , result , m , k , n) . await }) } async fn matmul_async (& self , a : & [f32] , b : & [f32] , result : & mut [f32] , m : usize , k : usize , n : usize ,) -> Result < () , String > { let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Matmul Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: MATMUL_SHADER . into ()) , }) ; let a_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Matrix A") , size : std :: mem :: size_of_val (a) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let b_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Matrix B") , size : std :: mem :: size_of_val (b) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let c_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Matrix C") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct Dimensions { m : u32 , k : u32 , n : u32 , _padding : u32 , } let dims = Dimensions { m : m as u32 , k : k as u32 , n : n as u32 , _padding : 0 , } ; let dims_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Dimensions") , size : std :: mem :: size_of :: < Dimensions > () as u64 , usage : wgpu :: BufferUsages :: UNIFORM | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& a_buffer , 0 , bytemuck :: cast_slice (a)) ; self . queue . write_buffer (& b_buffer , 0 , bytemuck :: cast_slice (b)) ; self . queue . write_buffer (& dims_buffer , 0 , bytemuck :: bytes_of (& dims)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Matmul Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 3 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Uniform , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Matmul Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : a_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : b_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : c_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 3 , resource : dims_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Matmul Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Matmul Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Matmul Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Matmul Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size_x = 16 ; let workgroup_size_y = 16 ; let num_workgroups_x = (m as u32) . div_ceil (workgroup_size_x) ; let num_workgroups_y = (n as u32) . div_ceil (workgroup_size_y) ; compute_pass . dispatch_workgroups (num_workgroups_x , num_workgroups_y , 1) ; } encoder . copy_buffer_to_buffer (& c_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; result . copy_from_slice (bytemuck :: cast_slice (& data)) ; } staging_buffer . unmap () ; Ok (()) } # [doc = " Execute vector addition on GPU: c = a + b"] pub fn vec_add (& self , a : & [f32] , b : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . vec_add_async (a , b , result) . await }) } async fn vec_add_async (& self , a : & [f32] , b : & [f32] , result : & mut [f32]) -> Result < () , String > { let len = a . len () ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Vec Add Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: VEC_ADD_SHADER . into ()) , }) ; let a_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector A") , size : std :: mem :: size_of_val (a) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let b_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector B") , size : std :: mem :: size_of_val (b) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let c_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector C") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& a_buffer , 0 , bytemuck :: cast_slice (a)) ; self . queue . write_buffer (& b_buffer , 0 , bytemuck :: cast_slice (b)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Vec Add Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Vec Add Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : a_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : b_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : c_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Vec Add Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Vec Add Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Vec Add Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Vec Add Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } encoder . copy_buffer_to_buffer (& c_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; result . copy_from_slice (bytemuck :: cast_slice (& data)) ; } staging_buffer . unmap () ; Ok (()) } # [doc = " Generic helper for element-wise GPU operations"] # [doc = ""] # [doc = " This helper eliminates code duplication between element-wise operations"] # [doc = " (relu, clip, sigmoid, tanh, etc.) by abstracting the common GPU compute pattern."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `op_name` - Operation name for labels (e.g., \"ReLU\", \"Clip\")"] # [doc = " * `shader_source` - WGSL shader source code"] # [doc = " * `input` - Input data"] # [doc = " * `result` - Output buffer"] # [doc = " * `uniform_data` - Optional uniform buffer data (e.g., clip parameters)"] async fn execute_element_wise_op (& self , op_name : & str , shader_source : & str , input : & [f32] , result : & mut [f32] , uniform_data : Option < & [u8] > ,) -> Result < () , String > { let len = input . len () ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some (& format ! ("{} Shader" , op_name)) , source : wgpu :: ShaderSource :: Wgsl (shader_source . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Input" , op_name)) , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let output_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Output" , op_name)) , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; let uniform_buffer = uniform_data . map (| data | { let buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Uniform" , op_name)) , size : data . len () as u64 , usage : wgpu :: BufferUsages :: UNIFORM | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& buffer , 0 , data) ; buffer }) ; let mut bind_group_entries = vec ! [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] ; if uniform_buffer . is_some () { bind_group_entries . push (wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Uniform , has_dynamic_offset : false , min_binding_size : None , } , count : None , }) ; } let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some (& format ! ("{} Bind Group Layout" , op_name)) , entries : & bind_group_entries , }) ; let mut bind_entries = vec ! [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : output_buffer . as_entire_binding () , } ,] ; if let Some (ref uniform_buf) = uniform_buffer { bind_entries . push (wgpu :: BindGroupEntry { binding : 2 , resource : uniform_buf . as_entire_binding () , }) ; } let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some (& format ! ("{} Bind Group" , op_name)) , layout : & bind_group_layout , entries : & bind_entries , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some (& format ! ("{} Pipeline Layout" , op_name)) , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some (& format ! ("{} Pipeline" , op_name)) , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Staging Buffer" , op_name)) , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some (& format ! ("{} Encoder" , op_name)) , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some (& format ! ("{} Pass" , op_name)) , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } encoder . copy_buffer_to_buffer (& output_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; result . copy_from_slice (bytemuck :: cast_slice (& data)) ; } staging_buffer . unmap () ; Ok (()) } # [doc = " Execute ReLU activation on GPU: result[i] = max(0, input[i])"] pub fn relu (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("ReLU" , shaders :: RELU_SHADER , input , result , None) . await }) } # [doc = " Execute leaky ReLU activation on GPU: result[i] = max(negative_slope * input[i], input[i])"] pub fn leaky_relu (& self , input : & [f32] , result : & mut [f32] , negative_slope : f32 ,) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct LeakyReluParams { negative_slope : f32 , } let params = LeakyReluParams { negative_slope } ; let uniform_data = bytemuck :: bytes_of (& params) ; pollster :: block_on (async { self . execute_element_wise_op ("LeakyReLU" , shaders :: LEAKY_RELU_SHADER , input , result , Some (uniform_data) ,) . await }) } # [doc = " Execute ELU activation on GPU: result[i] = x if x > 0, else alpha * (exp(x) - 1)"] pub fn elu (& self , input : & [f32] , result : & mut [f32] , alpha : f32) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct EluParams { alpha : f32 , } let params = EluParams { alpha } ; let uniform_data = bytemuck :: bytes_of (& params) ; pollster :: block_on (async { self . execute_element_wise_op ("ELU" , shaders :: ELU_SHADER , input , result , Some (uniform_data) ,) . await }) } # [doc = " Execute sigmoid activation on GPU: result[i] = 1 / (1 + exp(-input[i]))"] pub fn sigmoid (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("Sigmoid" , shaders :: SIGMOID_SHADER , input , result , None) . await }) } # [doc = " Execute tanh activation on GPU: result[i] = tanh(input[i])"] pub fn tanh (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("Tanh" , shaders :: TANH_SHADER , input , result , None) . await }) } # [doc = " Execute swish activation on GPU: result[i] = input[i] / (1 + exp(-input[i]))"] pub fn swish (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("Swish" , shaders :: SWISH_SHADER , input , result , None) . await }) } # [doc = " Execute GELU activation on GPU: result[i] = 0.5 * input[i] * (1 + tanh(...))"] pub fn gelu (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("GELU" , shaders :: GELU_SHADER , input , result , None) . await }) } # [doc = " Execute clip (clamp) operation on GPU: result[i] = clamp(input[i], min_val, max_val)"] pub fn clip (& self , input : & [f32] , result : & mut [f32] , min_val : f32 , max_val : f32 ,) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct ClipParams { min_val : f32 , max_val : f32 , } let params = ClipParams { min_val , max_val } ; let uniform_data = bytemuck :: bytes_of (& params) ; pollster :: block_on (async { self . execute_element_wise_op ("Clip" , shaders :: CLIP_SHADER , input , result , Some (uniform_data) ,) . await }) } # [doc = " Execute softmax on GPU: result[i] = exp(input[i] - max) / sum(exp(input - max))"] # [doc = ""] # [doc = " Multi-pass implementation:"] # [doc = " 1. Find max value (parallel reduction)"] # [doc = " 2. Compute exp(x - max) (element-wise)"] # [doc = " 3. Sum exp values (parallel reduction)"] # [doc = " 4. Normalize by sum (element-wise)"] pub fn softmax (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . softmax_async (input , result) . await }) } async fn softmax_async (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { let max_val = self . reduce_max (input) . await ? ; let exp_vals = self . compute_exp_subtract (input , max_val) . await ? ; let sum_exp = self . reduce_sum (& exp_vals) . await ? ; self . normalize_by_sum (& exp_vals , result , sum_exp) . await ? ; Ok (()) } # [doc = " Execute log_softmax on GPU: result[i] = input[i] - max - log(sum(exp(input - max)))"] # [doc = ""] # [doc = " Multi-pass implementation:"] # [doc = " 1. Find max value (parallel reduction)"] # [doc = " 2. Compute exp(x - max) (element-wise)"] # [doc = " 3. Sum exp values (parallel reduction)"] # [doc = " 4. Compute log_softmax (element-wise)"] pub fn log_softmax (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . log_softmax_async (input , result) . await }) } async fn log_softmax_async (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { let max_val = self . reduce_max (input) . await ? ; let exp_vals = self . compute_exp_subtract (input , max_val) . await ? ; let sum_exp = self . reduce_sum (& exp_vals) . await ? ; let log_sum_exp = sum_exp . ln () ; # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct LogSoftmaxParams { max_val : f32 , log_sum_exp : f32 , } let params = LogSoftmaxParams { max_val , log_sum_exp , } ; let uniform_data = bytemuck :: bytes_of (& params) ; self . execute_element_wise_op ("LogSoftmax" , shaders :: LOG_SOFTMAX_SHADER , input , result , Some (uniform_data) ,) . await ? ; Ok (()) } # [doc = " Helper: Parallel max reduction"] async fn reduce_max (& self , input : & [f32]) -> Result < f32 , String > { let len = input . len () ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Max Reduction Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: MAX_REDUCTION_SHADER . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Max Reduction Input") , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let partial_results = vec ! [f32 :: NEG_INFINITY ; num_workgroups as usize] ; let result_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Max Partial Results") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Max Reduction Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Max Reduction Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : result_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Max Reduction Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Max Reduction Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Max Reduction Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Max Reduction Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Max Staging Buffer") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; encoder . copy_buffer_to_buffer (& result_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (partial_results . as_slice ()) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Channel receive failed") ? . map_err (| e | format ! ("Buffer map failed: {:?}" , e)) ? ; let data = buffer_slice . get_mapped_range () ; let result : Vec < f32 > = bytemuck :: cast_slice (& data) . to_vec () ; drop (data) ; staging_buffer . unmap () ; Ok (result . iter () . copied () . fold (f32 :: NEG_INFINITY , f32 :: max)) } # [doc = " Helper: Parallel sum reduction"] async fn reduce_sum (& self , input : & [f32]) -> Result < f32 , String > { let len = input . len () ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Sum Reduction Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: SUM_REDUCTION_SHADER . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Sum Reduction Input") , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let partial_results = vec ! [0.0f32 ; num_workgroups as usize] ; let result_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Sum Partial Results") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Sum Reduction Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Sum Reduction Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : result_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Sum Reduction Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Sum Reduction Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Sum Reduction Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Sum Reduction Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Sum Staging Buffer") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; encoder . copy_buffer_to_buffer (& result_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (partial_results . as_slice ()) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Channel receive failed") ? . map_err (| e | format ! ("Buffer map failed: {:?}" , e)) ? ; let data = buffer_slice . get_mapped_range () ; let result : Vec < f32 > = bytemuck :: cast_slice (& data) . to_vec () ; drop (data) ; staging_buffer . unmap () ; Ok (result . iter () . sum ()) } # [doc = " Helper: Compute exp(input[i] - max_val)"] async fn compute_exp_subtract (& self , input : & [f32] , max_val : f32) -> Result < Vec < f32 > , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct MaxValue { max_val : f32 , } let params = MaxValue { max_val } ; let uniform_data = bytemuck :: bytes_of (& params) ; let mut result = vec ! [0.0f32 ; input . len ()] ; self . execute_element_wise_op ("SoftmaxExp" , shaders :: SOFTMAX_EXP_SHADER , input , & mut result , Some (uniform_data) ,) . await ? ; Ok (result) } # [doc = " Helper: Normalize by sum"] async fn normalize_by_sum (& self , input : & [f32] , result : & mut [f32] , sum_val : f32 ,) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct SumValue { sum_val : f32 , } let params = SumValue { sum_val } ; let uniform_data = bytemuck :: bytes_of (& params) ; self . execute_element_wise_op ("SoftmaxNormalize" , shaders :: SOFTMAX_NORMALIZE_SHADER , input , result , Some (uniform_data) ,) . await ? ; Ok (()) } # [doc = " Execute dot product on GPU: result = sum(a[i] * b[i])"] pub fn dot (& self , a : & [f32] , b : & [f32]) -> Result < f32 , String > { pollster :: block_on (async { self . dot_async (a , b) . await }) } async fn dot_async (& self , a : & [f32] , b : & [f32]) -> Result < f32 , String > { let len = a . len () ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Dot Product Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: DOT_PRODUCT_SHADER . into ()) , }) ; let a_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector A") , size : std :: mem :: size_of_val (a) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let b_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector B") , size : std :: mem :: size_of_val (b) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let partial_results = vec ! [0.0f32 ; num_workgroups as usize] ; let result_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Partial Results") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& a_buffer , 0 , bytemuck :: cast_slice (a)) ; self . queue . write_buffer (& b_buffer , 0 , bytemuck :: cast_slice (b)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Dot Product Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Dot Product Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : a_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : b_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : result_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Dot Product Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Dot Product Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Dot Product Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Dot Product Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } encoder . copy_buffer_to_buffer (& result_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (partial_results . as_slice ()) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; let final_result = { let data = buffer_slice . get_mapped_range () ; let partial_sums : & [f32] = bytemuck :: cast_slice (& data) ; partial_sums . iter () . sum () } ; staging_buffer . unmap () ; Ok (final_result) } # [doc = " Perform 2D convolution on GPU"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input image (row-major)"] # [doc = " * `kernel` - Convolution kernel (row-major)"] # [doc = " * `result` - Output buffer (row-major)"] # [doc = " * `input_rows` - Number of rows in input"] # [doc = " * `input_cols` - Number of columns in input"] # [doc = " * `kernel_rows` - Number of rows in kernel"] # [doc = " * `kernel_cols` - Number of columns in kernel"] # [doc = ""] # [doc = " Output dimensions: (input_rows - kernel_rows + 1) × (input_cols - kernel_cols + 1)"] # [allow (clippy :: too_many_arguments)] pub fn convolve2d (& self , input : & [f32] , kernel : & [f32] , result : & mut [f32] , input_rows : usize , input_cols : usize , kernel_rows : usize , kernel_cols : usize ,) -> Result < () , String > { pollster :: block_on (async { self . convolve2d_async (input , kernel , result , input_rows , input_cols , kernel_rows , kernel_cols ,) . await }) } # [allow (clippy :: too_many_arguments)] async fn convolve2d_async (& self , input : & [f32] , kernel : & [f32] , result : & mut [f32] , input_rows : usize , input_cols : usize , kernel_rows : usize , kernel_cols : usize ,) -> Result < () , String > { let output_rows = input_rows - kernel_rows + 1 ; let output_cols = input_cols - kernel_cols + 1 ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Convolve2D Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: CONVOLVE2D_SHADER . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Input Image") , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let kernel_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Kernel") , size : std :: mem :: size_of_val (kernel) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let output_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Output") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct ConvDimensions { input_rows : u32 , input_cols : u32 , kernel_rows : u32 , kernel_cols : u32 , output_rows : u32 , output_cols : u32 , } let dims = ConvDimensions { input_rows : input_rows as u32 , input_cols : input_cols as u32 , kernel_rows : kernel_rows as u32 , kernel_cols : kernel_cols as u32 , output_rows : output_rows as u32 , output_cols : output_cols as u32 , } ; let dims_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Conv Dimensions") , size : std :: mem :: size_of :: < ConvDimensions > () as u64 , usage : wgpu :: BufferUsages :: UNIFORM | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; self . queue . write_buffer (& kernel_buffer , 0 , bytemuck :: cast_slice (kernel)) ; self . queue . write_buffer (& dims_buffer , 0 , bytemuck :: bytes_of (& dims)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Convolve2D Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 3 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Uniform , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Convolve2D Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : kernel_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : output_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 3 , resource : dims_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Convolve2D Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Convolve2D Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Convolve2D Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Convolve2D Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size_x = 16 ; let workgroup_size_y = 16 ; let num_workgroups_x = (output_rows as u32) . div_ceil (workgroup_size_x) ; let num_workgroups_y = (output_cols as u32) . div_ceil (workgroup_size_y) ; compute_pass . dispatch_workgroups (num_workgroups_x , num_workgroups_y , 1) ; } let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; encoder . copy_buffer_to_buffer (& output_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . unwrap () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; let output_data : & [f32] = bytemuck :: cast_slice (& data) ; result . copy_from_slice (output_data) ; } staging_buffer . unmap () ; Ok (()) } } . self_ty`
- **Struct**: `Dimensions` [fields: 4]
- **Struct**: `LeakyReluParams` [fields: 1]
- **Struct**: `EluParams` [fields: 1]
- **Struct**: `ClipParams` [fields: 2]
- **Struct**: `LogSoftmaxParams` [fields: 2]
- **Struct**: `MaxValue` [fields: 1]
- **Struct**: `SumValue` [fields: 1]
- **Struct**: `ConvDimensions` [fields: 6]
- **Function**: `tests::test_is_available_consistency` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(16)] [tdg: 2.5]
- **Function**: `tests::test_reduce_sum_not_hardcoded` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(16)] [tdg: 2.5]

### ./src/backends/gpu/mod.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `GpuBackend` [fields: 1]
- **Impl**: `# [cfg (feature = "gpu")] impl GpuBackend { # [doc = " Create a new GPU backend"] pub fn new () -> Self { Self { device : None } } # [doc = " Initialize GPU device (lazy)"] fn ensure_device (& mut self) -> Result < & GpuDevice , String > { if self . device . is_none () { self . device = Some (GpuDevice :: new () ?) ; } Ok (self . device . as_ref () . unwrap ()) } # [doc = " Check if GPU is available"] pub fn is_available () -> bool { GpuDevice :: is_available () } # [doc = " Vector addition on GPU: c = a + b"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `a` - Vector a"] # [doc = " * `b` - Vector b"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector c (element-wise sum)"] pub fn vec_add (& mut self , a : & [f32] , b : & [f32]) -> Result < Vec < f32 > , String > { if a . len () != b . len () { return Err (format ! ("Vector length mismatch: {} != {}" , a . len () , b . len ())) ; } if a . is_empty () { return Err ("Cannot perform GPU operation on empty vectors" . to_string ()) ; } let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; a . len ()] ; device . vec_add (a , b , & mut result) ? ; Ok (result) } # [doc = " Dot product on GPU: result = sum(a[i] * b[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `a` - Vector a"] # [doc = " * `b` - Vector b"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Scalar dot product result"] pub fn dot (& mut self , a : & [f32] , b : & [f32]) -> Result < f32 , String > { if a . len () != b . len () { return Err (format ! ("Vector length mismatch: {} != {}" , a . len () , b . len ())) ; } let device = self . ensure_device () ? ; device . dot (a , b) } # [doc = " ReLU activation on GPU: result[i] = max(0, input[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with ReLU applied element-wise"] pub fn relu (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . relu (input , & mut result) ? ; Ok (result) } # [doc = " Leaky ReLU activation on GPU: result[i] = max(negative_slope * input[i], input[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = " * `negative_slope` - Slope for negative values (typically 0.01)"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with leaky ReLU applied element-wise"] pub fn leaky_relu (& mut self , input : & [f32] , negative_slope : f32) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . leaky_relu (input , & mut result , negative_slope) ? ; Ok (result) } # [doc = " ELU activation on GPU: result[i] = x if x > 0, else alpha * (exp(x) - 1)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = " * `alpha` - Scaling factor for negative values (typically 1.0)"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with ELU applied element-wise"] pub fn elu (& mut self , input : & [f32] , alpha : f32) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . elu (input , & mut result , alpha) ? ; Ok (result) } # [doc = " Clip (clamp) operation on GPU: result[i] = clamp(input[i], min_val, max_val)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = " * `min_val` - Minimum value"] # [doc = " * `max_val` - Maximum value"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with clip applied element-wise"] pub fn clip (& mut self , input : & [f32] , min_val : f32 , max_val : f32) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . clip (input , & mut result , min_val , max_val) ? ; Ok (result) } # [doc = " Sigmoid activation on GPU: result[i] = 1 / (1 + exp(-input[i]))"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with sigmoid applied element-wise"] pub fn sigmoid (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . sigmoid (input , & mut result) ? ; Ok (result) } # [doc = " Tanh activation on GPU: result[i] = tanh(input[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with tanh applied element-wise"] pub fn tanh (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . tanh (input , & mut result) ? ; Ok (result) } # [doc = " Swish activation on GPU: result[i] = input[i] / (1 + exp(-input[i]))"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with swish applied element-wise"] pub fn swish (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . swish (input , & mut result) ? ; Ok (result) } # [doc = " GELU activation on GPU: result[i] = 0.5 * input[i] * (1 + tanh(...))"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with GELU applied element-wise"] pub fn gelu (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . gelu (input , & mut result) ? ; Ok (result) } # [doc = " Softmax activation on GPU: result[i] = exp(input[i] - max) / sum(exp(input - max))"] # [doc = ""] # [doc = " Uses multi-pass reduction for numerical stability:"] # [doc = " - Pass 1: Max reduction (parallel)"] # [doc = " - Pass 2: Exp-subtract (element-wise)"] # [doc = " - Pass 3: Sum reduction (parallel)"] # [doc = " - Pass 4: Normalize (element-wise)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with softmax applied element-wise"] pub fn softmax (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . softmax (input , & mut result) ? ; Ok (result) } # [doc = " Log-softmax activation on GPU: result[i] = log(softmax(input)[i])"] # [doc = ""] # [doc = " Uses multi-pass reduction for numerical stability:"] # [doc = " - Pass 1: Max reduction (parallel)"] # [doc = " - Pass 2: Exp-subtract (element-wise)"] # [doc = " - Pass 3: Sum reduction (parallel)"] # [doc = " - Pass 4: Log-normalize (element-wise)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with log-softmax applied element-wise"] pub fn log_softmax (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . log_softmax (input , & mut result) ? ; Ok (result) } # [doc = " 2D Convolution on GPU: output = input ⊗ kernel"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input matrix (flattened row-major)"] # [doc = " * `kernel` - Convolution kernel (flattened row-major)"] # [doc = " * `input_rows` - Number of rows in input"] # [doc = " * `input_cols` - Number of columns in input"] # [doc = " * `kernel_rows` - Number of rows in kernel"] # [doc = " * `kernel_cols` - Number of columns in kernel"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Output matrix (flattened row-major, \"valid\" convolution)"] # [doc = " - output_rows = input_rows - kernel_rows + 1"] # [doc = " - output_cols = input_cols - kernel_cols + 1"] pub fn convolve2d (& mut self , input : & [f32] , kernel : & [f32] , input_rows : usize , input_cols : usize , kernel_rows : usize , kernel_cols : usize ,) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let output_rows = input_rows . saturating_sub (kernel_rows) . saturating_add (1) ; let output_cols = input_cols . saturating_sub (kernel_cols) . saturating_add (1) ; let mut result = vec ! [0.0f32 ; output_rows * output_cols] ; device . convolve2d (input , kernel , & mut result , input_rows , input_cols , kernel_rows , kernel_cols ,) ? ; Ok (result) } # [doc = " Matrix multiplication on GPU: C = A × B"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `a` - Matrix A (m×k) in row-major order"] # [doc = " * `b` - Matrix B (k×n) in row-major order"] # [doc = " * `m` - Rows of A and C"] # [doc = " * `k` - Cols of A, rows of B"] # [doc = " * `n` - Cols of B and C"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Matrix C (m×n) in row-major order"] pub fn matmul (& mut self , a : & [f32] , b : & [f32] , m : usize , k : usize , n : usize ,) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; m * n] ; device . matmul (a , b , & mut result , m , k , n) ? ; Ok (result) } } . self_ty`
- **Impl**: `Default` for `# [cfg (feature = "gpu")] impl Default for GpuBackend { fn default () -> Self { Self :: new () } } . self_ty`
- **Struct**: `GpuBackend` [fields: 0]
- **Impl**: `# [cfg (not (feature = "gpu"))] impl GpuBackend { pub fn new () -> Self { Self } pub fn is_available () -> bool { false } } . self_ty`
- **Impl**: `Default` for `# [cfg (not (feature = "gpu"))] impl Default for GpuBackend { fn default () -> Self { Self } } . self_ty`
- **Function**: `tests::test_gpu_vec_add_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_length_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_length_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_clip_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_leaky_relu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_elu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_tanh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_tanh_not_hardcoded` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_log_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]

### ./src/backends/gpu/shaders.rs

**File Complexity**: 1 | **Functions**: 0


### ./src/backends/mod.rs

**File Complexity**: 1 | **Functions**: 0

- **Trait**: `VectorBackend`

### ./src/backends/neon.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `NeonBackend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for NeonBackend { # [target_feature (enable = "neon")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vaddq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "neon")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vsubq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "neon")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vmulq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "neon")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vdivq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "neon")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; acc = vmlaq_f32 (acc , va , vb) ; i += 4 ; } let sum2 = vpadd_f32 (vget_low_f32 (acc) , vget_high_f32 (acc)) ; let sum1 = vpadd_f32 (sum2 , sum2) ; let mut result = vget_lane_f32 (sum1 , 0) ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "neon")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; acc = vaddq_f32 (acc , va) ; i += 4 ; } let sum2 = vpadd_f32 (vget_low_f32 (acc) , vget_high_f32 (acc)) ; let sum1 = vpadd_f32 (sum2 , sum2) ; let mut result = vget_lane_f32 (sum1 , 0) ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "neon")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmax = vmaxq_f32 (vmax , va) ; i += 4 ; } let max2 = vpmax_f32 (vget_low_f32 (vmax) , vget_high_f32 (vmax)) ; let max1 = vpmax_f32 (max2 , max2) ; let mut result = vget_lane_f32 (max1 , 0) ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "neon")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmin = vminq_f32 (vmin , va) ; i += 4 ; } let min2 = vpmin_f32 (vget_low_f32 (vmin) , vget_high_f32 (vmin)) ; let min1 = vpmin_f32 (min2 , min2) ; let mut result = vget_lane_f32 (min1 , 0) ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "neon")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut max_value = a [0] ; let mut max_index = 0 ; let mut vmax = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmax = vmaxq_f32 (vmax , va) ; i += 4 ; } let max2 = vpmax_f32 (vget_low_f32 (vmax) , vget_high_f32 (vmax)) ; let max1 = vpmax_f32 (max2 , max2) ; for (idx , & val) in a [.. i] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "neon")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut min_value = a [0] ; let mut min_index = 0 ; let mut vmin = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmin = vminq_f32 (vmin , va) ; i += 4 ; } let min2 = vpmin_f32 (vget_low_f32 (vmin) , vget_high_f32 (vmin)) ; let min1 = vpmin_f32 (min2 , min2) ; for (idx , & val) in a [.. i] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "neon")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [cfg (target_arch = "aarch64")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let abs_va = vabsq_f32 (va) ; acc = vaddq_f32 (acc , abs_va) ; i += 4 ; } let mut result = vaddvq_f32 (acc) ; for & val in & a [i ..] { result += val . abs () ; } result } # [cfg (target_arch = "arm")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let abs_va = vabsq_f32 (va) ; acc = vaddq_f32 (acc , abs_va) ; i += 4 ; } let mut result = { let sum_halves = vpadd_f32 (vget_low_f32 (acc) , vget_high_f32 (acc)) ; let sum_all = vpadd_f32 (sum_halves , sum_halves) ; vget_lane_f32 (sum_all , 0) } ; for & val in & a [i ..] { result += val . abs () ; } result } # [cfg (target_arch = "aarch64")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = vdupq_n_f32 (scalar) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmulq_f32 (va , scalar_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = vdupq_n_f32 (scalar) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmulq_f32 (va , scalar_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = vdupq_n_f32 (min_val) ; let max_vec = vdupq_n_f32 (max_val) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let clamped = vminq_f32 (vmaxq_f32 (va , min_vec) , max_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = vdupq_n_f32 (min_val) ; let max_vec = vdupq_n_f32 (max_val) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let clamped = vminq_f32 (vmaxq_f32 (va , min_vec) , max_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = vdupq_n_f32 (t) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let diff = vsubq_f32 (vb , va) ; let vresult = vfmaq_f32 (va , t_vec , diff) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = vdupq_n_f32 (t) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let diff = vsubq_f32 (vb , va) ; let vresult = vmlaq_f32 (va , t_vec , diff) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vc = vld1q_f32 (c . as_ptr () . add (i)) ; let vresult = vfmaq_f32 (vc , va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vc = vld1q_f32 (c . as_ptr () . add (i)) ; let vresult = vmlaq_f32 (vc , va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmaxq_f32 (zero , va) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmaxq_f32 (zero , va) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let one = vdupq_n_f32 (1.0) ; let half = vdupq_n_f32 (0.5) ; let zero = vdupq_n_f32 (0.0) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let neg_x = vsubq_f32 (zero , x) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (neg_x , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (neg_x , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_neg_x = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let sigmoid_result = vdivq_f32 (one , vaddq_f32 (one , exp_neg_x)) ; vst1q_f32 (result . as_mut_ptr () . add (i) , sigmoid_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; } } # [cfg (target_arch = "aarch64")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = vdupq_n_f32 (0.797_884_6) ; let coeff = vdupq_n_f32 (0.044715) ; let half = vdupq_n_f32 (0.5) ; let one = vdupq_n_f32 (1.0) ; let two = vdupq_n_f32 (2.0) ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let x2 = vmulq_f32 (x , x) ; let x3 = vmulq_f32 (x2 , x) ; let inner = vmulq_f32 (sqrt_2_over_pi , vaddq_f32 (x , vmulq_f32 (coeff , x3))) ; let z = vmulq_f32 (two , inner) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (z , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (z , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_2z = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let tanh_val = vdivq_f32 (vsubq_f32 (exp_2z , one) , vaddq_f32 (exp_2z , one)) ; let gelu_result = vmulq_f32 (half , vmulq_f32 (x , vaddq_f32 (one , tanh_val))) ; vst1q_f32 (result . as_mut_ptr () . add (i) , gelu_result) ; i += 4 ; } while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = 0.797_884_6 * (x + 0.044715 * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; for (i , & x) in a . iter () . enumerate () { let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; } } # [cfg (target_arch = "aarch64")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let one = vdupq_n_f32 (1.0) ; let half = vdupq_n_f32 (0.5) ; let zero = vdupq_n_f32 (0.0) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let neg_x = vsubq_f32 (zero , x) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (neg_x , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (neg_x , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_neg_x = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let swish_result = vdivq_f32 (x , vaddq_f32 (one , exp_neg_x)) ; vst1q_f32 (result . as_mut_ptr () . add (i) , swish_result) ; i += 4 ; } while i < len { let x = a [i] ; if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let one = vdupq_n_f32 (1.0) ; let two = vdupq_n_f32 (2.0) ; let half = vdupq_n_f32 (0.5) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let z = vmulq_f32 (two , x) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (z , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (z , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_2x = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let tanh_result = vdivq_f32 (vsubq_f32 (exp_2x , one) , vaddq_f32 (exp_2x , one)) ; vst1q_f32 (result . as_mut_ptr () . add (i) , tanh_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = val . tanh () ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } } } # [cfg (target_arch = "arm")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { result [i] = x . tanh () ; } } } . self_ty`
- **Function**: `tests::test_neon_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_tanh_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]

### ./src/backends/scalar.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `ScalarBackend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for ScalarBackend { unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] + b [i] ; } } unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] - b [i] ; } } unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] * b [i] ; } } unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] / b [i] ; } } unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let mut sum = 0.0 ; for i in 0 .. a . len () { sum += a [i] * b [i] ; } sum } unsafe fn sum (a : & [f32]) -> f32 { let mut total = 0.0 ; for & val in a { total += val ; } total } unsafe fn max (a : & [f32]) -> f32 { let mut maximum = a [0] ; for & val in & a [1 ..] { if val > maximum { maximum = val ; } } maximum } unsafe fn min (a : & [f32]) -> f32 { let mut minimum = a [0] ; for & val in & a [1 ..] { if val < minimum { minimum = val ; } } minimum } unsafe fn argmax (a : & [f32]) -> usize { let mut max_value = a [0] ; let mut max_index = 0 ; for (i , & val) in a . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i ; } } max_index } unsafe fn argmin (a : & [f32]) -> usize { let mut min_value = a [0] ; let mut min_index = 0 ; for (i , & val) in a . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { let mut sum = 0.0 ; let mut c = 0.0 ; for & value in a { let y = value - c ; let t = sum + y ; c = (t - sum) - y ; sum = t ; } sum } unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let mut sum_of_squares = 0.0 ; for & val in a { sum_of_squares += val * val ; } sum_of_squares . sqrt () } unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let mut sum = 0.0 ; for & val in a { sum += val . abs () ; } sum } unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let mut max_val = 0.0_f32 ; for & val in a { let abs_val = val . abs () ; if abs_val > max_val { max_val = abs_val ; } } max_val } unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val * scalar ; } } unsafe fn abs (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val . abs () ; } } unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val . max (min_val) . min (max_val) ; } } unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { for (i , (& a_val , & b_val)) in a . iter () . zip (b . iter ()) . enumerate () { result [i] = a_val + t * (b_val - a_val) ; } } unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { for (i , ((& a_val , & b_val) , & c_val)) in a . iter () . zip (b . iter ()) . zip (c . iter ()) . enumerate () { result [i] = a_val * b_val + c_val ; } } unsafe fn relu (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = if val > 0.0 { val } else { 0.0 } ; } } unsafe fn exp (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val . exp () ; } } unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; } } unsafe fn gelu (a : & [f32] , result : & mut [f32]) { const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; for (i , & x) in a . iter () . enumerate () { let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; } } unsafe fn swish (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } } } unsafe fn tanh (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { result [i] = x . tanh () ; } } } . self_ty`
- **Function**: `tests::test_scalar_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sub` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_div` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_argmax` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_argmin` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sum_kahan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_norm_l1` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_norm_l2` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_scale` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_clamp` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_lerp` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_fma` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sigmoid` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_gelu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_swish` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]

### ./src/backends/sse2.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `Sse2Backend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for Sse2Backend { # [target_feature (enable = "sse2")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm_add_ps (va , vb) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm_sub_ps (va , vb) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm_mul_ps (va , vb) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let two = _mm_set1_ps (2.0) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let rcp = _mm_rcp_ps (vb) ; let refined = _mm_mul_ps (rcp , _mm_sub_ps (two , _mm_mul_ps (vb , rcp))) ; let vresult = _mm_mul_ps (va , refined) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut sum_vec = _mm_setzero_ps () ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vmul = _mm_mul_ps (va , vb) ; sum_vec = _mm_add_ps (sum_vec , vmul) ; i += 4 ; } let mut sum = { let temp = _mm_add_ps (sum_vec , _mm_movehl_ps (sum_vec , sum_vec)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for j in i .. len { sum += a [j] * b [j] ; } sum } # [target_feature (enable = "sse2")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut sum_vec = _mm_setzero_ps () ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; sum_vec = _mm_add_ps (sum_vec , va) ; i += 4 ; } let mut sum = { let temp = _mm_add_ps (sum_vec , _mm_movehl_ps (sum_vec , sum_vec)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; sum += a [i .. len] . iter () . sum :: < f32 > () ; sum } # [target_feature (enable = "sse2")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut max_vec = _mm_set1_ps (a [0]) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; max_vec = _mm_max_ps (max_vec , va) ; i += 4 ; } let mut maximum = { let temp = _mm_max_ps (max_vec , _mm_movehl_ps (max_vec , max_vec)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i .. len] { if val > maximum { maximum = val ; } } maximum } # [target_feature (enable = "sse2")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut min_vec = _mm_set1_ps (a [0]) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; min_vec = _mm_min_ps (min_vec , va) ; i += 4 ; } let mut minimum = { let temp = _mm_min_ps (min_vec , _mm_movehl_ps (min_vec , min_vec)) ; let temp = _mm_min_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i .. len] { if val < minimum { minimum = val ; } } minimum } # [target_feature (enable = "sse2")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut vmax = _mm_set1_ps (a [0]) ; let mut vmax_idx = _mm_set1_ps (0.0) ; let mut vidx_current = _mm_set_ps (3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm_set1_ps (4.0) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm_cmpgt_ps (va , vmax) ; vmax = _mm_or_ps (_mm_and_ps (mask , va) , _mm_andnot_ps (mask , vmax)) ; vmax_idx = _mm_or_ps (_mm_and_ps (mask , vidx_current) , _mm_andnot_ps (mask , vmax_idx) ,) ; vidx_current = _mm_add_ps (vidx_current , vinc) ; i += 4 ; } let mut max_array = [0.0f32 ; 4] ; let mut idx_array = [0.0f32 ; 4] ; _mm_storeu_ps (max_array . as_mut_ptr () , vmax) ; _mm_storeu_ps (idx_array . as_mut_ptr () , vmax_idx) ; let mut max_value = max_array [0] ; let mut max_index = idx_array [0] as usize ; for j in 1 .. 4 { if max_array [j] > max_value { max_value = max_array [j] ; max_index = idx_array [j] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "sse2")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut vmin = _mm_set1_ps (a [0]) ; let mut vmin_idx = _mm_set1_ps (0.0) ; let mut vidx_current = _mm_set_ps (3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm_set1_ps (4.0) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm_cmplt_ps (va , vmin) ; vmin = _mm_or_ps (_mm_and_ps (mask , va) , _mm_andnot_ps (mask , vmin)) ; vmin_idx = _mm_or_ps (_mm_and_ps (mask , vidx_current) , _mm_andnot_ps (mask , vmin_idx) ,) ; vidx_current = _mm_add_ps (vidx_current , vinc) ; i += 4 ; } let mut min_array = [0.0f32 ; 4] ; let mut idx_array = [0.0f32 ; 4] ; _mm_storeu_ps (min_array . as_mut_ptr () , vmin) ; _mm_storeu_ps (idx_array . as_mut_ptr () , vmin_idx) ; let mut min_value = min_array [0] ; let mut min_index = idx_array [0] as usize ; for j in 1 .. 4 { if min_array [j] < min_value { min_value = min_array [j] ; min_index = idx_array [j] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "sse2")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [target_feature (enable = "sse2")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = _mm_setzero_ps () ; let sign_mask = _mm_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm_and_ps (va , sign_mask) ; acc = _mm_add_ps (acc , abs_va) ; i += 4 ; } let mut result = { let temp = _mm_add_ps (acc , _mm_movehl_ps (acc , acc)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { result += val . abs () ; } result } # [target_feature (enable = "sse2")] unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut max_vec = _mm_setzero_ps () ; let sign_mask = _mm_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm_and_ps (va , sign_mask) ; max_vec = _mm_max_ps (max_vec , abs_va) ; i += 4 ; } let mut result = { let temp = _mm_max_ps (max_vec , _mm_movehl_ps (max_vec , max_vec)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { let abs_val = val . abs () ; if abs_val > result { result = abs_val ; } } result } # [target_feature (enable = "sse2")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = _mm_set1_ps (scalar) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm_mul_ps (va , scalar_vec) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sign_mask = _mm_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm_and_ps (va , sign_mask) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , abs_va) ; i += 4 ; } while i < len { result [i] = a [i] . abs () ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = _mm_set1_ps (min_val) ; let max_vec = _mm_set1_ps (max_val) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let clamped = _mm_min_ps (_mm_max_ps (va , min_vec) , max_vec) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = _mm_set1_ps (t) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let diff = _mm_sub_ps (vb , va) ; let scaled_diff = _mm_mul_ps (t_vec , diff) ; let vresult = _mm_add_ps (va , scaled_diff) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vc = _mm_loadu_ps (c . as_ptr () . add (i)) ; let product = _mm_mul_ps (va , vb) ; let vresult = _mm_add_ps (product , vc) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = _mm_setzero_ps () ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm_max_ps (zero , va) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let x = _mm_max_ps (_mm_min_ps (x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let vresult = _mm_mul_ps (p , scale) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] . exp () ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm_sub_ps (_mm_setzero_ps () , x) ; let neg_x = _mm_max_ps (_mm_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (neg_x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (neg_x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_neg_x = _mm_mul_ps (p , scale) ; let denom = _mm_add_ps (one , exp_neg_x) ; let sigmoid_result = _mm_div_ps (one , denom) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , sigmoid_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = _mm_set1_ps (0.797_884_6) ; let coeff = _mm_set1_ps (0.044715) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let two = _mm_set1_ps (2.0) ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let x2 = _mm_mul_ps (x , x) ; let x3 = _mm_mul_ps (x2 , x) ; let inner_sum = _mm_add_ps (x , _mm_mul_ps (coeff , x3)) ; let inner = _mm_mul_ps (sqrt_2_over_pi , inner_sum) ; let two_inner = _mm_mul_ps (two , inner) ; let two_inner = _mm_max_ps (_mm_min_ps (two_inner , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (two_inner , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (two_inner , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_2inner = _mm_mul_ps (p , scale) ; let tanh_numer = _mm_sub_ps (exp_2inner , one) ; let tanh_denom = _mm_add_ps (exp_2inner , one) ; let tanh_result = _mm_div_ps (tanh_numer , tanh_denom) ; let one_plus_tanh = _mm_add_ps (one , tanh_result) ; let gelu_result = _mm_mul_ps (half , _mm_mul_ps (x , one_plus_tanh)) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , gelu_result) ; i += 4 ; } const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm_sub_ps (_mm_setzero_ps () , x) ; let neg_x = _mm_max_ps (_mm_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (neg_x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (neg_x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_neg_x = _mm_mul_ps (p , scale) ; let denom = _mm_add_ps (one , exp_neg_x) ; let swish_result = _mm_div_ps (x , denom) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , swish_result) ; i += 4 ; } while i < len { let x = a [i] ; result [i] = if x < - 50.0 { 0.0 } else if x > 50.0 { x } else { x / (1.0 + (- x) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let two = _mm_set1_ps (2.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let two_x = _mm_mul_ps (two , x) ; let two_x = _mm_max_ps (_mm_min_ps (two_x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (two_x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (two_x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_2x = _mm_mul_ps (p , scale) ; let tanh_numer = _mm_sub_ps (exp_2x , one) ; let tanh_denom = _mm_add_ps (exp_2x , one) ; let tanh_result = _mm_div_ps (tanh_numer , tanh_denom) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , tanh_result) ; i += 4 ; } while i < len { let x = a [i] ; result [i] = if x < - 30.0 { - 1.0 } else if x > 30.0 { 1.0 } else { let exp_2x = (2.0 * x) . exp () ; (exp_2x - 1.0) / (exp_2x + 1.0) } ; i += 1 ; } } } . self_ty`
- **Function**: `tests::test_sse2_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_scale_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_clamp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_fma_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_lerp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sum_kahan_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_norm_l1_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_norm_l2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_dot_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_add_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sum_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_max_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_tanh_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]

### ./src/backends/wasm.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `WasmBackend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for WasmBackend { # [target_feature (enable = "simd128")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_add (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_sub (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_mul (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_div (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let prod = f32x4_mul (va , vb) ; acc = f32x4_add (acc , prod) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (acc) + f32x4_extract_lane :: < 1 > (acc) + f32x4_extract_lane :: < 2 > (acc) + f32x4_extract_lane :: < 3 > (acc) ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "simd128")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; acc = f32x4_add (acc , va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (acc) + f32x4_extract_lane :: < 1 > (acc) + f32x4_extract_lane :: < 2 > (acc) + f32x4_extract_lane :: < 3 > (acc) ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "simd128")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmax = f32x4_max (vmax , va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (vmax) . max (f32x4_extract_lane :: < 1 > (vmax)) . max (f32x4_extract_lane :: < 2 > (vmax)) . max (f32x4_extract_lane :: < 3 > (vmax)) ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "simd128")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmin = f32x4_min (vmin , va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (vmin) . min (f32x4_extract_lane :: < 1 > (vmin)) . min (f32x4_extract_lane :: < 2 > (vmin)) . min (f32x4_extract_lane :: < 3 > (vmin)) ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "simd128")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut max_value = a [0] ; let mut max_index = 0 ; let mut vmax = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmax = f32x4_max (vmax , va) ; i += 4 ; } for (idx , & val) in a [.. i] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "simd128")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut min_value = a [0] ; let mut min_index = 0 ; let mut vmin = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmin = f32x4_min (vmin , va) ; i += 4 ; } for (idx , & val) in a [.. i] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "simd128")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [target_feature (enable = "simd128")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let abs_va = f32x4_abs (va) ; acc = f32x4_add (acc , abs_va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (acc) + f32x4_extract_lane :: < 1 > (acc) + f32x4_extract_lane :: < 2 > (acc) + f32x4_extract_lane :: < 3 > (acc) ; for & val in & a [i ..] { result += val . abs () ; } result } # [target_feature (enable = "simd128")] unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut vmax = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let abs_va = f32x4_abs (va) ; vmax = f32x4_max (vmax , abs_va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (vmax) . max (f32x4_extract_lane :: < 1 > (vmax)) . max (f32x4_extract_lane :: < 2 > (vmax)) . max (f32x4_extract_lane :: < 3 > (vmax)) ; for & val in & a [i ..] { let abs_val = val . abs () ; if abs_val > result { result = abs_val ; } } result } # [target_feature (enable = "simd128")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_abs (va) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] . abs () ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let half = f32x4_splat (0.5) ; let one = f32x4_splat (1.0) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; let exp_hi = f32x4_splat (88.376_26) ; let exp_lo = f32x4_splat (- 87.336_55) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let x = f32x4_pmin (f32x4_pmax (x , exp_lo) , exp_hi) ; let x_scaled = f32x4_mul (x , log2e) ; let k = f32x4_floor (f32x4_add (x_scaled , half)) ; let r = f32x4_sub (x , f32x4_mul (k , ln2)) ; let mut p = c6 ; p = f32x4_add (f32x4_mul (p , r) , c5) ; p = f32x4_add (f32x4_mul (p , r) , c4) ; p = f32x4_add (f32x4_mul (p , r) , c3) ; p = f32x4_add (f32x4_mul (p , r) , c2) ; p = f32x4_add (f32x4_mul (p , r) , c1) ; p = f32x4_add (f32x4_mul (p , r) , one) ; let k_int = i32x4_trunc_sat_f32x4 (k) ; let k_shifted = i32x4_shl (k_int , 23) ; let one_bits = i32x4_splat (0x3f80_0000_i32) ; let scale = v128_bitselect (i32x4_add (one_bits , k_shifted) , one_bits , i32x4_ne (k_int , i32x4_splat (0)) ,) ; let scale = i32x4_add (one_bits , k_shifted) ; let vresult = f32x4_mul (p , scale) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] . exp () ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = f32x4_splat (scalar) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_mul (va , scalar_vec) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = f32x4_splat (min_val) ; let max_vec = f32x4_splat (max_val) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let clamped = f32x4_pmin (f32x4_pmax (va , min_vec) , max_vec) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = f32x4_splat (t) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let diff = f32x4_sub (vb , va) ; let scaled_diff = f32x4_mul (t_vec , diff) ; let vresult = f32x4_add (va , scaled_diff) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vc = v128_load (c . as_ptr () . add (i) as * const v128) ; let product = f32x4_mul (va , vb) ; let vresult = f32x4_add (product , vc) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_max (zero , va) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let one = f32x4_splat (1.0) ; let half = f32x4_splat (0.5) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let neg_x = f32x4_sub (f32x4_splat (0.0) , x) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (neg_x , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (neg_x , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_neg_x = f32x4_mul (poly , k_shifted) ; let sigmoid_result = f32x4_div (one , f32x4_add (one , exp_neg_x)) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , sigmoid_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = f32x4_splat (0.797_884_6) ; let coeff = f32x4_splat (0.044715) ; let half = f32x4_splat (0.5) ; let one = f32x4_splat (1.0) ; let two = f32x4_splat (2.0) ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let x2 = f32x4_mul (x , x) ; let x3 = f32x4_mul (x2 , x) ; let inner = f32x4_mul (sqrt_2_over_pi , f32x4_add (x , f32x4_mul (coeff , x3))) ; let z = f32x4_mul (two , inner) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (z , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (z , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_2z = f32x4_mul (poly , k_shifted) ; let tanh_val = f32x4_div (f32x4_sub (exp_2z , one) , f32x4_add (exp_2z , one)) ; let gelu_result = f32x4_mul (half , f32x4_mul (x , f32x4_add (one , tanh_val))) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , gelu_result) ; i += 4 ; } while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = 0.797_884_6 * (x + 0.044715 * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let one = f32x4_splat (1.0) ; let half = f32x4_splat (0.5) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let neg_x = f32x4_sub (f32x4_splat (0.0) , x) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (neg_x , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (neg_x , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_neg_x = f32x4_mul (poly , k_shifted) ; let swish_result = f32x4_div (x , f32x4_add (one , exp_neg_x)) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , swish_result) ; i += 4 ; } while i < len { let x = a [i] ; if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let one = f32x4_splat (1.0) ; let two = f32x4_splat (2.0) ; let half = f32x4_splat (0.5) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let two_x = f32x4_mul (two , x) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (two_x , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (two_x , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_2x = f32x4_mul (poly , k_shifted) ; let numerator = f32x4_sub (exp_2x , one) ; let denominator = f32x4_add (exp_2x , one) ; let tanh_result = f32x4_div (numerator , denominator) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , tanh_result) ; i += 4 ; } while i < len { result [i] = a [i] . tanh () ; i += 1 ; } } } . self_ty`
- **Function**: `tests::test_wasm_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_tanh_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]

### ./src/chaos.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `ChaosConfig` [fields: 4]
- **Impl**: `Default` for `impl Default for ChaosConfig { fn default () -> Self { Self { memory_limit : 0 , cpu_limit : 0.0 , timeout : Duration :: from_secs (60) , signal_injection : false , } } } . self_ty`
- **Impl**: `impl ChaosConfig { # [doc = " Create a new chaos configuration with default values (no limits)"] pub fn new () -> Self { Self :: default () } # [doc = " Set memory limit in bytes"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = ""] # [doc = " let config = ChaosConfig::new()"] # [doc = "     .with_memory_limit(512 * 1024 * 1024); // 512 MB"] # [doc = " assert_eq!(config.memory_limit, 512 * 1024 * 1024);"] # [doc = " ```"] pub fn with_memory_limit (mut self , bytes : usize) -> Self { self . memory_limit = bytes ; self } # [doc = " Set CPU usage limit as fraction (0.0-1.0)"] # [doc = ""] # [doc = " Values are automatically clamped to valid range."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = ""] # [doc = " let config = ChaosConfig::new().with_cpu_limit(0.75);"] # [doc = " assert_eq!(config.cpu_limit, 0.75);"] # [doc = ""] # [doc = " // Values outside range are clamped"] # [doc = " let clamped = ChaosConfig::new().with_cpu_limit(1.5);"] # [doc = " assert_eq!(clamped.cpu_limit, 1.0);"] # [doc = " ```"] pub fn with_cpu_limit (mut self , fraction : f64) -> Self { self . cpu_limit = fraction . clamp (0.0 , 1.0) ; self } # [doc = " Set maximum execution timeout"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = " use std::time::Duration;"] # [doc = ""] # [doc = " let config = ChaosConfig::new()"] # [doc = "     .with_timeout(Duration::from_secs(30));"] # [doc = " assert_eq!(config.timeout, Duration::from_secs(30));"] # [doc = " ```"] pub fn with_timeout (mut self , timeout : Duration) -> Self { self . timeout = timeout ; self } # [doc = " Enable/disable random signal injection during execution"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = ""] # [doc = " let config = ChaosConfig::new().with_signal_injection(true);"] # [doc = " assert!(config.signal_injection);"] # [doc = " ```"] pub fn with_signal_injection (mut self , enabled : bool) -> Self { self . signal_injection = enabled ; self } # [doc = " Finalize configuration (no-op, for builder pattern consistency)"] pub fn build (self) -> Self { self } # [doc = " Gentle chaos configuration preset"] # [doc = ""] # [doc = " - 512 MB memory limit"] # [doc = " - 80% CPU limit"] # [doc = " - 120 second timeout"] # [doc = " - No signal injection"] # [doc = ""] # [doc = " Suitable for gradual stress testing and CI environments."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = " use std::time::Duration;"] # [doc = ""] # [doc = " let config = ChaosConfig::gentle();"] # [doc = " assert_eq!(config.memory_limit, 512 * 1024 * 1024);"] # [doc = " assert_eq!(config.cpu_limit, 0.8);"] # [doc = " assert_eq!(config.timeout, Duration::from_secs(120));"] # [doc = " assert!(!config.signal_injection);"] # [doc = " ```"] pub fn gentle () -> Self { Self :: new () . with_memory_limit (512 * 1024 * 1024) . with_cpu_limit (0.8) . with_timeout (Duration :: from_secs (120)) } # [doc = " Aggressive chaos configuration preset"] # [doc = ""] # [doc = " - 64 MB memory limit"] # [doc = " - 25% CPU limit"] # [doc = " - 10 second timeout"] # [doc = " - Signal injection enabled"] # [doc = ""] # [doc = " Suitable for extreme stress testing and finding edge cases."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = " use std::time::Duration;"] # [doc = ""] # [doc = " let config = ChaosConfig::aggressive();"] # [doc = " assert_eq!(config.memory_limit, 64 * 1024 * 1024);"] # [doc = " assert_eq!(config.cpu_limit, 0.25);"] # [doc = " assert_eq!(config.timeout, Duration::from_secs(10));"] # [doc = " assert!(config.signal_injection);"] # [doc = " ```"] pub fn aggressive () -> Self { Self :: new () . with_memory_limit (64 * 1024 * 1024) . with_cpu_limit (0.25) . with_timeout (Duration :: from_secs (10)) . with_signal_injection (true) } } . self_ty`
- **Enum**: `ChaosError` [variants: 3]
- **Impl**: `std :: fmt :: Display` for `impl std :: fmt :: Display for ChaosError { fn fmt (& self , f : & mut std :: fmt :: Formatter < '_ >) -> std :: fmt :: Result { match self { ChaosError :: MemoryLimitExceeded { limit , used } => { write ! (f , "Memory limit exceeded: {} > {} bytes" , used , limit) } ChaosError :: Timeout { elapsed , limit } => { write ! (f , "Timeout: {:?} > {:?}" , elapsed , limit) } ChaosError :: SignalInjectionFailed { signal , reason } => { write ! (f , "Signal injection failed ({}): {}" , signal , reason) } } } } . self_ty`
- **Impl**: `std :: error :: Error` for `impl std :: error :: Error for ChaosError { } . self_ty`
- **Function**: `tests::test_default_config` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_builder_pattern` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_cpu_limit_clamping` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_gentle_preset` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_aggressive_preset` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_chaos_error_display` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]

### ./src/error.rs

**File Complexity**: 1 | **Functions**: 0

- **Enum**: `TruenoError` [variants: 6]
- **Function**: `tests::test_unsupported_backend_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_size_mismatch_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_gpu_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_invalid_input_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_error_equality` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_division_by_zero_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_empty_vector_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]

### ./src/lib.rs

**File Complexity**: 2 | **Functions**: 4

- **Enum**: `Backend` [variants: 9]
- **Impl**: `impl Backend { # [doc = " Select the best available backend for the current platform"] # [doc = ""] # [doc = " This is a convenience wrapper around `select_best_available_backend()`"] pub fn select_best () -> Self { select_best_available_backend () } } . self_ty`
- **Enum**: `OpComplexity` [variants: 3]
- **Function**: `detect_x86_backend` [complexity: 6] [cognitive: 13] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `detect_arm_backend` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `detect_wasm_backend` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `select_best_available_backend` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_backend_enum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_op_complexity_ordering` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_select_best_available_backend` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_backend_selection_is_deterministic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]

### ./src/matrix.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `Matrix` [fields: 4]
- **Impl**: `impl Matrix < f32 > { # [doc = " Creates a new matrix with uninitialized values"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `rows` - Number of rows"] # [doc = " * `cols` - Number of columns"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new matrix with dimensions `rows x cols` containing uninitialized values"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::new(3, 4);"] # [doc = " assert_eq!(m.rows(), 3);"] # [doc = " assert_eq!(m.cols(), 4);"] # [doc = " ```"] pub fn new (rows : usize , cols : usize) -> Self { let backend = Backend :: select_best () ; Matrix { rows , cols , data : vec ! [0.0 ; rows * cols] , backend , } } # [doc = " Creates a matrix from a vector of data"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `rows` - Number of rows"] # [doc = " * `cols` - Number of columns"] # [doc = " * `data` - Vector containing matrix elements in row-major order"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if `data.len() != rows * cols`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 2, vec![1.0, 2.0, 3.0, 4.0]).unwrap();"] # [doc = " assert_eq!(m.rows(), 2);"] # [doc = " assert_eq!(m.cols(), 2);"] # [doc = " ```"] pub fn from_vec (rows : usize , cols : usize , data : Vec < f32 >) -> Result < Self , TruenoError > { if data . len () != rows * cols { return Err (TruenoError :: InvalidInput (format ! ("Data length {} does not match matrix dimensions {}x{} (expected {})" , data . len () , rows , cols , rows * cols))) ; } let backend = Backend :: select_best () ; Ok (Matrix { rows , cols , data , backend , }) } # [doc = " Creates a matrix filled with zeros"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::zeros(3, 3);"] # [doc = " assert_eq!(m.get(1, 1), Some(&0.0));"] # [doc = " ```"] pub fn zeros (rows : usize , cols : usize) -> Self { Matrix :: new (rows , cols) } # [doc = " Creates an identity matrix (square matrix with 1s on diagonal)"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::identity(3);"] # [doc = " assert_eq!(m.get(0, 0), Some(&1.0));"] # [doc = " assert_eq!(m.get(0, 1), Some(&0.0));"] # [doc = " assert_eq!(m.get(1, 1), Some(&1.0));"] # [doc = " ```"] pub fn identity (n : usize) -> Self { let mut data = vec ! [0.0 ; n * n] ; for i in 0 .. n { data [i * n + i] = 1.0 ; } let backend = Backend :: select_best () ; Matrix { rows : n , cols : n , data , backend , } } # [doc = " Returns the number of rows"] pub fn rows (& self) -> usize { self . rows } # [doc = " Returns the number of columns"] pub fn cols (& self) -> usize { self . cols } # [doc = " Returns the shape as (rows, cols)"] pub fn shape (& self) -> (usize , usize) { (self . rows , self . cols) } # [doc = " Gets a reference to an element at (row, col)"] # [doc = ""] # [doc = " Returns `None` if indices are out of bounds"] pub fn get (& self , row : usize , col : usize) -> Option < & f32 > { if row >= self . rows || col >= self . cols { None } else { self . data . get (row * self . cols + col) } } # [doc = " Gets a mutable reference to an element at (row, col)"] # [doc = ""] # [doc = " Returns `None` if indices are out of bounds"] pub fn get_mut (& mut self , row : usize , col : usize) -> Option < & mut f32 > { if row >= self . rows || col >= self . cols { None } else { let idx = row * self . cols + col ; self . data . get_mut (idx) } } # [doc = " Returns a reference to the underlying data"] pub fn as_slice (& self) -> & [f32] { & self . data } # [doc = " Matrix multiplication (matmul)"] # [doc = ""] # [doc = " Computes `C = A × B` where A is `m×n`, B is `n×p`, and C is `m×p`."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `other` - The matrix to multiply with (right operand)"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new matrix containing the result of matrix multiplication"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if matrix dimensions are incompatible"] # [doc = " (i.e., `self.cols != other.rows`)"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let a = Matrix::from_vec(2, 2, vec![1.0, 2.0, 3.0, 4.0]).unwrap();"] # [doc = " let b = Matrix::from_vec(2, 2, vec![5.0, 6.0, 7.0, 8.0]).unwrap();"] # [doc = " let c = a.matmul(&b).unwrap();"] # [doc = ""] # [doc = " // [[1, 2],   [[5, 6],   [[19, 22],"] # [doc = " //  [3, 4]] ×  [7, 8]] =  [43, 50]]"] # [doc = " assert_eq!(c.get(0, 0), Some(&19.0));"] # [doc = " assert_eq!(c.get(0, 1), Some(&22.0));"] # [doc = " assert_eq!(c.get(1, 0), Some(&43.0));"] # [doc = " assert_eq!(c.get(1, 1), Some(&50.0));"] # [doc = " ```"] pub fn matmul (& self , other : & Matrix < f32 >) -> Result < Matrix < f32 > , TruenoError > { if self . cols != other . rows { return Err (TruenoError :: InvalidInput (format ! ("Matrix dimension mismatch for multiplication: {}×{} × {}×{} (inner dimensions {} and {} must match)" , self . rows , self . cols , other . rows , other . cols , self . cols , other . rows))) ; } let mut result = Matrix :: zeros (self . rows , other . cols) ; # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = 500 ; const SIMD_THRESHOLD : usize = 64 ; # [cfg (feature = "gpu")] { if self . rows >= GPU_THRESHOLD && self . cols >= GPU_THRESHOLD && other . cols >= GPU_THRESHOLD { if let Ok (gpu_result) = self . matmul_gpu (other) { return Ok (gpu_result) ; } } } if self . rows >= SIMD_THRESHOLD || self . cols >= SIMD_THRESHOLD || other . cols >= SIMD_THRESHOLD { self . matmul_simd (other , & mut result) ? ; } else { self . matmul_naive (other , & mut result) ? ; } Ok (result) } # [doc = " Naive O(n³) matrix multiplication (baseline for small matrices)"] fn matmul_naive (& self , other : & Matrix < f32 > , result : & mut Matrix < f32 > ,) -> Result < () , TruenoError > { for i in 0 .. self . rows { for j in 0 .. other . cols { let mut sum = 0.0 ; for k in 0 .. self . cols { sum += self . get (i , k) . unwrap () * other . get (k , j) . unwrap () ; } * result . get_mut (i , j) . unwrap () = sum ; } } Ok (()) } # [doc = " SIMD-optimized matrix multiplication using Vector operations"] fn matmul_simd (& self , other : & Matrix < f32 > , result : & mut Matrix < f32 > ,) -> Result < () , TruenoError > { let b_transposed = other . transpose () ; for i in 0 .. self . rows { let row_start = i * self . cols ; let row_end = row_start + self . cols ; let a_row = & self . data [row_start .. row_end] ; let a_vec = Vector :: from_slice (a_row) ; for j in 0 .. other . cols { let col_start = j * b_transposed . cols ; let col_end = col_start + b_transposed . cols ; let b_col = & b_transposed . data [col_start .. col_end] ; let b_vec = Vector :: from_slice (b_col) ; let dot_result = a_vec . dot (& b_vec) ? ; * result . get_mut (i , j) . unwrap () = dot_result ; } } Ok (()) } # [doc = " GPU-accelerated matrix multiplication (very large matrices only)"] # [cfg (feature = "gpu")] fn matmul_gpu (& self , other : & Matrix < f32 >) -> Result < Matrix < f32 > , TruenoError > { use crate :: backends :: gpu :: GpuBackend ; if ! GpuBackend :: is_available () { return Err (TruenoError :: InvalidInput ("GPU not available" . to_string ())) ; } let mut gpu = GpuBackend :: new () ; let result_data = gpu . matmul (& self . data , & other . data , self . rows , self . cols , other . cols) . map_err (| e | TruenoError :: InvalidInput (format ! ("GPU matmul failed: {}" , e))) ? ; let mut result = Matrix :: zeros (self . rows , other . cols) ; result . data = result_data ; Ok (result) } # [doc = " Transpose the matrix (swap rows and columns)"] # [doc = ""] # [doc = " Returns a new matrix where element `(i, j)` of the original becomes"] # [doc = " element `(j, i)` in the result."] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new matrix with dimensions swapped: if input is `m×n`, output is `n×m`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).unwrap();"] # [doc = " let t = m.transpose();"] # [doc = ""] # [doc = " // [[1, 2, 3],     [[1, 4],"] # [doc = " //  [4, 5, 6]]  →   [2, 5],"] # [doc = " //                  [3, 6]]"] # [doc = " assert_eq!(t.rows(), 3);"] # [doc = " assert_eq!(t.cols(), 2);"] # [doc = " assert_eq!(t.get(0, 0), Some(&1.0));"] # [doc = " assert_eq!(t.get(0, 1), Some(&4.0));"] # [doc = " assert_eq!(t.get(1, 0), Some(&2.0));"] # [doc = " ```"] pub fn transpose (& self) -> Matrix < f32 > { let mut result = Matrix :: zeros (self . cols , self . rows) ; for i in 0 .. self . rows { for j in 0 .. self . cols { * result . get_mut (j , i) . unwrap () = * self . get (i , j) . unwrap () ; } } result } # [doc = " Matrix-vector multiplication (column vector): A × v"] # [doc = ""] # [doc = " Multiplies this matrix by a column vector, computing `A × v` where the result"] # [doc = " is a column vector with length equal to the number of rows in `A`."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " For an m×n matrix A and an n-dimensional vector v:"] # [doc = " ```text"] # [doc = " result[i] = Σ(j=0 to n-1) A[i,j] × v[j]"] # [doc = " ```"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `v` - Column vector with length equal to `self.cols()`"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector with length `self.rows()`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if `v.len() != self.cols()`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Matrix, Vector};"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).unwrap();"] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = m.matvec(&v).unwrap();"] # [doc = ""] # [doc = " // [[1, 2, 3]   [1]   [1×1 + 2×2 + 3×3]   [14]"] # [doc = " //  [4, 5, 6]] × [2] = [4×1 + 5×2 + 6×3] = [32]"] # [doc = " //               [3]"] # [doc = " assert_eq!(result.as_slice(), &[14.0, 32.0]);"] # [doc = " ```"] pub fn matvec (& self , v : & Vector < f32 >) -> Result < Vector < f32 > , TruenoError > { if v . len () != self . cols { return Err (TruenoError :: InvalidInput (format ! ("Vector length {} does not match matrix columns {} for matrix-vector multiplication" , v . len () , self . cols))) ; } let mut result_data = vec ! [0.0 ; self . rows] ; for (i , result_elem) in result_data . iter_mut () . enumerate () { let mut sum = 0.0 ; for j in 0 .. self . cols { sum += self . get (i , j) . unwrap () * v . as_slice () [j] ; } * result_elem = sum ; } Ok (Vector :: from_slice (& result_data)) } # [doc = " Vector-matrix multiplication (row vector): v^T × A"] # [doc = ""] # [doc = " Multiplies a row vector by this matrix, computing `v^T × A` where the result"] # [doc = " is a row vector with length equal to the number of columns in `A`."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " For an m-dimensional vector v and an m×n matrix A:"] # [doc = " ```text"] # [doc = " result[j] = Σ(i=0 to m-1) v[i] × A[i,j]"] # [doc = " ```"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `v` - Row vector with length equal to `m.rows()`"] # [doc = " * `m` - Matrix to multiply"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector with length `m.cols()`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if `v.len() != m.rows()`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Matrix, Vector};"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).unwrap();"] # [doc = " let v = Vector::from_slice(&[1.0, 2.0]);"] # [doc = " let result = Matrix::vecmat(&v, &m).unwrap();"] # [doc = ""] # [doc = " // [1, 2] × [[1, 2, 3]  = [1×1 + 2×4, 1×2 + 2×5, 1×3 + 2×6]"] # [doc = " //           [4, 5, 6]]"] # [doc = " //         = [9, 12, 15]"] # [doc = " assert_eq!(result.as_slice(), &[9.0, 12.0, 15.0]);"] # [doc = " ```"] pub fn vecmat (v : & Vector < f32 > , m : & Matrix < f32 >) -> Result < Vector < f32 > , TruenoError > { if v . len () != m . rows { return Err (TruenoError :: InvalidInput (format ! ("Vector length {} does not match matrix rows {} for vector-matrix multiplication" , v . len () , m . rows))) ; } let mut result_data = vec ! [0.0 ; m . cols] ; for (j , result_elem) in result_data . iter_mut () . enumerate () { let mut sum = 0.0 ; for i in 0 .. m . rows { sum += v . as_slice () [i] * m . get (i , j) . unwrap () ; } * result_elem = sum ; } Ok (Vector :: from_slice (& result_data)) } # [doc = " Perform 2D convolution with a kernel"] # [doc = ""] # [doc = " Applies a 2D convolution operation using \"valid\" padding (no padding),"] # [doc = " resulting in an output smaller than the input."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `kernel` - Convolution kernel (filter) to apply"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Convolved matrix with dimensions:"] # [doc = " - rows: `input.rows - kernel.rows + 1`"] # [doc = " - cols: `input.cols - kernel.cols + 1`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if:"] # [doc = " - Kernel is larger than input in any dimension"] # [doc = " - Kernel has even dimensions (center pixel ambiguous)"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " // 5x5 input image"] # [doc = " let input = Matrix::from_vec("] # [doc = "     5, 5,"] # [doc = "     vec!["] # [doc = "         0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = "         0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = "         0.0, 0.0, 9.0, 0.0, 0.0,"] # [doc = "         0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = "         0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = "     ]"] # [doc = " ).unwrap();"] # [doc = ""] # [doc = " // 3x3 averaging kernel"] # [doc = " let kernel_val = 1.0 / 9.0;"] # [doc = " let kernel = Matrix::from_vec("] # [doc = "     3, 3,"] # [doc = "     vec![kernel_val; 9]"] # [doc = " ).unwrap();"] # [doc = ""] # [doc = " let result = input.convolve2d(&kernel).unwrap();"] # [doc = " assert_eq!(result.rows(), 3); // 5 - 3 + 1"] # [doc = " assert_eq!(result.cols(), 3);"] # [doc = " ```"] pub fn convolve2d (& self , kernel : & Matrix < f32 >) -> Result < Matrix < f32 > , TruenoError > { if kernel . rows > self . rows || kernel . cols > self . cols { return Err (TruenoError :: InvalidInput (format ! ("Kernel size ({}x{}) larger than input ({}x{})" , kernel . rows , kernel . cols , self . rows , self . cols))) ; } let output_rows = self . rows - kernel . rows + 1 ; let output_cols = self . cols - kernel . cols + 1 ; let mut result = Matrix :: zeros (output_rows , output_cols) ; # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = 10_000 ; # [cfg (feature = "gpu")] { if output_rows * output_cols >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuBackend ; if GpuBackend :: is_available () { if let Ok (gpu_result) = self . convolve2d_gpu (kernel , & mut result , output_rows , output_cols) { return Ok (gpu_result) ; } } } } for out_row in 0 .. output_rows { for out_col in 0 .. output_cols { let mut sum = 0.0 ; for k_row in 0 .. kernel . rows { for k_col in 0 .. kernel . cols { let in_row = out_row + k_row ; let in_col = out_col + k_col ; let input_val = self . get (in_row , in_col) . unwrap () ; let kernel_val = kernel . get (k_row , k_col) . unwrap () ; sum += input_val * kernel_val ; } } * result . get_mut (out_row , out_col) . unwrap () = sum ; } } Ok (result) } # [doc = " GPU-accelerated 2D convolution helper"] # [cfg (feature = "gpu")] fn convolve2d_gpu (& self , kernel : & Matrix < f32 > , result : & mut Matrix < f32 > , _output_rows : usize , _output_cols : usize ,) -> Result < Matrix < f32 > , TruenoError > { use crate :: backends :: gpu :: GpuDevice ; let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; gpu . convolve2d (self . as_slice () , kernel . as_slice () , result . data . as_mut_slice () , self . rows , self . cols , kernel . rows , kernel . cols ,) . map_err (TruenoError :: InvalidInput) ? ; Ok (result . clone ()) } } . self_ty`
- **Function**: `tests::test_matrix_new` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_from_vec` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_from_vec_invalid_size` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_get_out_of_bounds` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_dimension_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_non_square` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_simd_equivalence_small` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_simd_equivalence_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_simd_equivalence_rectangular` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_gpu_availability` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_gpu_matmul_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_square` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_single_row` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_single_col` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::matrix_strategy` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_dimension_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_dimension_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_transpose_equivalence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_basic_3x3` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_edge_detection` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_averaging_filter` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_invalid_kernel` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]

### ./src/vector.rs

**File Complexity**: 1 | **Functions**: 0

- **Struct**: `Vector` [fields: 2]
- **Impl**: `impl < T > Vector < T > where T : Clone , { # [doc = " Create vector from slice using auto-selected optimal backend"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Auto-selects the best available backend at creation time based on:"] # [doc = " - CPU feature detection (AVX-512 > AVX2 > AVX > SSE2)"] # [doc = " - Vector size (GPU for large workloads)"] # [doc = " - Platform availability (NEON on ARM, WASM SIMD in browser)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " assert_eq!(v.len(), 4);"] # [doc = " ```"] pub fn from_slice (data : & [T]) -> Self { Self { data : data . to_vec () , backend : crate :: select_best_available_backend () , } } # [doc = " Create vector with specific backend (for benchmarking or testing)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, Backend};"] # [doc = ""] # [doc = " let v = Vector::from_slice_with_backend(&[1.0, 2.0], Backend::Scalar);"] # [doc = " assert_eq!(v.len(), 2);"] # [doc = " ```"] pub fn from_slice_with_backend (data : & [T] , backend : Backend) -> Self { let resolved_backend = match backend { Backend :: Auto => crate :: select_best_available_backend () , _ => backend , } ; Self { data : data . to_vec () , backend : resolved_backend , } } } . self_ty`
- **Impl**: `impl Vector < f32 > { # [doc = " Create vector with specified alignment for optimal SIMD performance"] # [doc = ""] # [doc = " This method attempts to create a vector with memory aligned to the specified byte boundary."] # [doc = " Note: Rust's Vec allocator may already provide sufficient alignment for most use cases."] # [doc = " This method validates the alignment requirement but uses standard Vec allocation."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `size` - Number of elements to allocate"] # [doc = " * `backend` - Backend to use for operations"] # [doc = " * `alignment` - Requested alignment in bytes (must be power of 2: 16, 32, 64)"] # [doc = ""] # [doc = " # Recommended Alignments"] # [doc = ""] # [doc = " - SSE2: 16 bytes (128-bit)"] # [doc = " - AVX2: 32 bytes (256-bit)"] # [doc = " - AVX-512: 64 bytes (512-bit)"] # [doc = ""] # [doc = " # Note on Implementation"] # [doc = ""] # [doc = " Currently uses Rust's default Vec allocator, which typically provides 16-byte alignment"] # [doc = " on modern systems. Custom allocators for specific alignments will be added in future versions."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, Backend};"] # [doc = ""] # [doc = " // Create vector with requested 16-byte alignment"] # [doc = " let v = Vector::with_alignment(100, Backend::SSE2, 16).unwrap();"] # [doc = " assert_eq!(v.len(), 100);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `TruenoError::InvalidInput` if alignment is not a power of 2."] pub fn with_alignment (size : usize , backend : Backend , alignment : usize) -> Result < Self > { if alignment == 0 || (alignment & (alignment - 1)) != 0 { return Err (TruenoError :: InvalidInput (format ! ("Alignment must be power of 2, got {}" , alignment))) ; } let resolved_backend = match backend { Backend :: Auto => crate :: select_best_available_backend () , _ => backend , } ; let data = vec ! [0.0f32 ; size] ; let ptr = data . as_ptr () as usize ; let actual_alignment = ptr & ! (ptr - 1) ; if alignment > actual_alignment { eprintln ! ("Note: Requested {}-byte alignment, got {}-byte alignment. Using unaligned loads." , alignment , actual_alignment) ; } Ok (Self { data , backend : resolved_backend , }) } } . self_ty`
- **Impl**: `impl < T > Vector < T > where T : Clone , { # [doc = " Get underlying data as slice"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " assert_eq!(v.as_slice(), &[1.0, 2.0, 3.0]);"] # [doc = " ```"] pub fn as_slice (& self) -> & [T] { & self . data } # [doc = " Get vector length"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " assert_eq!(v.len(), 5);"] # [doc = " ```"] pub fn len (& self) -> usize { self . data . len () } # [doc = " Check if vector is empty"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v1: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(v1.is_empty());"] # [doc = ""] # [doc = " let v2 = Vector::from_slice(&[1.0]);"] # [doc = " assert!(!v2.is_empty());"] # [doc = " ```"] pub fn is_empty (& self) -> bool { self . data . is_empty () } # [doc = " Get the backend being used"] pub fn backend (& self) -> Backend { self . backend } } . self_ty`
- **Impl**: `impl Vector < f32 > { # [doc = " Element-wise addition"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Auto-selects the best available backend:"] # [doc = " - **AVX2**: ~4x faster than scalar for 1K+ elements"] # [doc = " - **GPU**: ~50x faster than scalar for 10M+ elements"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[4.0, 5.0, 6.0]);"] # [doc = " let result = a.add(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[5.0, 7.0, 9.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::SizeMismatch`] if vectors have different lengths."] pub fn add (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 => { Avx2Backend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX512 => { Avx512Backend :: add (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Element-wise subtraction"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Auto-selects the best available backend:"] # [doc = " - **AVX2**: ~4x faster than scalar for 1K+ elements"] # [doc = " - **GPU**: ~50x faster than scalar for 10M+ elements"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[5.0, 7.0, 9.0]);"] # [doc = " let b = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = a.sub(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[4.0, 5.0, 6.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::SizeMismatch`] if vectors have different lengths."] pub fn sub (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Element-wise multiplication"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let b = Vector::from_slice(&[5.0, 6.0, 7.0]);"] # [doc = " let result = a.mul(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[10.0, 18.0, 28.0]);"] # [doc = " ```"] pub fn mul (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Element-wise division"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[10.0, 20.0, 30.0]);"] # [doc = " let b = Vector::from_slice(&[2.0, 4.0, 5.0]);"] # [doc = " let result = a.div(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[5.0, 5.0, 6.0]);"] # [doc = " ```"] pub fn div (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: div (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: div (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Dot product"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[4.0, 5.0, 6.0]);"] # [doc = " let result = a.dot(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result, 32.0); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32"] # [doc = " ```"] pub fn dot (& self , other : & Self) -> Result < f32 > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: dot (& self . data , & other . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: dot (& self . data , & other . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 => Avx2Backend :: dot (& self . data , & other . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX512 => Avx512Backend :: dot (& self . data , & other . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: dot (& self . data , & other . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: dot (& self . data , & other . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: dot (& self . data , & other . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: dot (& self . data , & other . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: dot (& self . data , & other . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: dot (& self . data , & other . data) , } } ; Ok (result) } # [doc = " Sum all elements"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " assert_eq!(v.sum().unwrap(), 10.0);"] # [doc = " ```"] pub fn sum (& self) -> Result < f32 > { let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: sum (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: sum (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: sum (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sum (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: sum (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: sum (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: sum (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: sum (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: sum (& self . data) , } } ; Ok (result) } # [doc = " Find maximum element"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.max().unwrap(), 5.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn max (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: max (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: max (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: max (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: max (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: max (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: max (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: max (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: max (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: max (& self . data) , } } ; Ok (result) } # [doc = " Find minimum value in the vector"] # [doc = ""] # [doc = " Returns the smallest element in the vector using SIMD optimization."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.min().unwrap(), 1.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn min (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: min (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: min (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: min (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: min (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: min (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: min (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: min (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: min (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: min (& self . data) , } } ; Ok (result) } # [doc = " Find index of maximum value in the vector"] # [doc = ""] # [doc = " Returns the index of the first occurrence of the maximum value using SIMD optimization."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.argmax().unwrap(), 1); // max value 5.0 is at index 1"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn argmax (& self) -> Result < usize > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: argmax (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: argmax (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: argmax (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: argmax (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: argmax (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: argmax (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: argmax (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: argmax (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: argmax (& self . data) , } } ; Ok (result) } # [doc = " Find index of minimum value in the vector"] # [doc = ""] # [doc = " Returns the index of the first occurrence of the minimum value using SIMD optimization."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.argmin().unwrap(), 0); // min value 1.0 is at index 0"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn argmin (& self) -> Result < usize > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: argmin (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: argmin (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: argmin (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: argmin (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: argmin (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: argmin (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: argmin (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: argmin (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: argmin (& self . data) , } } ; Ok (result) } # [doc = " Kahan summation (numerically stable sum)"] # [doc = ""] # [doc = " Uses the Kahan summation algorithm to reduce floating-point rounding errors"] # [doc = " when summing many numbers. This is more accurate than the standard sum() method"] # [doc = " for vectors with many elements or elements of vastly different magnitudes."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Note: Kahan summation is inherently sequential and cannot be effectively"] # [doc = " parallelized with SIMD. All backends use the scalar implementation."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " assert_eq!(v.sum_kahan().unwrap(), 10.0);"] # [doc = " ```"] pub fn sum_kahan (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: sum_kahan (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: sum_kahan (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: sum_kahan (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sum_kahan (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: sum_kahan (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: sum_kahan (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: sum_kahan (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: sum_kahan (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: sum_kahan (& self . data) , } } ; Ok (result) } # [doc = " Sum of squared elements"] # [doc = ""] # [doc = " Computes the sum of squares: sum(a\\[i\\]^2)."] # [doc = " This is the building block for computing L2 norm and variance."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let sum_sq = v.sum_of_squares().unwrap();"] # [doc = " assert_eq!(sum_sq, 14.0); // 1^2 + 2^2 + 3^2 = 1 + 4 + 9 = 14"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns 0.0 for empty vectors."] pub fn sum_of_squares (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } self . dot (self) } # [doc = " Arithmetic mean (average)"] # [doc = ""] # [doc = " Computes the arithmetic mean of all elements: sum(a\\[i\\]) / n."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD sum() implementation, then divides by length."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " let avg = v.mean().unwrap();"] # [doc = " assert!((avg - 2.5).abs() < 1e-5); // (1+2+3+4)/4 = 2.5"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors (division by zero)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(v.mean(), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn mean (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let total = self . sum () ? ; Ok (total / self . len () as f32) } # [doc = " Population variance"] # [doc = ""] # [doc = " Computes the population variance: Var(X) = E\\[(X - μ)²\\] = E\\[X²\\] - μ²"] # [doc = " Uses the computational formula to avoid two passes over the data."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via sum_of_squares() and mean()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let var = v.variance().unwrap();"] # [doc = " assert!((var - 2.0).abs() < 1e-5); // Population variance"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(v.variance(), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn variance (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let mean_val = self . mean () ? ; let sum_sq = self . sum_of_squares () ? ; let mean_sq = sum_sq / self . len () as f32 ; Ok (mean_sq - mean_val * mean_val) } # [doc = " Population standard deviation"] # [doc = ""] # [doc = " Computes the population standard deviation: σ = sqrt(Var(X))."] # [doc = " This is the square root of the variance."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via variance()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let sd = v.stddev().unwrap();"] # [doc = " assert!((sd - 1.4142135).abs() < 1e-5); // sqrt(2) ≈ 1.414"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(v.stddev(), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn stddev (& self) -> Result < f32 > { let var = self . variance () ? ; Ok (var . sqrt ()) } # [doc = " Population covariance between two vectors"] # [doc = ""] # [doc = " Computes the population covariance: Cov(X,Y) = E[(X - μx)(Y - μy)]"] # [doc = " Uses the computational formula: Cov(X,Y) = E\\[XY\\] - μx·μy"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via dot() and mean()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let y = Vector::from_slice(&[2.0, 4.0, 6.0]);"] # [doc = " let cov = x.covariance(&y).unwrap();"] # [doc = " assert!((cov - 1.333).abs() < 0.01); // Perfect positive covariance"] # [doc = " ```"] # [doc = ""] # [doc = " # Size mismatch"] # [doc = ""] # [doc = " Returns an error if vectors have different lengths."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[1.0, 2.0]);"] # [doc = " let y = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " assert!(matches!(x.covariance(&y), Err(TruenoError::SizeMismatch { .. })));"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let x: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " let y: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(x.covariance(&y), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn covariance (& self , other : & Self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mean_x = self . mean () ? ; let mean_y = other . mean () ? ; let dot_xy = self . dot (other) ? ; let mean_xy = dot_xy / self . len () as f32 ; Ok (mean_xy - mean_x * mean_y) } # [doc = " Pearson correlation coefficient"] # [doc = ""] # [doc = " Computes the Pearson correlation coefficient: ρ(X,Y) = Cov(X,Y) / (σx·σy)"] # [doc = " Normalized covariance in range [-1, 1]."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via covariance() and stddev()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let y = Vector::from_slice(&[2.0, 4.0, 6.0]);"] # [doc = " let corr = x.correlation(&y).unwrap();"] # [doc = " assert!((corr - 1.0).abs() < 1e-5); // Perfect positive correlation"] # [doc = " ```"] # [doc = ""] # [doc = " # Size mismatch"] # [doc = ""] # [doc = " Returns an error if vectors have different lengths."] # [doc = ""] # [doc = " # Division by zero"] # [doc = ""] # [doc = " Returns DivisionByZero error if either vector has zero standard deviation"] # [doc = " (i.e., is constant)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[5.0, 5.0, 5.0]); // Constant"] # [doc = " let y = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " assert!(matches!(x.correlation(&y), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn correlation (& self , other : & Self) -> Result < f32 > { let cov = self . covariance (other) ? ; let std_x = self . stddev () ? ; let std_y = other . stddev () ? ; if std_x . abs () < 1e-10 || std_y . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let corr = cov / (std_x * std_y) ; Ok (corr . clamp (- 1.0 , 1.0)) } # [doc = " Z-score normalization (standardization)"] # [doc = ""] # [doc = " Transforms the vector to have mean = 0 and standard deviation = 1."] # [doc = " Each element is transformed as: z\\[i\\] = (x\\[i\\] - μ) / σ"] # [doc = ""] # [doc = " This is a fundamental preprocessing step in machine learning and statistics,"] # [doc = " ensuring features have comparable scales and are centered around zero."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via mean() and stddev(), then applies"] # [doc = " element-wise operations (sub, scale) which also use SIMD."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let z = v.zscore().unwrap();"] # [doc = ""] # [doc = " // Verify mean ≈ 0"] # [doc = " let mean = z.mean().unwrap();"] # [doc = " assert!(mean.abs() < 1e-5);"] # [doc = ""] # [doc = " // Verify stddev ≈ 1"] # [doc = " let std = z.stddev().unwrap();"] # [doc = " assert!((std - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors (cannot compute mean/stddev)."] # [doc = ""] # [doc = " # Division by zero"] # [doc = ""] # [doc = " Returns DivisionByZero error if the vector has zero standard deviation"] # [doc = " (i.e., all elements are identical/constant)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[5.0, 5.0, 5.0]); // Constant"] # [doc = " assert!(matches!(v.zscore(), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn zscore (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let mean_val = self . mean () ? ; let std_val = self . stddev () ? ; if std_val . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let inv_std = 1.0 / std_val ; let data : Vec < f32 > = self . data . iter () . map (| & x | (x - mean_val) * inv_std) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Min-max normalization (scaling to [0, 1] range)"] # [doc = ""] # [doc = " Transforms the vector so that the minimum value becomes 0 and the maximum"] # [doc = " value becomes 1, with all other values scaled proportionally."] # [doc = " Formula: x'\\[i\\] = (x\\[i\\] - min) / (max - min)"] # [doc = ""] # [doc = " This is a fundamental preprocessing technique in machine learning, especially"] # [doc = " for algorithms sensitive to feature magnitudes (e.g., neural networks, k-NN)."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via min() and max() operations, then"] # [doc = " applies element-wise transformation."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let normalized = v.minmax_normalize().unwrap();"] # [doc = ""] # [doc = " // Verify range [0, 1]"] # [doc = " let min = normalized.min().unwrap();"] # [doc = " let max = normalized.max().unwrap();"] # [doc = " assert!((min - 0.0).abs() < 1e-5);"] # [doc = " assert!((max - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors (cannot compute min/max)."] # [doc = ""] # [doc = " # Division by zero"] # [doc = ""] # [doc = " Returns DivisionByZero error if the vector has all identical elements"] # [doc = " (i.e., min = max, causing division by zero in the normalization formula)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[5.0, 5.0, 5.0]); // Constant"] # [doc = " assert!(matches!(v.minmax_normalize(), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn minmax_normalize (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let min_val = self . min () ? ; let max_val = self . max () ? ; let range = max_val - min_val ; if range . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let inv_range = 1.0 / range ; let data : Vec < f32 > = self . data . iter () . map (| & x | (x - min_val) * inv_range) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Clip values to a specified range [min_val, max_val]"] # [doc = ""] # [doc = " Constrains each element to be within the specified range:"] # [doc = " - Values below min_val become min_val"] # [doc = " - Values above max_val become max_val"] # [doc = " - Values within range stay unchanged"] # [doc = ""] # [doc = " This is useful for outlier handling, gradient clipping in neural networks,"] # [doc = " and ensuring values stay within valid bounds."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);"] # [doc = " let clipped = v.clip(0.0, 10.0).unwrap();"] # [doc = ""] # [doc = " // Values: [-5, 0, 5, 10, 15] → [0, 0, 5, 10, 10]"] # [doc = " assert_eq!(clipped.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Invalid range"] # [doc = ""] # [doc = " Returns InvalidInput error if min_val > max_val."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = v.clip(10.0, 5.0); // min > max"] # [doc = " assert!(matches!(result, Err(TruenoError::InvalidInput(_))));"] # [doc = " ```"] pub fn clip (& self , min_val : f32 , max_val : f32) -> Result < Self > { if min_val > max_val { return Err (TruenoError :: InvalidInput (format ! ("min_val ({}) must be <= max_val ({})" , min_val , max_val))) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . clip (& self . data , & mut result , min_val , max_val) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let data : Vec < f32 > = self . data . iter () . map (| & x | x . max (min_val) . min (max_val)) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Softmax activation function"] # [doc = ""] # [doc = " Converts a vector of real values into a probability distribution."] # [doc = " Formula: softmax(x)\\[i\\] = exp(x\\[i\\] - max(x)) / sum(exp(x\\[j\\] - max(x)))"] # [doc = ""] # [doc = " Uses the numerically stable version with max subtraction to prevent overflow."] # [doc = " The output is a probability distribution: all values in [0, 1] and sum to 1."] # [doc = ""] # [doc = " This is the standard activation function for multi-class classification in neural networks."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let logits = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let probs = logits.softmax().unwrap();"] # [doc = ""] # [doc = " // Verify sum ≈ 1"] # [doc = " let sum: f32 = probs.as_slice().iter().sum();"] # [doc = " assert!((sum - 1.0).abs() < 1e-5);"] # [doc = ""] # [doc = " // Verify all values in [0, 1]"] # [doc = " for &p in probs.as_slice() {"] # [doc = "     assert!(p >= 0.0 && p <= 1.0);"] # [doc = " }"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors (cannot compute softmax)."] pub fn softmax (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . softmax (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let max_val = self . max () ? ; let exp_vals : Vec < f32 > = self . data . iter () . map (| & x | (x - max_val) . exp ()) . collect () ; let sum_exp : f32 = exp_vals . iter () . sum () ; let data : Vec < f32 > = exp_vals . iter () . map (| & e | e / sum_exp) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Log-softmax activation function"] # [doc = ""] # [doc = " Computes the logarithm of the softmax function in a numerically stable way."] # [doc = " Formula: log_softmax(x)\\[i\\] = x\\[i\\] - max(x) - log(sum(exp(x\\[j\\] - max(x))))"] # [doc = ""] # [doc = " This is more numerically stable than computing log(softmax(x)) and is commonly"] # [doc = " used in neural networks for computing cross-entropy loss."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let logits = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let log_probs = logits.log_softmax().unwrap();"] # [doc = ""] # [doc = " // Verify exp(log_softmax) = softmax"] # [doc = " let probs_from_log: Vec<f32> = log_probs.as_slice().iter().map(|&x| x.exp()).collect();"] # [doc = " let sum: f32 = probs_from_log.iter().sum();"] # [doc = " assert!((sum - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors."] pub fn log_softmax (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . log_softmax (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let max_val = self . max () ? ; let exp_vals : Vec < f32 > = self . data . iter () . map (| & x | (x - max_val) . exp ()) . collect () ; let sum_exp : f32 = exp_vals . iter () . sum () ; let log_sum_exp = sum_exp . ln () ; let data : Vec < f32 > = self . data . iter () . map (| & x | x - max_val - log_sum_exp) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " ReLU (Rectified Linear Unit) activation function"] # [doc = ""] # [doc = " Computes the element-wise ReLU: max(0, x)."] # [doc = " ReLU is one of the most widely used activation functions in neural networks."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " relu(x)[i] = max(0, x\\[i\\])"] # [doc = "            = x\\[i\\]  if x\\[i\\] > 0"] # [doc = "            = 0     otherwise"] # [doc = " ```"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Non-linearity**: Introduces non-linearity while preserving linearity for positive values"] # [doc = " - **Sparsity**: Produces exactly zero for negative inputs (sparse activations)"] # [doc = " - **Gradient**: Derivative is 1 for positive inputs, 0 for negative (solves vanishing gradient)"] # [doc = " - **Computational efficiency**: Simple max operation, no exponentials"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Deep neural networks**: Default activation for hidden layers"] # [doc = " - **Convolutional networks**: Standard activation in CNNs"] # [doc = " - **Feature learning**: Encourages sparse representations"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is memory-bound. SIMD provides modest speedups since"] # [doc = " the computation (comparison and selection) is simpler than memory access."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.relu().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[0.0, 0.0, 0.0, 1.0, 2.0]);"] # [doc = " ```"] pub fn relu (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . relu (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: relu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: relu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: relu (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: relu (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: relu (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: relu (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: relu (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: relu (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: relu (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Sigmoid (logistic) activation function"] # [doc = ""] # [doc = " Computes the element-wise sigmoid: σ(x) = 1 / (1 + e^(-x))."] # [doc = " Sigmoid is a classic activation function that squashes inputs to the range (0, 1)."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " sigmoid(x)[i] = 1 / (1 + exp(-x\\[i\\]))"] # [doc = "               = exp(x\\[i\\]) / (1 + exp(x\\[i\\]))"] # [doc = " ```"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Bounded output**: Maps all inputs to (0, 1) range"] # [doc = " - **Smooth**: Infinitely differentiable (C^∞)"] # [doc = " - **Symmetric**: σ(-x) = 1 - σ(x)"] # [doc = " - **Derivative**: σ'(x) = σ(x) * (1 - σ(x))"] # [doc = " - **Interpretable**: Output can be interpreted as probability"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Binary classification**: Final layer for binary output (0 or 1)"] # [doc = " - **Logistic regression**: Traditional ML algorithm"] # [doc = " - **Gating mechanisms**: LSTM/GRU gates (input, forget, output)"] # [doc = " - **Attention mechanisms**: Soft attention weights"] # [doc = ""] # [doc = " # Numerical Considerations"] # [doc = ""] # [doc = " For very large negative inputs (x < -50), exp(-x) overflows to infinity."] # [doc = " However, sigmoid(x) approaches 0, so we return 0 for numerical stability."] # [doc = " For very large positive inputs (x > 50), exp(-x) underflows to 0,"] # [doc = " and sigmoid(x) approaches 1."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is compute-bound due to the exp() operation. SIMD provides"] # [doc = " modest speedups, but the exponential is the bottleneck."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, 0.0, 2.0]);"] # [doc = " let result = v.sigmoid().unwrap();"] # [doc = ""] # [doc = " // sigmoid(-2) ≈ 0.119, sigmoid(0) = 0.5, sigmoid(2) ≈ 0.881"] # [doc = " assert!((result.as_slice()[0] - 0.119).abs() < 0.001);"] # [doc = " assert!((result.as_slice()[1] - 0.5).abs() < 0.001);"] # [doc = " assert!((result.as_slice()[2] - 0.881).abs() < 0.001);"] # [doc = " ```"] pub fn sigmoid (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . sigmoid (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: sigmoid (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: sigmoid (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Leaky ReLU activation function"] # [doc = ""] # [doc = " Computes the element-wise Leaky ReLU with a configurable negative slope."] # [doc = " Leaky ReLU addresses the \"dying ReLU\" problem by allowing small negative values."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " leaky_relu(x, α)[i] = max(αx\\[i\\], x\\[i\\])"] # [doc = "                     = x\\[i\\]    if x\\[i\\] > 0"] # [doc = "                     = αx\\[i\\]   if x\\[i\\] ≤ 0"] # [doc = " ```"] # [doc = ""] # [doc = " # Parameters"] # [doc = ""] # [doc = " - `negative_slope`: The slope for negative values (typically 0.01)"] # [doc = "   - Must be in range [0.0, 1.0)"] # [doc = "   - Common values: 0.01 (default), 0.1, 0.2"] # [doc = "   - α = 0 reduces to standard ReLU"] # [doc = "   - α = 1 reduces to identity function"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Fixes dying ReLU**: Neurons can't completely die (always has gradient)"] # [doc = " - **Non-zero gradient**: Gradient is α for negative inputs (not zero)"] # [doc = " - **Unbounded positive**: No saturation for positive values"] # [doc = " - **Parameterized**: Negative slope can be tuned or learned (PReLU)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Deep networks**: Prevents dying neurons in very deep networks"] # [doc = " - **GANs**: Often used in generator and discriminator networks"] # [doc = " - **Better gradient flow**: Helps with vanishing gradient problem"] # [doc = " - **Empirical improvements**: Often outperforms ReLU in practice"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is memory-bound (simple multiplication and comparison)."] # [doc = " SIMD provides modest speedups."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = " Returns `InvalidInput` if negative_slope is not in [0.0, 1.0)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.leaky_relu(0.01).unwrap();"] # [doc = ""] # [doc = " // Negative values multiplied by 0.01, positive unchanged"] # [doc = " assert_eq!(result.as_slice(), &[-0.02, -0.01, 0.0, 1.0, 2.0]);"] # [doc = " ```"] pub fn leaky_relu (& self , negative_slope : f32) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } if ! (0.0 .. 1.0) . contains (& negative_slope) { return Err (TruenoError :: InvalidInput (format ! ("negative_slope must be in [0.0, 1.0), got {}" , negative_slope))) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . leaky_relu (& self . data , & mut result , negative_slope) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let data : Vec < f32 > = self . data . iter () . map (| & x | if x > 0.0 { x } else { negative_slope * x }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " ELU (Exponential Linear Unit) activation function"] # [doc = ""] # [doc = " Computes the element-wise ELU with a configurable alpha parameter."] # [doc = " ELU pushes mean activations closer to zero, improving learning."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " elu(x, α)[i] = x\\[i\\]           if x\\[i\\] > 0"] # [doc = "              = α(e^x\\[i\\] - 1)  if x\\[i\\] ≤ 0"] # [doc = " ```"] # [doc = ""] # [doc = " # Parameters"] # [doc = ""] # [doc = " - `alpha`: Controls the saturation value for negative inputs (typically 1.0)"] # [doc = "   - Must be > 0"] # [doc = "   - Common value: 1.0 (original ELU paper)"] # [doc = "   - Larger α → slower saturation for negative inputs"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Smooth**: Unlike ReLU/Leaky ReLU, has smooth gradients everywhere"] # [doc = " - **Negative values**: Allows negative outputs (pushes mean closer to zero)"] # [doc = " - **Bounded below**: Saturates to -α for very negative inputs"] # [doc = " - **Unbounded above**: No saturation for positive values"] # [doc = " - **Non-zero gradient**: Has gradient everywhere (no dead neurons)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Deep networks**: Better gradient flow than ReLU"] # [doc = " - **Mean activation near zero**: Reduces internal covariate shift"] # [doc = " - **Noise robustness**: Smooth activation helps with noisy gradients"] # [doc = " - **Empirical improvements**: Often outperforms ReLU and Leaky ReLU"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is compute-bound due to exp() for negative values."] # [doc = " More expensive than ReLU/Leaky ReLU but provides better properties."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = " Returns `InvalidInput` if alpha <= 0."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.elu(1.0).unwrap();"] # [doc = ""] # [doc = " // Negative values: α(e^x - 1), positive unchanged"] # [doc = " // elu(-2, 1) ≈ -0.865, elu(-1, 1) ≈ -0.632"] # [doc = " assert!((result.as_slice()[0] - (-0.865)).abs() < 0.01);"] # [doc = " assert!((result.as_slice()[1] - (-0.632)).abs() < 0.01);"] # [doc = " assert_eq!(result.as_slice()[2], 0.0);"] # [doc = " assert_eq!(result.as_slice()[3], 1.0);"] # [doc = " assert_eq!(result.as_slice()[4], 2.0);"] # [doc = " ```"] pub fn elu (& self , alpha : f32) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } if alpha <= 0.0 { return Err (TruenoError :: InvalidInput (format ! ("alpha must be > 0, got {}" , alpha))) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . elu (& self . data , & mut result , alpha) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let data : Vec < f32 > = self . data . iter () . map (| & x | if x > 0.0 { x } else { alpha * (x . exp () - 1.0) }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " GELU (Gaussian Error Linear Unit) activation function"] # [doc = ""] # [doc = " Computes the element-wise GELU activation using the tanh approximation."] # [doc = " GELU is the activation function used in transformers (BERT, GPT, etc.)."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " gelu(x) ≈ 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x³)))"] # [doc = " ```"] # [doc = ""] # [doc = " This is the tanh approximation which is faster than the exact form"] # [doc = " involving the error function (erf)."] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Smooth**: Infinitely differentiable everywhere"] # [doc = " - **Non-monotonic**: Unlike ReLU variants, has slight non-monotonicity near zero"] # [doc = " - **Stochastic regularizer**: Can be viewed as adaptive dropout"] # [doc = " - **Zero-centered**: Mean activation close to zero"] # [doc = " - **Bounded below**: Approaches 0 as x → -∞"] # [doc = " - **Unbounded above**: Linear growth for large positive x"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Transformers**: BERT, GPT-2, GPT-3, GPT-4 (default activation)"] # [doc = " - **Vision transformers**: ViT, DINO, MAE"] # [doc = " - **Modern architectures**: State-of-the-art NLP and vision models"] # [doc = " - **Better than ReLU**: Empirically outperforms ReLU in many tasks"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is compute-intensive (tanh, x³ calculations)."] # [doc = " More expensive than ReLU but comparable to ELU."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.gelu().unwrap();"] # [doc = ""] # [doc = " // GELU is smooth and non-monotonic near zero"] # [doc = " assert!(result.as_slice()[0] < 0.0); // Negative inputs → small negative outputs"] # [doc = " assert_eq!(result.as_slice()[2], 0.0); // gelu(0) = 0"] # [doc = " assert!(result.as_slice()[4] > 1.5); // Large positive → ~linear"] # [doc = " ```"] pub fn gelu (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . gelu (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: gelu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: gelu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: gelu (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: gelu (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: gelu (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: gelu (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: gelu (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: gelu (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: gelu (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Swish activation function (also known as SiLU - Sigmoid Linear Unit)"] # [doc = ""] # [doc = " Applies the Swish activation element-wise: swish(x) = x * sigmoid(x) = x / (1 + e^(-x))."] # [doc = ""] # [doc = " Swish is a smooth, non-monotonic activation function that consistently matches or"] # [doc = " outperforms ReLU in deep networks. It's used in EfficientNet, MobileNet v3, and"] # [doc = " many modern architectures. The function is self-gated: it adaptively gates the"] # [doc = " input based on its value."] # [doc = ""] # [doc = " Properties:"] # [doc = " - Smooth and differentiable everywhere"] # [doc = " - Non-monotonic: has a slight \"dip\" for negative values"] # [doc = " - swish(0) = 0"] # [doc = " - swish(x) ≈ x for large positive x (linear)"] # [doc = " - swish(x) ≈ 0 for large negative x"] # [doc = " - Unbounded above, bounded below by ≈ -0.278 at x ≈ -1.278"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Compute-bound operation requiring exponential and division."] # [doc = " Future SIMD optimizations planned for Phase 9 (GPU backend)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.swish().unwrap();"] # [doc = ""] # [doc = " // Swish is smooth and self-gated"] # [doc = " assert!(result.as_slice()[0] < 0.0); // Negative inputs → small negative outputs"] # [doc = " assert_eq!(result.as_slice()[2], 0.0); // swish(0) = 0"] # [doc = " assert!(result.as_slice()[4] > 1.5); // Large positive → ~linear"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Ramachandran et al. (2017): \"Searching for Activation Functions\""] # [doc = " - Also known as SiLU (Sigmoid Linear Unit): Elfwing et al. (2018)"] pub fn swish (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . swish (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: swish (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: swish (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: swish (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: swish (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: swish (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: swish (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: swish (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: swish (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: swish (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Hard Swish activation function"] # [doc = ""] # [doc = " Applies the hardswish activation element-wise: hardswish(x) = x * relu6(x + 3) / 6"] # [doc = ""] # [doc = " Hardswish is a piece-wise linear approximation to swish, designed for efficient"] # [doc = " computation in mobile neural networks. It's used in MobileNetV3 and avoids the"] # [doc = " expensive sigmoid computation of standard swish."] # [doc = ""] # [doc = " Properties:"] # [doc = " - Piece-wise linear: efficient to compute"] # [doc = " - hardswish(x) = 0 for x ≤ -3"] # [doc = " - hardswish(x) = x for x ≥ 3"] # [doc = " - hardswish(x) = x * (x + 3) / 6 for -3 < x < 3"] # [doc = " - hardswish(0) = 0"] # [doc = " - Smooth transitions at boundaries"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " More efficient than swish as it uses only multiply/divide operations"] # [doc = " instead of expensive exponential functions. Ideal for inference on"] # [doc = " resource-constrained devices."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-4.0, -3.0, 0.0, 3.0, 4.0]);"] # [doc = " let result = v.hardswish().unwrap();"] # [doc = ""] # [doc = " // Piece-wise linear behavior"] # [doc = " assert_eq!(result.as_slice()[0], 0.0); // x ≤ -3 → 0"] # [doc = " assert_eq!(result.as_slice()[1], 0.0); // x = -3 → 0"] # [doc = " assert_eq!(result.as_slice()[2], 0.0); // x = 0 → 0"] # [doc = " assert_eq!(result.as_slice()[3], 3.0); // x = 3 → x"] # [doc = " assert_eq!(result.as_slice()[4], 4.0); // x ≥ 3 → x"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Howard et al. (2019): \"Searching for MobileNetV3\""] pub fn hardswish (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let data : Vec < f32 > = self . data . iter () . map (| & x | { if x <= - 3.0 { 0.0 } else if x >= 3.0 { x } else { x * (x + 3.0) / 6.0 } }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Mish activation function"] # [doc = ""] # [doc = " Applies the mish activation element-wise: mish(x) = x * tanh(softplus(x)) = x * tanh(ln(1 + e^x))"] # [doc = ""] # [doc = " Mish is a self-regularizing non-monotonic activation function that often outperforms"] # [doc = " ReLU and swish in computer vision tasks. It's used in YOLOv4 and many modern architectures."] # [doc = ""] # [doc = " Properties:"] # [doc = " - Smooth and non-monotonic (similar to swish)"] # [doc = " - Self-regularizing: prevents dying neurons"] # [doc = " - mish(0) ≈ 0 (small positive value)"] # [doc = " - mish(x) ≈ x for large positive x (nearly linear)"] # [doc = " - mish(x) ≈ 0 for large negative x"] # [doc = " - Bounded below by ≈ -0.31 at x ≈ -1.19"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Compute-bound operation requiring exponential, logarithm, and tanh."] # [doc = " More expensive than ReLU/swish but often provides better accuracy."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.mish().unwrap();"] # [doc = ""] # [doc = " // Mish is smooth and self-gated"] # [doc = " assert!(result.as_slice()[0] < 0.0); // Small negative output for negative inputs"] # [doc = " assert!(result.as_slice()[2].abs() < 1e-5); // mish(0) = 0"] # [doc = " assert!(result.as_slice()[4] > 1.5); // Large positive → near linear"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Misra (2019): \"Mish: A Self Regularized Non-Monotonic Neural Activation Function\""] pub fn mish (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let data : Vec < f32 > = self . data . iter () . map (| & x | { if x < - 20.0 { 0.0 } else if x > 20.0 { x } else { let softplus = (1.0 + x . exp ()) . ln () ; x * softplus . tanh () } }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " SELU (Scaled Exponential Linear Unit) activation function"] # [doc = ""] # [doc = " Computes selu(x) = λ * (x if x > 0 else α * (exp(x) - 1))"] # [doc = " where λ ≈ 1.0507 and α ≈ 1.6733"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Self-normalizing**: Activations converge to zero mean and unit variance"] # [doc = " - **Vanishing gradient prevention**: Non-zero gradient for negative inputs"] # [doc = " - **Automatic normalization**: Reduces need for batch normalization"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses scalar implementation (GPU disabled for element-wise ops)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.selu().unwrap();"] # [doc = ""] # [doc = " // Positive values scaled by λ ≈ 1.0507"] # [doc = " assert!((result.as_slice()[3] - 1.0507).abs() < 0.001);"] # [doc = " assert!((result.as_slice()[4] - 2.1014).abs() < 0.001);"] # [doc = ""] # [doc = " // Zero stays zero"] # [doc = " assert!(result.as_slice()[2].abs() < 1e-5);"] # [doc = ""] # [doc = " // Negative values use ELU-like formula"] # [doc = " assert!(result.as_slice()[0] < 0.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Klambauer et al. (2017): \"Self-Normalizing Neural Networks\""] pub fn selu (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } const LAMBDA : f32 = 1.0507009873554804934193349852946 ; const ALPHA : f32 = 1.6732632423543772848170429916717 ; let data : Vec < f32 > = self . data . iter () . map (| & x | { if x > 0.0 { LAMBDA * x } else { LAMBDA * ALPHA * (x . exp () - 1.0) } }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " L2 norm (Euclidean norm)"] # [doc = ""] # [doc = " Computes the Euclidean length of the vector: sqrt(sum(a\\[i\\]^2))."] # [doc = " This is mathematically equivalent to sqrt(dot(self, self))."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via the dot product operation."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, 4.0]);"] # [doc = " let norm = v.norm_l2().unwrap();"] # [doc = " assert!((norm - 5.0).abs() < 1e-5); // sqrt(3^2 + 4^2) = 5"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns 0.0 for empty vectors (consistent with the mathematical definition)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert_eq!(v.norm_l2().unwrap(), 0.0);"] # [doc = " ```"] pub fn norm_l2 (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: norm_l2 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: norm_l2 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: norm_l2 (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: norm_l2 (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: norm_l2 (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: norm_l2 (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: norm_l2 (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: norm_l2 (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: norm_l2 (& self . data) , } } ; Ok (result) } # [doc = " Normalize the vector to unit length (L2 norm = 1)"] # [doc = ""] # [doc = " Returns a new vector in the same direction but with magnitude 1."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `TruenoError::DivisionByZero` if the vector has zero norm (cannot normalize zero vector)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, 4.0]);"] # [doc = " let unit = v.normalize().unwrap();"] # [doc = ""] # [doc = " // Result is [0.6, 0.8] (a unit vector)"] # [doc = " assert!((unit.as_slice()[0] - 0.6).abs() < 1e-5);"] # [doc = " assert!((unit.as_slice()[1] - 0.8).abs() < 1e-5);"] # [doc = ""] # [doc = " // Verify it's a unit vector (norm = 1)"] # [doc = " assert!((unit.norm_l2().unwrap() - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Zero Vector Error"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 0.0]);"] # [doc = " assert!(matches!(v.normalize(), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn normalize (& self) -> Result < Vector < f32 > > { let norm = self . norm_l2 () ? ; if norm . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let norm_vec = Vector :: from_slice (& vec ! [norm ; self . len ()]) ; self . div (& norm_vec) } # [doc = " Compute the L1 norm (Manhattan norm) of the vector"] # [doc = ""] # [doc = " Returns the sum of absolute values: ||v||₁ = sum(|v\\[i\\]|)"] # [doc = ""] # [doc = " The L1 norm is used in:"] # [doc = " - Machine learning (L1 regularization, Lasso regression)"] # [doc = " - Distance metrics (Manhattan distance)"] # [doc = " - Sparse modeling and feature selection"] # [doc = " - Signal processing"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, -4.0, 5.0]);"] # [doc = " let norm = v.norm_l1().unwrap();"] # [doc = ""] # [doc = " // |3| + |-4| + |5| = 12"] # [doc = " assert!((norm - 12.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty Vector"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert_eq!(v.norm_l1().unwrap(), 0.0);"] # [doc = " ```"] pub fn norm_l1 (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: norm_l1 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: norm_l1 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: norm_l1 (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: norm_l1 (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: norm_l1 (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: norm_l1 (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: norm_l1 (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: norm_l1 (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: norm_l1 (& self . data) , } } ; Ok (result) } # [doc = " Compute the L∞ norm (infinity norm / max norm) of the vector"] # [doc = ""] # [doc = " Returns the maximum absolute value: ||v||∞ = max(|v\\[i\\]|)"] # [doc = ""] # [doc = " The L∞ norm is used in:"] # [doc = " - Numerical analysis (error bounds, stability analysis)"] # [doc = " - Optimization (Chebyshev approximation)"] # [doc = " - Signal processing (peak detection)"] # [doc = " - Distance metrics (Chebyshev distance)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, -7.0, 5.0, -2.0]);"] # [doc = " let norm = v.norm_linf().unwrap();"] # [doc = ""] # [doc = " // max(|3|, |-7|, |5|, |-2|) = 7"] # [doc = " assert!((norm - 7.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty Vector"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert_eq!(v.norm_linf().unwrap(), 0.0);"] # [doc = " ```"] pub fn norm_linf (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let max_abs = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: norm_linf (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: norm_linf (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: norm_linf (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: norm_linf (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => ScalarBackend :: norm_linf (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: norm_linf (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => ScalarBackend :: norm_linf (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: norm_linf (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: norm_linf (& self . data) , } } ; Ok (max_abs) } # [doc = " Compute element-wise absolute value"] # [doc = ""] # [doc = " Returns a new vector where each element is the absolute value of the corresponding input element."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, -4.0, 5.0, -2.0]);"] # [doc = " let result = v.abs().unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[3.0, 4.0, 5.0, 2.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty Vector"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " let result = v.abs().unwrap();"] # [doc = " assert_eq!(result.len(), 0);"] # [doc = " ```"] pub fn abs (& self) -> Result < Vector < f32 > > { let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: abs (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: abs (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: abs (& self . data , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: abs (& self . data , & mut result_data) , # [cfg (target_arch = "wasm32")] Backend :: WASM => WasmBackend :: abs (& self . data , & mut result_data) , Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: abs (& self . data , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Scalar multiplication (scale all elements by a scalar value)"] # [doc = ""] # [doc = " Returns a new vector where each element is multiplied by the scalar."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " let result = v.scale(2.0).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[2.0, 4.0, 6.0, 8.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Scaling by Zero"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = v.scale(0.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[0.0, 0.0, 0.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Negative Scaling"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, -2.0, 3.0]);"] # [doc = " let result = v.scale(-2.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-2.0, 4.0, -6.0]);"] # [doc = " ```"] pub fn scale (& self , scalar : f32) -> Result < Vector < f32 > > { let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: scale (& self . data , scalar , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: scale (& self . data , scalar , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: scale (& self . data , scalar , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: scale (& self . data , scalar , & mut result_data) , # [cfg (target_arch = "wasm32")] Backend :: WASM => WasmBackend :: scale (& self . data , scalar , & mut result_data) , Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: scale (& self . data , scalar , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Clamp elements to range [min_val, max_val]"] # [doc = ""] # [doc = " Returns a new vector where each element is constrained to the specified range."] # [doc = " Elements below min_val become min_val, elements above max_val become max_val."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);"] # [doc = " let result = v.clamp(0.0, 10.0).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Negative Range"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-10.0, -5.0, 0.0, 5.0]);"] # [doc = " let result = v.clamp(-8.0, -2.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-8.0, -5.0, -2.0, -2.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if min_val > max_val."] pub fn clamp (& self , min_val : f32 , max_val : f32) -> Result < Vector < f32 > > { if min_val > max_val { return Err (TruenoError :: InvalidInput (format ! ("Invalid clamp range: min ({}) > max ({})" , min_val , max_val))) ; } let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (target_arch = "wasm32")] Backend :: WASM => { WasmBackend :: clamp (& self . data , min_val , max_val , & mut result_data) } Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: clamp (& self . data , min_val , max_val , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Linear interpolation between two vectors"] # [doc = ""] # [doc = " Computes element-wise linear interpolation: `result\\[i\\] = a\\[i\\] + t * (b\\[i\\] - a\\[i\\])`"] # [doc = ""] # [doc = " - When `t = 0.0`, returns `self`"] # [doc = " - When `t = 1.0`, returns `other`"] # [doc = " - Values outside `[0, 1]` perform extrapolation"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[0.0, 10.0, 20.0]);"] # [doc = " let b = Vector::from_slice(&[100.0, 110.0, 120.0]);"] # [doc = " let result = a.lerp(&b, 0.5).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[50.0, 60.0, 70.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Extrapolation"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[0.0, 10.0]);"] # [doc = " let b = Vector::from_slice(&[10.0, 20.0]);"] # [doc = ""] # [doc = " // t > 1.0 extrapolates beyond b"] # [doc = " let result = a.lerp(&b, 2.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[20.0, 30.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `SizeMismatch` if vectors have different lengths."] pub fn lerp (& self , other : & Vector < f32 > , t : f32) -> Result < Vector < f32 > > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (target_arch = "wasm32")] Backend :: WASM => { WasmBackend :: lerp (& self . data , & other . data , t , & mut result_data) } Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: lerp (& self . data , & other . data , t , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Fused multiply-add: result\\[i\\] = self\\[i\\] * b\\[i\\] + c\\[i\\]"] # [doc = ""] # [doc = " Computes element-wise fused multiply-add operation. On hardware with FMA support"] # [doc = " (AVX2, NEON), this is a single instruction with better performance and numerical"] # [doc = " accuracy (no intermediate rounding). On platforms without FMA (SSE2, WASM), uses"] # [doc = " separate multiply and add operations."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `b` - The second vector to multiply with"] # [doc = " * `c` - The vector to add to the product"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector where each element is `self\\[i\\] * b\\[i\\] + c\\[i\\]`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `SizeMismatch` if vector lengths don't match"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let b = Vector::from_slice(&[5.0, 6.0, 7.0]);"] # [doc = " let c = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = a.fma(&b, &c).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[11.0, 20.0, 31.0]);  // [2*5+1, 3*6+2, 4*7+3]"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = ""] # [doc = " - Neural networks: matrix multiplication, backpropagation"] # [doc = " - Scientific computing: polynomial evaluation, numerical integration"] # [doc = " - Graphics: transformation matrices, shader computations"] # [doc = " - Physics simulations: force calculations, particle systems"] pub fn fma (& self , b : & Vector < f32 > , c : & Vector < f32 >) -> Result < Vector < f32 > > { if self . len () != b . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : b . len () , }) ; } if self . len () != c . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : c . len () , }) ; } let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (target_arch = "wasm32")] Backend :: WASM => { WasmBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) } Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Element-wise square root: result\\[i\\] = sqrt(self\\[i\\])"] # [doc = ""] # [doc = " Computes the square root of each element. For negative values, returns NaN"] # [doc = " following IEEE 754 floating-point semantics."] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector where each element is the square root of the corresponding input element"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[4.0, 9.0, 16.0, 25.0]);"] # [doc = " let result = a.sqrt().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[2.0, 3.0, 4.0, 5.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " Negative values produce NaN:"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[-1.0, 4.0]);"] # [doc = " let result = a.sqrt().unwrap();"] # [doc = " assert!(result.as_slice()[0].is_nan());"] # [doc = " assert_eq!(result.as_slice()[1], 2.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = ""] # [doc = " - Distance calculations: Euclidean distance computation"] # [doc = " - Statistics: Standard deviation, RMS (root mean square)"] # [doc = " - Machine learning: Normalization, gradient descent with adaptive learning rates"] # [doc = " - Signal processing: Amplitude calculations, power spectrum analysis"] # [doc = " - Physics simulations: Velocity from kinetic energy, wave propagation"] pub fn sqrt (& self) -> Result < Vector < f32 > > { let sqrt_data : Vec < f32 > = self . data . iter () . map (| x | x . sqrt ()) . collect () ; Ok (Vector { data : sqrt_data , backend : self . backend , }) } # [doc = " Element-wise reciprocal: result\\[i\\] = 1 / self\\[i\\]"] # [doc = ""] # [doc = " Computes the reciprocal (multiplicative inverse) of each element."] # [doc = " For zero values, returns infinity following IEEE 754 floating-point semantics."] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector where each element is the reciprocal of the corresponding input element"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[2.0, 4.0, 5.0, 10.0]);"] # [doc = " let result = a.recip().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[0.5, 0.25, 0.2, 0.1]);"] # [doc = " ```"] # [doc = ""] # [doc = " Zero values produce infinity:"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[0.0, 2.0]);"] # [doc = " let result = a.recip().unwrap();"] # [doc = " assert!(result.as_slice()[0].is_infinite());"] # [doc = " assert_eq!(result.as_slice()[1], 0.5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = ""] # [doc = " - Division optimization: `a / b` → `a * recip(b)` (multiplication is faster)"] # [doc = " - Neural networks: Learning rate schedules, weight normalization"] # [doc = " - Statistics: Harmonic mean calculations, inverse transformations"] # [doc = " - Physics: Resistance (R = 1/G), optical power (P = 1/f)"] # [doc = " - Signal processing: Frequency to period conversion, filter design"] pub fn recip (& self) -> Result < Vector < f32 > > { let recip_data : Vec < f32 > = self . data . iter () . map (| x | x . recip ()) . collect () ; Ok (Vector { data : recip_data , backend : self . backend , }) } # [doc = " Element-wise power: result\\[i\\] = base\\[i\\]^n"] # [doc = ""] # [doc = " Raises each element to the given power `n`."] # [doc = " Uses Rust's optimized f32::powf() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let squared = v.pow(2.0).unwrap();"] # [doc = " assert_eq!(squared.as_slice(), &[4.0, 9.0, 16.0]);"] # [doc = ""] # [doc = " let sqrt = v.pow(0.5).unwrap();  // Fractional power = root"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `x.pow(0.0)` returns 1.0 for all x (even x=0)"] # [doc = " - `x.pow(1.0)` returns x (identity)"] # [doc = " - `x.pow(-1.0)` returns 1/x (reciprocal)"] # [doc = " - `x.pow(0.5)` returns sqrt(x) (square root)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Statistics: Power transformations (Box-Cox, Yeo-Johnson)"] # [doc = " - Machine learning: Polynomial features, activation functions"] # [doc = " - Physics: Inverse square law (1/r²), power laws"] # [doc = " - Signal processing: Power spectral density, root mean square"] pub fn pow (& self , n : f32) -> Result < Vector < f32 > > { let pow_data : Vec < f32 > = self . data . iter () . map (| x | x . powf (n)) . collect () ; Ok (Vector { data : pow_data , backend : self . backend , }) } # [doc = " Element-wise exponential: result\\[i\\] = e^x\\[i\\]"] # [doc = ""] # [doc = " Computes the natural exponential (e^x) for each element."] # [doc = " Uses Rust's optimized f32::exp() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, 2.0]);"] # [doc = " let result = v.exp().unwrap();"] # [doc = " // result ≈ [1.0, 2.718, 7.389]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `exp(0.0)` returns 1.0"] # [doc = " - `exp(1.0)` returns e ≈ 2.71828"] # [doc = " - `exp(-∞)` returns 0.0"] # [doc = " - `exp(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Machine learning: Softmax activation, sigmoid, exponential loss"] # [doc = " - Statistics: Exponential distribution, log-normal distribution"] # [doc = " - Physics: Radioactive decay, population growth models"] # [doc = " - Signal processing: Exponential smoothing, envelope detection"] # [doc = " - Numerical methods: Solving differential equations"] pub fn exp (& self) -> Result < Vector < f32 > > { let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: exp (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: exp (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: exp (& self . data , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: exp (& self . data , & mut result_data) , # [cfg (target_arch = "wasm32")] Backend :: WASM => WasmBackend :: exp (& self . data , & mut result_data) , Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: exp (& self . data , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Element-wise natural logarithm: result\\[i\\] = ln(x\\[i\\])"] # [doc = ""] # [doc = " Computes the natural logarithm (base e) for each element."] # [doc = " Uses Rust's optimized f32::ln() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, std::f32::consts::E, std::f32::consts::E.powi(2)]);"] # [doc = " let result = v.ln().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 2.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `ln(1.0)` returns 0.0"] # [doc = " - `ln(e)` returns 1.0"] # [doc = " - `ln(x)` for x ≤ 0 returns NaN"] # [doc = " - `ln(0.0)` returns -∞"] # [doc = " - `ln(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Machine learning: Log loss, log-likelihood, softmax normalization"] # [doc = " - Statistics: Log-normal distribution, log transformation for skewed data"] # [doc = " - Information theory: Entropy calculation, mutual information"] # [doc = " - Economics: Log returns, elasticity calculations"] # [doc = " - Signal processing: Decibel conversion, log-frequency analysis"] pub fn ln (& self) -> Result < Vector < f32 > > { let ln_data : Vec < f32 > = self . data . iter () . map (| x | x . ln ()) . collect () ; Ok (Vector { data : ln_data , backend : self . backend , }) } # [doc = " Element-wise base-2 logarithm: result\\[i\\] = log₂(x\\[i\\])"] # [doc = ""] # [doc = " Computes the base-2 logarithm for each element."] # [doc = " Uses Rust's optimized f32::log2() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 4.0, 8.0]);"] # [doc = " let result = v.log2().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 2.0, 3.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `log2(1.0)` returns 0.0"] # [doc = " - `log2(2.0)` returns 1.0"] # [doc = " - `log2(x)` for x ≤ 0 returns NaN"] # [doc = " - `log2(0.0)` returns -∞"] # [doc = " - `log2(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Information theory: Entropy in bits, mutual information"] # [doc = " - Computer science: Bit manipulation, binary search complexity"] # [doc = " - Audio: Octave calculations, pitch detection"] # [doc = " - Data compression: Huffman coding, arithmetic coding"] pub fn log2 (& self) -> Result < Vector < f32 > > { let log2_data : Vec < f32 > = self . data . iter () . map (| x | x . log2 ()) . collect () ; Ok (Vector { data : log2_data , backend : self . backend , }) } # [doc = " Element-wise base-10 logarithm: result\\[i\\] = log₁₀(x\\[i\\])"] # [doc = ""] # [doc = " Computes the base-10 (common) logarithm for each element."] # [doc = " Uses Rust's optimized f32::log10() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 10.0, 100.0, 1000.0]);"] # [doc = " let result = v.log10().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 2.0, 3.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `log10(1.0)` returns 0.0"] # [doc = " - `log10(10.0)` returns 1.0"] # [doc = " - `log10(x)` for x ≤ 0 returns NaN"] # [doc = " - `log10(0.0)` returns -∞"] # [doc = " - `log10(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Audio: Decibel calculations (dB = 20 * log10(amplitude))"] # [doc = " - Chemistry: pH calculations (-log10(H+ concentration))"] # [doc = " - Seismology: Richter scale"] # [doc = " - Scientific notation: Order of magnitude calculations"] pub fn log10 (& self) -> Result < Vector < f32 > > { let log10_data : Vec < f32 > = self . data . iter () . map (| x | x . log10 ()) . collect () ; Ok (Vector { data : log10_data , backend : self . backend , }) } # [doc = " Element-wise sine: result\\[i\\] = sin(x\\[i\\])"] # [doc = ""] # [doc = " Computes the sine for each element (input in radians)."] # [doc = " Uses Rust's optimized f32::sin() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, PI / 2.0, PI]);"] # [doc = " let result = v.sin().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 0.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `sin(0)` returns 0.0"] # [doc = " - `sin(π/2)` returns 1.0"] # [doc = " - `sin(π)` returns 0.0 (approximately)"] # [doc = " - `sin(-x)` returns -sin(x) (odd function)"] # [doc = " - Periodic with period 2π: sin(x + 2π) = sin(x)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Signal processing: Waveform generation, oscillators, modulation"] # [doc = " - Physics: Harmonic motion, wave propagation, pendulums"] # [doc = " - Audio: Synthesizers, tone generation, effects processing"] # [doc = " - Graphics: Animation, rotation transformations, procedural generation"] # [doc = " - Fourier analysis: Frequency decomposition, spectral analysis"] pub fn sin (& self) -> Result < Vector < f32 > > { let sin_data : Vec < f32 > = self . data . iter () . map (| x | x . sin ()) . collect () ; Ok (Vector { data : sin_data , backend : self . backend , }) } # [doc = " Element-wise cosine: result\\[i\\] = cos(x\\[i\\])"] # [doc = ""] # [doc = " Computes the cosine for each element (input in radians)."] # [doc = " Uses Rust's optimized f32::cos() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, PI / 2.0, PI]);"] # [doc = " let result = v.cos().unwrap();"] # [doc = " // result ≈ [1.0, 0.0, -1.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `cos(0)` returns 1.0"] # [doc = " - `cos(π/2)` returns 0.0 (approximately)"] # [doc = " - `cos(π)` returns -1.0"] # [doc = " - `cos(-x)` returns cos(x) (even function)"] # [doc = " - Periodic with period 2π: cos(x + 2π) = cos(x)"] # [doc = " - Relation to sine: cos(x) = sin(x + π/2)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Signal processing: Phase-shifted waveforms, I/Q modulation, quadrature signals"] # [doc = " - Physics: Projectile motion, wave interference, damped oscillations"] # [doc = " - Graphics: Rotation matrices, camera transforms, circular motion"] # [doc = " - Audio: Stereo panning, spatial audio, frequency synthesis"] # [doc = " - Engineering: Control systems, frequency response, AC circuits"] pub fn cos (& self) -> Result < Vector < f32 > > { let cos_data : Vec < f32 > = self . data . iter () . map (| x | x . cos ()) . collect () ; Ok (Vector { data : cos_data , backend : self . backend , }) } # [doc = " Computes element-wise tangent (tan) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the tangent of the corresponding input element."] # [doc = " tan(x) = sin(x) / cos(x)"] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with tan(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Odd function: tan(-x) = -tan(x)"] # [doc = " - Period: 2π (not π, despite common misconception)"] # [doc = " - Undefined at x = π/2 + nπ (where n is any integer)"] # [doc = " - tan(x) = sin(x) / cos(x)"] # [doc = " - Range: (-∞, +∞)"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::tan()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let angles = Vector::from_slice(&[0.0, PI / 4.0, -PI / 4.0]);"] # [doc = " let result = angles.tan().unwrap();"] # [doc = " // Result: [0.0, 1.0, -1.0] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Trigonometry: Slope calculations, angle relationships"] # [doc = " - Signal processing: Phase analysis, modulation"] # [doc = " - Physics: Projectile trajectories, optics (Snell's law angles)"] # [doc = " - Graphics: Perspective projection, field of view calculations"] # [doc = " - Engineering: Slope gradients, tangent lines to curves"] pub fn tan (& self) -> Result < Vector < f32 > > { let tan_data : Vec < f32 > = self . data . iter () . map (| x | x . tan ()) . collect () ; Ok (Vector { data : tan_data , backend : self . backend , }) } # [doc = " Computes element-wise arcsine (asin/sin⁻¹) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the inverse sine of the corresponding input element."] # [doc = " This is the inverse function of sin: if y = sin(x), then x = asin(y)."] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with asin(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Domain: [-1, 1] (inputs outside this range produce NaN)"] # [doc = " - Range: [-π/2, π/2]"] # [doc = " - Odd function: asin(-x) = -asin(x)"] # [doc = " - Inverse relation: asin(sin(x)) = x for x ∈ [-π/2, π/2]"] # [doc = " - asin(0) = 0"] # [doc = " - asin(1) = π/2"] # [doc = " - asin(-1) = -π/2"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::asin()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let values = Vector::from_slice(&[0.0, 0.5, 1.0]);"] # [doc = " let result = values.asin().unwrap();"] # [doc = " // Result: [0.0, π/6, π/2] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Physics: Calculating angles from sine values in mechanics, optics"] # [doc = " - Signal processing: Phase recovery, demodulation"] # [doc = " - Graphics: Inverse transformations, angle calculations"] # [doc = " - Navigation: GPS calculations, spherical trigonometry"] # [doc = " - Control systems: Inverse kinematics, servo positioning"] pub fn asin (& self) -> Result < Vector < f32 > > { let asin_data : Vec < f32 > = self . data . iter () . map (| x | x . asin ()) . collect () ; Ok (Vector { data : asin_data , backend : self . backend , }) } # [doc = " Computes element-wise arccosine (acos/cos⁻¹) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the inverse cosine of the corresponding input element."] # [doc = " This is the inverse function of cos: if y = cos(x), then x = acos(y)."] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with acos(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Domain: [-1, 1] (inputs outside this range produce NaN)"] # [doc = " - Range: [0, π]"] # [doc = " - Symmetry: acos(-x) = π - acos(x)"] # [doc = " - Inverse relation: acos(cos(x)) = x for x ∈ [0, π]"] # [doc = " - acos(0) = π/2"] # [doc = " - acos(1) = 0"] # [doc = " - acos(-1) = π"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::acos()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let values = Vector::from_slice(&[0.0, 0.5, 1.0]);"] # [doc = " let result = values.acos().unwrap();"] # [doc = " // Result: [π/2, π/3, 0.0] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Physics: Angle calculations in mechanics, optics, reflections"] # [doc = " - Signal processing: Phase analysis, correlation functions"] # [doc = " - Graphics: View angle calculations, lighting models"] # [doc = " - Navigation: Bearing calculations, great circle distances"] # [doc = " - Robotics: Joint angle solving, orientation calculations"] pub fn acos (& self) -> Result < Vector < f32 > > { let acos_data : Vec < f32 > = self . data . iter () . map (| x | x . acos ()) . collect () ; Ok (Vector { data : acos_data , backend : self . backend , }) } # [doc = " Computes element-wise arctangent (atan/tan⁻¹) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the inverse tangent of the corresponding input element."] # [doc = " This is the inverse function of tan: if y = tan(x), then x = atan(y)."] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with atan(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Domain: All real numbers (-∞, +∞)"] # [doc = " - Range: (-π/2, π/2)"] # [doc = " - Odd function: atan(-x) = -atan(x)"] # [doc = " - Inverse relation: atan(tan(x)) = x for x ∈ (-π/2, π/2)"] # [doc = " - atan(0) = 0"] # [doc = " - atan(1) = π/4"] # [doc = " - atan(-1) = -π/4"] # [doc = " - lim(x→∞) atan(x) = π/2"] # [doc = " - lim(x→-∞) atan(x) = -π/2"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::atan()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let values = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = values.atan().unwrap();"] # [doc = " // Result: [0.0, π/4, -π/4] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Physics: Angle calculations from slopes, velocity components"] # [doc = " - Signal processing: Phase unwrapping, FM demodulation"] # [doc = " - Graphics: Rotation calculations, camera orientation"] # [doc = " - Robotics: Inverse kinematics, steering angles"] # [doc = " - Navigation: Heading calculations from coordinates"] pub fn atan (& self) -> Result < Vector < f32 > > { let atan_data : Vec < f32 > = self . data . iter () . map (| x | x . atan ()) . collect () ; Ok (Vector { data : atan_data , backend : self . backend , }) } # [doc = " Computes the hyperbolic sine (sinh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " sinh(x) = (e^x - e^(-x)) / 2"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: (-∞, +∞)"] # [doc = " - Odd function: sinh(-x) = -sinh(x)"] # [doc = " - sinh(0) = 0"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.sinh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " ```"] pub fn sinh (& self) -> Result < Vector < f32 > > { let sinh_data : Vec < f32 > = self . data . iter () . map (| x | x . sinh ()) . collect () ; Ok (Vector { data : sinh_data , backend : self . backend , }) } # [doc = " Computes the hyperbolic cosine (cosh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " cosh(x) = (e^x + e^(-x)) / 2"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: [1, +∞)"] # [doc = " - Even function: cosh(-x) = cosh(x)"] # [doc = " - cosh(0) = 1"] # [doc = " - Always positive: cosh(x) ≥ 1 for all x"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.cosh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 1.0).abs() < 1e-5);"] # [doc = " ```"] pub fn cosh (& self) -> Result < Vector < f32 > > { let cosh_data : Vec < f32 > = self . data . iter () . map (| x | x . cosh ()) . collect () ; Ok (Vector { data : cosh_data , backend : self . backend , }) } # [doc = " Computes the hyperbolic tangent (tanh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " tanh(x) = sinh(x) / cosh(x) = (e^x - e^(-x)) / (e^x + e^(-x))"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: (-1, 1)"] # [doc = " - Odd function: tanh(-x) = -tanh(x)"] # [doc = " - tanh(0) = 0"] # [doc = " - Bounded: -1 < tanh(x) < 1 for all x"] # [doc = " - Commonly used as activation function in neural networks"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.tanh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " // All values are in range (-1, 1)"] # [doc = " assert!(result.as_slice().iter().all(|&x| x > -1.0 && x < 1.0));"] # [doc = " ```"] pub fn tanh (& self) -> Result < Vector < f32 > > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . tanh (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: tanh (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: tanh (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: tanh (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: tanh (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: tanh (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: tanh (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: tanh (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: tanh (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { # [cfg (target_arch = "x86_64")] { if is_x86_feature_detected ! ("avx2") { Avx2Backend :: tanh (& self . data , & mut result) ; } else { Sse2Backend :: tanh (& self . data , & mut result) ; } } # [cfg (not (target_arch = "x86_64"))] { ScalarBackend :: tanh (& self . data , & mut result) ; } } } } Ok (Vector { data : result , backend : self . backend , }) } # [doc = " Computes the inverse hyperbolic sine (asinh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " asinh(x) = ln(x + sqrt(x² + 1))"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: (-∞, +∞)"] # [doc = " - Odd function: asinh(-x) = -asinh(x)"] # [doc = " - asinh(0) = 0"] # [doc = " - Inverse of sinh: asinh(sinh(x)) = x"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.asinh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " ```"] pub fn asinh (& self) -> Result < Vector < f32 > > { let asinh_data : Vec < f32 > = self . data . iter () . map (| x | x . asinh ()) . collect () ; Ok (Vector { data : asinh_data , backend : self . backend , }) } # [doc = " Computes the inverse hyperbolic cosine (acosh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " acosh(x) = ln(x + sqrt(x² - 1))"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: [1, +∞)"] # [doc = " - Range: [0, +∞)"] # [doc = " - acosh(1) = 0"] # [doc = " - Inverse of cosh: acosh(cosh(x)) = x for x >= 0"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = v.acosh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " ```"] pub fn acosh (& self) -> Result < Vector < f32 > > { let acosh_data : Vec < f32 > = self . data . iter () . map (| x | x . acosh ()) . collect () ; Ok (Vector { data : acosh_data , backend : self . backend , }) } # [doc = " Computes the inverse hyperbolic tangent (atanh) of each element."] # [doc = ""] # [doc = " Domain: (-1, 1)"] # [doc = " Range: (-∞, +∞)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 0.5, -0.5]);"] # [doc = " let result = v.atanh().unwrap();"] # [doc = " // atanh(0) = 0, atanh(0.5) ≈ 0.549, atanh(-0.5) ≈ -0.549"] # [doc = " ```"] pub fn atanh (& self) -> Result < Vector < f32 > > { let atanh_data : Vec < f32 > = self . data . iter () . map (| x | x . atanh ()) . collect () ; Ok (Vector { data : atanh_data , backend : self . backend , }) } # [doc = " Computes the floor (round down to nearest integer) of each element."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.7, -2.3, 5.0]);"] # [doc = " let result = v.floor().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[3.0, -3.0, 5.0]);"] # [doc = " ```"] pub fn floor (& self) -> Result < Vector < f32 > > { let floor_data : Vec < f32 > = self . data . iter () . map (| x | x . floor ()) . collect () ; Ok (Vector { data : floor_data , backend : self . backend , }) } # [doc = " Computes the ceiling (round up to nearest integer) of each element."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.2, -2.7, 5.0]);"] # [doc = " let result = v.ceil().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[4.0, -2.0, 5.0]);"] # [doc = " ```"] pub fn ceil (& self) -> Result < Vector < f32 > > { let ceil_data : Vec < f32 > = self . data . iter () . map (| x | x . ceil ()) . collect () ; Ok (Vector { data : ceil_data , backend : self . backend , }) } # [doc = " Rounds each element to the nearest integer."] # [doc = ""] # [doc = " Uses \"round half away from zero\" strategy:"] # [doc = " - 0.5 rounds to 1.0, 1.5 rounds to 2.0, -1.5 rounds to -2.0, etc."] # [doc = " - Positive halfway cases round up, negative halfway cases round down."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.2, 3.7, -2.3, -2.8]);"] # [doc = " let result = v.round().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[3.0, 4.0, -2.0, -3.0]);"] # [doc = " ```"] pub fn round (& self) -> Result < Vector < f32 > > { let round_data : Vec < f32 > = self . data . iter () . map (| x | x . round ()) . collect () ; Ok (Vector { data : round_data , backend : self . backend , }) } # [doc = " Truncates each element toward zero (removes fractional part)."] # [doc = ""] # [doc = " Truncation always moves toward zero:"] # [doc = " - Positive values: equivalent to floor() (e.g., 3.7 → 3.0)"] # [doc = " - Negative values: equivalent to ceil() (e.g., -3.7 → -3.0)"] # [doc = " - This differs from floor() which always rounds down"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.7, -2.7, 5.0]);"] # [doc = " let result = v.trunc().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[3.0, -2.0, 5.0]);"] # [doc = " ```"] pub fn trunc (& self) -> Result < Vector < f32 > > { let trunc_data : Vec < f32 > = self . data . iter () . map (| x | x . trunc ()) . collect () ; Ok (Vector { data : trunc_data , backend : self . backend , }) } # [doc = " Returns the fractional part of each element."] # [doc = ""] # [doc = " The fractional part has the same sign as the original value:"] # [doc = " - Positive: fract(3.7) = 0.7"] # [doc = " - Negative: fract(-3.7) = -0.7"] # [doc = " - Decomposition property: x = trunc(x) + fract(x)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.7, -2.3, 5.0]);"] # [doc = " let result = v.fract().unwrap();"] # [doc = " // Fractional parts: 0.7, -0.3, 0.0"] # [doc = " assert!((result.as_slice()[0] - 0.7).abs() < 1e-5);"] # [doc = " assert!((result.as_slice()[1] - (-0.3)).abs() < 1e-5);"] # [doc = " ```"] pub fn fract (& self) -> Result < Vector < f32 > > { let fract_data : Vec < f32 > = self . data . iter () . map (| x | x . fract ()) . collect () ; Ok (Vector { data : fract_data , backend : self . backend , }) } # [doc = " Returns the sign of each element."] # [doc = ""] # [doc = " Returns:"] # [doc = " - `1.0` if the value is positive (including +0.0 and +∞)"] # [doc = " - `-1.0` if the value is negative (including -0.0 and -∞)"] # [doc = " - `NaN` if the value is NaN"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[5.0, -3.0, 0.0, -0.0]);"] # [doc = " let result = v.signum().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[1.0, -1.0, 1.0, -1.0]);"] # [doc = " ```"] pub fn signum (& self) -> Result < Vector < f32 > > { let signum_data : Vec < f32 > = self . data . iter () . map (| x | x . signum ()) . collect () ; Ok (Vector { data : signum_data , backend : self . backend , }) } # [doc = " Returns a vector with the magnitude of `self` and the sign of `sign`."] # [doc = ""] # [doc = " For each element pair, takes the magnitude from `self` and the sign from `sign`."] # [doc = " Equivalent to `abs(self\\[i\\])` with the sign of `sign\\[i\\]`."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `sign` - Vector providing the sign for each element"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `TruenoError::SizeMismatch` if vectors have different lengths."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let magnitude = Vector::from_slice(&[5.0, 3.0, 2.0]);"] # [doc = " let sign = Vector::from_slice(&[-1.0, 1.0, -1.0]);"] # [doc = " let result = magnitude.copysign(&sign).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-5.0, 3.0, -2.0]);"] # [doc = " ```"] pub fn copysign (& self , sign : & Self) -> Result < Vector < f32 > > { if self . len () != sign . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : sign . len () , }) ; } let copysign_data : Vec < f32 > = self . data . iter () . zip (sign . data . iter ()) . map (| (mag , sgn) | mag . copysign (* sgn)) . collect () ; Ok (Vector { data : copysign_data , backend : self . backend , }) } # [doc = " Element-wise minimum of two vectors."] # [doc = ""] # [doc = " Returns a new vector where each element is the minimum of the corresponding"] # [doc = " elements from self and other."] # [doc = ""] # [doc = " NaN handling: Prefers non-NaN values (NAN.min(x) = x)."] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " let a = Vector::from_slice(&[1.0, 5.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let result = a.minimum(&b).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[1.0, 3.0, 3.0]);"] # [doc = " ```"] pub fn minimum (& self , other : & Self) -> Result < Vector < f32 > > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let minimum_data : Vec < f32 > = self . data . iter () . zip (other . data . iter ()) . map (| (a , b) | a . min (* b)) . collect () ; Ok (Vector { data : minimum_data , backend : self . backend , }) } # [doc = " Element-wise maximum of two vectors."] # [doc = ""] # [doc = " Returns a new vector where each element is the maximum of the corresponding"] # [doc = " elements from self and other."] # [doc = ""] # [doc = " NaN handling: Prefers non-NaN values (NAN.max(x) = x)."] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " let a = Vector::from_slice(&[1.0, 5.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let result = a.maximum(&b).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[2.0, 5.0, 4.0]);"] # [doc = " ```"] pub fn maximum (& self , other : & Self) -> Result < Vector < f32 > > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let maximum_data : Vec < f32 > = self . data . iter () . zip (other . data . iter ()) . map (| (a , b) | a . max (* b)) . collect () ; Ok (Vector { data : maximum_data , backend : self . backend , }) } # [doc = " Element-wise negation (unary minus)."] # [doc = ""] # [doc = " Returns a new vector where each element is the negation of the corresponding"] # [doc = " element from self."] # [doc = ""] # [doc = " Properties: Double negation is identity: -(-x) = x"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " let a = Vector::from_slice(&[1.0, -2.0, 3.0]);"] # [doc = " let result = a.neg().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-1.0, 2.0, -3.0]);"] # [doc = " ```"] pub fn neg (& self) -> Result < Vector < f32 > > { let neg_data : Vec < f32 > = self . data . iter () . map (| x | - x) . collect () ; Ok (Vector { data : neg_data , backend : self . backend , }) } } . self_ty`
- **Function**: `tests::test_from_slice` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_from_slice_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_from_slice_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_from_slice_with_backend` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_auto_backend_resolution` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_negative_result` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mul_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mul_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_by_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_dot_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_dot_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan_numerical_stability` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_first_occurrence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_first_occurrence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_unit_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize_already_unit` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_mixed` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_with_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_fraction` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_all_within_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_all_below_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_all_above_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_negative_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_same_min_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_invalid_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_at_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_at_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_extrapolate_above` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_extrapolate_below` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_ones` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_negatives` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_size_mismatch_b` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_size_mismatch_c` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_ones` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_negatives` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_cube` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_zero_exponent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_one_exponent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_negative_exponent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_backend_auto_unsupported` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_small_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_inverse_exp` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_non_powers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_non_powers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_quarter_circle` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_periodicity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_quarter_circle` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_sin_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_quarter_circle` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_sin_cos_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_sin_inverse` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_symmetry` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_cos_inverse` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_tan_inverse` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_odd_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_even_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_sinh_cosh_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_odd_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_cosh_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_odd_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_integers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_integers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_halfway` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_toward_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_integers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_mixed` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_zero_handling` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_negative_magnitude` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_nan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_nan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_double_negation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_nan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_pythagorean` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_mixed` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_all_same` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_constant` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_symmetric` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_two_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_constant` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_symmetric` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_two_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_self` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_perfect_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_perfect_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_self` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_constant_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_constant_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_already_normalized` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_constant_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_already_normalized` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_no_change` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_all_below` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_all_above` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_invalid_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_equal_bounds` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_uniform` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_uniform` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_zero_boundary` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_sparsity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_symmetry` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_extreme_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_different_slopes` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_reduces_to_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_preserves_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_invalid_slope` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_different_alphas` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_saturation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_preserves_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_invalid_alpha` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_smoothness` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_minimum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_boundary_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_transition_region` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_minimum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_positive_scaling` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_negative_asymptote` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_continuity_at_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_aligned_vector_creation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_aligned_vector_operations` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]

### ./tests/chaos_tests.rs

**File Complexity**: 1 | **Functions**: 5

- **Function**: `test_gentle_preset_properties` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_aggressive_preset_properties` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_chaos_error_display_messages` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_default_is_permissive` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_presets_are_distinct` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]

### ./tests/integration_test.rs

**File Complexity**: 1 | **Functions**: 4

- **Function**: `integration_error_handling` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `integration_backend_selection` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `integration_smoke_test_all_operations` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `integration_performance_gate` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]

### ./xtask/src/main.rs

**File Complexity**: 3 | **Functions**: 1

- **Function**: `main` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]

### ./xtask/src/validate_examples.rs

**File Complexity**: 5 | **Functions**: 13

- **Function**: `run` [complexity: 5] [cognitive: 4] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `get_project_root` [complexity: 5] [cognitive: 10] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `collect_examples` [complexity: 6] [cognitive: 7] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_compile_examples` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_clippy_examples` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_module_docs` [complexity: 5] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `has_module_doc` [complexity: 6] [cognitive: 14] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_runnable` [complexity: 7] [cognitive: 13] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `has_main_function` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `run_example_with_timeout` [complexity: 8] [cognitive: 19] [big-o: O(n log n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_book_references` [complexity: 10] [cognitive: 16] [big-o: O(n log n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `find_markdown_files` [complexity: 3] [cognitive: 3] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_naming_conventions` [complexity: 5] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Struct**: `ValidationResults` [fields: 1]
- **Struct**: `StepResult` [fields: 4]
- **Impl**: `impl ValidationResults { fn new () -> Self { Self { steps : Vec :: new () } } fn add_step < F > (& mut self , number : usize , name : & str , f : F) where F : FnOnce () -> Result < () > , { print ! ("Step {}/6: {}... " , number , name) ; match f () { Ok (_) => { println ! ("{}" , "✓" . green ()) ; self . steps . push (StepResult { number , name : name . to_string () , success : true , error : None , }) ; } Err (e) => { println ! ("{}" , "✗" . red ()) ; eprintln ! ("  {}" , format ! ("{}" , e) . red ()) ; self . steps . push (StepResult { number , name : name . to_string () , success : false , error : Some (format ! ("{}" , e)) , }) ; } } } fn has_failures (& self) -> bool { self . steps . iter () . any (| s | ! s . success) } fn print_summary (& self) { println ! () ; println ! ("{}" , "═══════════════════════════════════" . bold ()) ; println ! ("{}" , "Summary" . bold ()) ; println ! ("{}" , "═══════════════════════════════════" . bold ()) ; let total = self . steps . len () ; let passed = self . steps . iter () . filter (| s | s . success) . count () ; let failed = total - passed ; for step in & self . steps { let status = if step . success { "✓" . green () } else { "✗" . red () } ; println ! ("{} Step {}: {}" , status , step . number , step . name) ; } println ! () ; println ! ("Total: {}, Passed: {}, Failed: {}" , total , format ! ("{}" , passed) . green () , if failed > 0 { format ! ("{}" , failed) . red () } else { format ! ("{}" , failed) . green () }) ; if failed == 0 { println ! () ; println ! ("{}" , "✅ All validation checks passed!" . green () . bold ()) ; } } } . self_ty`
- **Function**: `tests::test_has_module_doc_with_doc` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_module_doc_without_doc` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_module_doc_empty_file` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_main_function_present` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_main_function_absent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_main_function_with_result` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_snake_case_validation_valid` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_snake_case_validation_invalid` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_collect_examples_empty_dir` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_collect_examples_with_files` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_collect_examples_nonexistent_dir` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_find_markdown_files` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_validation_results_all_pass` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_validation_results_with_failure` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]