@@ -49,10 +49,10 @@ internal Tensor()
49
49
}
50
50
51
51
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
52
- internal Tensor ( T [ ] ? values , ReadOnlySpan < nint > lengths , bool isPinned = false , int memoryOffset = 0 ) : this ( values , lengths , Array . Empty < nint > ( ) , isPinned , memoryOffset ) { }
52
+ internal Tensor ( T [ ] ? values , ReadOnlySpan < nint > lengths , int memoryOffset , bool isPinned = false ) : this ( values , lengths , Array . Empty < nint > ( ) , memoryOffset , isPinned ) { }
53
53
54
54
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
55
- internal Tensor ( T [ ] ? values , ReadOnlySpan < nint > lengths , ReadOnlySpan < nint > strides , bool isPinned = false , int memoryOffset = 0 )
55
+ internal Tensor ( T [ ] ? values , ReadOnlySpan < nint > lengths , ReadOnlySpan < nint > strides , int memoryOffset , bool isPinned = false )
56
56
{
57
57
if ( values == null )
58
58
{
@@ -69,6 +69,9 @@ internal Tensor(T[]? values, ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> stri
69
69
_lengths = lengths . IsEmpty ? [ values . Length ] : lengths . ToArray ( ) ;
70
70
_memoryOffset = memoryOffset ;
71
71
72
+ if ( _memoryOffset < 0 || ( _memoryOffset >= values . Length && values . Length != 0 ) )
73
+ ThrowHelper . ThrowIndexOutOfRangeException ( ) ;
74
+
72
75
_flattenedLength = TensorSpanHelpers . CalculateTotalLength ( _lengths ) ;
73
76
_strides = strides . IsEmpty ? TensorSpanHelpers . CalculateStrides ( _lengths , _flattenedLength ) : strides . ToArray ( ) ;
74
77
TensorSpanHelpers . ValidateStrides ( _strides , _lengths ) ;
@@ -77,12 +80,12 @@ internal Tensor(T[]? values, ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> stri
77
80
if ( Environment . Is64BitProcess )
78
81
{
79
82
// See comment in Span<T>.Slice for how this works.
80
- if ( ( ulong ) ( uint ) maxElements >= ( ulong ) ( uint ) values . Length && values . Length != 0 )
83
+ if ( ( ulong ) ( uint ) maxElements >= ( ulong ) ( uint ) ( values . Length - memoryOffset ) && values . Length != 0 )
81
84
ThrowHelper . ThrowArgument_InvalidStridesAndLengths ( ) ;
82
85
}
83
86
else
84
87
{
85
- if ( ( ( uint ) maxElements >= ( uint ) ( values . Length ) ) && values . Length != 0 )
88
+ if ( ( ( uint ) maxElements >= ( uint ) ( values . Length - memoryOffset ) ) && values . Length != 0 )
86
89
ThrowHelper . ThrowArgument_InvalidStridesAndLengths ( ) ;
87
90
}
88
91
@@ -99,7 +102,7 @@ static Tensor<T> ITensor<Tensor<T>, T>.Create(scoped ReadOnlySpan<nint> lengths,
99
102
{
100
103
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
101
104
T [ ] values = pinned ? GC . AllocateArray < T > ( ( int ) linearLength , pinned ) : ( new T [ linearLength ] ) ;
102
- return new Tensor < T > ( values , lengths . ToArray ( ) , pinned ) ;
105
+ return new Tensor < T > ( values , lengths . ToArray ( ) , memoryOffset : 0 , pinned ) ;
103
106
}
104
107
105
108
/// <summary>
@@ -112,7 +115,7 @@ static Tensor<T> ITensor<Tensor<T>, T>.Create(scoped ReadOnlySpan<nint> lengths,
112
115
{
113
116
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
114
117
T [ ] values = pinned ? GC . AllocateArray < T > ( ( int ) linearLength , pinned ) : ( new T [ linearLength ] ) ;
115
- return new Tensor < T > ( values , lengths . ToArray ( ) , strides . ToArray ( ) , pinned ) ;
118
+ return new Tensor < T > ( values , lengths . ToArray ( ) , strides . ToArray ( ) , memoryOffset : 0 , pinned ) ;
116
119
}
117
120
118
121
/// <summary>
@@ -124,7 +127,7 @@ static Tensor<T> ITensor<Tensor<T>, T>.CreateUninitialized(scoped ReadOnlySpan<n
124
127
{
125
128
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
126
129
T [ ] values = GC . AllocateUninitializedArray < T > ( ( int ) linearLength , pinned ) ;
127
- return new Tensor < T > ( values , lengths . ToArray ( ) , pinned ) ;
130
+ return new Tensor < T > ( values , lengths . ToArray ( ) , memoryOffset : 0 , pinned ) ;
128
131
}
129
132
130
133
/// <summary>
@@ -137,7 +140,7 @@ static Tensor<T> ITensor<Tensor<T>, T>.CreateUninitialized(scoped ReadOnlySpan<n
137
140
{
138
141
nint linearLength = TensorSpanHelpers . CalculateTotalLength ( lengths ) ;
139
142
T [ ] values = GC . AllocateUninitializedArray < T > ( ( int ) linearLength , pinned ) ;
140
- return new Tensor < T > ( values , lengths . ToArray ( ) , strides . ToArray ( ) , pinned ) ;
143
+ return new Tensor < T > ( values , lengths . ToArray ( ) , strides . ToArray ( ) , memoryOffset : 0 , pinned ) ;
141
144
}
142
145
143
146
// ITensor
@@ -374,24 +377,24 @@ public Tensor<T> this[Tensor<bool> filter]
374
377
}
375
378
}
376
379
377
- return new Tensor < T > ( values , [ linearLength ] , _isPinned ) ;
380
+ return new Tensor < T > ( values , [ linearLength ] , _memoryOffset , _isPinned ) ;
378
381
}
379
382
}
380
383
381
384
/// <summary>
382
385
/// Defines an implicit conversion of an array to a <see cref="Tensor{T}"/>.
383
386
/// </summary>
384
- public static implicit operator Tensor < T > ( T [ ] array ) => new Tensor < T > ( array , [ array . Length ] ) ;
387
+ public static implicit operator Tensor < T > ( T [ ] array ) => new Tensor < T > ( array , [ array . Length ] , memoryOffset : 0 ) ;
385
388
386
389
/// <summary>
387
390
/// Defines an implicit conversion of a <see cref="Tensor{T}"/> to a <see cref="TensorSpan{T}"/>.
388
391
/// </summary>
389
- public static implicit operator TensorSpan < T > ( Tensor < T > value ) => new TensorSpan < T > ( ref MemoryMarshal . GetArrayDataReference ( value . _values ) , value . _lengths , value . _strides , value . _flattenedLength ) ;
392
+ public static implicit operator TensorSpan < T > ( Tensor < T > value ) => value . AsTensorSpan ( ) ;
390
393
391
394
/// <summary>
392
395
/// Defines an implicit conversion of a <see cref="Tensor{T}"/> to a <see cref="TensorSpan{T}"/>.
393
396
/// </summary>
394
- public static implicit operator ReadOnlyTensorSpan < T > ( Tensor < T > value ) => new ReadOnlyTensorSpan < T > ( ref MemoryMarshal . GetArrayDataReference ( value . _values ) , value . _lengths , value . _strides , value . FlattenedLength ) ;
397
+ public static implicit operator ReadOnlyTensorSpan < T > ( Tensor < T > value ) => value . AsReadOnlyTensorSpan ( ) ;
395
398
396
399
/// <summary>
397
400
/// Converts this <see cref="Tensor{T}"/> to a <see cref="TensorSpan{T}"/> pointing to the same backing memory."/>
@@ -411,7 +414,7 @@ public Tensor<T> this[Tensor<bool> filter]
411
414
/// </summary>
412
415
/// <param name="start">The start location you want in the <see cref="TensorSpan{T}"/>.</param>
413
416
/// <returns><see cref="TensorSpan{T}"/> based on the provided ranges.</returns>
414
- public TensorSpan < T > AsTensorSpan ( params scoped ReadOnlySpan < nint > start ) => Slice ( start ) ;
417
+ public TensorSpan < T > AsTensorSpan ( params scoped ReadOnlySpan < nint > start ) => AsTensorSpan ( ) . Slice ( start ) ;
415
418
416
419
/// <summary>
417
420
/// Converts this <see cref="Tensor{T}"/> to a <see cref="TensorSpan{T}"/> pointing to the same backing memory based on the provided start indexes."/>
@@ -424,7 +427,7 @@ public Tensor<T> this[Tensor<bool> filter]
424
427
/// Converts this <see cref="Tensor{T}"/> to a <see cref="ReadOnlyTensorSpan{T}"/> pointing to the same backing memory."/>
425
428
/// </summary>
426
429
/// <returns><see cref="ReadOnlyTensorSpan{T}"/></returns>
427
- public ReadOnlyTensorSpan < T > AsReadOnlyTensorSpan ( ) => new ReadOnlyTensorSpan < T > ( ref MemoryMarshal . GetArrayDataReference ( _values ) , _lengths , _strides , _flattenedLength ) ;
430
+ public ReadOnlyTensorSpan < T > AsReadOnlyTensorSpan ( ) => new ReadOnlyTensorSpan < T > ( ref Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( _values ) , _memoryOffset ) , _lengths , _strides , _flattenedLength ) ;
428
431
429
432
/// <summary>
430
433
/// Converts this <see cref="Tensor{T}"/> to a <see cref="ReadOnlyTensorSpan{T}"/> pointing to the same backing memory based on the provided ranges."/>
@@ -438,7 +441,7 @@ public Tensor<T> this[Tensor<bool> filter]
438
441
/// </summary>
439
442
/// <param name="start">The start locations you want in the <see cref="ReadOnlyTensorSpan{T}"/></param>
440
443
/// <returns></returns>
441
- public ReadOnlyTensorSpan < T > AsReadOnlyTensorSpan ( params scoped ReadOnlySpan < nint > start ) => Slice ( start ) ;
444
+ public ReadOnlyTensorSpan < T > AsReadOnlyTensorSpan ( params scoped ReadOnlySpan < nint > start ) => AsTensorSpan ( ) . Slice ( start ) ;
442
445
443
446
/// <summary>
444
447
/// Converts this <see cref="Tensor{T}"/> to a <see cref="ReadOnlyTensorSpan{T}"/> pointing to the same backing memory based on the provided start indexes."/>
@@ -515,7 +518,7 @@ public Tensor<T> Slice(params ReadOnlySpan<NRange> start)
515
518
if ( ( memoryOffset >= _values . Length || memoryOffset < 0 ) && flattenedLength != 0 )
516
519
ThrowHelper . ThrowIndexOutOfRangeException ( ) ;
517
520
518
- Tensor < T > toReturn = new Tensor < T > ( _values , lengths , Strides , _isPinned , memoryOffset ) ;
521
+ Tensor < T > toReturn = new Tensor < T > ( _values , lengths , Strides , memoryOffset , _isPinned ) ;
519
522
520
523
if ( offsetsArray != null )
521
524
ArrayPool < nint > . Shared . Return ( offsetsArray ) ;
0 commit comments