This commit is contained in:
2026-06-12 23:34:00 +07:00
parent 790a5f8e10
commit d7e9bb7b5b
27 changed files with 1167 additions and 1020 deletions

View File

@@ -1254,15 +1254,6 @@ public readonly partial record struct {typeNameZ} : IMensuraUnit<{typeNameZ}>, I
public static class {typeNameZ}Extensions
{
internal static double Protected(this {typeNameZ}? unit) => unit is null ? 0d : unit.Value._Value;
internal static {typeNameZ} ProtectedU(this {typeNameZ}? unit) => unit is null ? {typeNameZ}.Zero : unit.Value;
internal static double ToDouble(this {typeNameB}? unit) => unit?._Value ?? 0d;
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeNameZ}> units,
double divisor, Span<{typeNameZ}> destination) => units.Div<{typeNameZ}>(divisor, destination);

View File

@@ -1073,14 +1073,6 @@ public readonly partial record struct {typeName} : IMensuraUnit<{typeName}>, IEq
public static class {typeName}Extensions
{
internal static double Protected(this {typeName}? unit) => unit is null ? 0d : unit.Value._Value;
internal static {typeName} ProtectedU(this {typeName}? unit) => unit is null ? {typeName}.Zero : unit.Value;
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeName}> units,
double divisor, Span<{typeName}> destination) => units.Div<{typeName}>(divisor, destination);

View File

@@ -2,7 +2,7 @@
namespace QWERTYkez.Mensura.Tests;
public class AggregateUnitExtensions
public class AggregateUnitExtensionsTest
{
// Вспомогательный метод для создания объекта Length.
// Если у вас используется фабричный метод (например, Length.FromMeters), замените код внутри.

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests;
public class CastExtensions
public class CastExtensionsTest
{
private const double NormalValue1 = 42.42;
private const double NormalValue2 = 100.05;

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests
{
public class CollectionsDivideExtensionsTests
public class CollectionsDivideExtensionsTest
{
private const double Tolerance = 1e-12;
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
@@ -31,7 +31,7 @@
var result = nullableUnitsArray.Div<Length>(scalarDouble);
Assert.Equal(3, result.Length);
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 / 2.0, (double)result[1]!, Tolerance);
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
}
@@ -52,7 +52,7 @@
var result = scalarDouble.Div<Length>(nullableUnitsArray);
Assert.Equal(3, result.Length);
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(2.0 / 0, (double)result[1]!, Tolerance);
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
}
@@ -73,7 +73,7 @@
var result = nullableUnitsList.Div<Length>(scalarDouble);
Assert.Equal(3, result.Count);
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 / 2.0, (double)result[1]!, Tolerance);
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
}
@@ -94,7 +94,7 @@
var result = scalarDouble.Div<Length>(nullableUnitsList);
Assert.Equal(3, result.Count);
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(2.0 / 0, (double)result[1]!, Tolerance);
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
}
@@ -115,7 +115,7 @@
Span<Length?> dest = new Length?[3];
((IReadOnlyCollection<Length?>)nullableUnitsArray).Div(scalarDouble, dest);
Assert.Equal(1000 / 2.0, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]);
Assert.Equal(0 / 2.0, (double)dest[1]!, Tolerance);
Assert.Equal(1 / 2.0, (double)dest[2]!, Tolerance);
}
@@ -136,7 +136,7 @@
Span<Length?> dest = new Length?[3];
scalarDouble.Div((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
Assert.Equal(2.0 / 1000, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]);
Assert.Equal(2.0 / 0, (double)dest[1]!, Tolerance);
Assert.Equal(2.0 / 1, (double)dest[2]!, Tolerance);
}
@@ -157,7 +157,7 @@
var result = ((IEnumerable<Length?>)nullableUnitsArray).Div<Length>(scalarDouble).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 / 2.0, (double)result[1]!, Tolerance);
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
}
@@ -178,7 +178,7 @@
var result = scalarDouble.Div<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(2.0 / 0, (double)result[1]!, Tolerance);
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
}
@@ -199,7 +199,7 @@
var result = nullableDoubleArray.Div(scalarUnit);
Assert.Equal(3, result.Length);
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 / 1000, (double)result[1]!, Tolerance);
Assert.Equal(3.0 / 1000, (double)result[2]!, Tolerance);
}
@@ -220,7 +220,7 @@
var result = scalarUnit.Div(nullableDoubleArray);
Assert.Equal(3, result.Length);
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 / 0.0, (double)result[1]!, Tolerance);
Assert.Equal(1000 / 3.0, (double)result[2]!, Tolerance);
}
@@ -243,7 +243,7 @@
var result = list.Div(scalarUnit);
Assert.Equal(3, result.Count);
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 / 1000, (double)result[1]!, Tolerance);
Assert.Equal(3.0 / 1000, (double)result[2]!, Tolerance);
}
@@ -266,7 +266,7 @@
var result = scalarUnit.Div(list);
Assert.Equal(3, result.Count);
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 / 0.0, (double)result[1]!, Tolerance);
Assert.Equal(1000 / 3.0, (double)result[2]!, Tolerance);
}

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests
{
public class CollectionsMinusExtensionsTests
public class CollectionsMinusExtensionsTest
{
private const double Tolerance = 1e-12;
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
@@ -44,7 +44,7 @@
var result = nullableUnitsArray.Minus<Length>(scalarDouble);
Assert.Equal(3, result.Length);
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
}
@@ -65,7 +65,7 @@
var result = scalarDouble.Minus<Length>(nullableUnitsArray);
Assert.Equal(3, result.Length);
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
}
@@ -86,7 +86,7 @@
var result = nullableUnitsList.Minus<Length>(scalarDouble);
Assert.Equal(3, result.Count);
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
}
@@ -107,7 +107,7 @@
var result = scalarDouble.Minus<Length>(nullableUnitsList);
Assert.Equal(3, result.Count);
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
}
@@ -128,7 +128,7 @@
Span<Length?> dest = new Length?[3];
((IReadOnlyCollection<Length?>)nullableUnitsArray).Minus<Length>(scalarDouble, dest);
Assert.Equal(1000 - 1000, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]);
Assert.Equal(0 - 1000, (double)dest[1]!, Tolerance);
Assert.Equal(1 - 1000, (double)dest[2]!, Tolerance);
}
@@ -149,7 +149,7 @@
Span<Length?> dest = new Length?[3];
scalarDouble.Minus<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
Assert.Equal(1000 - 1000, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]);
Assert.Equal(1000 - 0, (double)dest[1]!, Tolerance);
Assert.Equal(1000 - 1, (double)dest[2]!, Tolerance);
}
@@ -170,7 +170,7 @@
var result = ((IEnumerable<Length?>)nullableUnitsArray).Minus<Length>(scalarDouble).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
}
@@ -191,7 +191,7 @@
var result = scalarDouble.Minus<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
}
@@ -212,7 +212,7 @@
var result = nullableDoubleArray.Minus(scalarUnit);
Assert.Equal(3, result.Length);
Assert.Equal(500 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
Assert.Equal(200 - 1000, (double)result[2]!, Tolerance);
}
@@ -233,7 +233,7 @@
var result = scalarUnit.Minus(nullableDoubleArray);
Assert.Equal(3, result.Length);
Assert.Equal(1000 - 500, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 - 200, (double)result[2]!, Tolerance);
}
@@ -254,7 +254,7 @@
var result = nullableDoubleList.Minus(scalarUnit);
Assert.Equal(3, result.Count);
Assert.Equal(500 - 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
Assert.Equal(200 - 1000, (double)result[2]!, Tolerance);
}
@@ -275,7 +275,7 @@
var result = scalarUnit.Minus(nullableDoubleList);
Assert.Equal(3, result.Count);
Assert.Equal(1000 - 500, (double)result[0]!, Tolerance);
Assert.Null(result[1]);
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 - 200, (double)result[2]!, Tolerance);
}

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests
{
public class CollectionsMultiplyExtensionsTests
public class CollectionsMultiplyExtensionsTest
{
private const double Tolerance = 1e-12;
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
@@ -43,7 +43,7 @@
var result = nullableUnitsArray.Mul<Length>(scalarDouble);
Assert.Equal(3, result.Length);
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null * 2 = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
}
@@ -64,7 +64,7 @@
var result = scalarDouble.Mul<Length>(nullableUnitsArray);
Assert.Equal(3, result.Length);
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // 2 * null = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
}
@@ -85,7 +85,7 @@
var result = nullableUnitsList.Mul<Length>(scalarDouble);
Assert.Equal(3, result.Count);
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null * 2 = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
}
@@ -106,7 +106,7 @@
var result = scalarDouble.Mul<Length>(nullableUnitsList);
Assert.Equal(3, result.Count);
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // 2 * null = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
}
@@ -127,7 +127,7 @@
Span<Length?> dest = new Length?[3];
((IReadOnlyCollection<Length?>)nullableUnitsArray).Mul<Length>(scalarDouble, dest);
Assert.Equal(1000 * 2, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]); // null * 2 = null
Assert.Equal(0, (double)dest[1]!, Tolerance);
Assert.Equal(1 * 2, (double)dest[2]!, Tolerance);
}
@@ -148,7 +148,7 @@
Span<Length?> dest = new Length?[3];
scalarDouble.Mul<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
Assert.Equal(2 * 1000, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]); // 2 * null = null
Assert.Equal(0, (double)dest[1]!, Tolerance);
Assert.Equal(2 * 1, (double)dest[2]!, Tolerance);
}
@@ -169,7 +169,7 @@
var result = ((IEnumerable<Length?>)nullableUnitsArray).Mul<Length>(scalarDouble).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null * 2 = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
}
@@ -190,7 +190,7 @@
var result = scalarDouble.Mul<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // 2 * null = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
}
@@ -211,7 +211,7 @@
var result = nullableDoubleArray.Mul(scalarUnit);
Assert.Equal(3, result.Length);
Assert.Equal(5 * 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null * Length = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(3 * 1000, (double)result[2]!, Tolerance);
}
@@ -232,7 +232,7 @@
var result = scalarUnit.Mul(nullableDoubleArray);
Assert.Equal(3, result.Length);
Assert.Equal(1000 * 5, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // Length * null = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(1000 * 3, (double)result[2]!, Tolerance);
}
@@ -253,7 +253,7 @@
var result = nullableDoubleList.Mul(scalarUnit);
Assert.Equal(3, result.Count);
Assert.Equal(5 * 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null * Length = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(3 * 1000, (double)result[2]!, Tolerance);
}
@@ -274,7 +274,7 @@
var result = scalarUnit.Mul(nullableDoubleList);
Assert.Equal(3, result.Count);
Assert.Equal(1000 * 5, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // Length * null = null
Assert.Equal(0, (double)result[1]!, Tolerance);
Assert.Equal(1000 * 3, (double)result[2]!, Tolerance);
}

View File

@@ -1,13 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using QWERTYkez.Mensura.Units;
using QWERTYkez.Mensura.Extensions;
using Xunit;
namespace QWERTYkez.Mensura.Tests
namespace QWERTYkez.Mensura.Tests
{
public class CollectionsPlusExtensionsTests
public class CollectionsPlusExtensionsTest
{
private const double Tolerance = 1e-12;
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
@@ -42,7 +35,7 @@ namespace QWERTYkez.Mensura.Tests
var result = nullableUnitsArray.Plus<Length>(scalarDouble);
Assert.Equal(3, result.Length);
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null + число = null
Assert.Equal(0 + 500, (double)result[1]!, Tolerance);
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
}
@@ -63,7 +56,7 @@ namespace QWERTYkez.Mensura.Tests
var result = scalarDouble.Plus<Length>(nullableUnitsArray);
Assert.Equal(3, result.Length);
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // число + null = null
Assert.Equal(500 + 0, (double)result[1]!, Tolerance);
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
}
@@ -84,7 +77,7 @@ namespace QWERTYkez.Mensura.Tests
var result = nullableUnitsList.Plus<Length>(scalarDouble);
Assert.Equal(3, result.Count);
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null + число = null
Assert.Equal(0 + 500, (double)result[1]!, Tolerance);
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
}
@@ -105,7 +98,7 @@ namespace QWERTYkez.Mensura.Tests
var result = scalarDouble.Plus<Length>(nullableUnitsList);
Assert.Equal(3, result.Count);
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // число + null = null
Assert.Equal(500 + 0, (double)result[1]!, Tolerance);
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
}
@@ -126,7 +119,7 @@ namespace QWERTYkez.Mensura.Tests
Span<Length?> dest = new Length?[3];
((IReadOnlyCollection<Length?>)nullableUnitsArray).Plus<Length>(scalarDouble, dest);
Assert.Equal(1000 + 500, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]); // null + число = null
Assert.Equal(0 + 500, (double)dest[1]!, Tolerance);
Assert.Equal(1 + 500, (double)dest[2]!, Tolerance);
}
@@ -147,7 +140,7 @@ namespace QWERTYkez.Mensura.Tests
Span<Length?> dest = new Length?[3];
scalarDouble.Plus<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
Assert.Equal(500 + 1000, (double)dest[0]!, Tolerance);
Assert.Null(dest[1]); // число + null = null
Assert.Equal(500 + 0, (double)dest[1]!, Tolerance);
Assert.Equal(500 + 1, (double)dest[2]!, Tolerance);
}
@@ -168,7 +161,7 @@ namespace QWERTYkez.Mensura.Tests
var result = ((IEnumerable<Length?>)nullableUnitsArray).Plus<Length>(scalarDouble).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null + число = null
Assert.Equal(0 + 500, (double)result[1]!, Tolerance);
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
}
@@ -189,7 +182,7 @@ namespace QWERTYkez.Mensura.Tests
var result = scalarDouble.Plus<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
Assert.Equal(3, result.Count);
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // число + null = null
Assert.Equal(500 + 0, (double)result[1]!, Tolerance);
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
}
@@ -210,7 +203,7 @@ namespace QWERTYkez.Mensura.Tests
var result = nullableDoubleArray.Plus(scalarUnit);
Assert.Equal(3, result.Length);
Assert.Equal(200 + 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null + Length = null
Assert.Equal(0 + 1000, (double)result[1]!, Tolerance);
Assert.Equal(300 + 1000, (double)result[2]!, Tolerance);
}
@@ -231,7 +224,7 @@ namespace QWERTYkez.Mensura.Tests
var result = scalarUnit.Plus(nullableDoubleArray);
Assert.Equal(3, result.Length);
Assert.Equal(1000 + 200, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // Length + null = null
Assert.Equal(1000 + 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 + 300, (double)result[2]!, Tolerance);
}
@@ -252,7 +245,7 @@ namespace QWERTYkez.Mensura.Tests
var result = nullableDoubleList.Plus(scalarUnit);
Assert.Equal(3, result.Count);
Assert.Equal(200 + 1000, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // null + Length = null
Assert.Equal(0 + 1000, (double)result[1]!, Tolerance);
Assert.Equal(300 + 1000, (double)result[2]!, Tolerance);
}
@@ -273,7 +266,7 @@ namespace QWERTYkez.Mensura.Tests
var result = scalarUnit.Plus(nullableDoubleList);
Assert.Equal(3, result.Count);
Assert.Equal(1000 + 200, (double)result[0]!, Tolerance);
Assert.Null(result[1]); // Length + null = null
Assert.Equal(1000 + 0, (double)result[1]!, Tolerance);
Assert.Equal(1000 + 300, (double)result[2]!, Tolerance);
}

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests;
public class CollectionsPow2Extensions
public class CollectionsPow2ExtensionsTest
{
[Fact]
public void Pow2_Array_CalculatesCorrectly()

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests;
public class Pow3ExtensionsTests
public class CollectionsPow3ExtensionsTest
{
[Fact]
public void Pow3_Array_CalculatesCorrectly()

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests;
public class CollectionsPowNExtensions
public class CollectionsPowNExtensionsTest
{
private const double BaseVal = 3.0;
private const double Expected = 9.0; // 3^2 = 9

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests;
public class CollectionsRootOfCubeExtensions
public class CollectionsRootOfCubeExtensionsTest
{
[Fact]
public void Cbrt_Array_CalculatesCorrectly()
@@ -23,7 +23,7 @@ public class CollectionsRootOfCubeExtensions
var result = source.Cbrt<Length, Length>();
Assert.Equal(4, result[0]?._Value);
Assert.Null(result[1]);
Assert.Equal(0, result[1]?._Value);
Assert.Equal(6, result[2]?._Value);
}

View File

@@ -1,6 +1,6 @@
namespace QWERTYkez.Mensura.Tests;
public class CollectionsRootOfSquareExtensions
public class CollectionsRootOfSquareExtensionsTest
{
[Fact]
public void Sqrt_Array_ShouldCalculateCorrectly()
@@ -28,7 +28,7 @@ public class CollectionsRootOfSquareExtensions
// Assert
Assert.Equal(5, result[0]?._Value);
Assert.Null(result[1]);
Assert.Equal(0, result[1]?._Value);
Assert.Equal(10, result[2]?._Value);
}

View File

@@ -1,164 +0,0 @@
namespace QWERTYkez.Mensura.Tests;
public class DoubleExtensions
{
#region 1. Тесты скалярных типов (Обычные, Экзотические и Nullable)
[Fact]
public void ToDouble_Should_Convert_ExoticTypes_Without_InvalidCastException()
{
// Проверяем типы, которые раньше могли падать в рантайме из-за Convert.ToDouble(object)
Half halfValue = (Half)3.14f;
Int128 int128Value = Int128.Parse("1234567890123456789012345");
UInt128 uInt128Value = UInt128.Parse("9876543210987654321098765");
nint nintValue = 42;
// Act & Assert
Assert.Equal(3.14, halfValue.ToDouble(), 2);
Assert.Equal((double)int128Value, int128Value.ToDouble());
Assert.Equal((double)uInt128Value, uInt128Value.ToDouble());
Assert.Equal(42.0, nintValue.ToDouble());
}
[Theory]
[InlineData((int)100, 100.0)]
[InlineData((byte)5, 5.0)]
[InlineData((float)1.5f, 1.5)]
public void ToDouble_StandardScalars_ShouldConvertCorrectly(object input, double expected)
{
double result = input switch
{
int i => i.ToDouble(),
byte b => b.ToDouble(),
float f => f.ToDouble(),
_ => throw new ArgumentException("Unsupported type in test")
};
Assert.Equal(expected, result);
}
[Fact]
public void ToDouble_NullableScalars_Should_Return_Zero_When_Null()
{
// Arrange
int? nullInt = null;
Half? nullHalf = null;
Int128? nullInt128 = null;
int? validInt = 10;
Half? validHalf = (Half)2.5f;
// Act & Assert
Assert.Equal(0d, nullInt.ToDouble());
Assert.Equal(0d, nullHalf.ToDouble());
Assert.Equal(0d, nullInt128.ToDouble());
Assert.Equal(10d, validInt.ToDouble());
Assert.Equal(2.5d, validHalf.ToDouble(), 1);
}
#endregion
#region 2. Тесты SIMD и оптимизаций коллекций (Различные длины массивов)
[Theory]
[InlineData(0)] // Пустой массив
[InlineData(1)] // 1 элемент (чисто скалярный fallback)
[InlineData(7)] // Нечетное число элементов
[InlineData(16)] // Кратный размер (размер Vector128/Vector256)
[InlineData(35)] // Большой массив с остатком для скалярного хвоста
public void ToDouble_ArrayAndList_Should_Correctly_Map_Via_SIMD_Or_Fallback(int count)
{
// Arrange
float[] sourceArray = [.. Enumerable.Range(1, count).Select(x => x * 1.5f)];
List<float> sourceList = [.. sourceArray];
double[] destFromArray = new double[count];
double[] destFromList = new double[count];
// Act
// Явное приведение к IReadOnlyCollection устраняет ошибку CS0121 (неоднозначность вызова)
((IReadOnlyCollection<float>)sourceArray).ToDouble(destFromArray);
((IReadOnlyCollection<float>)sourceList).ToDouble(destFromList);
// Assert
for (int i = 0; i < count; i++)
{
double expected = sourceArray[i];
Assert.Equal(expected, destFromArray[i]);
Assert.Equal(expected, destFromList[i]);
}
}
#endregion
#region 3. Тесты Nullable-коллекций (Проверка на null-элементы внутри)
[Fact]
public void ToDouble_Nullable_Collections_Should_Keep_Nulls_In_Destination()
{
// Arrange
UInt128?[] sourceArray = [10, null, 20, null, 30];
double?[] destination = new double?[sourceArray.Length];
// Act
((IReadOnlyCollection<UInt128?>)sourceArray).ToDouble(destination);
// Assert
Assert.Equal(10d, destination[0]);
Assert.Null(destination[1]);
Assert.Equal(20d, destination[2]);
Assert.Null(destination[3]);
Assert.Equal(30d, destination[4]);
}
#endregion
#region 4. Тесты LINQ / Отложенного выполнения (IEnumerable)
[Fact]
public void ToDouble_IEnumerable_Extension_Should_Handle_Execution_Types_Correctly()
{
// Arrange
int[] array = [1, 2, 3];
List<int> list = [4, 5, 6];
IEnumerable<int> genericEnum = Enumerable.Range(7, 3);
// Act
var resFromArray = array.ToDouble(); // Быстрый бранч для массива
var resFromList = list.ToDouble(); // Быстрый бранч для списка
var resFromEnum = genericEnum.ToDouble(); // Медленный итератор по IEnumerable
// Assert
Assert.Equal([1d, 2d, 3d], resFromArray);
Assert.Equal([4d, 5d, 6d], resFromList);
Assert.Equal([7d, 8d, 9d], resFromEnum);
}
#endregion
#region 5. Тесты безопасности и валидации аргументов
[Fact]
public void ToDouble_Should_Throw_ArgumentException_When_Destination_Is_Too_Short()
{
// Arrange
int[] source = [1, 2, 3, 4, 5];
double[] destinationTooShort = new double[4]; // Нужен размер >= 5
// Act & Assert
Assert.Throws<ArgumentException>(() => ((IReadOnlyCollection<int>)source).ToDouble(destinationTooShort));
}
[Fact]
public void ToDouble_Should_Do_Nothing_And_Return_When_Collection_Is_Empty_Or_Null()
{
// Arrange
int[]? nullArray = null;
int[] emptyArray = [];
double[] destination = new double[5];
// Act & Assert (Не должно выбрасывать NullReferenceException или ArgumentException)
((IReadOnlyCollection<int>?)nullArray)!.ToDouble(destination);
((IReadOnlyCollection<int>)emptyArray).ToDouble(destination);
Assert.All(destination, x => Assert.Equal(0d, x)); // Назначение осталось нетронутым (все нули по умолчанию)
}
#endregion
}

View File

@@ -0,0 +1,394 @@
using System;
using System.Collections.Generic;
using System.Linq;
using QWERTYkez.Mensura.Extensions;
using Xunit;
namespace QWERTYkez.Mensura.Tests
{
public class DoubleExtensionsTests
{
private const double Tolerance = 1e-12;
#region Single value conversions (non-nullable)
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(255)]
public void ToDouble_Byte_ReturnsExpected(byte value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-128)]
[InlineData(0)]
[InlineData(127)]
public void ToDouble_SByte_ReturnsExpected(sbyte value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-32768)]
[InlineData(0)]
[InlineData(32767)]
public void ToDouble_Short_ReturnsExpected(short value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(65535)]
public void ToDouble_UShort_ReturnsExpected(ushort value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-2147483648)]
[InlineData(0)]
[InlineData(2147483647)]
public void ToDouble_Int_ReturnsExpected(int value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(0U)]
[InlineData(1U)]
[InlineData(uint.MaxValue)]
public void ToDouble_UInt_ReturnsExpected(uint value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(-9223372036854775808)]
[InlineData(0)]
[InlineData(9223372036854775807)]
public void ToDouble_Long_ReturnsExpected(long value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0UL)]
[InlineData(1UL)]
[InlineData(ulong.MaxValue)]
public void ToDouble_ULong_ReturnsExpected(ulong value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(-123456789)]
[InlineData(0)]
[InlineData(123456789)]
public void ToDouble_NInt_ReturnsExpected(nint value) => Assert.Equal(value, value.ToDouble());
[Theory]
[InlineData(0u)]
[InlineData(123456789u)]
public void ToDouble_NUInt_ReturnsExpected(nuint value) => Assert.Equal((double)value, value.ToDouble());
[Theory]
[InlineData(0.0f)]
[InlineData(123.456f)]
[InlineData(-987.654f)]
[InlineData(float.Epsilon)]
[InlineData(float.MaxValue)]
public void ToDouble_Float_ReturnsExpected(float value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0.0)]
[InlineData(123.456)]
[InlineData(-987.654)]
public void ToDouble_Decimal_ReturnsExpected(decimal value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0.0)]
[InlineData(123.456)]
[InlineData(-987.654)]
public void ToDouble_Half_ReturnsExpected(Half value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
#endregion
#region Single value conversions (nullable)
[Fact]
public void ToDouble_NullableByte_Null_ReturnsZero() => Assert.Equal(0.0, ((byte?)null).ToDouble());
[Fact]
public void ToDouble_NullableSByte_Null_ReturnsZero() => Assert.Equal(0.0, ((sbyte?)null).ToDouble());
[Fact]
public void ToDouble_NullableShort_Null_ReturnsZero() => Assert.Equal(0.0, ((short?)null).ToDouble());
[Fact]
public void ToDouble_NullableUShort_Null_ReturnsZero() => Assert.Equal(0.0, ((ushort?)null).ToDouble());
[Fact]
public void ToDouble_NullableInt_Null_ReturnsZero() => Assert.Equal(0.0, ((int?)null).ToDouble());
[Fact]
public void ToDouble_NullableUInt_Null_ReturnsZero() => Assert.Equal(0.0, ((uint?)null).ToDouble());
[Fact]
public void ToDouble_NullableLong_Null_ReturnsZero() => Assert.Equal(0.0, ((long?)null).ToDouble());
[Fact]
public void ToDouble_NullableULong_Null_ReturnsZero() => Assert.Equal(0.0, ((ulong?)null).ToDouble());
[Fact]
public void ToDouble_NullableNInt_Null_ReturnsZero() => Assert.Equal(0.0, ((nint?)null).ToDouble());
[Fact]
public void ToDouble_NullableNUInt_Null_ReturnsZero() => Assert.Equal(0.0, ((nuint?)null).ToDouble());
[Fact]
public void ToDouble_NullableFloat_Null_ReturnsZero() => Assert.Equal(0.0, ((float?)null).ToDouble());
[Fact]
public void ToDouble_NullableDecimal_Null_ReturnsZero() => Assert.Equal(0.0, ((decimal?)null).ToDouble());
[Fact]
public void ToDouble_NullableHalf_Null_ReturnsZero() => Assert.Equal(0.0, ((Half?)null).ToDouble());
#endregion
#region NET7_0_OR_GREATER
#if NET7_0_OR_GREATER
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(-1)]
[InlineData(long.MaxValue)]
public void ToDouble_Int128_ReturnsExpected(Int128 value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(ulong.MaxValue)]
public void ToDouble_UInt128_ReturnsExpected(UInt128 value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
[Fact]
public void ToDouble_NullableInt128_Null_ReturnsZero() => Assert.Equal(0.0, ((Int128?)null).ToDouble());
[Fact]
public void ToDouble_NullableUInt128_Null_ReturnsZero() => Assert.Equal(0.0, ((UInt128?)null).ToDouble());
#endif
#endregion
#region IEnumerable<T> -> IEnumerable<double> (non-nullable)
[Fact]
public void ToDouble_IEnumerableByte_ReturnsCorrect()
{
byte[] source = [1, 2, 3];
var result = source.ToDouble();
Assert.Equal(new double[] { 1, 2, 3 }, result);
}
[Fact]
public void ToDouble_IEnumerableByte_Empty_ReturnsEmpty()
{
var source = Array.Empty<byte>();
var result = source.ToDouble();
Assert.Empty(result);
}
[Fact]
public void ToDouble_IEnumerableByte_Null_Throws() => Assert.Null(((IEnumerable<byte>)null!).ToDouble());
[Fact]
public void ToDouble_IEnumerableInt_ReturnsCorrect()
{
int[] source = [-5, 0, 10];
var result = source.ToDouble();
Assert.Equal(new double[] { -5, 0, 10 }, result);
}
[Fact]
public void ToDouble_IEnumerableInt_Null_Throws() => Assert.Null(((IEnumerable<int>)null!).ToDouble());
#endregion
#region IEnumerable<T?> -> IEnumerable<double?>
[Fact]
public void ToDouble_IEnumerableNullableInt_ReturnsCorrect()
{
int?[] source = [1, null, 3];
var result = source.ToDouble();
Assert.Equal(3, result.Length);
Assert.Equal(1.0, result.First());
Assert.Null(result.Skip(1).First());
Assert.Equal(3.0, result.Last());
}
[Fact]
public void ToDouble_IEnumerableNullableInt_Null_Throws() => Assert.Null(((IEnumerable<int?>)null!).ToDouble());
#endregion
#region Array and List conversions (non-nullable)
[Fact]
public void ToDouble_ByteArray_ReturnsDoubleArray()
{
byte[] arr = [10, 20];
var result = arr.ToDouble();
Assert.Equal(new double[] { 10, 20 }, result);
}
[Fact]
public void ToDouble_ByteArray_Null_ReturnsNull() => Assert.Null(((byte[])null!).ToDouble());
[Fact]
public void ToDouble_ByteList_ReturnsDoubleList()
{
var list = new List<byte> { 10, 20 };
var result = list.ToDouble();
Assert.Equal([10, 20], result);
}
[Fact]
public void ToDouble_ByteList_Null_ReturnsNull() => Assert.Null(((List<byte>)null!).ToDouble());
[Fact]
public void ToDouble_IntArray_ReturnsDoubleArray()
{
int[] arr = [-5, 0, 7];
var result = arr.ToDouble();
Assert.Equal(new double[] { -5, 0, 7 }, result);
}
[Fact]
public void ToDouble_IntList_ReturnsDoubleList()
{
var list = new List<int> { -5, 0, 7 };
var result = list.ToDouble();
Assert.Equal([-5, 0, 7], result);
}
#endregion
#region Array and List conversions (nullable)
[Fact]
public void ToDouble_NullableIntArray_ReturnsNullableDoubleArray()
{
int?[] arr = [1, null, 3];
var result = arr.ToDouble();
Assert.Equal(3, result.Length);
Assert.Equal(1.0, result[0]);
Assert.Null(result[1]);
Assert.Equal(3.0, result[2]);
}
[Fact]
public void ToDouble_NullableIntArray_Null_ReturnsNull() => Assert.Null(((int?[])null!).ToDouble());
[Fact]
public void ToDouble_NullableIntList_ReturnsNullableDoubleList()
{
var list = new List<int?> { 1, null, 3 };
var result = list.ToDouble();
Assert.Equal(3, result.Count);
Assert.Equal(1.0, result[0]);
Assert.Null(result[1]);
Assert.Equal(3.0, result[2]);
}
[Fact]
public void ToDouble_NullableIntList_Null_ReturnsNull() => Assert.Null(((List<int?>)null!).ToDouble());
#endregion
#region IReadOnlyCollection<T> -> Span<double>
[Fact]
public void ToDouble_IReadOnlyCollectionByte_Span_Works()
{
byte[] source = [1, 2];
Span<double> dest = new double[source.Length];
((IReadOnlyCollection<byte>)source).ToDouble(dest);
Assert.Equal(1.0, dest[0]);
Assert.Equal(2.0, dest[1]);
}
[Fact]
public void ToDouble_IReadOnlyCollectionByte_EmptySpan_Works()
{
byte[] source = [];
Span<double> dest = [];
((IReadOnlyCollection<byte>)source).ToDouble(dest);
}
[Fact]
public void ToDouble_IReadOnlyCollectionByte_DestinationTooShort_Throws()
{
byte[] source = [1, 2];
Assert.Throws<ArgumentException>(() =>
{
Span<double> dest = new double[1];
((IReadOnlyCollection<byte>)source).ToDouble(dest);
});
}
[Fact]
public void ToDouble_IReadOnlyCollectionNullableInt_Span_HandlesNulls()
{
int?[] source = [1, null, 3];
Span<double?> dest = new double?[3];
((IReadOnlyCollection<int?>)source).ToDouble(dest);
Assert.Equal(1.0, dest[0]);
Assert.Null(dest[1]);
Assert.Equal(3.0, dest[2]);
}
#endregion
#region Span conversions (ToDoubleCore) - через массивы
[Fact]
public void IntSpan_ToDouble_ConversionWorks()
{
int[] source = [1, 2, 3];
var result = source.ToDouble();
Assert.Equal(new double[] { 1, 2, 3 }, result);
}
[Fact]
public void FloatSpan_ToDouble_ConversionWorks()
{
float[] source = [1.1f, -2.2f];
var result = source.ToDouble();
Assert.Equal(1.1f, result[0], Tolerance);
Assert.Equal(-2.2f, result[1], Tolerance);
}
[Fact]
public void NullableDecimalSpan_ToDouble_HandlesNulls()
{
decimal?[] source = [1.5m, null, -3.3m];
var result = source.ToDouble();
Assert.Equal(3, result.Length);
Assert.Equal(1.5, result[0]!.Value, Tolerance);
Assert.Null(result[1]);
Assert.Equal(-3.3, result[2]!.Value, Tolerance);
}
#endregion
#region Edge cases
[Fact]
public void ToDouble_LongMaxValue_DoesNotOverflow()
{
long max = long.MaxValue;
double result = max.ToDouble();
Assert.Equal((double)max, result, Tolerance);
}
[Fact]
public void ToDouble_ULongMaxValue_DoesNotOverflow()
{
ulong max = ulong.MaxValue;
double result = max.ToDouble();
Assert.Equal((double)max, result, Tolerance);
}
[Fact]
public void ToDouble_Decimal_HighPrecision_DoesNotCrash()
{
decimal huge = decimal.MaxValue;
var result = huge.ToDouble();
Assert.False(double.IsInfinity(result));
}
#endregion
}
}

View File

@@ -5,13 +5,19 @@ namespace QWERTYkez.Mensura.Extensions;
internal static partial class CastExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double ToDouble<T>(this T unit) where T : struct, IMensuraUnit, IEquatable<T>
=> Unsafe.As<T, double>(ref unit);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double ToDouble<T>(this T unit)
where T : struct, IMensuraUnit, IEquatable<T> => Unsafe.As<T, double>(ref unit);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double Protected<T>(this T? unit)
where T : struct, IMensuraUnit, IEquatable<T> => unit.GetValueOrDefault().ToDouble();
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ProtectedU<T>(this T? unit)
where T : struct, IMensuraUnit, IEquatable<T> => unit ?? default;
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ToUnit<T>(this double val)
where T : struct, IMensuraUnit, IEquatable<T> => Unsafe.As<double, T>(ref val);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<R> WrapAsList<T, R>(this T[] array)
where T : struct, IMensuraUnit, IEquatable<T>

View File

@@ -2,8 +2,8 @@
internal static partial class CollectionsDivideExtensions
{
// === DivideCore === SIMD
internal static void DivideCore<T, R>(this ReadOnlySpan<T> units, double divisor, int len, Span<R> destination)
// === DivCore === SIMD
internal static void DivCore<T, R>(this ReadOnlySpan<T> units, double divisor, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -40,7 +40,7 @@ internal static partial class CollectionsDivideExtensions
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor;
}
}
internal static void DivideCore<T, R>(this ReadOnlySpan<T?> units, double divisor, int len, Span<R?> destination)
internal static void DivCore<T, R>(this ReadOnlySpan<T?> units, double divisor, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -67,10 +67,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
d0 = (u0.Protected() * invDivisor).ToUnit<R>();
d1 = (u1.Protected() * invDivisor).ToUnit<R>();
d2 = (u2.Protected() * invDivisor).ToUnit<R>();
d3 = (u3.Protected() * invDivisor).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -78,12 +78,11 @@ internal static partial class CollectionsDivideExtensions
{
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
dst = (unit.Protected() * invDivisor).ToUnit<R>();
}
}
//SIMD
internal static void DivideCore<T, R>(this double dividend, ReadOnlySpan<T> units, int len, Span<R> destination)
internal static void DivCore<T, R>(this double dividend, ReadOnlySpan<T> units, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -118,7 +117,7 @@ internal static partial class CollectionsDivideExtensions
Unsafe.Add(ref dstRef, i) = dividend / Unsafe.Add(ref srcRef, i);
}
}
internal static void DivideCore<T, R>(this double dividend, ReadOnlySpan<T?> units, int len, Span<R?> destination)
internal static void DivCore<T, R>(this double dividend, ReadOnlySpan<T?> units, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -144,10 +143,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (dividend / u0.Value.ToDouble()).ToUnit<R>() : null;
d1 = u1.HasValue ? (dividend / u1.Value.ToDouble()).ToUnit<R>() : null;
d2 = u2.HasValue ? (dividend / u2.Value.ToDouble()).ToUnit<R>() : null;
d3 = u3.HasValue ? (dividend / u3.Value.ToDouble()).ToUnit<R>() : null;
d0 = (dividend / u0.Protected()).ToUnit<R>();
d1 = (dividend / u1.Protected()).ToUnit<R>();
d2 = (dividend / u2.Protected()).ToUnit<R>();
d3 = (dividend / u3.Protected()).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -156,7 +155,7 @@ internal static partial class CollectionsDivideExtensions
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (dividend / unit.Value.ToDouble()).ToUnit<R>() : null;
dst = (dividend / unit.Protected()).ToUnit<R>();
}
}
@@ -174,7 +173,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new R[len];
units.DivideCore(divisor, len, result);
units.DivCore(divisor, len, result);
return result;
}
internal static R?[] Div<T, R>(this T?[] units, double divisor)
@@ -186,7 +185,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new R?[len];
units.DivideCore(divisor, len, result);
units.DivCore(divisor, len, result);
return result;
}
internal static R[] Div<T, R>(this double dividend, T[] units)
@@ -198,7 +197,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new R[len];
dividend.DivideCore(units, len, result);
dividend.DivCore(units, len, result);
return result;
}
internal static R?[] Div<T, R>(this double dividend, T?[] units)
@@ -210,7 +209,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new R?[len];
dividend.DivideCore(units, len, result);
dividend.DivCore(units, len, result);
return result;
}
@@ -223,9 +222,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
DivideCore(CollectionsMarshal.AsSpan(units), divisor, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
DivCore(CollectionsMarshal.AsSpan(units), divisor, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Div<T, R>(this List<T?> units, double divisor)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -235,9 +234,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
DivideCore(CollectionsMarshal.AsSpan(units), divisor, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
DivCore(CollectionsMarshal.AsSpan(units), divisor, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R> Div<T, R>(this double dividend, List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -247,9 +246,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
DivideCore(dividend, CollectionsMarshal.AsSpan(units), count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
DivCore(dividend, CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Div<T, R>(this double dividend, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -259,9 +258,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
DivideCore(dividend, CollectionsMarshal.AsSpan(units), count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
DivCore(dividend, CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection<T> ===
@@ -275,8 +274,8 @@ internal static partial class CollectionsDivideExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.DivideCore(divisor, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).DivideCore(divisor, count, destination); return; }
if (units is T[] array) { array.DivCore(divisor, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).DivCore(divisor, count, destination); return; }
int i = 0;
double invDivisor = 1.0 / divisor;
@@ -293,14 +292,13 @@ internal static partial class CollectionsDivideExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.DivideCore(divisor, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).DivideCore(divisor, count, destination); return; }
if (units is T?[] array) { array.DivCore(divisor, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).DivCore(divisor, count, destination); return; }
int i = 0;
double invDivisor = 1.0 / divisor;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
destination[i++] = (item.Protected() * invDivisor).ToUnit<R>();
}
internal static void Div<T, R>(this double dividend, IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -312,8 +310,8 @@ internal static partial class CollectionsDivideExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { dividend.DivideCore(array, count, destination); return; }
if (units is List<T> list) { dividend.DivideCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
if (units is T[] array) { dividend.DivCore(array, count, destination); return; }
if (units is List<T> list) { dividend.DivCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -329,13 +327,12 @@ internal static partial class CollectionsDivideExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { dividend.DivideCore(array, count, destination); return; }
if (units is List<T?> list) { dividend.DivideCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
if (units is T?[] array) { dividend.DivCore(array, count, destination); return; }
if (units is List<T?> list) { dividend.DivCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend / item.Value.ToDouble()).ToUnit<R>() : null;
destination[i++] = (dividend / item.Protected()).ToUnit<R>();
}
// === IEnumerable<T> + yeild ===
@@ -353,8 +350,7 @@ internal static partial class CollectionsDivideExtensions
{
double invDivisor = 1.0 / divisor;
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
yield return (item.Protected() * invDivisor).ToUnit<R>();
}
static IEnumerable<R> DivideIterator<T, R>(double dividend, IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -368,8 +364,7 @@ internal static partial class CollectionsDivideExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (T? item in units)
yield return item.HasValue
? (dividend / item.Value.ToDouble()).ToUnit<R>() : null;
yield return (dividend / item.Protected()).ToUnit<R>();
}
// === IEnumerable<T> ===
@@ -383,7 +378,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Div(divisor, arr);
arr.DivCore(divisor, arr.Length, arr);
return arr.ReCast<T, R>();
}
return DivideIterator<T, R>(units, divisor);
@@ -398,7 +393,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Div(divisor, arr);
arr.DivCore(divisor, arr.Length, arr);
return arr.ReCast<T, R>();
}
return DivideNullableIterator<T, R>(units, divisor);
@@ -413,7 +408,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
dividend.Div(arr, arr);
dividend.DivCore(arr, arr.Length, arr);
return arr.ReCast<T, R>();
}
return DivideIterator<T, R>(dividend, units);
@@ -428,7 +423,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
dividend.Div(arr, arr);
dividend.DivCore(arr, arr.Length, arr);
return arr.ReCast<T, R>();
}
return DivideNullableIterator<T, R>(dividend, units);
@@ -447,7 +442,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.DivideCore(divisor, len, destination);
units.DivCore(divisor, len, destination);
}
internal static void Div<T>(this ReadOnlySpan<T?> units, double divisor, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -457,7 +452,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.DivideCore(divisor, len, destination);
units.DivCore(divisor, len, destination);
}
internal static void Div<T>(this double dividend, ReadOnlySpan<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -467,7 +462,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
dividend.DivideCore(units, len, destination);
dividend.DivCore(units, len, destination);
}
internal static void Div<T>(this double dividend, ReadOnlySpan<T?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -477,7 +472,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
dividend.DivideCore(units, len, destination);
dividend.DivCore(units, len, destination);
}
// === Array ===
@@ -489,7 +484,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T[len];
Div(units, divisor, result);
units.DivCore(divisor, len, result);
return result;
}
internal static T?[] Div<T>(this T?[] units, double divisor)
@@ -500,7 +495,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T?[len];
Div(units, divisor, result);
units.DivCore(divisor, len, result);
return result;
}
internal static T[] Div<T>(this double dividend, T[] units)
@@ -511,7 +506,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T[len];
Div(dividend, units, result);
dividend.DivCore(units, len, result);
return result;
}
internal static T?[] Div<T>(this double dividend, T?[] units)
@@ -522,7 +517,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T?[len];
Div(dividend, units, result);
dividend.DivCore(units, len, result);
return result;
}
@@ -531,12 +526,12 @@ internal static partial class CollectionsDivideExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).DivCore(divisor, count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Div<T>(this List<T?> units, double divisor)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -545,9 +540,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).DivCore(divisor, count, result);
return result.WrapAsList<T, T>();
}
internal static List<T> Div<T>(this double dividend, List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -556,9 +551,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[count];
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
dividend.DivCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Div<T>(this double dividend, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -567,9 +562,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
dividend.DivCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
// === IReadOnlyCollection<T> ===
@@ -605,8 +600,7 @@ internal static partial class CollectionsDivideExtensions
int i = 0;
double invDivisor = 1.0 / divisor;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * invDivisor).ToUnit<T>() : null;
destination[i++] = (item.Protected() * invDivisor).ToUnit<T>();
}
internal static void Div<T>(this double dividend, IReadOnlyCollection<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -638,8 +632,7 @@ internal static partial class CollectionsDivideExtensions
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend / item.Value.ToDouble()).ToUnit<T>() : null;
destination[i++] = (dividend / item.Protected()).ToUnit<T>();
}
// === IEnumerable<T> + yeild ===
@@ -655,8 +648,7 @@ internal static partial class CollectionsDivideExtensions
{
double invDivisor = 1.0 / divisor;
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() * invDivisor).ToUnit<T>() : null;
yield return (item.Protected() * invDivisor).ToUnit<T>();
}
static IEnumerable<T> DivideIterator<T>(double dividend, IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -668,8 +660,7 @@ internal static partial class CollectionsDivideExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (T? item in units)
yield return item.HasValue
? (dividend / item.Value.ToDouble()).ToUnit<T>() : null;
yield return (dividend / item.Protected()).ToUnit<T>();
}
// === IEnumerable<T> ===
@@ -682,7 +673,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Div(divisor, arr);
arr.DivCore(divisor, arr.Length, arr);
return arr;
}
return DivideIterator(units, divisor);
@@ -696,7 +687,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Div(divisor, arr);
arr.DivCore(divisor, arr.Length, arr);
return arr;
}
return DivideNullableIterator(units, divisor);
@@ -710,7 +701,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
dividend.Div(arr, arr);
dividend.DivCore(arr, arr.Length, arr);
return arr;
}
return DivideIterator(dividend, units);
@@ -724,7 +715,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
dividend.Div(arr, arr);
dividend.DivCore(arr, arr.Length, arr);
return arr;
}
return DivideNullableIterator(dividend, units);
@@ -738,7 +729,7 @@ internal static partial class CollectionsDivideExtensions
// === DivideCore === SIMD
// === DivCore === SIMD
internal static void DivCore<R>(this ReadOnlySpan<double> dividends, double unit, int len, Span<R> destination)
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -800,10 +791,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value * invDivisor).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value * invDivisor).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value * invDivisor).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value * invDivisor).ToUnit<R>() : null;
d0 = ((u0 ?? 0d) * invDivisor).ToUnit<R>();
d1 = ((u1 ?? 0d) * invDivisor).ToUnit<R>();
d2 = ((u2 ?? 0d) * invDivisor).ToUnit<R>();
d3 = ((u3 ?? 0d) * invDivisor).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -811,8 +802,7 @@ internal static partial class CollectionsDivideExtensions
{
var div = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = div.HasValue ? (div.Value * invDivisor).ToUnit<R>() : null;
dst = ((div ?? 0d) * invDivisor).ToUnit<R>();
}
}
//SIMD
@@ -874,10 +864,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (unit / u0.Value).ToUnit<R>() : null;
d1 = u1.HasValue ? (unit / u1.Value).ToUnit<R>() : null;
d2 = u2.HasValue ? (unit / u2.Value).ToUnit<R>() : null;
d3 = u3.HasValue ? (unit / u3.Value).ToUnit<R>() : null;
d0 = (unit / (u0 ?? 0d)).ToUnit<R>();
d1 = (unit / (u1 ?? 0d)).ToUnit<R>();
d2 = (unit / (u2 ?? 0d)).ToUnit<R>();
d3 = (unit / (u3 ?? 0d)).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -886,12 +876,12 @@ internal static partial class CollectionsDivideExtensions
var div = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = div.HasValue ? (unit / div.Value).ToUnit<R>() : null;
dst = (unit / (div ?? 0d)).ToUnit<R>();
}
}
// === DivideCore === SIMD
// === DivCore === SIMD
internal static void DivCore(this ReadOnlySpan<double> dividends, double unit, int len, Span<double> dstDouble)
{
// Вместо деления в цикле, умножаем на обратное число (invDivisor)
@@ -949,10 +939,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? u0.Value * invDivisor : null;
d1 = u1.HasValue ? u1.Value * invDivisor : null;
d2 = u2.HasValue ? u2.Value * invDivisor : null;
d3 = u3.HasValue ? u3.Value * invDivisor : null;
d0 = (u0 ?? 0d) * invDivisor;
d1 = (u1 ?? 0d) * invDivisor;
d2 = (u2 ?? 0d) * invDivisor;
d3 = (u3 ?? 0d) * invDivisor;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -960,8 +950,7 @@ internal static partial class CollectionsDivideExtensions
{
double? div = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = div.HasValue ? div.Value * invDivisor : null;
dst = (div ?? 0d) * invDivisor;
}
}
//SIMD
@@ -1019,10 +1008,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? dUnit / u0.Value : null;
d1 = u1.HasValue ? dUnit / u1.Value : null;
d2 = u2.HasValue ? dUnit / u2.Value : null;
d3 = u3.HasValue ? dUnit / u3.Value : null;
d0 = dUnit / (u0 ?? 0d);
d1 = dUnit / (u1 ?? 0d);
d2 = dUnit / (u2 ?? 0d);
d3 = dUnit / (u3 ?? 0d);
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -1030,8 +1019,7 @@ internal static partial class CollectionsDivideExtensions
{
double? div = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = div.HasValue ? dUnit / div.Value : null;
dst = dUnit / (div ?? 0d);
}
}
@@ -1090,7 +1078,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T[len];
Div(units, divisor, result);
units.DivCore(divisor.ToDouble(), len, result);
return result;
}
internal static T?[] Div<T>(this double?[] units, T divisor)
@@ -1101,7 +1089,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T?[len];
Div(units, divisor, result);
units.DivCore(divisor.ToDouble(), len, result);
return result;
}
internal static T[] Div<T>(this T dividend, double[] units)
@@ -1112,7 +1100,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T[len];
Div(dividend, units, result);
dividend.ToDouble().DivCore(units, len, result);
return result;
}
internal static T?[] Div<T>(this T dividend, double?[] units)
@@ -1123,7 +1111,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T?[len];
Div(dividend, units, result);
dividend.ToDouble().DivCore(units, len, result);
return result;
}
@@ -1132,12 +1120,12 @@ internal static partial class CollectionsDivideExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Div<T>(this List<double?> units, T divisor)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1146,9 +1134,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T> Div<T>(this T dividend, List<double> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1157,9 +1145,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[count];
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Div<T>(this T dividend, List<double?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1168,9 +1156,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
// === IReadOnlyCollection<T> ===
@@ -1206,8 +1194,7 @@ internal static partial class CollectionsDivideExtensions
int i = 0;
double invDivisor = 1.0 / divisor.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value * invDivisor).ToUnit<T>() : null;
destination[i++] = ((item ?? 0d) * invDivisor).ToUnit<T>();
}
internal static void Div<T>(this T dividend, IReadOnlyCollection<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1238,9 +1225,9 @@ internal static partial class CollectionsDivideExtensions
if (units is List<double?> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
var divD = dividend.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend.ToDouble() / item.Value).ToUnit<T>() : null;
destination[i++] = (divD / (item ?? 0d)).ToUnit<T>();
}
// === IEnumerable<T> + yeild ===
@@ -1256,8 +1243,7 @@ internal static partial class CollectionsDivideExtensions
{
double invDivisor = 1.0 / divisor;
foreach (var item in units)
yield return item.HasValue
? (item.Value * invDivisor).ToUnit<T>() : null;
yield return ((item ?? 0d) * invDivisor).ToUnit<T>();
}
static IEnumerable<T> DivideIterator<T>(double dividend, IEnumerable<double> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1269,8 +1255,7 @@ internal static partial class CollectionsDivideExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (var item in units)
yield return item.HasValue
? (dividend / item.Value).ToUnit<T>() : null;
yield return (dividend / (item ?? 0d)).ToUnit<T>();
}
// === IEnumerable<T> ===
@@ -1339,8 +1324,8 @@ internal static partial class CollectionsDivideExtensions
// === DivideCore === SIMD
internal static void DivideCore<T>(this ReadOnlySpan<T> units, double divisor, int len, Span<double> dstDouble)
// === DivCore === SIMD
internal static void DivCore<T>(this ReadOnlySpan<T> units, double divisor, int len, Span<double> dstDouble)
where T : struct, IMensuraUnit, IEquatable<T>
{
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
@@ -1375,7 +1360,7 @@ internal static partial class CollectionsDivideExtensions
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor;
}
}
internal static void DivideCore<T>(this ReadOnlySpan<T?> units, double divisor, int len, Span<double?> destination)
internal static void DivCore<T>(this ReadOnlySpan<T?> units, double divisor, int len, Span<double?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
@@ -1401,10 +1386,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? u0.Value.ToDouble() * invDivisor : null;
d1 = u1.HasValue ? u1.Value.ToDouble() * invDivisor : null;
d2 = u2.HasValue ? u2.Value.ToDouble() * invDivisor : null;
d3 = u3.HasValue ? u3.Value.ToDouble() * invDivisor : null;
d0 = u0.Protected() * invDivisor;
d1 = u1.Protected() * invDivisor;
d2 = u2.Protected() * invDivisor;
d3 = u3.Protected() * invDivisor;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -1413,11 +1398,11 @@ internal static partial class CollectionsDivideExtensions
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? unit.Value.ToDouble() * invDivisor : null;
dst = unit.Protected() * invDivisor;
}
}
//SIMD
internal static void DivideCore<T>(this double dividend, ReadOnlySpan<T> units, int len, Span<double> dstDouble)
internal static void DivCore<T>(this double dividend, ReadOnlySpan<T> units, int len, Span<double> dstDouble)
where T : struct, IMensuraUnit, IEquatable<T>
{
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
@@ -1450,7 +1435,7 @@ internal static partial class CollectionsDivideExtensions
Unsafe.Add(ref dstRef, i) = dividend / Unsafe.Add(ref srcRef, i);
}
}
internal static void DivideCore<T>(this double dividend, ReadOnlySpan<T?> units, int len, Span<double?> destination)
internal static void DivCore<T>(this double dividend, ReadOnlySpan<T?> units, int len, Span<double?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
@@ -1475,10 +1460,10 @@ internal static partial class CollectionsDivideExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? dividend / u0.Value.ToDouble() : null;
d1 = u1.HasValue ? dividend / u1.Value.ToDouble() : null;
d2 = u2.HasValue ? dividend / u2.Value.ToDouble() : null;
d3 = u3.HasValue ? dividend / u3.Value.ToDouble() : null;
d0 = dividend / u0.Protected();
d1 = dividend / u1.Protected();
d2 = dividend / u2.Protected();
d3 = dividend / u3.Protected();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -1487,7 +1472,7 @@ internal static partial class CollectionsDivideExtensions
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? dividend / unit.Value.ToDouble() : null;
dst = dividend / unit.Protected();
}
}
@@ -1504,7 +1489,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.DivideCore(divisor.ToDouble(), len, destination);
units.DivCore(divisor.ToDouble(), len, destination);
}
internal static void Div<T>(this ReadOnlySpan<T?> units, T divisor, Span<double?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1514,7 +1499,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.DivideCore(divisor.ToDouble(), len, destination);
units.DivCore(divisor.ToDouble(), len, destination);
}
internal static void Div<T>(this T dividend, ReadOnlySpan<T> units, Span<double> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1524,7 +1509,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
dividend.ToDouble().DivideCore(units, len, destination);
dividend.ToDouble().DivCore(units, len, destination);
}
internal static void Div<T>(this T dividend, ReadOnlySpan<T?> units, Span<double?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1534,7 +1519,7 @@ internal static partial class CollectionsDivideExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
dividend.ToDouble().DivideCore(units, len, destination);
dividend.ToDouble().DivCore(units, len, destination);
}
// === Array ===
@@ -1546,7 +1531,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T[len];
units.DivideCore(divisor.ToDouble(), len, result);
units.DivCore(divisor.ToDouble(), len, result);
return result.ReCast();
}
internal static double?[] Div<T>(this T?[] units, T divisor)
@@ -1557,7 +1542,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T?[len];
units.DivideCore(divisor.ToDouble(), len, result);
units.DivCore(divisor.ToDouble(), len, result);
return result.ReCast();
}
internal static double[] Div<T>(this T dividend, T[] units)
@@ -1568,7 +1553,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T[len];
dividend.ToDouble().DivideCore(units, len, result);
dividend.ToDouble().DivCore(units, len, result);
return result.ReCast();
}
internal static double?[] Div<T>(this T dividend, T?[] units)
@@ -1579,7 +1564,7 @@ internal static partial class CollectionsDivideExtensions
if (len == 0) return [];
var result = new T?[len];
dividend.ToDouble().DivideCore(units, len, result);
dividend.ToDouble().DivCore(units, len, result);
return result.ReCast();
}
@@ -1591,9 +1576,9 @@ internal static partial class CollectionsDivideExtensions
int len = units.Count;
if (len == 0) return [];
var resultArray = new double[len];
CollectionsMarshal.AsSpan(units).DivideCore(divisor.ToDouble(), len, resultArray);
return resultArray.WrapAsList();
var result = new double[len];
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), len, result);
return result.WrapAsList();
}
internal static List<double?> Div<T>(this List<T?> units, T divisor)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1602,9 +1587,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new double?[count];
CollectionsMarshal.AsSpan(units).DivideCore(divisor.ToDouble(), count, resultArray);
return resultArray.WrapAsList();
var result = new double?[count];
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), count, result);
return result.WrapAsList();
}
internal static List<double> Div<T>(this T dividend, List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1613,9 +1598,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[count];
dividend.ToDouble().DivideCore(CollectionsMarshal.AsSpan(units), count, resultArray);
return resultArray.WrapAsList();
var result = new T[count];
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList();
}
internal static List<double?> Div<T>(this T dividend, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1624,9 +1609,9 @@ internal static partial class CollectionsDivideExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
dividend.ToDouble().DivideCore(CollectionsMarshal.AsSpan(units), count, resultArray);
return resultArray.WrapAsList();
var result = new T?[count];
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList();
}
// === IReadOnlyCollection<T> ===
@@ -1662,7 +1647,7 @@ internal static partial class CollectionsDivideExtensions
int i = 0;
double invDivisor = 1.0 / divisor.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue ? item.Value.ToDouble() * invDivisor : null;
destination[i++] = item.Protected() * invDivisor;
}
internal static void Div<T>(this T dividend, IReadOnlyCollection<T> units, Span<double> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1696,7 +1681,7 @@ internal static partial class CollectionsDivideExtensions
int i = 0;
var div = dividend.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue ? div / item.Value.ToDouble() : null;
destination[i++] = div / item.Protected();
}
// === IEnumerable<T> + yeild ===
@@ -1712,7 +1697,7 @@ internal static partial class CollectionsDivideExtensions
{
double invDivisor = 1.0 / divisor.ToDouble();
foreach (var item in units)
yield return item.HasValue ? item.Value.ToDouble() * invDivisor : null;
yield return item.Protected() * invDivisor;
}
static IEnumerable<double> DivideIterator<T>(T dividend, IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1726,7 +1711,7 @@ internal static partial class CollectionsDivideExtensions
{
var div = dividend.ToDouble();
foreach (var item in units)
yield return item.HasValue ? div / item.Value.ToDouble() : null;
yield return div / item.Protected();
}
// === IEnumerable<T> ===
@@ -1739,7 +1724,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.DivideCore(divisor.ToDouble(), arr.Length, arr);
arr.DivCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast();
}
return DivideIterator(units, divisor);
@@ -1753,7 +1738,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.DivideCore(divisor.ToDouble(), arr.Length, arr);
arr.DivCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast();
}
return DivideNullableIterator(units, divisor);
@@ -1767,7 +1752,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
dividend.ToDouble().DivideCore(arr, arr.Length, arr);
dividend.ToDouble().DivCore(arr, arr.Length, arr);
return arr.ReCast();
}
return DivideIterator(dividend, units);
@@ -1781,7 +1766,7 @@ internal static partial class CollectionsDivideExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
dividend.ToDouble().DivideCore(arr, arr.Length, arr);
dividend.ToDouble().DivCore(arr, arr.Length, arr);
return arr.ReCast();
}
return DivideNullableIterator(dividend, units);

View File

@@ -62,10 +62,10 @@ internal static partial class CollectionsMinusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
d0 = (u0.Protected() - subtrahend).ToUnit<R>();
d1 = (u1.Protected() - subtrahend).ToUnit<R>();
d2 = (u2.Protected() - subtrahend).ToUnit<R>();
d3 = (u3.Protected() - subtrahend).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -73,8 +73,7 @@ internal static partial class CollectionsMinusExtensions
{
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
dst = (unit.Protected() - subtrahend).ToUnit<R>();
}
}
//SIMD
@@ -139,10 +138,10 @@ internal static partial class CollectionsMinusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (minuend - u0.Value.ToDouble()).ToUnit<R>() : null;
d1 = u1.HasValue ? (minuend - u1.Value.ToDouble()).ToUnit<R>() : null;
d2 = u2.HasValue ? (minuend - u2.Value.ToDouble()).ToUnit<R>() : null;
d3 = u3.HasValue ? (minuend - u3.Value.ToDouble()).ToUnit<R>() : null;
d0 = (minuend - u0.Protected()).ToUnit<R>();
d1 = (minuend - u1.Protected()).ToUnit<R>();
d2 = (minuend - u2.Protected()).ToUnit<R>();
d3 = (minuend - u3.Protected()).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -150,8 +149,7 @@ internal static partial class CollectionsMinusExtensions
{
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (minuend - unit.Value.ToDouble()).ToUnit<R>() : null;
dst = (minuend - unit.Protected()).ToUnit<R>();
}
}
@@ -218,9 +216,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Minus<T, R>(this List<T?> units, double subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -230,9 +228,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R> Minus<T, R>(this double minuend, List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -242,9 +240,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Minus<T, R>(this double minuend, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -254,9 +252,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection<T> ===
@@ -292,8 +290,7 @@ internal static partial class CollectionsMinusExtensions
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
destination[i++] = (item.Protected() - subtrahend).ToUnit<R>();
}
internal static void Minus<T, R>(this double minuend, IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -327,8 +324,7 @@ internal static partial class CollectionsMinusExtensions
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (minuend - item.Value.ToDouble()).ToUnit<R>() : null;
destination[i++] = (minuend - item.Protected()).ToUnit<R>();
}
// === IEnumerable<T> + yeild ===
@@ -344,8 +340,7 @@ internal static partial class CollectionsMinusExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
yield return (item.Protected() - subtrahend).ToUnit<R>();
}
static IEnumerable<R> MinusIterator<T, R>(double minuend, IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -359,8 +354,7 @@ internal static partial class CollectionsMinusExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (T? item in units)
yield return item.HasValue
? (minuend - item.Value.ToDouble()).ToUnit<R>() : null;
yield return (minuend - item.Protected()).ToUnit<R>();
}
// === IEnumerable<T> ===
@@ -374,7 +368,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Minus(subtrahend, arr);
arr.MinusCore(subtrahend, arr.Length, arr);
return arr.ReCast<T, R>();
}
return MinusIterator<T, R>(units, subtrahend);
@@ -389,7 +383,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Minus(subtrahend, arr);
arr.MinusCore(subtrahend, arr.Length, arr);
return arr.ReCast<T, R>();
}
return MinusNullableIterator<T, R>(units, subtrahend);
@@ -404,7 +398,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
minuend.Minus(arr, arr);
minuend.MinusCore(arr, arr.Length, arr);
return arr.ReCast<T, R>();
}
return MinusIterator<T, R>(minuend, units);
@@ -419,7 +413,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
minuend.Minus(arr, arr);
minuend.MinusCore(arr, arr.Length, arr);
return arr.ReCast<T, R>();
}
return MinusNullableIterator<T, R>(minuend, units);
@@ -481,7 +475,7 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T[len];
Minus(units, subtrahend, result);
units.MinusCore(subtrahend, len, result);
return result;
}
internal static T?[] Minus<T>(this T?[] units, double subtrahend)
@@ -492,7 +486,7 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T?[len];
Minus(units, subtrahend, result);
units.MinusCore(subtrahend, len, result);
return result;
}
internal static T[] Minus<T>(this double minuend, T[] units)
@@ -503,7 +497,7 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T[len];
Minus(minuend, units, result);
minuend.MinusCore(units, len, result);
return result;
}
internal static T?[] Minus<T>(this double minuend, T?[] units)
@@ -514,7 +508,7 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T?[len];
Minus(minuend, units, result);
minuend.MinusCore(units, len, result);
return result;
}
@@ -523,12 +517,12 @@ internal static partial class CollectionsMinusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Minus(CollectionsMarshal.AsSpan(units), subtrahend, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend, count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Minus<T>(this List<T?> units, double subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -537,9 +531,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Minus(CollectionsMarshal.AsSpan(units), subtrahend, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend, count, result);
return result.WrapAsList<T, T>();
}
internal static List<T> Minus<T>(this double minuend, List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -548,9 +542,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[count];
Minus(minuend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
minuend.MinusCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Minus<T>(this double minuend, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -559,9 +553,9 @@ internal static partial class CollectionsMinusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Minus(minuend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
minuend.MinusCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
// === IReadOnlyCollection<T> ===
@@ -574,8 +568,8 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Minus(subtrahend, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Minus(subtrahend, destination); return; }
if (units is T[] array) { array.MinusCore(subtrahend, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend, count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -590,13 +584,12 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Minus(subtrahend, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Minus(subtrahend, destination); return; }
if (units is T?[] array) { array.MinusCore(subtrahend, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() - subtrahend).ToUnit<T>() : null;
destination[i++] = (item.Protected() - subtrahend).ToUnit<T>();
}
internal static void Minus<T>(this double minuend, IReadOnlyCollection<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -607,8 +600,8 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { minuend.Minus(array, destination); return; }
if (units is List<T> list) { minuend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
if (units is T[] array) { minuend.MinusCore(array, count, destination); return; }
if (units is List<T> list) { minuend.MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -623,13 +616,12 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { minuend.Minus(array, destination); return; }
if (units is List<T?> list) { minuend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
if (units is T?[] array) { minuend.MinusCore(array, count, destination); return; }
if (units is List<T?> list) { minuend.MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (minuend - item.Value.ToDouble()).ToUnit<T>() : null;
destination[i++] = (minuend - item.Protected()).ToUnit<T>();
}
// === IEnumerable<T> + yeild ===
@@ -643,8 +635,7 @@ internal static partial class CollectionsMinusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() - subtrahend).ToUnit<T>() : null;
yield return (item.Protected() - subtrahend).ToUnit<T>();
}
static IEnumerable<T> MinusIterator<T>(double minuend, IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -656,8 +647,7 @@ internal static partial class CollectionsMinusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (T? item in units)
yield return item.HasValue
? (minuend - item.Value.ToDouble()).ToUnit<T>() : null;
yield return (minuend - item.Protected()).ToUnit<T>();
}
// === IEnumerable<T> ===
@@ -670,7 +660,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Minus(subtrahend, arr);
arr.MinusCore(subtrahend, arr.Length, arr);
return arr;
}
return MinusIterator(units, subtrahend);
@@ -684,7 +674,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Minus(subtrahend, arr);
arr.MinusCore(subtrahend, arr.Length, arr);
return arr;
}
return MinusNullableIterator(units, subtrahend);
@@ -698,7 +688,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
minuend.Minus(arr, arr);
minuend.MinusCore(arr, arr.Length, arr);
return arr;
}
return MinusIterator(minuend, units);
@@ -712,7 +702,7 @@ internal static partial class CollectionsMinusExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
minuend.Minus(arr, arr);
minuend.MinusCore(arr, arr.Length, arr);
return arr;
}
return MinusNullableIterator(minuend, units);
@@ -783,10 +773,10 @@ internal static partial class CollectionsMinusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value - subtrahend).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value - subtrahend).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value - subtrahend).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value - subtrahend).ToUnit<R>() : null;
d0 = ((u0 ?? 0d) - subtrahend).ToUnit<R>();
d1 = ((u1 ?? 0d) - subtrahend).ToUnit<R>();
d2 = ((u2 ?? 0d) - subtrahend).ToUnit<R>();
d3 = ((u3 ?? 0d) - subtrahend).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -794,8 +784,7 @@ internal static partial class CollectionsMinusExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value - subtrahend).ToUnit<R>() : null;
dst = ((unit ?? 0d) - subtrahend).ToUnit<R>();
}
}
//SIMD
@@ -857,10 +846,10 @@ internal static partial class CollectionsMinusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (minuend - u0.Value).ToUnit<R>() : null;
d1 = u1.HasValue ? (minuend - u1.Value).ToUnit<R>() : null;
d2 = u2.HasValue ? (minuend - u2.Value).ToUnit<R>() : null;
d3 = u3.HasValue ? (minuend - u3.Value).ToUnit<R>() : null;
d0 = (minuend - (u0 ?? 0d)).ToUnit<R>();
d1 = (minuend - (u1 ?? 0d)).ToUnit<R>();
d2 = (minuend - (u2 ?? 0d)).ToUnit<R>();
d3 = (minuend - (u3 ?? 0d)).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -868,13 +857,12 @@ internal static partial class CollectionsMinusExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (minuend - unit.Value).ToUnit<R>() : null;
dst = (minuend - (unit ?? 0d)).ToUnit<R>();
}
}
// === DivideCore === SIMD
// === DivCore === SIMD
internal static void MinusCore(this ReadOnlySpan<double> srcDouble, double subtrahend, int len, Span<double> dstDouble)
{
var vectorizedSubtrahend = new Vector<double>(subtrahend);
@@ -927,10 +915,10 @@ internal static partial class CollectionsMinusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? u0.Value - subtrahend : null;
d1 = u1.HasValue ? u1.Value - subtrahend : null;
d2 = u2.HasValue ? u2.Value - subtrahend : null;
d3 = u3.HasValue ? u3.Value - subtrahend : null;
d0 = (u0 ?? 0d) - subtrahend;
d1 = (u1 ?? 0d) - subtrahend;
d2 = (u2 ?? 0d) - subtrahend;
d3 = (u3 ?? 0d) - subtrahend;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -938,8 +926,7 @@ internal static partial class CollectionsMinusExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? unit.Value - subtrahend : null;
dst = (unit ?? 0d) - subtrahend;
}
}
//SIMD
@@ -997,10 +984,10 @@ internal static partial class CollectionsMinusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? minuend - u0.Value : null;
d1 = u1.HasValue ? minuend - u1.Value : null;
d2 = u2.HasValue ? minuend - u2.Value : null;
d3 = u3.HasValue ? minuend - u3.Value : null;
d0 = minuend - u0 ?? 0d;
d1 = minuend - u1 ?? 0d;
d2 = minuend - u2 ?? 0d;
d3 = minuend - u3 ?? 0d;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -1008,8 +995,7 @@ internal static partial class CollectionsMinusExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? minuend - unit.Value : null;
dst = minuend - unit ?? 0d;
}
}
@@ -1018,7 +1004,7 @@ internal static partial class CollectionsMinusExtensions
// === ReadOnlySpan
internal static void Minus<T>(this ReadOnlySpan<double> units, T divisor, Span<T> destination)
internal static void Minus<T>(this ReadOnlySpan<double> units, T subtrahend, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units.IsEmpty) return;
@@ -1026,9 +1012,9 @@ internal static partial class CollectionsMinusExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.MinusCore(divisor.ToDouble(), len, destination);
units.MinusCore(subtrahend.ToDouble(), len, destination);
}
internal static void Minus<T>(this ReadOnlySpan<double?> units, T divisor, Span<T?> destination)
internal static void Minus<T>(this ReadOnlySpan<double?> units, T subtrahend, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units.IsEmpty) return;
@@ -1036,9 +1022,9 @@ internal static partial class CollectionsMinusExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.MinusCore(divisor.ToDouble(), len, destination);
units.MinusCore(subtrahend.ToDouble(), len, destination);
}
internal static void Minus<T>(this T dividend, ReadOnlySpan<double> units, Span<T> destination)
internal static void Minus<T>(this T minuend, ReadOnlySpan<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units.IsEmpty) return;
@@ -1046,9 +1032,9 @@ internal static partial class CollectionsMinusExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
dividend.ToDouble().MinusCore(units, len, destination);
minuend.ToDouble().MinusCore(units, len, destination);
}
internal static void Minus<T>(this T dividend, ReadOnlySpan<double?> units, Span<T?> destination)
internal static void Minus<T>(this T minuend, ReadOnlySpan<double?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units.IsEmpty) return;
@@ -1056,11 +1042,11 @@ internal static partial class CollectionsMinusExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
dividend.ToDouble().MinusCore(units, len, destination);
minuend.ToDouble().MinusCore(units, len, destination);
}
// === Array ===
internal static T[] Minus<T>(this double[] units, T divisor)
internal static T[] Minus<T>(this double[] units, T subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
@@ -1068,10 +1054,10 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T[len];
Minus(units, divisor, result);
units.MinusCore(subtrahend.ToDouble(), len, result);
return result;
}
internal static T?[] Minus<T>(this double?[] units, T divisor)
internal static T?[] Minus<T>(this double?[] units, T subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
@@ -1079,10 +1065,10 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T?[len];
Minus(units, divisor, result);
units.MinusCore(subtrahend.ToDouble(), len, result);
return result;
}
internal static T[] Minus<T>(this T dividend, double[] units)
internal static T[] Minus<T>(this T minuend, double[] units)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
@@ -1090,10 +1076,10 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T[len];
Minus(dividend, units, result);
minuend.ToDouble().MinusCore(units, len, result);
return result;
}
internal static T?[] Minus<T>(this T dividend, double?[] units)
internal static T?[] Minus<T>(this T minuend, double?[] units)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
@@ -1101,58 +1087,58 @@ internal static partial class CollectionsMinusExtensions
if (len == 0) return [];
var result = new T?[len];
Minus(dividend, units, result);
minuend.ToDouble().MinusCore(units, len, result);
return result;
}
// === List<T> ===
internal static List<T> Minus<T>(this List<double> units, T divisor)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
var resultArray = new T[len];
Minus(CollectionsMarshal.AsSpan(units), divisor, resultArray);
return resultArray.WrapAsList<T, T>();
}
internal static List<T?> Minus<T>(this List<double?> units, T divisor)
internal static List<T> Minus<T>(this List<double> units, T subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Minus(CollectionsMarshal.AsSpan(units), divisor, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T> Minus<T>(this T dividend, List<double> units)
internal static List<T?> Minus<T>(this List<double?> units, T subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[count];
Minus(dividend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Minus<T>(this T dividend, List<double?> units)
internal static List<T> Minus<T>(this T minuend, List<double> units)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Minus(dividend, CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Minus<T>(this T minuend, List<double?> units)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int count = units.Count;
if (count == 0) return [];
var result = new T?[count];
minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(units), count, result);
return result.WrapAsList<T, T>();
}
// === IReadOnlyCollection<T> ===
internal static void Minus<T>(this IReadOnlyCollection<double> units, T divisor, Span<T> destination)
internal static void Minus<T>(this IReadOnlyCollection<double> units, T subtrahend, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return;
@@ -1161,15 +1147,15 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is double[] array) { array.Minus(divisor, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).Minus(divisor, destination); return; }
if (units is double[] array) { array.MinusCore(subtrahend.ToDouble(), count, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend.ToDouble(), count, destination); return; }
int i = 0;
double invMinusisor = 1.0 / divisor.ToDouble();
double invMinusisor = 1.0 / subtrahend.ToDouble();
foreach (var item in units)
destination[i++] = (item * invMinusisor).ToUnit<T>();
}
internal static void Minus<T>(this IReadOnlyCollection<double?> units, T divisor, Span<T?> destination)
internal static void Minus<T>(this IReadOnlyCollection<double?> units, T subtrahend, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return;
@@ -1178,16 +1164,15 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is double?[] array) { array.Minus(divisor, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).Minus(divisor, destination); return; }
if (units is double?[] array) { array.MinusCore(subtrahend.ToDouble(), count, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend.ToDouble(), count, destination); return; }
int i = 0;
double invMinusisor = 1.0 / divisor.ToDouble();
double invMinusisor = 1.0 / subtrahend.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value * invMinusisor).ToUnit<T>() : null;
destination[i++] = ((item ?? 0d) * invMinusisor).ToUnit<T>();
}
internal static void Minus<T>(this T dividend, IReadOnlyCollection<double> units, Span<T> destination)
internal static void Minus<T>(this T minuend, IReadOnlyCollection<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return;
@@ -1196,14 +1181,15 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is double[] array) { dividend.Minus(array, destination); return; }
if (units is List<double> list) { dividend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
if (units is double[] array) { minuend.ToDouble().MinusCore(array, count, destination); return; }
if (units is List<double> list) { minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
var div = minuend.ToDouble();
foreach (var item in units)
destination[i++] = (dividend.ToDouble() / item).ToUnit<T>();
destination[i++] = (div / item).ToUnit<T>();
}
internal static void Minus<T>(this T dividend, IReadOnlyCollection<double?> units, Span<T?> destination)
internal static void Minus<T>(this T minuend, IReadOnlyCollection<double?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return;
@@ -1212,100 +1198,98 @@ internal static partial class CollectionsMinusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is double?[] array) { dividend.Minus(array, destination); return; }
if (units is List<double?> list) { dividend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
if (units is double?[] array) { minuend.ToDouble().MinusCore(array, count, destination); return; }
if (units is List<double?> list) { minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
var div = minuend.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend.ToDouble() / item.Value).ToUnit<T>() : null;
destination[i++] = (div / (item ?? 0d)).ToUnit<T>();
}
// === IEnumerable<T> + yeild ===
static IEnumerable<T> MinusideIterator<T>(IEnumerable<double> units, double divisor)
static IEnumerable<T> MinusideIterator<T>(IEnumerable<double> units, double subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
double invMinusisor = 1.0 / divisor;
double invMinusisor = 1.0 / subtrahend;
foreach (var item in units)
yield return (item * invMinusisor).ToUnit<T>();
}
static IEnumerable<T?> MinusideNullableIterator<T>(IEnumerable<double?> units, double divisor)
static IEnumerable<T?> MinusideNullableIterator<T>(IEnumerable<double?> units, double subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
double invMinusisor = 1.0 / divisor;
double invMinusisor = 1.0 / subtrahend;
foreach (var item in units)
yield return item.HasValue
? (item.Value * invMinusisor).ToUnit<T>() : null;
yield return ((item ?? 0d) * invMinusisor).ToUnit<T>();
}
static IEnumerable<T> MinusideIterator<T>(double dividend, IEnumerable<double> units)
static IEnumerable<T> MinusideIterator<T>(double minuend, IEnumerable<double> units)
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (var item in units)
yield return (dividend / item).ToUnit<T>();
yield return (minuend / item).ToUnit<T>();
}
static IEnumerable<T?> MinusideNullableIterator<T>(double dividend, IEnumerable<double?> units)
static IEnumerable<T?> MinusideNullableIterator<T>(double minuend, IEnumerable<double?> units)
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (var item in units)
yield return item.HasValue
? (dividend / item.Value).ToUnit<T>() : null;
yield return (minuend / (item ?? 0d)).ToUnit<T>();
}
// === IEnumerable<T> ===
internal static IEnumerable<T> Minus<T>(this IEnumerable<double> units, T divisor)
internal static IEnumerable<T> Minus<T>(this IEnumerable<double> units, T subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
if (units is double[] array) return array.Minus(divisor);
if (units is List<double> list) return list.Minus(divisor);
if (units is double[] array) return array.Minus(subtrahend);
if (units is List<double> list) return list.Minus(subtrahend);
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
arr.MinusCore(divisor.ToDouble(), arr.Length, arr);
arr.MinusCore(subtrahend.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
return MinusideIterator<T>(units, divisor.ToDouble());
return MinusideIterator<T>(units, subtrahend.ToDouble());
}
internal static IEnumerable<T?> Minus<T>(this IEnumerable<double?> units, T divisor)
internal static IEnumerable<T?> Minus<T>(this IEnumerable<double?> units, T subtrahend)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
if (units is double?[] array) return array.Minus(divisor);
if (units is List<double?> list) return list.Minus(divisor);
if (units is double?[] array) return array.Minus(subtrahend);
if (units is List<double?> list) return list.Minus(subtrahend);
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();
arr.MinusCore(divisor.ToDouble(), arr.Length, arr);
arr.MinusCore(subtrahend.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
return MinusideNullableIterator<T>(units, divisor.ToDouble());
return MinusideNullableIterator<T>(units, subtrahend.ToDouble());
}
internal static IEnumerable<T> Minus<T>(this T dividend, IEnumerable<double> units)
internal static IEnumerable<T> Minus<T>(this T minuend, IEnumerable<double> units)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
if (units is double[] array) return dividend.Minus(array);
if (units is List<double> list) return dividend.Minus(list);
if (units is double[] array) return minuend.Minus(array);
if (units is List<double> list) return minuend.Minus(list);
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
dividend.ToDouble().MinusCore(arr, arr.Length, arr);
minuend.ToDouble().MinusCore(arr, arr.Length, arr);
return arr.ReCast<T>();
}
return MinusideIterator<T>(dividend.ToDouble(), units);
return MinusideIterator<T>(minuend.ToDouble(), units);
}
internal static IEnumerable<T?> Minus<T>(this T dividend, IEnumerable<double?> units)
internal static IEnumerable<T?> Minus<T>(this T minuend, IEnumerable<double?> units)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
if (units is double?[] array) return dividend.Minus(array);
if (units is List<double?> list) return dividend.Minus(list);
if (units is double?[] array) return minuend.Minus(array);
if (units is List<double?> list) return minuend.Minus(list);
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();
dividend.ToDouble().MinusCore(arr, arr.Length, arr);
minuend.ToDouble().MinusCore(arr, arr.Length, arr);
return arr.ReCast<T>();
}
return MinusideNullableIterator<T>(dividend.ToDouble(), units);
return MinusideNullableIterator<T>(minuend.ToDouble(), units);
}
}

View File

@@ -2,8 +2,8 @@
internal static partial class CollectionsMultiplyExtensions
{
// === MultiplyCore === SIMD
internal static void MultiplyCore<T, R>(this ReadOnlySpan<T> units, double multiplicator, int len, Span<R> destination)
// === MulCore === SIMD
internal static void MulCore<T, R>(this ReadOnlySpan<T> units, double multiplicator, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -35,7 +35,7 @@ internal static partial class CollectionsMultiplyExtensions
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
}
}
internal static void MultiplyCore<T, R>(this ReadOnlySpan<T?> units, double multiplicator, int len, Span<R?> destination)
internal static void MulCore<T, R>(this ReadOnlySpan<T?> units, double multiplicator, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -61,10 +61,10 @@ internal static partial class CollectionsMultiplyExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
d0 = (u0.Protected() * multiplicator).ToUnit<R>();
d1 = (u1.Protected() * multiplicator).ToUnit<R>();
d2 = (u2.Protected() * multiplicator).ToUnit<R>();
d3 = (u3.Protected() * multiplicator).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -72,20 +72,19 @@ internal static partial class CollectionsMultiplyExtensions
{
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
dst = (unit.Protected() * multiplicator).ToUnit<R>();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void MultiplyCore<T, R>(this double multiplicator, ReadOnlySpan<T> units, int len, Span<R> destination)
internal static void MulCore<T, R>(this double multiplicator, ReadOnlySpan<T> units, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void MultiplyCore<T, R>(this double multiplicator, ReadOnlySpan<T?> units, int len, Span<R?> destination)
internal static void MulCore<T, R>(this double multiplicator, ReadOnlySpan<T?> units, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
@@ -100,7 +99,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len == 0) return [];
var result = new R[len];
units.MultiplyCore(multiplicator, len, result);
units.MulCore(multiplicator, len, result);
return result;
}
internal static R?[] Mul<T, R>(this T?[] units, double multiplicator)
@@ -112,7 +111,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len == 0) return [];
var result = new R?[len];
units.MultiplyCore(multiplicator, len, result);
units.MulCore(multiplicator, len, result);
return result;
}
@@ -135,9 +134,9 @@ internal static partial class CollectionsMultiplyExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
MultiplyCore(CollectionsMarshal.AsSpan(units), multiplicator, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
MulCore(CollectionsMarshal.AsSpan(units), multiplicator, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Mul<T, R>(this List<T?> units, double multiplicator)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -147,9 +146,9 @@ internal static partial class CollectionsMultiplyExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
MultiplyCore(CollectionsMarshal.AsSpan(units), multiplicator, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
MulCore(CollectionsMarshal.AsSpan(units), multiplicator, count, result);
return result.WrapAsList<R, R>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -173,8 +172,8 @@ internal static partial class CollectionsMultiplyExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { MultiplyCore(array, multiplicator, count, destination); return; }
if (units is List<T> list) { MultiplyCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
if (units is T[] array) { MulCore(array, multiplicator, count, destination); return; }
if (units is List<T> list) { MulCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -190,13 +189,12 @@ internal static partial class CollectionsMultiplyExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { MultiplyCore(array, multiplicator, count, destination); return; }
if (units is List<T?> list) { MultiplyCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
if (units is T?[] array) { MulCore(array, multiplicator, count, destination); return; }
if (units is List<T?> list) { MulCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
destination[i++] = (item.Protected() * multiplicator).ToUnit<R>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -222,8 +220,7 @@ internal static partial class CollectionsMultiplyExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
yield return (item.Protected() * multiplicator).ToUnit<R>();
}
// === IEnumerable<T> ===
@@ -237,7 +234,7 @@ internal static partial class CollectionsMultiplyExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Mul(multiplicator, arr);
arr.MulCore(multiplicator, arr.Length, arr);
return arr.ReCast<T, R>();
}
return MultiplyIterator<T, R>(units, multiplicator);
@@ -252,7 +249,7 @@ internal static partial class CollectionsMultiplyExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Mul(multiplicator, arr);
arr.MulCore(multiplicator, arr.Length, arr);
return arr.ReCast<T, R>();
}
return MultiplyNullableIterator<T, R>(units, multiplicator);
@@ -280,7 +277,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.MultiplyCore(multiplicator, len, destination);
units.MulCore(multiplicator, len, destination);
}
internal static void Mul<T>(this ReadOnlySpan<T?> units, double multiplicator, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -290,7 +287,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.MultiplyCore(multiplicator, len, destination);
units.MulCore(multiplicator, len, destination);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -310,7 +307,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len == 0) return [];
var result = new T[len];
Mul(units, multiplicator, result);
units.MulCore(multiplicator, len, result);
return result;
}
internal static T?[] Mul<T>(this T?[] units, double multiplicator)
@@ -321,7 +318,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len == 0) return [];
var result = new T?[len];
Mul(units, multiplicator, result);
units.MulCore(multiplicator, len, result);
return result;
}
@@ -338,12 +335,12 @@ internal static partial class CollectionsMultiplyExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).MulCore(multiplicator, count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Mul<T>(this List<T?> units, double multiplicator)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -352,9 +349,9 @@ internal static partial class CollectionsMultiplyExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).MulCore(multiplicator, count, result);
return result.WrapAsList<T, T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -375,8 +372,8 @@ internal static partial class CollectionsMultiplyExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Mul(multiplicator, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Mul(multiplicator, destination); return; }
if (units is T[] array) { array.MulCore(multiplicator, array.Length, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator, list.Count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -391,13 +388,12 @@ internal static partial class CollectionsMultiplyExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Mul(multiplicator, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Mul(multiplicator, destination); return; }
if (units is T?[] array) { array.MulCore(multiplicator, array.Length, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator, list.Count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * multiplicator).ToUnit<T>() : null;
destination[i++] = (item.Protected() * multiplicator).ToUnit<T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -419,8 +415,7 @@ internal static partial class CollectionsMultiplyExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() * multiplicator).ToUnit<T>() : null;
yield return (item.Protected() * multiplicator).ToUnit<T>();
}
// === IEnumerable<T> ===
@@ -433,7 +428,7 @@ internal static partial class CollectionsMultiplyExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Mul(multiplicator, arr);
arr.MulCore(multiplicator, arr.Length, arr);
return arr;
}
return MultiplyIterator(units, multiplicator);
@@ -447,7 +442,7 @@ internal static partial class CollectionsMultiplyExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Mul(multiplicator, arr);
arr.MulCore(multiplicator, arr.Length, arr);
return arr;
}
return MultiplyNullableIterator(units, multiplicator);
@@ -469,8 +464,8 @@ internal static partial class CollectionsMultiplyExtensions
// === MultiplyCore === SIMD
internal static void MultiplyCore<R>(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<R> destination)
// === MulCore === SIMD
internal static void MulCore<R>(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<R> destination)
where R : struct, IMensuraUnit, IEquatable<R>
{
Span<double> dstDouble = MemoryMarshal.Cast<R, double>(destination);
@@ -500,7 +495,7 @@ internal static partial class CollectionsMultiplyExtensions
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
}
}
internal static void MultiplyCore<R>(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<R?> destination)
internal static void MulCore<R>(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<R?> destination)
where R : struct, IMensuraUnit, IEquatable<R>
{
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
@@ -525,10 +520,10 @@ internal static partial class CollectionsMultiplyExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value * multiplicator).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value * multiplicator).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value * multiplicator).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value * multiplicator).ToUnit<R>() : null;
d0 = ((u0 ?? 0d) * multiplicator).ToUnit<R>();
d1 = ((u1 ?? 0d) * multiplicator).ToUnit<R>();
d2 = ((u2 ?? 0d) * multiplicator).ToUnit<R>();
d3 = ((u3 ?? 0d) * multiplicator).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -537,18 +532,18 @@ internal static partial class CollectionsMultiplyExtensions
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value * multiplicator).ToUnit<R>() : null;
dst = ((unit ?? 0d) * multiplicator).ToUnit<R>();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore<R>(this double multiplicator, ReadOnlySpan<double> units,
int len, Span<R> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore<R>(this double multiplicator, ReadOnlySpan<double?> units,
int len, Span<R?> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore<R>(this double multiplicator, ReadOnlySpan<double> units,
int len, Span<R> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore<R>(this double multiplicator, ReadOnlySpan<double?> units,
int len, Span<R?> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
// === MultiplyCore === SIMD
internal static void MultiplyCore(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<double> dstDouble)
// === MulCore === SIMD
internal static void MulCore(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<double> dstDouble)
{
var vectorizedMultiplicator = new Vector<double>(multiplicator);
int vectorSize = Vector<double>.Count;
@@ -575,7 +570,7 @@ internal static partial class CollectionsMultiplyExtensions
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
}
}
internal static void MultiplyCore(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<double?> destination)
internal static void MulCore(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<double?> destination)
{
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
ref var srcRef = ref MemoryMarshal.GetReference(units);
@@ -599,10 +594,10 @@ internal static partial class CollectionsMultiplyExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? u0.Value * multiplicator : null;
d1 = u1.HasValue ? u1.Value * multiplicator : null;
d2 = u2.HasValue ? u2.Value * multiplicator : null;
d3 = u3.HasValue ? u3.Value * multiplicator : null;
d0 = (u0 ?? 0d) * multiplicator;
d1 = (u1 ?? 0d) * multiplicator;
d2 = (u2 ?? 0d) * multiplicator;
d3 = (u3 ?? 0d) * multiplicator;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -610,15 +605,14 @@ internal static partial class CollectionsMultiplyExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? unit.Value * multiplicator : null;
dst = (unit ?? 0d) * multiplicator;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore(this double multiplicator,
ReadOnlySpan<double> units, int len, Span<double> destination) => units.MultiplyCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore(this double multiplicator,
ReadOnlySpan<double?> units, int len, Span<double?> destination) => units.MultiplyCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore(this double multiplicator,
ReadOnlySpan<double> units, int len, Span<double> destination) => units.MulCore(multiplicator, len, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore(this double multiplicator,
ReadOnlySpan<double?> units, int len, Span<double?> destination) => units.MulCore(multiplicator, len, destination);
@@ -633,7 +627,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.MultiplyCore(multiplicator.ToDouble(), len, destination);
units.MulCore(multiplicator.ToDouble(), len, destination);
}
internal static void Mul<T>(this ReadOnlySpan<double?> units, T multiplicator, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -643,7 +637,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.MultiplyCore(multiplicator.ToDouble(), len, destination);
units.MulCore(multiplicator.ToDouble(), len, destination);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -663,7 +657,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len == 0) return [];
var result = new T[len];
Mul(units, multiplicator, result);
units.MulCore(multiplicator.ToDouble(), len, result);
return result;
}
internal static T?[] Mul<T>(this double?[] units, T multiplicator)
@@ -674,7 +668,7 @@ internal static partial class CollectionsMultiplyExtensions
if (len == 0) return [];
var result = new T?[len];
Mul(units, multiplicator, result);
units.MulCore(multiplicator.ToDouble(), len, result);
return result;
}
@@ -691,12 +685,12 @@ internal static partial class CollectionsMultiplyExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).MulCore(multiplicator.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Mul<T>(this List<double?> units, T multiplicator)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -705,9 +699,9 @@ internal static partial class CollectionsMultiplyExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).MulCore(multiplicator.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -728,12 +722,13 @@ internal static partial class CollectionsMultiplyExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is double[] array) { array.MultiplyCore(multiplicator.ToDouble(), array.Length, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MultiplyCore(multiplicator.ToDouble(), list.Count, destination); return; }
if (units is double[] array) { array.MulCore(multiplicator.ToDouble(), array.Length, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator.ToDouble(), list.Count, destination); return; }
int i = 0;
var mul = multiplicator.ToDouble();
foreach (var item in units)
destination[i++] = (item * multiplicator.ToDouble()).ToUnit<T>();
destination[i++] = (item * mul).ToUnit<T>();
}
internal static void Mul<T>(this IReadOnlyCollection<double?> units, T multiplicator, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -744,13 +739,13 @@ internal static partial class CollectionsMultiplyExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is double?[] array) { array.MultiplyCore(multiplicator.ToDouble(), array.Length, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MultiplyCore(multiplicator.ToDouble(), list.Count, destination); return; }
if (units is double?[] array) { array.MulCore(multiplicator.ToDouble(), array.Length, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator.ToDouble(), list.Count, destination); return; }
int i = 0;
var mul = multiplicator.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value * multiplicator.ToDouble()).ToUnit<T>() : null;
destination[i++] = ((item ?? 0d) * mul).ToUnit<T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -772,8 +767,7 @@ internal static partial class CollectionsMultiplyExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (var item in units)
yield return item.HasValue
? (item.Value * multiplicator).ToUnit<T>() : null;
yield return ((item ?? 0d) * multiplicator).ToUnit<T>();
}
// === IEnumerable<T> ===
@@ -786,7 +780,7 @@ internal static partial class CollectionsMultiplyExtensions
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
arr.MultiplyCore(multiplicator.ToDouble(), arr.Length, arr);
arr.MulCore(multiplicator.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
return MultiplyIterator<T>(units, multiplicator.ToDouble());
@@ -800,7 +794,7 @@ internal static partial class CollectionsMultiplyExtensions
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();
arr.MultiplyCore(multiplicator.ToDouble(), arr.Length, arr);
arr.MulCore(multiplicator.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
return MultiplyNullableIterator<T>(units, multiplicator.ToDouble());

View File

@@ -62,10 +62,10 @@ internal static partial class CollectionsPlusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value.ToDouble() + summand).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value.ToDouble() + summand).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value.ToDouble() + summand).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value.ToDouble() + summand).ToUnit<R>() : null;
d0 = (u0.Protected() + summand).ToUnit<R>();
d1 = (u1.Protected() + summand).ToUnit<R>();
d2 = (u2.Protected() + summand).ToUnit<R>();
d3 = (u3.Protected() + summand).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -73,8 +73,7 @@ internal static partial class CollectionsPlusExtensions
{
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value.ToDouble() + summand).ToUnit<R>() : null;
dst = (unit.Protected() + summand).ToUnit<R>();
}
}
@@ -136,9 +135,9 @@ internal static partial class CollectionsPlusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Plus<T, R>(this List<T?> units, double summand)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -148,9 +147,9 @@ internal static partial class CollectionsPlusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, result);
return result.WrapAsList<R, R>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -196,8 +195,7 @@ internal static partial class CollectionsPlusExtensions
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() + summand).ToUnit<R>() : null;
destination[i++] = (item.Protected() + summand).ToUnit<R>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -223,8 +221,7 @@ internal static partial class CollectionsPlusExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() + summand).ToUnit<R>() : null;
yield return (item.Protected() + summand).ToUnit<R>();
}
// === IEnumerable<T> ===
@@ -238,7 +235,7 @@ internal static partial class CollectionsPlusExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Plus(summand, arr);
arr.PlusCore(summand, arr.Length, arr);
return arr.ReCast<T, R>();
}
return PlusIterator<T, R>(units, summand);
@@ -253,7 +250,7 @@ internal static partial class CollectionsPlusExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Plus(summand, arr);
arr.PlusCore(summand, arr.Length, arr);
return arr.ReCast<T, R>();
}
return PlusNullableIterator<T, R>(units, summand);
@@ -311,7 +308,7 @@ internal static partial class CollectionsPlusExtensions
if (len == 0) return [];
var result = new T[len];
Plus(units, summand, result);
units.PlusCore(summand, len, result);
return result;
}
internal static T?[] Plus<T>(this T?[] units, double summand)
@@ -322,7 +319,7 @@ internal static partial class CollectionsPlusExtensions
if (len == 0) return [];
var result = new T?[len];
Plus(units, summand, result);
PlusCore(units, summand, len, result);
return result;
}
@@ -339,12 +336,12 @@ internal static partial class CollectionsPlusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).PlusCore(summand, count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Plus<T>(this List<T?> units, double summand)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -353,9 +350,9 @@ internal static partial class CollectionsPlusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).PlusCore(summand, count, result);
return result.WrapAsList<T, T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -376,8 +373,8 @@ internal static partial class CollectionsPlusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Plus(summand, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Plus(summand, destination); return; }
if (units is T[] array) { array.PlusCore(summand, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand, count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -392,13 +389,12 @@ internal static partial class CollectionsPlusExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Plus(summand, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Plus(summand, destination); return; }
if (units is T?[] array) { array.PlusCore(summand, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() + summand).ToUnit<T>() : null;
destination[i++] = (item.Protected() + summand).ToUnit<T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -420,8 +416,7 @@ internal static partial class CollectionsPlusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (T? item in units)
yield return item.HasValue
? (item.Value.ToDouble() + summand).ToUnit<T>() : null;
yield return (item.Protected() + summand).ToUnit<T>();
}
// === IEnumerable<T> ===
@@ -434,7 +429,7 @@ internal static partial class CollectionsPlusExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Plus(summand, arr);
arr.PlusCore(summand, arr.Length, arr);
return arr;
}
return PlusIterator(units, summand);
@@ -448,7 +443,7 @@ internal static partial class CollectionsPlusExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Plus(summand, arr);
arr.PlusCore(summand, arr.Length, arr);
return arr;
}
return PlusNullableIterator(units, summand);
@@ -526,10 +521,10 @@ internal static partial class CollectionsPlusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? (u0.Value + summand).ToUnit<R>() : null;
d1 = u1.HasValue ? (u1.Value + summand).ToUnit<R>() : null;
d2 = u2.HasValue ? (u2.Value + summand).ToUnit<R>() : null;
d3 = u3.HasValue ? (u3.Value + summand).ToUnit<R>() : null;
d0 = ((u0 ?? 0d) + summand).ToUnit<R>();
d1 = ((u1 ?? 0d) + summand).ToUnit<R>();
d2 = ((u2 ?? 0d) + summand).ToUnit<R>();
d3 = ((u3 ?? 0d) + summand).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -537,8 +532,7 @@ internal static partial class CollectionsPlusExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? (unit.Value + summand).ToUnit<R>() : null;
dst = ((unit ?? 0d) + summand).ToUnit<R>();
}
}
@@ -602,10 +596,10 @@ internal static partial class CollectionsPlusExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
d0 = u0.HasValue ? u0.Value + summand : null;
d1 = u1.HasValue ? u1.Value + summand : null;
d2 = u2.HasValue ? u2.Value + summand : null;
d3 = u3.HasValue ? u3.Value + summand : null;
d0 = (u0 ?? 0d) + summand;
d1 = (u1 ?? 0d) + summand;
d2 = (u2 ?? 0d) + summand;
d3 = (u3 ?? 0d) + summand;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
@@ -613,8 +607,7 @@ internal static partial class CollectionsPlusExtensions
{
var unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? unit.Value + summand : null;
dst = (unit ?? 0d) + summand;
}
}
@@ -668,7 +661,7 @@ internal static partial class CollectionsPlusExtensions
if (len == 0) return [];
var result = new T[len];
Plus(units, summand, result);
units.PlusCore(summand.ToDouble(), len, result);
return result;
}
internal static T?[] Plus<T>(this double?[] units, T summand)
@@ -679,7 +672,7 @@ internal static partial class CollectionsPlusExtensions
if (len == 0) return [];
var result = new T?[len];
Plus(units, summand, result);
units.PlusCore(summand.ToDouble(), len, result);
return result;
}
@@ -696,12 +689,12 @@ internal static partial class CollectionsPlusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new T[len];
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T[count];
CollectionsMarshal.AsSpan(units).PlusCore(summand.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
internal static List<T?> Plus<T>(this List<double?> units, T summand)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -710,9 +703,9 @@ internal static partial class CollectionsPlusExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new T?[count];
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
return resultArray.WrapAsList<T, T>();
var result = new T?[count];
CollectionsMarshal.AsSpan(units).PlusCore(summand.ToDouble(), count, result);
return result.WrapAsList<T, T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -737,8 +730,9 @@ internal static partial class CollectionsPlusExtensions
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
int i = 0;
var sum = summand.ToDouble();
foreach (var item in units)
destination[i++] = (item + summand.ToDouble()).ToUnit<T>();
destination[i++] = (item + sum).ToUnit<T>();
}
internal static void Plus<T>(this IReadOnlyCollection<double?> units, T summand, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -753,9 +747,9 @@ internal static partial class CollectionsPlusExtensions
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
int i = 0;
var sum = summand.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value + summand.ToDouble()).ToUnit<T>() : null;
destination[i++] = ((item ?? 0d) + sum).ToUnit<T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -777,8 +771,7 @@ internal static partial class CollectionsPlusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
{
foreach (var item in units)
yield return item.HasValue
? (item.Value + summand).ToUnit<T>() : null;
yield return ((item ?? 0d) + summand).ToUnit<T>();
}
// === IEnumerable<T> ===

View File

@@ -130,7 +130,7 @@ internal static partial class CollectionsPow2Extensions
if (len == 0) return [];
var result = new R[len];
Pow2(units, result);
units.Pow2Core(len, result);
return result;
}
internal static R?[] Pow2<T, R>(this T?[] units)
@@ -142,7 +142,7 @@ internal static partial class CollectionsPow2Extensions
if (len == 0) return [];
var result = new R?[len];
Pow2(units, result);
units.Pow2Core(len, result);
return result;
}
@@ -155,9 +155,9 @@ internal static partial class CollectionsPow2Extensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
Pow2(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
CollectionsMarshal.AsSpan(units).Pow2Core(count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Pow2<T, R>(this List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -167,9 +167,9 @@ internal static partial class CollectionsPow2Extensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
Pow2(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
CollectionsMarshal.AsSpan(units).Pow2Core(count, result);
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection<Length> ===
@@ -183,8 +183,8 @@ internal static partial class CollectionsPow2Extensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Pow2(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow2(destination); return; }
if (units is T[] array) { array.Pow2Core(count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow2Core(count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -200,13 +200,12 @@ internal static partial class CollectionsPow2Extensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Pow2(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow2(destination); return; }
if (units is T?[] array) { array.Pow2Core(count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow2Core(count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? item.Value.ToDouble().QuickPow2().ToUnit<R>() : null;
destination[i++] = item.Protected().QuickPow2().ToUnit<R>();
}
// === IEnumerable<T, R> + yeild ===
@@ -222,8 +221,7 @@ internal static partial class CollectionsPow2Extensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? item.Value.ToDouble().QuickPow2().ToUnit<R>() : null;
yield return item.Protected().QuickPow2().ToUnit<R>();
}
// === IEnumerable<Length> ===
@@ -237,7 +235,7 @@ internal static partial class CollectionsPow2Extensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Pow2(arr);
arr.Pow2Core(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return Pow2Iterator<T, R>(units);
@@ -252,7 +250,7 @@ internal static partial class CollectionsPow2Extensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Pow2(arr);
arr.Pow2Core(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return Pow2NullableIterator<T, R>(units);

View File

@@ -1,7 +1,4 @@
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace QWERTYkez.Mensura.Extensions;
namespace QWERTYkez.Mensura.Extensions;
internal static partial class CollectionsPow3Extensions
{
@@ -10,8 +7,8 @@ internal static partial class CollectionsPow3Extensions
// === ТРЕТЬЯ СТЕПЕНЬ ==========================================
// === PowCore3 === SIMD
internal static void PowCore3<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
// === Pow3Core === SIMD
internal static void Pow3Core<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -46,7 +43,7 @@ internal static partial class CollectionsPow3Extensions
dstDouble[i] = val * val * val;
}
}
internal static void PowCore3<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
internal static void Pow3Core<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -109,7 +106,7 @@ internal static partial class CollectionsPow3Extensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.PowCore3(len, destination);
units.Pow3Core(len, destination);
}
internal static void Pow3<T, R>(this ReadOnlySpan<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -120,7 +117,7 @@ internal static partial class CollectionsPow3Extensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.PowCore3(len, destination);
units.Pow3Core(len, destination);
}
// === Array ===
@@ -133,7 +130,7 @@ internal static partial class CollectionsPow3Extensions
if (len == 0) return [];
var result = new R[len];
Pow3(units, result);
units.Pow3Core(len, result);
return result;
}
internal static R?[] Pow3<T, R>(this T?[] units)
@@ -145,7 +142,7 @@ internal static partial class CollectionsPow3Extensions
if (len == 0) return [];
var result = new R?[len];
Pow3(units, result);
units.Pow3Core(len, result);
return result;
}
@@ -158,9 +155,9 @@ internal static partial class CollectionsPow3Extensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
Pow3(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
CollectionsMarshal.AsSpan(units).Pow3Core(count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Pow3<T, R>(this List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -170,9 +167,9 @@ internal static partial class CollectionsPow3Extensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
Pow3(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
CollectionsMarshal.AsSpan(units).Pow3Core(count, result);
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection<Length> ===
@@ -186,8 +183,8 @@ internal static partial class CollectionsPow3Extensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Pow3(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow3(destination); return; }
if (units is T[] array) { array.Pow3Core(count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow3Core(count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -203,13 +200,12 @@ internal static partial class CollectionsPow3Extensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Pow3(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow3(destination); return; }
if (units is T?[] array) { array.Pow3Core(count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow3Core(count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? item.Value.ToDouble().QuickPow3().ToUnit<R>() : null;
destination[i++] = item.Protected().QuickPow3().ToUnit<R>();
}
// === IEnumerable<T, R> + yeild ===
@@ -225,8 +221,7 @@ internal static partial class CollectionsPow3Extensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? item.Value.ToDouble().QuickPow3().ToUnit<R>() : null;
yield return item.Protected().QuickPow3().ToUnit<R>();
}
// === IEnumerable<Length> ===
@@ -240,7 +235,7 @@ internal static partial class CollectionsPow3Extensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Pow3(arr);
arr.Pow3Core(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return PowIterator3<T, R>(units);
@@ -255,7 +250,7 @@ internal static partial class CollectionsPow3Extensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Pow3(arr);
arr.Pow3Core(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return PowNullableIterator3<T, R>(units);

View File

@@ -129,10 +129,10 @@ internal static partial class CollectionsPowNExtensions
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
// Выполняем быструю бинарную математику и трансформируем тип из T в R по месту
d0 = u0.HasValue ? u0.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
d1 = u1.HasValue ? u1.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
d2 = u2.HasValue ? u2.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
d3 = u3.HasValue ? u3.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
d0 = u0.Protected().QuickPow(power).ToUnit<R>();
d1 = u1.Protected().QuickPow(power).ToUnit<R>();
d2 = u2.Protected().QuickPow(power).ToUnit<R>();
d3 = u3.Protected().QuickPow(power).ToUnit<R>();
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 шчку)
@@ -141,7 +141,7 @@ internal static partial class CollectionsPowNExtensions
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? unit.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
dst = unit.Protected().QuickPow(power).ToUnit<R>();
}
}
@@ -180,7 +180,7 @@ internal static partial class CollectionsPowNExtensions
if (len == 0) return [];
var result = new R[len];
Pow(units, power, result);
units.PowCore(power, len, result);
return result;
}
internal static R?[] Pow<T, R>(this T?[] units, int power)
@@ -192,7 +192,7 @@ internal static partial class CollectionsPowNExtensions
if (len == 0) return [];
var result = new R?[len];
Pow(units, power, result);
units.PowCore(power, len, result);
return result;
}
@@ -205,9 +205,9 @@ internal static partial class CollectionsPowNExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[count];
Pow(CollectionsMarshal.AsSpan(units), power, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Pow<T, R>(this List<T?> units, int power)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -217,9 +217,9 @@ internal static partial class CollectionsPowNExtensions
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[count];
Pow(CollectionsMarshal.AsSpan(units), power, resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection<Length> ===
@@ -233,8 +233,8 @@ internal static partial class CollectionsPowNExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Pow(power, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
if (units is T[] array) { array.PowCore(power, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
int i = 0;
foreach (var item in units)
@@ -250,13 +250,12 @@ internal static partial class CollectionsPowNExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Pow(power, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
if (units is T?[] array) { array.PowCore(power, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? item.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
destination[i++] = item.Protected().QuickPow(power).ToUnit<R>();
}
// === IEnumerable<T, R> + yeild ===
@@ -272,8 +271,7 @@ internal static partial class CollectionsPowNExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? item.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
yield return item.Protected().QuickPow(power).ToUnit<R>();
}
// === IEnumerable<Length> ===
@@ -287,7 +285,7 @@ internal static partial class CollectionsPowNExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Pow(power, arr);
arr.PowCore(power, arr.Length, arr);
return arr.ReCast<T, R>();
}
else return PowIterator<T, R>(units, power);
@@ -302,7 +300,7 @@ internal static partial class CollectionsPowNExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Pow(power, arr);
arr.PowCore(power, arr.Length, arr);
return arr.ReCast<T, R>();
}
else return PowNullableIterator<T, R>(units, power);
@@ -402,7 +400,7 @@ internal static partial class CollectionsPowNExtensions
{
// Прямая ref-запись в переданный снаружи destination
ref var dst = ref destination[i];
dst = Math.Pow(item.Value.ToDouble(), power).ToUnit<R>();
dst = Math.Pow(item.Protected(), power).ToUnit<R>();
}
}
}
@@ -443,7 +441,7 @@ internal static partial class CollectionsPowNExtensions
if (len == 0) return [];
var result = new R[len];
units.Pow(power, result);
units.PowCore(power, len, result);
return result;
}
internal static R?[] Pow<T, R>(this T?[] units, double power)
@@ -455,7 +453,7 @@ internal static partial class CollectionsPowNExtensions
if (len == 0) return [];
var result = new R?[len];
units.Pow(power, result);
units.PowCore(power, len, result);
return result;
}
@@ -465,11 +463,11 @@ internal static partial class CollectionsPowNExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var result = new R[len];
CollectionsMarshal.AsSpan(units).Pow(power, result);
var result = new R[count];
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Pow<T, R>(this List<T?> units, double power)
@@ -477,11 +475,11 @@ internal static partial class CollectionsPowNExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var result = new R?[len];
CollectionsMarshal.AsSpan(units).Pow(power, result);
var result = new R?[count];
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
return result.WrapAsList<R, R>();
}
@@ -496,8 +494,8 @@ internal static partial class CollectionsPowNExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Pow(power, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
if (units is T[] array) { array.PowCore(power, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
int i = 0;
foreach (T item in units)
@@ -513,13 +511,12 @@ internal static partial class CollectionsPowNExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Pow(power, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
if (units is T?[] array) { array.PowCore(power, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Pow(item.Value.ToDouble(), power).ToUnit<R>() : null;
destination[i++] = Math.Pow(item.Protected(), power).ToUnit<R>();
}
// === IEnumerable<Length> + yield ===
@@ -535,8 +532,7 @@ internal static partial class CollectionsPowNExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? Math.Pow(item.Value.ToDouble(), power).ToUnit<R>() : null;
yield return Math.Pow(item.Protected(), power).ToUnit<R>();
}
// === IEnumerable<Length> ===
@@ -550,7 +546,7 @@ internal static partial class CollectionsPowNExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Pow(power, arr);
arr.PowCore(power, arr.Length, arr);
return arr.ReCast<T, R>();
}
else return PowIterator<T, R>(units, power);
@@ -565,7 +561,7 @@ internal static partial class CollectionsPowNExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Pow(power, arr);
arr.PowCore(power, arr.Length, arr);
return arr.ReCast<T, R>();
}
else return PowNullableIterator<T, R>(units, power);

View File

@@ -46,13 +46,13 @@ internal static partial class CollectionsRootOfCubeExtensions
for (; i < unrollEnd; i += 4)
{
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 1)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 2)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 3)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Protected()).ToUnit<R>();
Unsafe.Add(ref dstRef, i + 1) = Math.Sqrt(Unsafe.Add(ref srcRef, i + 1)!.Protected()).ToUnit<R>();
Unsafe.Add(ref dstRef, i + 2) = Math.Sqrt(Unsafe.Add(ref srcRef, i + 2)!.Protected()).ToUnit<R>();
Unsafe.Add(ref dstRef, i + 3) = Math.Sqrt(Unsafe.Add(ref srcRef, i + 3)!.Protected()).ToUnit<R>();
}
for (; i < len; i++)
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Protected()).ToUnit<R>();
}
// === ReadOnlySpan ===
@@ -85,10 +85,11 @@ internal static partial class CollectionsRootOfCubeExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units.Length == 0) return [];
var len = units.Length;
if (len == 0) return [];
var result = new R[units.Length];
Cbrt(units, result);
var result = new R[len];
units.CbrtCore(len, result);
return result;
}
internal static R?[] Cbrt<T, R>(this T?[] units)
@@ -96,10 +97,11 @@ internal static partial class CollectionsRootOfCubeExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units.Length == 0) return [];
var len = units.Length;
if (len == 0) return [];
var result = new R?[units.Length];
Cbrt(units, result);
var result = new R?[len];
units.CbrtCore(len, result);
return result;
}
@@ -109,24 +111,24 @@ internal static partial class CollectionsRootOfCubeExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[len];
Cbrt(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R[count];
CollectionsMarshal.AsSpan(units).CbrtCore(count, result);
return result.WrapAsList<R, R>();
}
internal static List<R?> Cbrt<T, R>(this List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[len];
Cbrt(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
CollectionsMarshal.AsSpan(units).CbrtCore(count, result);
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection ===
@@ -156,13 +158,12 @@ internal static partial class CollectionsRootOfCubeExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Cbrt(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Cbrt(destination); return; }
if (units is T?[] array) { array.CbrtCore(count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).CbrtCore(count, destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
destination[i++] = Math.Sqrt(item.Protected()).ToUnit<R>();
}
// === IEnumerable + yield ===
@@ -177,8 +178,7 @@ internal static partial class CollectionsRootOfCubeExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
yield return Math.Sqrt(item.Protected()).ToUnit<R>();
}
// === IEnumerable ===
@@ -192,7 +192,7 @@ internal static partial class CollectionsRootOfCubeExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Cbrt(arr);
arr.CbrtCore(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return SqrtIterator3<T, R>(units);
@@ -207,7 +207,7 @@ internal static partial class CollectionsRootOfCubeExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Cbrt(arr);
arr.CbrtCore(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return SqrtNullableIterator3<T, R>(units);

View File

@@ -77,10 +77,10 @@ internal static partial class CollectionsRootOfSquareExtensions
ref var d2 = ref Unsafe.Add(ref dstRef, i + 2);
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
d0 = u0.HasValue ? Math.Sqrt(u0.Value.ToDouble()).ToUnit<R>() : null;
d1 = u1.HasValue ? Math.Sqrt(u1.Value.ToDouble()).ToUnit<R>() : null;
d2 = u2.HasValue ? Math.Sqrt(u2.Value.ToDouble()).ToUnit<R>() : null;
d3 = u3.HasValue ? Math.Sqrt(u3.Value.ToDouble()).ToUnit<R>() : null;
d0 = Math.Sqrt(u0.Protected()).ToUnit<R>();
d1 = Math.Sqrt(u1.Protected()).ToUnit<R>();
d2 = Math.Sqrt(u2.Protected()).ToUnit<R>();
d3 = Math.Sqrt(u3.Protected()).ToUnit<R>();
}
// ХВОСТ ЦИКЛА: Остаток элементов
@@ -88,7 +88,7 @@ internal static partial class CollectionsRootOfSquareExtensions
{
ref readonly T? unit = ref Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? Math.Sqrt(unit.Value.ToDouble()).ToUnit<R>() : null;
dst = Math.Sqrt(unit.Protected()).ToUnit<R>();
}
}
@@ -146,24 +146,24 @@ internal static partial class CollectionsRootOfSquareExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new R[len];
CollectionsMarshal.AsSpan(units).SqrtCore(len, resultArray.AsSpan());
return resultArray.WrapAsList<R, R>();
var result = new R[count];
CollectionsMarshal.AsSpan(units).SqrtCore(count, result.AsSpan());
return result.WrapAsList<R, R>();
}
internal static List<R?> Sqrt<T, R>(this List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
int count = units.Count;
if (count == 0) return [];
var resultArray = new R?[len];
CollectionsMarshal.AsSpan(units).SqrtCore(len, resultArray.AsSpan());
return resultArray.WrapAsList<R, R>();
var result = new R?[count];
CollectionsMarshal.AsSpan(units).SqrtCore(count, result.AsSpan());
return result.WrapAsList<R, R>();
}
// === IReadOnlyCollection ===
@@ -206,8 +206,7 @@ internal static partial class CollectionsRootOfSquareExtensions
foreach (T? item in units)
{
if ((uint)i >= (uint)count) break;
Unsafe.Add(ref dstRef, i++) = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i++) = Math.Sqrt(item.Protected()).ToUnit<R>();
}
}
@@ -224,8 +223,7 @@ internal static partial class CollectionsRootOfSquareExtensions
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
yield return Math.Sqrt(item.Protected()).ToUnit<R>();
}
// === IEnumerable API ===
@@ -239,7 +237,7 @@ internal static partial class CollectionsRootOfSquareExtensions
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Sqrt(arr);
arr.SqrtCore(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return SqrtIterator<T, R>(units);
@@ -254,7 +252,7 @@ internal static partial class CollectionsRootOfSquareExtensions
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Sqrt(arr);
arr.SqrtCore(arr.Length, arr);
return arr.ReCast<T, R>();
}
else return SqrtNullableIterator<T, R>(units);

View File

@@ -16,18 +16,18 @@ internal static partial class DoubleExtensions
internal static double ToDouble(this float number) => number;
internal static double ToDouble(this decimal number) => (double)number;
internal static double ToDouble(this byte? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this sbyte? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this short? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this ushort? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this int? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this uint? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this nint? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this nuint? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this long? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this ulong? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this byte? number) => number ?? 0d;
internal static double ToDouble(this sbyte? number) => number ?? 0d;
internal static double ToDouble(this short? number) => number ?? 0d;
internal static double ToDouble(this ushort? number) => number ?? 0d;
internal static double ToDouble(this int? number) => number ?? 0d;
internal static double ToDouble(this uint? number) => number ?? 0d;
internal static double ToDouble(this nint? number) => number ?? 0d;
internal static double ToDouble(this nuint? number) => number ?? 0d;
internal static double ToDouble(this long? number) => number ?? 0d;
internal static double ToDouble(this ulong? number) => number ?? 0d;
internal static double ToDouble(this Half? number) => number.HasValue ? (double)number.Value : 0d;
internal static double ToDouble(this float? number) => number.HasValue ? number.Value : 0d;
internal static double ToDouble(this float? number) => number ?? 0d;
internal static double ToDouble(this decimal? number) => number.HasValue ? (double)number.Value : 0d;
#if NET7_0_OR_GREATER
@@ -1432,12 +1432,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1451,12 +1451,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1470,12 +1470,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1489,12 +1489,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1508,12 +1508,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1527,12 +1527,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1546,12 +1546,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1565,12 +1565,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1584,12 +1584,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1603,12 +1603,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1622,12 +1622,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1641,12 +1641,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1660,12 +1660,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
}
#if NET7_0_OR_GREATER
@@ -1680,12 +1680,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1699,12 +1699,12 @@ internal static partial class DoubleExtensions
{
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
}
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
}
#endif

View File

@@ -926,14 +926,6 @@ public readonly partial record struct XXXXXXXX : IMensuraUnit<XXXXXXXX>, IEquata
public static class XXXXXXXXExtensions
{
internal static double Protected(this XXXXXXXX? unit) => unit is null ? 0d : unit.Value._Value;
internal static XXXXXXXX ProtectedU(this XXXXXXXX? unit) => unit is null ? XXXXXXXX.Zero : unit.Value;
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<XXXXXXXX> units,
double divisor, Span<XXXXXXXX> destination) => units.Div<XXXXXXXX>(divisor, destination);