Skip to content

Commit 7ba3876

Browse files
Fix the formatting of the tensor ToString functions (#118750)
* Fix the formatting of the tensor ToString functions * Fix the compat suppressions
1 parent a1d5e43 commit 7ba3876

File tree

9 files changed

+582
-88
lines changed

9 files changed

+582
-88
lines changed

src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ public void FlattenTo(scoped System.Span<T> destination) { }
206206
public System.Numerics.Tensors.ReadOnlyTensorSpan<T> Slice(params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges) { throw null; }
207207
public System.Numerics.Tensors.ReadOnlyTensorSpan<T> Slice(params scoped System.ReadOnlySpan<nint> startIndexes) { throw null; }
208208
public override string ToString() { throw null; }
209+
public string ToString(params scoped System.ReadOnlySpan<nint> maximumLengths) { throw null; }
209210
public bool TryCopyTo(scoped in System.Numerics.Tensors.TensorSpan<T> destination) { throw null; }
210211
public bool TryFlattenTo(scoped System.Span<T> destination) { throw null; }
211212
public bool TryGetSpan(scoped System.ReadOnlySpan<nint> startIndexes, int length, out System.ReadOnlySpan<T> span) { throw null; }
@@ -570,9 +571,6 @@ public static void ResizeTo<T>(scoped in System.Numerics.Tensors.Tensor<T> tenso
570571
public static ref readonly System.Numerics.Tensors.TensorSpan<T> TanPi<T>(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x, in System.Numerics.Tensors.TensorSpan<T> destination) where T : System.Numerics.ITrigonometricFunctions<T> { throw null; }
571572
public static System.Numerics.Tensors.Tensor<T> Tan<T>(in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x) where T : System.Numerics.ITrigonometricFunctions<T> { throw null; }
572573
public static ref readonly System.Numerics.Tensors.TensorSpan<T> Tan<T>(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x, in System.Numerics.Tensors.TensorSpan<T> destination) where T : System.Numerics.ITrigonometricFunctions<T> { throw null; }
573-
public static string ToString<T>(this in System.Numerics.Tensors.ReadOnlyTensorSpan<T> tensor, System.ReadOnlySpan<nint> maximumLengths) { throw null; }
574-
public static string ToString<T>(this in System.Numerics.Tensors.TensorSpan<T> tensor, System.ReadOnlySpan<nint> maximumLengths) { throw null; }
575-
public static string ToString<T>(this System.Numerics.Tensors.Tensor<T> tensor, System.ReadOnlySpan<nint> maximumLengths) { throw null; }
576574
public static System.Numerics.Tensors.Tensor<T> TrailingZeroCount<T>(in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x) where T : System.Numerics.IBinaryInteger<T> { throw null; }
577575
public static ref readonly System.Numerics.Tensors.TensorSpan<T> TrailingZeroCount<T>(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x, in System.Numerics.Tensors.TensorSpan<T> destination) where T : System.Numerics.IBinaryInteger<T> { throw null; }
578576
public static System.Numerics.Tensors.Tensor<T> Transpose<T>(System.Numerics.Tensors.Tensor<T> tensor) { throw null; }
@@ -1218,6 +1216,7 @@ public void FlattenTo(scoped System.Span<T> destination) { }
12181216
public System.Numerics.Tensors.TensorSpan<T> Slice(params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges) { throw null; }
12191217
public System.Numerics.Tensors.TensorSpan<T> Slice(params scoped System.ReadOnlySpan<nint> startIndexes) { throw null; }
12201218
public override string ToString() { throw null; }
1219+
public string ToString(params scoped System.ReadOnlySpan<nint> maximumLengths) { throw null; }
12211220
public bool TryCopyTo(scoped in System.Numerics.Tensors.TensorSpan<T> destination) { throw null; }
12221221
public bool TryFlattenTo(scoped System.Span<T> destination) { throw null; }
12231222
public bool TryGetSpan(scoped System.ReadOnlySpan<nint> startIndexes, int length, out System.Span<T> span) { throw null; }
@@ -1297,6 +1296,7 @@ void System.Numerics.Tensors.ITensor.Fill(object value) { }
12971296
static System.Numerics.Tensors.Tensor<T> System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>.CreateFromShapeUninitialized(scoped System.ReadOnlySpan<nint> lengths, bool pinned) { throw null; }
12981297
static System.Numerics.Tensors.Tensor<T> System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>.CreateFromShapeUninitialized(scoped System.ReadOnlySpan<nint> lengths, scoped System.ReadOnlySpan<nint> strides, bool pinned) { throw null; }
12991298
public System.Numerics.Tensors.Tensor<T> ToDenseTensor() { throw null; }
1299+
public override string ToString() { throw null; }
13001300
public string ToString(params scoped System.ReadOnlySpan<nint> maximumLengths) { throw null; }
13011301
public bool TryCopyTo(scoped in System.Numerics.Tensors.TensorSpan<T> destination) { throw null; }
13021302
public bool TryFlattenTo(scoped System.Span<T> destination) { throw null; }

src/libraries/System.Numerics.Tensors/src/CompatibilitySuppressions.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,27 @@
176176
<Right>lib/net8.0/System.Numerics.Tensors.dll</Right>
177177
<IsBaselineSuppression>true</IsBaselineSuppression>
178178
</Suppression>
179+
<Suppression>
180+
<DiagnosticId>CP0002</DiagnosticId>
181+
<Target>M:System.Numerics.Tensors.Tensor.ToString``1(System.Numerics.Tensors.ReadOnlyTensorSpan{``0}@,System.ReadOnlySpan{System.IntPtr})</Target>
182+
<Left>lib/net8.0/System.Numerics.Tensors.dll</Left>
183+
<Right>lib/net8.0/System.Numerics.Tensors.dll</Right>
184+
<IsBaselineSuppression>true</IsBaselineSuppression>
185+
</Suppression>
186+
<Suppression>
187+
<DiagnosticId>CP0002</DiagnosticId>
188+
<Target>M:System.Numerics.Tensors.Tensor.ToString``1(System.Numerics.Tensors.Tensor{``0},System.ReadOnlySpan{System.IntPtr})</Target>
189+
<Left>lib/net8.0/System.Numerics.Tensors.dll</Left>
190+
<Right>lib/net8.0/System.Numerics.Tensors.dll</Right>
191+
<IsBaselineSuppression>true</IsBaselineSuppression>
192+
</Suppression>
193+
<Suppression>
194+
<DiagnosticId>CP0002</DiagnosticId>
195+
<Target>M:System.Numerics.Tensors.Tensor.ToString``1(System.Numerics.Tensors.TensorSpan{``0}@,System.ReadOnlySpan{System.IntPtr})</Target>
196+
<Left>lib/net8.0/System.Numerics.Tensors.dll</Left>
197+
<Right>lib/net8.0/System.Numerics.Tensors.dll</Right>
198+
<IsBaselineSuppression>true</IsBaselineSuppression>
199+
</Suppression>
179200
<Suppression>
180201
<DiagnosticId>CP0002</DiagnosticId>
181202
<Target>M:System.Numerics.Tensors.Tensor`1.get_Item(System.Numerics.Tensors.Tensor{System.Boolean})</Target>
@@ -379,6 +400,27 @@
379400
<Right>lib/net9.0/System.Numerics.Tensors.dll</Right>
380401
<IsBaselineSuppression>true</IsBaselineSuppression>
381402
</Suppression>
403+
<Suppression>
404+
<DiagnosticId>CP0002</DiagnosticId>
405+
<Target>M:System.Numerics.Tensors.Tensor.ToString``1(System.Numerics.Tensors.ReadOnlyTensorSpan{``0}@,System.ReadOnlySpan{System.IntPtr})</Target>
406+
<Left>lib/net9.0/System.Numerics.Tensors.dll</Left>
407+
<Right>lib/net9.0/System.Numerics.Tensors.dll</Right>
408+
<IsBaselineSuppression>true</IsBaselineSuppression>
409+
</Suppression>
410+
<Suppression>
411+
<DiagnosticId>CP0002</DiagnosticId>
412+
<Target>M:System.Numerics.Tensors.Tensor.ToString``1(System.Numerics.Tensors.Tensor{``0},System.ReadOnlySpan{System.IntPtr})</Target>
413+
<Left>lib/net9.0/System.Numerics.Tensors.dll</Left>
414+
<Right>lib/net9.0/System.Numerics.Tensors.dll</Right>
415+
<IsBaselineSuppression>true</IsBaselineSuppression>
416+
</Suppression>
417+
<Suppression>
418+
<DiagnosticId>CP0002</DiagnosticId>
419+
<Target>M:System.Numerics.Tensors.Tensor.ToString``1(System.Numerics.Tensors.TensorSpan{``0}@,System.ReadOnlySpan{System.IntPtr})</Target>
420+
<Left>lib/net9.0/System.Numerics.Tensors.dll</Left>
421+
<Right>lib/net9.0/System.Numerics.Tensors.dll</Right>
422+
<IsBaselineSuppression>true</IsBaselineSuppression>
423+
</Suppression>
382424
<Suppression>
383425
<DiagnosticId>CP0002</DiagnosticId>
384426
<Target>M:System.Numerics.Tensors.Tensor`1.get_Item(System.Numerics.Tensors.Tensor{System.Boolean})</Target>

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan_1.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,20 @@ ref Unsafe.Add(ref _reference, linearOffset),
432432
);
433433
}
434434

435-
/// <summary>Returns the string representation of the tensor span.</summary>
436-
/// <returns>The string representation of the tensor span.</returns>
437-
public override string ToString() => $"System.Numerics.Tensors.ReadOnlyTensorSpan<{typeof(T).Name}>[{_shape}]";
435+
/// <summary>Returns the string representation of the tensor.</summary>
436+
/// <returns>The string representation of the tensor.</returns>
437+
/// <remarks>This API only lists the shape of the tensor, it does not include the contents.</remarks>
438+
public override string ToString() => ToString([]);
439+
440+
/// <summary>Creates a <see cref="string"/> representation of the tensor.</summary>
441+
/// <param name="maximumLengths">The maximum number of elements to print for each dimension of the tensor.</param>
442+
/// <returns>A <see cref="string"/> representation of the tensor.</returns>
443+
/// <exception cref="ArgumentOutOfRangeException"><paramref name="maximumLengths" /> is not empty and does not contain <see cref="Rank" /> elements.</exception>
444+
/// <remarks>
445+
/// <para>No contents will be printed if <paramref name="maximumLengths" /> is empty.</para>
446+
/// <para>If a given dimension contains more elements then the corresponding limit specified by <paramref name="maximumLengths" />, remaining elements will be represented by <c>..</c>.</para>
447+
/// </remarks>
448+
public string ToString(params scoped ReadOnlySpan<nint> maximumLengths) => Tensor.ToString(this, maximumLengths, "System.Numerics.Tensors.ReadOnlyTensorSpan");
438449

439450
/// <inheritdoc cref="IReadOnlyTensor{TSelf, T}.TryCopyTo(in TensorSpan{T})" />
440451
public bool TryCopyTo(scoped in TensorSpan<T> destination)

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs

Lines changed: 115 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,98 +2064,147 @@ public static ref readonly TensorSpan<T> StackAlongDimension<T>(scoped ReadOnlyS
20642064
#endregion
20652065

20662066
#region ToString
2067-
/// <summary>
2068-
/// Creates a <see cref="string"/> representation of the <see cref="TensorSpan{T}"/>."/>
2069-
/// </summary>
2070-
/// <param name="tensor">The <see cref="TensorSpan{T}"/> you want to represent as a string.</param>
2071-
/// <param name="maximumLengths">Maximum Length of each dimension</param>
2072-
/// <returns>A <see cref="string"/> representation of the <paramref name="tensor"/></returns>
2073-
public static string ToString<T>(this in TensorSpan<T> tensor, ReadOnlySpan<nint> maximumLengths)
2074-
=> tensor.AsReadOnlyTensorSpan().ToString(maximumLengths);
2075-
2076-
/// <summary>
2077-
/// Creates a <see cref="string"/> representation of the <see cref="ReadOnlyTensorSpan{T}"/>."/>
2078-
/// </summary>
2079-
/// <typeparam name="T"></typeparam>
2080-
/// <param name="tensor">The <see cref="ReadOnlyTensorSpan{T}"/> you want to represent as a string.</param>
2081-
/// <param name="maximumLengths">Maximum Length of each dimension</param>
2082-
public static string ToString<T>(this in ReadOnlyTensorSpan<T> tensor, ReadOnlySpan<nint> maximumLengths)
2067+
internal static string ToString<T>(in ReadOnlyTensorSpan<T> tensor, ReadOnlySpan<nint> maximumLengths, string typeName)
20832068
{
2084-
if (maximumLengths.Length != tensor.Rank)
2069+
if (!maximumLengths.IsEmpty)
20852070
{
2086-
ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(tensor));
2071+
ArgumentOutOfRangeException.ThrowIfNotEqual(maximumLengths.Length, tensor.Rank);
20872072
}
20882073

2089-
StringBuilder sb = new();
2090-
ToString(in tensor, maximumLengths, sb);
2091-
return sb.ToString();
2092-
}
2074+
var sb = new StringBuilder(typeName);
20932075

2094-
internal static void ToString<T>(in ReadOnlyTensorSpan<T> tensor, ReadOnlySpan<nint> maximumLengths, StringBuilder sb, int indentLevel = 0)
2095-
{
2096-
Debug.Assert(maximumLengths.Length != tensor.Rank);
2076+
sb.Append('<');
2077+
sb.Append(typeof(T).Name);
2078+
sb.Append('>');
20972079

2098-
sb.Append(' ', indentLevel * 2);
20992080
sb.Append('[');
2081+
sb.AppendJoin(", ", tensor.Lengths);
2082+
sb.Append(']');
21002083

2101-
if (tensor.Rank != 0)
2084+
if (!maximumLengths.IsEmpty)
21022085
{
2103-
nint length = nint.Max(tensor.Lengths[0], maximumLengths[0]);
2086+
sb.AppendLine(" {");
21042087

2105-
if (tensor.Rank != 1)
2088+
if (tensor.Rank == 1)
21062089
{
2107-
string separator = string.Empty;
2108-
2109-
for (nint i = 0; i < length; i++)
2110-
{
2111-
sb.AppendLine(separator);
2090+
nint length = nint.Min(tensor.Lengths[0], maximumLengths[0]);
2091+
ToString(tensor, length, sb, indentLevel: 1);
2092+
sb.AppendLine();
2093+
}
2094+
else
2095+
{
2096+
ToString(tensor, maximumLengths, sb);
2097+
}
21122098

2113-
TensorShape tmpShape = TensorShape.Create(tensor.Lengths[1..], tensor.Strides[1..], tensor.IsPinned);
2114-
ReadOnlyTensorSpan<T> tmpTensor = new ReadOnlyTensorSpan<T>(ref Unsafe.Add(ref tensor._reference, i * tensor.Strides[0]), tmpShape);
2115-
ToString(tmpTensor, maximumLengths[1..], sb, indentLevel + 1);
2099+
sb.Append('}');
2100+
}
2101+
return sb.ToString();
2102+
}
21162103

2117-
separator = ",";
2118-
}
2104+
private static void ToString<T>(in ReadOnlyTensorSpan<T> tensor, ReadOnlySpan<nint> maximumLengths, StringBuilder sb, int indentLevel = 0)
2105+
{
2106+
nint length = nint.Min(tensor.Lengths[0], maximumLengths[0]);
21192107

2120-
if (length != tensor.Lengths[0])
2121-
{
2122-
sb.AppendLine(separator);
2123-
sb.Append(' ', indentLevel * 2);
2124-
sb.AppendLine("...");
2125-
}
2108+
if (indentLevel != 0)
2109+
{
2110+
if (tensor.Rank != 1)
2111+
{
2112+
sb.Append(' ', indentLevel * 2);
2113+
sb.AppendLine("[");
21262114
}
21272115
else
21282116
{
2129-
string separator = " ";
2117+
ToString(tensor, length, sb, indentLevel);
2118+
return;
2119+
}
2120+
}
21302121

2131-
for (nint i = 0; i < length; i++)
2132-
{
2133-
sb.Append(separator);
2134-
sb.Append(Unsafe.Add(ref tensor._reference, i));
2135-
separator = ", ";
2136-
}
2122+
if (length != 0)
2123+
{
2124+
TensorShape tmpShape = TensorShape.Create(tensor.Lengths[1..], tensor.Strides[1..], tensor.IsPinned);
21372125

2138-
if (length != tensor.Lengths[0])
2139-
{
2140-
sb.Append(separator);
2141-
sb.Append("...");
2142-
}
2126+
ReadOnlyTensorSpan<T> tmpTensor = new ReadOnlyTensorSpan<T>(ref tensor._reference, tmpShape);
2127+
ToString(tmpTensor, maximumLengths[1..], sb, indentLevel + 1);
21432128

2144-
sb.Append(separator);
2129+
for (nint i = 1; i < length; i++)
2130+
{
2131+
sb.AppendLine(",");
2132+
tmpTensor = new ReadOnlyTensorSpan<T>(ref Unsafe.Add(ref tensor._reference, i * tensor.Strides[0]), tmpShape);
2133+
ToString(tmpTensor, maximumLengths[1..], sb, indentLevel + 1);
21452134
}
2135+
2136+
if (length != tensor.Lengths[0])
2137+
{
2138+
sb.AppendLine(",");
2139+
sb.Append(' ', (indentLevel + 1) * 2);
2140+
sb.Append("..");
2141+
}
2142+
sb.AppendLine();
21462143
}
2144+
else
2145+
{
2146+
sb.Append(' ', (indentLevel + 1) * 2);
2147+
sb.AppendLine("..");
2148+
}
2149+
sb.Append(' ', indentLevel * 2);
2150+
2151+
if (indentLevel != 0)
2152+
{
2153+
sb.Append(']');
2154+
}
2155+
}
2156+
2157+
private static void ToString<T>(in ReadOnlyTensorSpan<T> tensor, nint length, StringBuilder sb, int indentLevel)
2158+
{
2159+
sb.Append(' ', indentLevel * 2);
2160+
sb.Append('[');
2161+
2162+
if (length != 0)
2163+
{
2164+
sb.Append(tensor._reference);
2165+
2166+
for (nint i = 1; i < length; i++)
2167+
{
2168+
sb.Append(", ");
2169+
sb.Append(Unsafe.Add(ref tensor._reference, i));
2170+
}
2171+
2172+
if (length != tensor.Lengths[0])
2173+
{
2174+
sb.Append(", ..");
2175+
}
2176+
}
2177+
else
2178+
{
2179+
sb.Append("..");
2180+
}
2181+
21472182
sb.Append(']');
21482183
}
21492184

2150-
/// <summary>
2151-
/// Creates a <see cref="string"/> representation of the <see cref="Tensor{T}"/>."/>
2152-
/// </summary>
2153-
/// <param name="tensor">The <see cref="Span{T}"/> you want to represent as a string.</param>
2154-
/// <param name="maximumLengths">Maximum Length of each dimension</param>
2155-
/// <returns>A <see cref="string"/> representation of the <paramref name="tensor"/></returns>
2156-
public static string ToString<T>(this Tensor<T> tensor, ReadOnlySpan<nint> maximumLengths)
2157-
=> tensor.AsReadOnlyTensorSpan().ToString(maximumLengths);
2185+
private static StringBuilder AppendJoin<T>(this StringBuilder sb, string separator, ReadOnlySpan<T> values)
2186+
{
2187+
if (values.IsEmpty)
2188+
{
2189+
return sb;
2190+
}
21582191

2192+
if (values[0] is not null)
2193+
{
2194+
sb.Append(values[0]);
2195+
}
2196+
2197+
for (int i = 1; i < values.Length; i++)
2198+
{
2199+
sb.Append(separator);
2200+
2201+
if (values[i] is not null)
2202+
{
2203+
sb.Append(values[i]);
2204+
}
2205+
}
2206+
return sb;
2207+
}
21592208
#endregion
21602209

21612210
#region Transpose

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan_1.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,11 @@ ref Unsafe.Add(ref _reference, linearOffset),
328328
);
329329
}
330330

331-
/// <inheritdoc cref="ReadOnlyTensorSpan{T}.ToString" />
332-
public override string ToString() => $"System.Numerics.Tensors.TensorSpan<{typeof(T).Name}>[{_shape}]";
331+
/// <inheritdoc cref="ReadOnlyTensorSpan{T}.ToString()" />
332+
public override string ToString() => ToString([]);
333+
334+
/// <inheritdoc cref="ReadOnlyTensorSpan{T}.ToString(ReadOnlySpan{nint})" />
335+
public string ToString(params scoped ReadOnlySpan<nint> maximumLengths) => Tensor.ToString(AsReadOnlyTensorSpan(), maximumLengths, "System.Numerics.Tensors.TensorSpan");
333336

334337
/// <inheritdoc cref="IReadOnlyTensor{TSelf, T}.TryCopyTo(in TensorSpan{T})" />
335338
public bool TryCopyTo(scoped in TensorSpan<T> destination) => AsReadOnlyTensorSpan().TryCopyTo(destination);

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor_1.cs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -288,21 +288,11 @@ public Tensor<T> ToDenseTensor()
288288
/// <inheritdoc cref="IReadOnlyTensor{TSelf, T}.TryGetSpan(ReadOnlySpan{NIndex}, int, out ReadOnlySpan{T})" />
289289
public bool TryGetSpan(scoped ReadOnlySpan<NIndex> startIndexes, int length, out ReadOnlySpan<T> span) => AsReadOnlyTensorSpan().TryGetSpan(startIndexes, length, out span);
290290

291-
/// <summary>
292-
/// Creates a <see cref="string"/> representation of the <see cref="TensorSpan{T}"/>."/>
293-
/// </summary>
294-
/// <param name="maximumLengths">Maximum Length of each dimension</param>
295-
/// <returns>A <see cref="string"/> representation of the <see cref="Tensor{T}"/></returns>
296-
public string ToString(params ReadOnlySpan<nint> maximumLengths)
297-
{
298-
var sb = new StringBuilder($"System.Numerics.Tensors.Tensor<{typeof(T).Name}>[{_shape}]");
299-
300-
sb.AppendLine("{");
301-
Tensor.ToString(AsReadOnlyTensorSpan(), maximumLengths, sb);
302-
sb.AppendLine("}");
291+
/// <inheritdoc cref="ReadOnlyTensorSpan{T}.ToString()" />
292+
public override string ToString() => ToString([]);
303293

304-
return sb.ToString();
305-
}
294+
/// <inheritdoc cref="ReadOnlyTensorSpan{T}.ToString(ReadOnlySpan{nint})" />
295+
public string ToString(params scoped ReadOnlySpan<nint> maximumLengths) => Tensor.ToString(AsReadOnlyTensorSpan(), maximumLengths, "System.Numerics.Tensors.Tensor");
306296

307297
//
308298
// IEnumerable

0 commit comments

Comments
 (0)