1+ using System ;
2+ using System . Numerics . Tensors ;
3+
4+ namespace LLama . Extensions ;
5+
6+ /// <summary>
7+ /// Extensions to span which apply <b>in-place</b> normalization
8+ /// </summary>
9+ public static class SpanNormalizationExtensions
10+ {
11+ /// <summary>
12+ /// <b>In-place</b> multiple every element by 32760 and divide every element in the span by the max absolute value in the span
13+ /// </summary>
14+ /// <param name="vector"></param>
15+ /// <returns>The same array</returns>
16+ public static float [ ] MaxAbsoluteNormalization ( this float [ ] vector )
17+ {
18+ vector . AsSpan ( ) . MaxAbsoluteNormalization ( ) ;
19+ return vector ;
20+ }
21+
22+ /// <summary>
23+ /// <b>In-place</b> multiple every element by 32760 and divide every element in the span by the max absolute value in the span
24+ /// </summary>
25+ /// <param name="vector"></param>
26+ /// <returns>The same span</returns>
27+ public static Span < float > MaxAbsoluteNormalization ( this Span < float > vector )
28+ {
29+ var factor = 32760 / TensorPrimitives . MaxMagnitude ( vector ) ;
30+ TensorPrimitives . Multiply ( vector , factor , vector ) ;
31+ return vector ;
32+ }
33+
34+ /// <summary>
35+ /// <b>In-place</b> divide every element in the array by the sum of absolute values in the array
36+ /// </summary>
37+ /// <remarks>Also known as "Manhattan normalization".</remarks>
38+ /// <param name="vector"></param>
39+ /// <returns>The same array</returns>
40+ public static float [ ] TaxicabNormalization ( this float [ ] vector )
41+ {
42+ vector . AsSpan ( ) . TaxicabNormalization ( ) ;
43+ return vector ;
44+ }
45+
46+ /// <summary>
47+ /// <b>In-place</b> divide every element in the span by the sum of absolute values in the span
48+ /// </summary>
49+ /// <remarks>Also known as "Manhattan normalization".</remarks>
50+ /// <param name="vector"></param>
51+ /// <returns>The same span</returns>
52+ public static Span < float > TaxicabNormalization ( this Span < float > vector )
53+ {
54+ var sumAbs = TensorPrimitives . SumOfMagnitudes ( vector ) ;
55+ TensorPrimitives . Divide ( vector , sumAbs , vector ) ;
56+ return vector ;
57+ }
58+
59+ /// <summary>
60+ /// <b>In-place</b> divide every element by the euclidean length of the vector
61+ /// </summary>
62+ /// <remarks>Also known as "L2 normalization".</remarks>
63+ /// <param name="vector"></param>
64+ /// <returns>The same array</returns>
65+ public static float [ ] EuclideanNormalization ( this float [ ] vector )
66+ {
67+ vector . AsSpan ( ) . EuclideanNormalization ( ) ;
68+ return vector ;
69+ }
70+
71+ /// <summary>
72+ /// <b>In-place</b> divide every element by the euclidean length of the vector
73+ /// </summary>
74+ /// <remarks>Also known as "L2 normalization".</remarks>
75+ /// <param name="vector"></param>
76+ /// <returns>The same span</returns>
77+ public static Span < float > EuclideanNormalization ( this Span < float > vector )
78+ {
79+ var norm = TensorPrimitives . Norm ( vector ) ;
80+ TensorPrimitives . Divide ( vector , norm , vector ) ;
81+ return vector ;
82+ }
83+
84+ /// <summary>
85+ /// <b>In-place</b> apply p-normalization. https://en.wikipedia.org/wiki/Norm_(mathematics)#p-norm
86+ /// <list type="bullet">
87+ /// <item>For p = 1, this is taxicab normalization</item>
88+ /// <item>For p = 2, this is euclidean normalization</item>
89+ /// <item>As p => infinity, this approaches infinity norm or maximum norm</item>
90+ /// </list>
91+ /// </summary>
92+ /// <param name="vector"></param>
93+ /// <param name="p"></param>
94+ /// <returns>The same array</returns>
95+ public static float [ ] PNormalization ( this float [ ] vector , int p )
96+ {
97+ vector . AsSpan ( ) . PNormalization ( p ) ;
98+ return vector ;
99+ }
100+
101+ /// <summary>
102+ /// <b>In-place</b> apply p-normalization. https://en.wikipedia.org/wiki/Norm_(mathematics)#p-norm
103+ /// <list type="bullet">
104+ /// <item>For p = 1, this is taxicab normalization</item>
105+ /// <item>For p = 2, this is euclidean normalization</item>
106+ /// <item>As p => infinity, this approaches infinity norm or maximum norm</item>
107+ /// </list>
108+ /// </summary>
109+ /// <param name="vector"></param>
110+ /// <param name="p"></param>
111+ /// <returns>The same span</returns>
112+ public static Span < float > PNormalization ( this Span < float > vector , int p )
113+ {
114+ if ( p == 2 )
115+ return vector . EuclideanNormalization ( ) ;
116+
117+ var sum = 0.0 ;
118+ for ( var i = 0 ; i < vector . Length ; i ++ )
119+ sum += MathF . Pow ( vector [ i ] , p ) ;
120+ var divisor = ( float ) Math . Pow ( sum , 1.0 / p ) ;
121+
122+ TensorPrimitives . Divide ( vector , divisor , vector ) ;
123+
124+ return vector ;
125+ }
126+ }
0 commit comments