7
7
using System . Linq ;
8
8
using System . Runtime . CompilerServices ;
9
9
using System . Runtime . InteropServices ;
10
- using System . Runtime . InteropServices . Marshalling ;
11
- using System . Runtime . Versioning ;
12
- using System . Text ;
10
+ using static System . Runtime . InteropServices . JavaScript . JSType ;
13
11
using EditorBrowsableAttribute = System . ComponentModel . EditorBrowsableAttribute ;
14
12
using EditorBrowsableState = System . ComponentModel . EditorBrowsableState ;
15
13
@@ -43,7 +41,7 @@ public readonly ref struct ReadOnlyTensorSpan<T>
43
41
/// <param name="array">The target array.</param>
44
42
/// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
45
43
/// <exception cref="ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
46
- public ReadOnlyTensorSpan ( T [ ] ? array ) : this ( array , 0 , [ ] , [ ] )
44
+ public ReadOnlyTensorSpan ( T [ ] ? array ) : this ( array , 0 , [ array ? . Length ?? 0 ] , [ ] )
47
45
{
48
46
}
49
47
@@ -81,6 +79,9 @@ public ReadOnlyTensorSpan(T[]? array, Index startIndex, scoped ReadOnlySpan<nint
81
79
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
82
80
public ReadOnlyTensorSpan ( T [ ] ? array , int start , scoped ReadOnlySpan < nint > lengths , scoped ReadOnlySpan < nint > strides )
83
81
{
82
+ if ( lengths . IsEmpty && array != null )
83
+ lengths = [ array . Length ] ;
84
+
84
85
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
85
86
if ( array == null )
86
87
{
@@ -92,18 +93,20 @@ public ReadOnlyTensorSpan(T[]? array, int start, scoped ReadOnlySpan<nint> lengt
92
93
if ( ! typeof ( T ) . IsValueType && array . GetType ( ) != typeof ( T [ ] ) )
93
94
ThrowHelper . ThrowArrayTypeMismatchException ( ) ;
94
95
95
- strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths ) : strides ;
96
- nint maxElements = TensorSpanHelpers . ComputeMaxElementCount ( strides , lengths ) ;
96
+ strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths , linearLength ) : strides ;
97
+ TensorSpanHelpers . ValidateStrides ( strides , lengths ) ;
98
+ nint maxElements = TensorSpanHelpers . ComputeMaxLinearIndex ( strides , lengths ) ;
99
+
97
100
if ( Environment . Is64BitProcess )
98
101
{
99
102
// See comment in Span<T>.Slice for how this works.
100
- if ( ( ulong ) ( uint ) start + ( ulong ) ( uint ) maxElements > ( ulong ) ( uint ) array . Length )
101
- ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
103
+ if ( ( ulong ) ( uint ) start + ( ulong ) ( uint ) maxElements >= ( ulong ) ( uint ) array . Length && array . Length != 0 )
104
+ ThrowHelper . ThrowArgument_InvalidStridesAndLengths ( ) ;
102
105
}
103
106
else
104
107
{
105
- if ( ( uint ) start > ( uint ) array . Length || ( uint ) maxElements > ( uint ) ( array . Length - start ) )
106
- ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
108
+ if ( ( ( uint ) start > ( uint ) array . Length || ( uint ) maxElements >= ( uint ) ( array . Length - start ) ) && array . Length != 0 )
109
+ ThrowHelper . ThrowArgument_InvalidStridesAndLengths ( ) ;
107
110
}
108
111
109
112
_flattenedLength = linearLength ;
@@ -115,8 +118,8 @@ public ReadOnlyTensorSpan(T[]? array, int start, scoped ReadOnlySpan<nint> lengt
115
118
}
116
119
117
120
/// <summary>
118
- /// Creates a new <see cref="ReadOnlyTensorSpan{T}"/> over the provided <see cref="Span {T}"/>. The new <see cref="ReadOnlyTensorSpan{T}"/> will
119
- /// have a rank of 1 and a length equal to the length of the provided <see cref="Span {T}"/>.
121
+ /// Creates a new <see cref="ReadOnlyTensorSpan{T}"/> over the provided <see cref="ReadOnlySpan {T}"/>. The new <see cref="ReadOnlyTensorSpan{T}"/> will
122
+ /// have a rank of 1 and a length equal to the length of the provided <see cref="ReadOnlySpan {T}"/>.
120
123
/// </summary>
121
124
/// <param name="span">The target span.</param>
122
125
public ReadOnlyTensorSpan ( ReadOnlySpan < T > span ) : this ( span , [ span . Length ] , [ ] ) { }
@@ -130,18 +133,15 @@ public ReadOnlyTensorSpan(ReadOnlySpan<T> span) : this(span, [span.Length], [])
130
133
/// <param name="strides">The strides for each dimension. Will be automatically calculated if not provided.</param>
131
134
public ReadOnlyTensorSpan ( ReadOnlySpan < T > span , scoped ReadOnlySpan < nint > lengths , scoped ReadOnlySpan < nint > strides )
132
135
{
136
+ if ( lengths . IsEmpty )
137
+ lengths = [ span . Length ] ;
138
+
133
139
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
134
- if ( span . IsEmpty )
135
- {
136
- if ( linearLength != 0 )
137
- ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
138
- this = default ;
139
- return ; // returns default
140
- }
141
140
142
- strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths ) : strides ;
143
- nint maxElements = TensorSpanHelpers . ComputeMaxElementCount ( strides , lengths ) ;
144
- if ( maxElements >= span . Length )
141
+ strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths , linearLength ) : strides ;
142
+ TensorSpanHelpers . ValidateStrides ( strides , lengths ) ;
143
+ nint maxElements = TensorSpanHelpers . ComputeMaxLinearIndex ( strides , lengths ) ;
144
+ if ( maxElements >= span . Length && span . Length != 0 )
145
145
ThrowHelper . ThrowArgument_InvalidStridesAndLengths ( ) ;
146
146
147
147
_flattenedLength = linearLength ;
@@ -157,7 +157,7 @@ public ReadOnlyTensorSpan(ReadOnlySpan<T> span, scoped ReadOnlySpan<nint> length
157
157
/// have a rank of 1 and a length equal to the length of the provided <see cref="Array"/>.
158
158
/// </summary>
159
159
/// <param name="array">The target array.</param>
160
- public ReadOnlyTensorSpan ( Array ? array ) : this ( array , ReadOnlySpan < int > . Empty , [ ] , [ ] ) { }
160
+ public ReadOnlyTensorSpan ( Array ? array ) : this ( array , ReadOnlySpan < int > . Empty , array == null ? [ 0 ] : ( from dim in Enumerable . Range ( 0 , array . Rank ) select ( nint ) array . GetLength ( dim ) ) . ToArray ( ) , [ ] ) { }
161
161
162
162
/// <summary>
163
163
/// Creates a new <see cref="ReadOnlyTensorSpan{T}"/> over the provided <see cref="Array"/> using the specified start offsets, lengths, and strides.
@@ -169,9 +169,10 @@ public ReadOnlyTensorSpan(Array? array) : this(array, ReadOnlySpan<int>.Empty, [
169
169
/// <param name="strides">The strides for each dimension. Will be automatically calculated if not provided.</param>
170
170
public ReadOnlyTensorSpan ( Array ? array , scoped ReadOnlySpan < int > start , scoped ReadOnlySpan < nint > lengths , scoped ReadOnlySpan < nint > strides )
171
171
{
172
+ if ( lengths . IsEmpty && array != null )
173
+ lengths = ( from dim in Enumerable . Range ( 0 , array . Rank ) select ( nint ) array . GetLength ( dim ) ) . ToArray ( ) ;
174
+
172
175
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
173
- strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths ) : strides ;
174
- nint startOffset = TensorSpanHelpers . ComputeLinearIndex ( start , strides , lengths ) ;
175
176
if ( array == null )
176
177
{
177
178
if ( ! start . IsEmpty || linearLength != 0 )
@@ -182,16 +183,20 @@ public ReadOnlyTensorSpan(Array? array, scoped ReadOnlySpan<int> start, scoped R
182
183
if ( ! typeof ( T ) . IsValueType && array . GetType ( ) != typeof ( T [ ] ) )
183
184
ThrowHelper . ThrowArrayTypeMismatchException ( ) ;
184
185
185
- nint maxElements = TensorSpanHelpers . ComputeMaxElementCount ( strides , lengths ) ;
186
+ strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths , linearLength ) : strides ;
187
+ TensorSpanHelpers . ValidateStrides ( strides , lengths ) ;
188
+
189
+ nint startOffset = TensorSpanHelpers . ComputeStartOffsetSystemArray ( array , start ) ;
190
+ nint maxElements = TensorSpanHelpers . ComputeMaxLinearIndex ( strides , lengths ) ;
186
191
if ( Environment . Is64BitProcess )
187
192
{
188
193
// See comment in Span<T>.Slice for how this works.
189
- if ( ( ulong ) ( uint ) startOffset + ( ulong ) ( uint ) maxElements > ( ulong ) ( uint ) array . Length )
194
+ if ( ( ulong ) ( uint ) startOffset + ( ulong ) ( uint ) maxElements >= ( ulong ) ( uint ) array . Length && array . Length != 0 )
190
195
ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
191
196
}
192
197
else
193
198
{
194
- if ( ( uint ) startOffset > ( uint ) array . Length || ( uint ) maxElements > ( uint ) ( array . Length - startOffset ) )
199
+ if ( ( ( uint ) startOffset > ( uint ) array . Length || ( uint ) maxElements >= ( uint ) ( array . Length - startOffset ) ) && array . Length != 0 )
195
200
ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
196
201
}
197
202
@@ -213,9 +218,10 @@ public ReadOnlyTensorSpan(Array? array, scoped ReadOnlySpan<int> start, scoped R
213
218
/// <param name="strides">The strides for each dimension. Will be automatically calculated if not provided.</param>
214
219
public ReadOnlyTensorSpan ( Array ? array , scoped ReadOnlySpan < NIndex > startIndex , scoped ReadOnlySpan < nint > lengths , scoped ReadOnlySpan < nint > strides )
215
220
{
221
+ if ( lengths . IsEmpty && array != null )
222
+ lengths = ( from dim in Enumerable . Range ( 0 , array . Rank ) select ( nint ) array . GetLength ( dim ) ) . ToArray ( ) ;
223
+
216
224
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
217
- strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths ) : strides ;
218
- nint start = TensorSpanHelpers . ComputeLinearIndex ( startIndex , strides , lengths ) ;
219
225
if ( array == null )
220
226
{
221
227
if ( ! startIndex . IsEmpty || linearLength != 0 )
@@ -226,22 +232,26 @@ public ReadOnlyTensorSpan(Array? array, scoped ReadOnlySpan<NIndex> startIndex,
226
232
if ( ! typeof ( T ) . IsValueType && array . GetType ( ) != typeof ( T [ ] ) )
227
233
ThrowHelper . ThrowArrayTypeMismatchException ( ) ;
228
234
229
- nint maxElements = TensorSpanHelpers . ComputeMaxElementCount ( strides , lengths ) ;
235
+ strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths , linearLength ) : strides ;
236
+ TensorSpanHelpers . ValidateStrides ( strides , lengths ) ;
237
+
238
+ nint startOffset = TensorSpanHelpers . ComputeStartOffsetSystemArray ( array , startIndex ) ;
239
+ nint maxElements = TensorSpanHelpers . ComputeMaxLinearIndex ( strides , lengths ) ;
230
240
if ( Environment . Is64BitProcess )
231
241
{
232
242
// See comment in Span<T>.Slice for how this works.
233
- if ( ( ulong ) ( uint ) start + ( ulong ) ( uint ) maxElements > ( ulong ) ( uint ) array . Length )
243
+ if ( ( ulong ) ( uint ) startOffset + ( ulong ) ( uint ) maxElements > ( ulong ) ( uint ) array . Length )
234
244
ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
235
245
}
236
246
else
237
247
{
238
- if ( ( uint ) start > ( uint ) array . Length || ( uint ) maxElements > ( uint ) ( array . Length - start ) )
248
+ if ( ( uint ) startOffset > ( uint ) array . Length || ( uint ) maxElements >= ( uint ) ( array . Length - startOffset ) )
239
249
ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
240
250
}
241
251
242
252
_flattenedLength = linearLength ;
243
253
_memoryLength = array . Length ;
244
- _reference = ref Unsafe . Add ( ref Unsafe . As < byte , T > ( ref MemoryMarshal . GetArrayDataReference ( array ) ) , ( nint ) ( uint ) start /* force zero-extension */ ) ;
254
+ _reference = ref Unsafe . Add ( ref Unsafe . As < byte , T > ( ref MemoryMarshal . GetArrayDataReference ( array ) ) , ( nint ) ( uint ) startOffset /* force zero-extension */ ) ;
245
255
246
256
_lengths = lengths . ToArray ( ) ;
247
257
_strides = strides . ToArray ( ) ;
@@ -276,13 +286,21 @@ public unsafe ReadOnlyTensorSpan(T* data, nint dataLength) : this(data, dataLeng
276
286
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
277
287
public unsafe ReadOnlyTensorSpan ( T * data , nint dataLength , scoped ReadOnlySpan < nint > lengths , scoped ReadOnlySpan < nint > strides )
278
288
{
279
- nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
289
+ if ( dataLength < 0 )
290
+ ThrowHelper . ThrowArgumentOutOfRangeException ( ) ;
291
+
280
292
if ( RuntimeHelpers . IsReferenceOrContainsReferences < T > ( ) )
281
293
ThrowHelper . ThrowInvalidTypeWithPointersNotSupported ( typeof ( T ) ) ;
282
294
283
- strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths ) : strides ;
284
- nint maxElements = TensorSpanHelpers . ComputeMaxElementCount ( strides , lengths ) ;
285
- if ( maxElements >= dataLength )
295
+ if ( lengths . IsEmpty )
296
+ lengths = [ dataLength ] ;
297
+
298
+ nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
299
+
300
+ strides = strides . IsEmpty ? ( ReadOnlySpan < nint > ) TensorSpanHelpers . CalculateStrides ( lengths , linearLength ) : strides ;
301
+ TensorSpanHelpers . ValidateStrides ( strides , lengths ) ;
302
+ nint maxElements = TensorSpanHelpers . ComputeMaxLinearIndex ( strides , lengths ) ;
303
+ if ( maxElements >= dataLength && dataLength != 0 )
286
304
ThrowHelper . ThrowArgument_InvalidStridesAndLengths ( ) ;
287
305
288
306
_flattenedLength = linearLength ;
0 commit comments