5
5
using Microsoft . ML . Runtime . Internal . CpuMath . Core ;
6
6
using System ;
7
7
8
- namespace Microsoft . ML . Runtime . FactorizationMachine
8
+ namespace Microsoft . ML . Runtime . Internal . CpuMath
9
9
{
10
10
using Float = System . Single ;
11
11
@@ -17,6 +17,7 @@ namespace Microsoft.ML.Runtime.FactorizationMachine
17
17
///
18
18
/// The ctor takes an alignment value, which must be a power of two at least sizeof(Float).
19
19
/// </summary>
20
+ [ BestFriend ]
20
21
internal sealed class AlignedArray
21
22
{
22
23
// Items includes "head" items filled with NaN, followed by _size entries, followed by "tail"
@@ -109,12 +110,102 @@ public Float this[int index]
109
110
}
110
111
}
111
112
113
+ public void CopyTo ( Span < Float > dst , int index , int count )
114
+ {
115
+ Contracts . Assert ( 0 <= count && count <= _size ) ;
116
+ Contracts . Assert ( dst != null ) ;
117
+ Contracts . Assert ( 0 <= index && index <= dst . Length - count ) ;
118
+ Items . AsSpan ( _base , count ) . CopyTo ( dst . Slice ( index ) ) ;
119
+ }
120
+
121
+ public void CopyTo ( int start , Span < Float > dst , int index , int count )
122
+ {
123
+ Contracts . Assert ( 0 <= count ) ;
124
+ Contracts . Assert ( 0 <= start && start <= _size - count ) ;
125
+ Contracts . Assert ( dst != null ) ;
126
+ Contracts . Assert ( 0 <= index && index <= dst . Length - count ) ;
127
+ Items . AsSpan ( start + _base , count ) . CopyTo ( dst . Slice ( index ) ) ;
128
+ }
129
+
130
+ public void CopyFrom ( ReadOnlySpan < Float > src )
131
+ {
132
+ Contracts . Assert ( src . Length <= _size ) ;
133
+ src . CopyTo ( Items . AsSpan ( _base ) ) ;
134
+ }
135
+
136
+ public void CopyFrom ( int start , ReadOnlySpan < Float > src )
137
+ {
138
+ Contracts . Assert ( 0 <= start && start <= _size - src . Length ) ;
139
+ src . CopyTo ( Items . AsSpan ( start + _base ) ) ;
140
+ }
141
+
142
+ // Copies values from a sparse vector.
143
+ // valuesSrc contains only the non-zero entries. Those are copied into their logical positions in the dense array.
144
+ // rgposSrc contains the logical positions + offset of the non-zero entries in the dense array.
145
+ // rgposSrc runs parallel to the valuesSrc array.
146
+ public void CopyFrom ( ReadOnlySpan < int > rgposSrc , ReadOnlySpan < Float > valuesSrc , int posMin , int iposMin , int iposLim , bool zeroItems )
147
+ {
148
+ Contracts . Assert ( rgposSrc != null ) ;
149
+ Contracts . Assert ( valuesSrc != null ) ;
150
+ Contracts . Assert ( rgposSrc . Length <= valuesSrc . Length ) ;
151
+ Contracts . Assert ( 0 <= iposMin && iposMin <= iposLim && iposLim <= rgposSrc . Length ) ;
152
+
153
+ // Zeroing-out and setting the values in one-pass does not seem to give any perf benefit.
154
+ // So explicitly zeroing and then setting the values.
155
+ if ( zeroItems )
156
+ ZeroItems ( ) ;
157
+
158
+ for ( int ipos = iposMin ; ipos < iposLim ; ++ ipos )
159
+ {
160
+ Contracts . Assert ( posMin <= rgposSrc [ ipos ] ) ;
161
+ int iv = _base + rgposSrc [ ipos ] - posMin ;
162
+ Contracts . Assert ( iv < _size + _base ) ;
163
+ Items [ iv ] = valuesSrc [ ipos ] ;
164
+ }
165
+ }
166
+
112
167
public void CopyFrom ( AlignedArray src )
113
168
{
114
169
Contracts . Assert ( src != null ) ;
115
170
Contracts . Assert ( src . _size == _size ) ;
116
171
Contracts . Assert ( src . _cbAlign == _cbAlign ) ;
117
172
Array . Copy ( src . Items , src . _base , Items , _base , _size ) ;
118
173
}
174
+
175
+ public void ZeroItems ( )
176
+ {
177
+ Array . Clear ( Items , _base , _size ) ;
178
+ }
179
+
180
+ public void ZeroItems ( int [ ] rgposSrc , int posMin , int iposMin , int iposLim )
181
+ {
182
+ Contracts . Assert ( rgposSrc != null ) ;
183
+ Contracts . Assert ( 0 <= iposMin && iposMin <= iposLim && iposLim <= rgposSrc . Length ) ;
184
+ Contracts . Assert ( iposLim - iposMin <= _size ) ;
185
+
186
+ int ivCur = 0 ;
187
+ for ( int ipos = iposMin ; ipos < iposLim ; ++ ipos )
188
+ {
189
+ int ivNextNonZero = rgposSrc [ ipos ] - posMin ;
190
+ Contracts . Assert ( ivCur <= ivNextNonZero && ivNextNonZero < _size ) ;
191
+ while ( ivCur < ivNextNonZero )
192
+ Items [ _base + ivCur ++ ] = 0 ;
193
+ Contracts . Assert ( ivCur == ivNextNonZero ) ;
194
+ // Skip the non-zero element at ivNextNonZero.
195
+ ivCur ++ ;
196
+ }
197
+
198
+ while ( ivCur < _size )
199
+ Items [ _base + ivCur ++ ] = 0 ;
200
+ }
201
+
202
+ // REVIEW: This is hackish and slightly dangerous. Perhaps we should wrap this in an
203
+ // IDisposable that "locks" this, prohibiting GetBase from being called, while the buffer
204
+ // is "checked out".
205
+ public void GetRawBuffer ( out Float [ ] items , out int offset )
206
+ {
207
+ items = Items ;
208
+ offset = _base ;
209
+ }
119
210
}
120
211
}
0 commit comments