diff --git a/QWERTYkez.Mensura.Generator/TestsGenerator.cs b/QWERTYkez.Mensura.Generator/TestsGenerator.cs index 98d0f8f..85cc706 100644 --- a/QWERTYkez.Mensura.Generator/TestsGenerator.cs +++ b/QWERTYkez.Mensura.Generator/TestsGenerator.cs @@ -247,7 +247,7 @@ public class TestsGenerator : IIncrementalGenerator string propName = baseProp.Name; // Создаём массив из двух тестовых значений - sb.AppendLine($" private {typeName}[] GetTestArray() => new[] {{ {typeName}.{propName}, {typeName}.{propName} }};"); + sb.AppendLine($" private {typeName}[] {typeName}_GetTestArray() => {typeName}.{propName}.Mul(new double[] {{ 5d, 3d }});"); sb.AppendLine(); // ========== Multiply ========== @@ -255,57 +255,57 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Multiply_ScalarByArray_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); - sb.AppendLine($" var result = scalar.Multiply(arr);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); + sb.AppendLine($" var result = scalar.Mul(arr);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[0], Tolerance);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[1], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 5d, (double)result[0], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 3d, (double)result[1], Tolerance);"); sb.AppendLine($" }}"); sb.AppendLine(); // array * scalar sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Multiply_ArrayByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); - sb.AppendLine($" var result = arr.Multiply(scalar);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); + sb.AppendLine($" var result = arr.Mul(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[0], Tolerance);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[1], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 5d, (double)result[0], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 3d, (double)result[1], Tolerance);"); sb.AppendLine($" }}"); sb.AppendLine(); // scalar * List sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Multiply_ScalarByList_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); - sb.AppendLine($" var result = scalar.Multiply(list);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); + sb.AppendLine($" var result = scalar.Mul(list);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[0], Tolerance);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[1], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 5d, (double)result[0], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 3d, (double)result[1], Tolerance);"); sb.AppendLine($" }}"); sb.AppendLine(); // List * scalar sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Multiply_ListByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); - sb.AppendLine($" var result = list.Multiply(scalar);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); + sb.AppendLine($" var result = list.Mul(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[0], Tolerance);"); - sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result[1], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 5d, (double)result[0], Tolerance);"); + sb.AppendLine($" Assert.Equal(scalar * 3d, (double)result[1], Tolerance);"); sb.AppendLine($" }}"); sb.AppendLine(); // scalar * IEnumerable sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Multiply_ScalarByEnumerable_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); - sb.AppendLine($" var result = scalar.Multiply(enumerable);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); + sb.AppendLine($" var result = scalar.Mul(enumerable);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result.ElementAt(0), Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result.ElementAt(1), Tolerance);"); @@ -315,9 +315,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Multiply_EnumerableByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); - sb.AppendLine($" var result = enumerable.Multiply(scalar);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); + sb.AppendLine($" var result = enumerable.Mul(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result.ElementAt(0), Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar * (double)scalar, (double)result.ElementAt(1), Tolerance);"); @@ -329,9 +329,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Divide_ScalarByArray_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); - sb.AppendLine($" var result = scalar.Divide(arr);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); + sb.AppendLine($" var result = scalar.Div(arr);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[0], Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[1], Tolerance);"); @@ -341,9 +341,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Divide_ArrayByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); - sb.AppendLine($" var result = arr.Divide(scalar);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); + sb.AppendLine($" var result = arr.Div(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[0], Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[1], Tolerance);"); @@ -353,9 +353,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Divide_ScalarByList_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); - sb.AppendLine($" var result = scalar.Divide(list);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); + sb.AppendLine($" var result = scalar.Div(list);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[0], Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[1], Tolerance);"); @@ -365,9 +365,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Divide_ListByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); - sb.AppendLine($" var result = list.Divide(scalar);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); + sb.AppendLine($" var result = list.Div(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[0], Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result[1], Tolerance);"); @@ -377,9 +377,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Divide_ScalarByEnumerable_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); - sb.AppendLine($" var result = scalar.Divide(enumerable);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); + sb.AppendLine($" var result = scalar.Div(enumerable);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result.ElementAt(0), Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result.ElementAt(1), Tolerance);"); @@ -389,9 +389,9 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Divide_EnumerableByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); - sb.AppendLine($" var result = enumerable.Divide(scalar);"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); + sb.AppendLine($" var result = enumerable.Div(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result.ElementAt(0), Tolerance);"); sb.AppendLine($" Assert.Equal((double)scalar / (double)scalar, (double)result.ElementAt(1), Tolerance);"); @@ -403,8 +403,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Plus_ScalarByArray_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); sb.AppendLine($" var result = scalar.Plus(arr);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); sb.AppendLine($" Assert.Equal((double)scalar + (double)scalar, (double)result[0], Tolerance);"); @@ -415,8 +415,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Plus_ArrayByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); sb.AppendLine($" var result = arr.Plus(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); sb.AppendLine($" Assert.Equal((double)scalar + (double)scalar, (double)result[0], Tolerance);"); @@ -427,8 +427,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Plus_ScalarByList_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); sb.AppendLine($" var result = scalar.Plus(list);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); sb.AppendLine($" Assert.Equal((double)scalar + (double)scalar, (double)result[0], Tolerance);"); @@ -439,8 +439,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Plus_ListByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); sb.AppendLine($" var result = list.Plus(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); sb.AppendLine($" Assert.Equal((double)scalar + (double)scalar, (double)result[0], Tolerance);"); @@ -451,8 +451,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Plus_ScalarByEnumerable_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); sb.AppendLine($" var result = scalar.Plus(enumerable);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar + (double)scalar, (double)result.ElementAt(0), Tolerance);"); @@ -463,8 +463,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Plus_EnumerableByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); sb.AppendLine($" var result = enumerable.Plus(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar + (double)scalar, (double)result.ElementAt(0), Tolerance);"); @@ -477,8 +477,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Minus_ScalarByArray_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); sb.AppendLine($" var result = scalar.Minus(arr);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); sb.AppendLine($" Assert.Equal((double)scalar - (double)scalar, (double)result[0], Tolerance);"); @@ -489,8 +489,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Minus_ArrayByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var arr = GetTestArray();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var arr = {typeName}_GetTestArray();"); sb.AppendLine($" var result = arr.Minus(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Length);"); sb.AppendLine($" Assert.Equal((double)scalar - (double)scalar, (double)result[0], Tolerance);"); @@ -501,8 +501,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Minus_ScalarByList_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); sb.AppendLine($" var result = scalar.Minus(list);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); sb.AppendLine($" Assert.Equal((double)scalar - (double)scalar, (double)result[0], Tolerance);"); @@ -513,8 +513,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Minus_ListByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var list = GetTestArray().ToList();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var list = {typeName}_GetTestArray().ToList();"); sb.AppendLine($" var result = list.Minus(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count);"); sb.AppendLine($" Assert.Equal((double)scalar - (double)scalar, (double)result[0], Tolerance);"); @@ -525,8 +525,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Minus_ScalarByEnumerable_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); sb.AppendLine($" var result = scalar.Minus(enumerable);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar - (double)scalar, (double)result.ElementAt(0), Tolerance);"); @@ -537,8 +537,8 @@ public class TestsGenerator : IIncrementalGenerator sb.AppendLine($" [Fact]"); sb.AppendLine($" public void {typeName}_Minus_EnumerableByScalar_Works()"); sb.AppendLine($" {{"); - sb.AppendLine($" var scalar = {typeName}.{propName};"); - sb.AppendLine($" var enumerable = GetTestArray().AsEnumerable();"); + sb.AppendLine($" var scalar = 9d;"); + sb.AppendLine($" var enumerable = {typeName}_GetTestArray().AsEnumerable();"); sb.AppendLine($" var result = enumerable.Minus(scalar);"); sb.AppendLine($" Assert.Equal(2, result.Count());"); sb.AppendLine($" Assert.Equal((double)scalar - (double)scalar, (double)result.ElementAt(0), Tolerance);"); diff --git a/QWERTYkez.Mensura/Extensions/CastExtensions.cs b/QWERTYkez.Mensura/Extensions/CastExtensions.cs index 6f90ffb..d154eac 100644 --- a/QWERTYkez.Mensura/Extensions/CastExtensions.cs +++ b/QWERTYkez.Mensura/Extensions/CastExtensions.cs @@ -85,4 +85,32 @@ internal static partial class CastExtensions { return Unsafe.As(ref array); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static double[] ReCast(this T[] array) + where T : struct, IMensuraUnit, IEquatable + { + return Unsafe.As(ref array); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static double?[] ReCast(this T?[] array) + where T : struct, IMensuraUnit, IEquatable + { + return Unsafe.As(ref array); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static R[] ReCast(this double[] array) + where R : struct, IMensuraUnit, IEquatable + { + return Unsafe.As(ref array); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static R?[] ReCast(this double?[] array) + where R : struct, IMensuraUnit, IEquatable + { + return Unsafe.As(ref array); + } } \ No newline at end of file diff --git a/QWERTYkez.Mensura/Extensions/CollectionsDivideExtensions.cs b/QWERTYkez.Mensura/Extensions/CollectionsDivideExtensions.cs index 77c805a..8a468bd 100644 --- a/QWERTYkez.Mensura/Extensions/CollectionsDivideExtensions.cs +++ b/QWERTYkez.Mensura/Extensions/CollectionsDivideExtensions.cs @@ -921,4 +921,705 @@ internal static partial class CollectionsDivideExtensions } return DivideNullableIterator(dividend, units); } + + + + + + + + + + // === DivideCore === SIMD + internal static void DivCore(this ReadOnlySpan dividends, T unit, int len, Span destination) + where T : struct, IMensuraUnit, IEquatable + where R : struct, IMensuraUnit, IEquatable + { + Span dstDouble = MemoryMarshal.Cast(destination); + + // Вместо деления в цикле, умножаем на обратное число (invDivisor) + double invDivisor = 1.0 / unit.ToDouble(); + var vectorizedInvDivisor = new Vector(invDivisor); + + int vectorSize = Vector.Count; + int i = 0; + + ref double srcRef = ref MemoryMarshal.GetReference(dividends); + ref double dstRef = ref MemoryMarshal.GetReference(dstDouble); + + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + ref double currentSrc = ref Unsafe.Add(ref srcRef, i); + ref double currentDst = ref Unsafe.Add(ref dstRef, i); + + // Загрузка, быстрое умножение вместо деления, и сохранение + var vector = Unsafe.As>(ref currentSrc); + var multiplied = vector * vectorizedInvDivisor; + + Unsafe.As>(ref currentDst) = multiplied; + } + + // Хвост + for (; i < len; i++) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor; + } + } + internal static void DivCore(this ReadOnlySpan dividends, T unit, int len, Span destination) + where T : struct, IMensuraUnit, IEquatable + where R : struct, IMensuraUnit, IEquatable + { + // Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов + ref var srcRef = ref MemoryMarshal.GetReference(dividends); + ref var dstRef = ref MemoryMarshal.GetReference(destination); + + int i = 0; + int unrollEnd = len & ~3; // Граница развернутого цикла (кратная 4) + double invDivisor = 1.0 / unit.ToDouble(); + + // 1. ОСНОВНОЙ ЦИКЛ: Обрабатываем конвейером по 4 элемента за итерацию + for (; i < unrollEnd; i += 4) + { + double? u0 = Unsafe.Add(ref srcRef, i); + double? u1 = Unsafe.Add(ref srcRef, i + 1); + double? u2 = Unsafe.Add(ref srcRef, i + 2); + double? u3 = Unsafe.Add(ref srcRef, i + 3); + + // Получаем ref-ссылки на ячейки назначения (zero-cost адресация) + ref var d0 = ref Unsafe.Add(ref dstRef, i); + ref var d1 = ref Unsafe.Add(ref dstRef, i + 1); + ref var d2 = ref Unsafe.Add(ref dstRef, i + 2); + ref var d3 = ref Unsafe.Add(ref dstRef, i + 3); + + // Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага) + d0 = u0.HasValue ? (u0.Value * invDivisor).ToUnit() : null; + d1 = u1.HasValue ? (u1.Value * invDivisor).ToUnit() : null; + d2 = u2.HasValue ? (u2.Value * invDivisor).ToUnit() : null; + d3 = u3.HasValue ? (u3.Value * invDivisor).ToUnit() : null; + } + + // 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук) + for (; i < len; i++) + { + double? div = Unsafe.Add(ref srcRef, i); + ref var dst = ref Unsafe.Add(ref dstRef, i); + + dst = div.HasValue ? (div.Value * invDivisor).ToUnit() : null; + } + } + //SIMD + internal static void DivCore(this T unit, ReadOnlySpan divisors, int len, Span destination) + where T : struct, IMensuraUnit, IEquatable + where R : struct, IMensuraUnit, IEquatable + { + var dUnit = unit.ToDouble(); + Span dstDouble = MemoryMarshal.Cast(destination); + + var vectorizedDividend = new Vector(dUnit); + int vectorSize = Vector.Count; + int i = 0; + + ref double srcRef = ref MemoryMarshal.GetReference(divisors); + ref double dstRef = ref MemoryMarshal.GetReference(dstDouble); + + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + ref double currentSrc = ref Unsafe.Add(ref srcRef, i); + ref double currentDst = ref Unsafe.Add(ref dstRef, i); + + var vector = Unsafe.As>(ref currentSrc); + + // Векторное деление: константа делится на покомпонентные элементы массива + var divided = Vector.Divide(vectorizedDividend, vector); + + Unsafe.As>(ref currentDst) = divided; + } + + // Хвост + for (; i < len; i++) + { + Unsafe.Add(ref dstRef, i) = dUnit / Unsafe.Add(ref srcRef, i); + } + } + internal static void DivCore(this T unit, ReadOnlySpan divisors, int len, Span destination) + where T : struct, IMensuraUnit, IEquatable + where R : struct, IMensuraUnit, IEquatable + { + var dUnit = unit.ToDouble(); + // Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов + ref var srcRef = ref MemoryMarshal.GetReference(divisors); + ref var dstRef = ref MemoryMarshal.GetReference(destination); + + int i = 0; + int unrollEnd = len & ~3; // Граница развернутого цикла (кратная 4) + + // 1. ОСНОВНОЙ ЦИКЛ: Обрабатываем конвейером по 4 элемента за итерацию + for (; i < unrollEnd; i += 4) + { + double? u0 = Unsafe.Add(ref srcRef, i); + double? u1 = Unsafe.Add(ref srcRef, i + 1); + double? u2 = Unsafe.Add(ref srcRef, i + 2); + double? u3 = Unsafe.Add(ref srcRef, i + 3); + + // Получаем ref-ссылки на ячейки назначения (zero-cost адресация) + ref var d0 = ref Unsafe.Add(ref dstRef, i); + ref var d1 = ref Unsafe.Add(ref dstRef, i + 1); + ref var d2 = ref Unsafe.Add(ref dstRef, i + 2); + ref var d3 = ref Unsafe.Add(ref dstRef, i + 3); + + // Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага) + d0 = u0.HasValue ? (dUnit / u0.Value).ToUnit() : null; + d1 = u1.HasValue ? (dUnit / u1.Value).ToUnit() : null; + d2 = u2.HasValue ? (dUnit / u2.Value).ToUnit() : null; + d3 = u3.HasValue ? (dUnit / u3.Value).ToUnit() : null; + } + + // 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук) + for (; i < len; i++) + { + double? div = Unsafe.Add(ref srcRef, i); + ref var dst = ref Unsafe.Add(ref dstRef, i); + + dst = div.HasValue ? (unit.ToDouble() / div.Value).ToUnit() : null; + } + } + + + // === DivideCore === SIMD + internal static void DivCore(this ReadOnlySpan dividends, double unit, int len, Span dstDouble) + { + // Вместо деления в цикле, умножаем на обратное число (invDivisor) + double invDivisor = 1.0 / unit; + var vectorizedInvDivisor = new Vector(invDivisor); + + int vectorSize = Vector.Count; + int i = 0; + + ref double srcRef = ref MemoryMarshal.GetReference(dividends); + ref double dstRef = ref MemoryMarshal.GetReference(dstDouble); + + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + ref double currentSrc = ref Unsafe.Add(ref srcRef, i); + ref double currentDst = ref Unsafe.Add(ref dstRef, i); + + // Загрузка, быстрое умножение вместо деления, и сохранение + var vector = Unsafe.As>(ref currentSrc); + var multiplied = vector * vectorizedInvDivisor; + + Unsafe.As>(ref currentDst) = multiplied; + } + + // Хвост + for (; i < len; i++) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor; + } + } + internal static void DivCore(this ReadOnlySpan dividends, double unit, int len, Span destination) + { + // Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов + ref var srcRef = ref MemoryMarshal.GetReference(dividends); + ref var dstRef = ref MemoryMarshal.GetReference(destination); + + int i = 0; + int unrollEnd = len & ~3; // Граница развернутого цикла (кратная 4) + double invDivisor = 1.0 / unit; + + // 1. ОСНОВНОЙ ЦИКЛ: Обрабатываем конвейером по 4 элемента за итерацию + for (; i < unrollEnd; i += 4) + { + double? u0 = Unsafe.Add(ref srcRef, i); + double? u1 = Unsafe.Add(ref srcRef, i + 1); + double? u2 = Unsafe.Add(ref srcRef, i + 2); + double? u3 = Unsafe.Add(ref srcRef, i + 3); + + // Получаем ref-ссылки на ячейки назначения (zero-cost адресация) + ref var d0 = ref Unsafe.Add(ref dstRef, i); + ref var d1 = ref Unsafe.Add(ref dstRef, i + 1); + ref var d2 = ref Unsafe.Add(ref dstRef, i + 2); + 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; + } + + // 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук) + for (; i < len; i++) + { + double? div = Unsafe.Add(ref srcRef, i); + ref var dst = ref Unsafe.Add(ref dstRef, i); + + dst = div.HasValue ? div.Value * invDivisor : null; + } + } + //SIMD + internal static void DivCore(this double dUnit, ReadOnlySpan divisors, int len, Span dstDouble) + { + var vectorizedDividend = new Vector(dUnit); + int vectorSize = Vector.Count; + int i = 0; + + ref double srcRef = ref MemoryMarshal.GetReference(divisors); + ref double dstRef = ref MemoryMarshal.GetReference(dstDouble); + + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + ref double currentSrc = ref Unsafe.Add(ref srcRef, i); + ref double currentDst = ref Unsafe.Add(ref dstRef, i); + + var vector = Unsafe.As>(ref currentSrc); + + // Векторное деление: константа делится на покомпонентные элементы массива + var divided = Vector.Divide(vectorizedDividend, vector); + + Unsafe.As>(ref currentDst) = divided; + } + + // Хвост + for (; i < len; i++) + { + Unsafe.Add(ref dstRef, i) = dUnit / Unsafe.Add(ref srcRef, i); + } + } + internal static void DivCore(this double dUnit, ReadOnlySpan divisors, int len, Span destination) + { + // Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов + ref var srcRef = ref MemoryMarshal.GetReference(divisors); + ref var dstRef = ref MemoryMarshal.GetReference(destination); + + int i = 0; + int unrollEnd = len & ~3; // Граница развернутого цикла (кратная 4) + + // 1. ОСНОВНОЙ ЦИКЛ: Обрабатываем конвейером по 4 элемента за итерацию + for (; i < unrollEnd; i += 4) + { + double? u0 = Unsafe.Add(ref srcRef, i); + double? u1 = Unsafe.Add(ref srcRef, i + 1); + double? u2 = Unsafe.Add(ref srcRef, i + 2); + double? u3 = Unsafe.Add(ref srcRef, i + 3); + + // Получаем ref-ссылки на ячейки назначения (zero-cost адресация) + ref var d0 = ref Unsafe.Add(ref dstRef, i); + ref var d1 = ref Unsafe.Add(ref dstRef, i + 1); + ref var d2 = ref Unsafe.Add(ref dstRef, i + 2); + 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; + } + + // 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук) + for (; i < len; i++) + { + double? div = Unsafe.Add(ref srcRef, i); + ref var dst = ref Unsafe.Add(ref dstRef, i); + + dst = div.HasValue ? dUnit / div.Value : null; + } + } + + + + + + // === ReadOnlySpan + internal static void Div(this ReadOnlySpan units, T divisor, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units.IsEmpty) return; + int len = units.Length; + if (len > destination.Length) + throw new ArgumentException("Целевой буфер destination меньше исходного source."); + + units.DivCore(divisor, len, destination); + } + internal static void Div(this ReadOnlySpan units, T divisor, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units.IsEmpty) return; + int len = units.Length; + if (len > destination.Length) + throw new ArgumentException("Целевой буфер destination меньше исходного source."); + + units.DivCore(divisor, len, destination); + } + internal static void Div(this T dividend, ReadOnlySpan units, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units.IsEmpty) return; + int len = units.Length; + if (len > destination.Length) + throw new ArgumentException("Целевой буфер destination меньше исходного source."); + + dividend.DivCore(units, len, destination); + } + internal static void Div(this T dividend, ReadOnlySpan units, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units.IsEmpty) return; + int len = units.Length; + if (len > destination.Length) + throw new ArgumentException("Целевой буфер destination меньше исходного source."); + + dividend.DivCore(units, len, destination); + } + + // === Array === + internal static T[] Div(this double[] units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int len = units.Length; + if (len == 0) return []; + + var result = new T[len]; + Div(units, divisor, result); + return result; + } + internal static T?[] Div(this double?[] units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int len = units.Length; + if (len == 0) return []; + + var result = new T?[len]; + Div(units, divisor, result); + return result; + } + internal static T[] Div(this T dividend, double[] units) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int len = units.Length; + if (len == 0) return []; + + var result = new T[len]; + Div(dividend, units, result); + return result; + } + internal static T?[] Div(this T dividend, double?[] units) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int len = units.Length; + if (len == 0) return []; + + var result = new T?[len]; + Div(dividend, units, result); + return result; + } + + // === List === + internal static List Div(this List units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int len = units.Count; + if (len == 0) return []; + + var resultArray = new T[len]; + Div(CollectionsMarshal.AsSpan(units), divisor, resultArray); + return resultArray.WrapAsList(); + } + internal static List Div(this List units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int count = units.Count; + if (count == 0) return []; + + var resultArray = new T?[count]; + Div(CollectionsMarshal.AsSpan(units), divisor, resultArray); + return resultArray.WrapAsList(); + } + internal static List Div(this T dividend, List units) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int count = units.Count; + if (count == 0) return []; + + var resultArray = new T[count]; + Div(dividend, CollectionsMarshal.AsSpan(units), resultArray); + return resultArray.WrapAsList(); + } + internal static List Div(this T dividend, List units) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + int count = units.Count; + if (count == 0) return []; + + var resultArray = new T?[count]; + Div(dividend, CollectionsMarshal.AsSpan(units), resultArray); + return resultArray.WrapAsList(); + } + + // === ICollection === + internal static void Div(this ICollection units, T divisor, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double[] array) { array.Div(divisor, destination); return; } + if (units is List list) { CollectionsMarshal.AsSpan(list).Div(divisor, destination); return; } + + int i = 0; + double invDivisor = 1.0 / divisor.ToDouble(); + foreach (var item in units) + destination[i++] = (item * invDivisor).ToUnit(); + } + internal static void Div(this ICollection units, T divisor, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double?[] array) { array.Div(divisor, destination); return; } + if (units is List list) { CollectionsMarshal.AsSpan(list).Div(divisor, destination); return; } + + int i = 0; + double invDivisor = 1.0 / divisor.ToDouble(); + foreach (var item in units) + destination[i++] = item.HasValue + ? (item.Value * invDivisor).ToUnit() : null; + } + internal static void Div(this T dividend, ICollection units, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double[] array) { dividend.Div(array, destination); return; } + if (units is List list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; } + + int i = 0; + foreach (var item in units) + destination[i++] = (dividend.ToDouble() / item).ToUnit(); + } + internal static void Div(this T dividend, ICollection units, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double?[] array) { dividend.Div(array, destination); return; } + if (units is List list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; } + + int i = 0; + foreach (var item in units) + destination[i++] = item.HasValue + ? (dividend.ToDouble() / item.Value).ToUnit() : null; + } + + // === IReadOnlyCollection === + internal static void Div(this IReadOnlyCollection units, T divisor, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double[] array) { array.Div(divisor, destination); return; } + if (units is List list) { CollectionsMarshal.AsSpan(list).Div(divisor, destination); return; } + + int i = 0; + double invDivisor = 1.0 / divisor.ToDouble(); + foreach (var item in units) + destination[i++] = (item * invDivisor).ToUnit(); + } + internal static void Div(this IReadOnlyCollection units, T divisor, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double?[] array) { array.Div(divisor, destination); return; } + if (units is List list) { CollectionsMarshal.AsSpan(list).Div(divisor, destination); return; } + + int i = 0; + double invDivisor = 1.0 / divisor.ToDouble(); + foreach (var item in units) + destination[i++] = item.HasValue + ? (item.Value * invDivisor).ToUnit() : null; + } + internal static void Div(this T dividend, IReadOnlyCollection units, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double[] array) { dividend.Div(array, destination); return; } + if (units is List list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; } + + int i = 0; + foreach (var item in units) + destination[i++] = (dividend.ToDouble() / item).ToUnit(); + } + internal static void Div(this T dividend, IReadOnlyCollection units, Span destination) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return; + int count = units.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (units is double?[] array) { dividend.Div(array, destination); return; } + if (units is List list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; } + + int i = 0; + foreach (var item in units) + destination[i++] = item.HasValue + ? (dividend.ToDouble() / item.Value).ToUnit() : null; + } + + // === IEnumerable + yeild === + static IEnumerable DivideIterator(IEnumerable units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + double invDivisor = 1.0 / divisor.ToDouble(); + foreach (var item in units) + yield return (item * invDivisor).ToUnit(); + } + static IEnumerable DivideNullableIterator(IEnumerable units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + double invDivisor = 1.0 / divisor.ToDouble(); + foreach (var item in units) + yield return item.HasValue + ? (item.Value * invDivisor).ToUnit() : null; + } + static IEnumerable DivideIterator(T dividend, IEnumerable units) + where T : struct, IMensuraUnit, IEquatable + { + foreach (var item in units) + yield return (dividend.ToDouble() / item).ToUnit(); + } + static IEnumerable DivideNullableIterator(T dividend, IEnumerable units) + where T : struct, IMensuraUnit, IEquatable + { + foreach (var item in units) + yield return item.HasValue + ? (dividend.ToDouble() / item.Value).ToUnit() : null; + } + + // === IEnumerable === + internal static IEnumerable Div(this IEnumerable units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + if (units is double[] array) return array.Div(divisor); + if (units is List list) return list.Div(divisor); + if (units is ICollection col) + { + var arr = col.ToArray(); + arr.DivCore(divisor.ToDouble(), arr.Length, arr); + return arr.ReCast(); + } + if (units is IReadOnlyCollection roc) + { + var arr = roc.ToArray(); + arr.DivCore(divisor.ToDouble(), arr.Length, arr); + return arr.ReCast(); + } + return DivideIterator(units, divisor); + } + internal static IEnumerable Div(this IEnumerable units, T divisor) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + if (units is double?[] array) return array.Div(divisor); + if (units is List list) return list.Div(divisor); + if (units is ICollection col) + { + var arr = col.ToArray(); + arr.DivCore(divisor.ToDouble(), arr.Length, arr); + return arr.ReCast(); + } + if (units is IReadOnlyCollection roc) + { + var arr = roc.ToArray(); + arr.DivCore(divisor.ToDouble(), arr.Length, arr); + return arr.ReCast(); + } + return DivideNullableIterator(units, divisor); + } + internal static IEnumerable Div(this T dividend, IEnumerable units) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + if (units is double[] array) return dividend.Div(array); + if (units is List list) return dividend.Div(list); + if (units is ICollection col) + { + var arr = col.ToArray(); + dividend.ToDouble().DivCore(arr, arr.Length, arr); + return arr.ReCast(); + } + if (units is IReadOnlyCollection roc) + { + var arr = roc.ToArray(); + dividend.ToDouble().DivCore(arr, arr.Length, arr); + return arr.ReCast(); + } + return DivideIterator(dividend, units); + } + internal static IEnumerable Div(this T dividend, IEnumerable units) + where T : struct, IMensuraUnit, IEquatable + { + if (units is null) return null!; + if (units is double?[] array) return dividend.Div(array); + if (units is List list) return dividend.Div(list); + if (units is ICollection col) + { + var arr = col.ToArray(); + dividend.ToDouble().DivCore(arr, arr.Length, arr); + return arr.ReCast(); + } + if (units is IReadOnlyCollection roc) + { + var arr = roc.ToArray(); + dividend.ToDouble().DivCore(arr, arr.Length, arr); + return arr.ReCast(); + } + return DivideNullableIterator(dividend, units); + } } \ No newline at end of file diff --git a/QWERTYkez.Mensura/Extensions/DoubleExtensions.cs b/QWERTYkez.Mensura/Extensions/DoubleExtensions.cs new file mode 100644 index 0000000..3c77d22 --- /dev/null +++ b/QWERTYkez.Mensura/Extensions/DoubleExtensions.cs @@ -0,0 +1,1559 @@ +namespace QWERTYkez.Mensura.Extensions; + +public static partial class DoubleExtensions +{ + internal static double ToDouble(this byte number) => Convert.ToDouble(number); + internal static double ToDouble(this sbyte number) => Convert.ToDouble(number); + internal static double ToDouble(this short number) => Convert.ToDouble(number); + internal static double ToDouble(this ushort number) => Convert.ToDouble(number); + internal static double ToDouble(this int number) => Convert.ToDouble(number); + internal static double ToDouble(this uint number) => Convert.ToDouble(number); + internal static double ToDouble(this nint number) => Convert.ToDouble(number); + internal static double ToDouble(this nuint number) => Convert.ToDouble(number); + internal static double ToDouble(this long number) => Convert.ToDouble(number); + internal static double ToDouble(this ulong number) => Convert.ToDouble(number); + internal static double ToDouble(this float number) => Convert.ToDouble(number); + internal static double ToDouble(this decimal number) => Convert.ToDouble(number); + + internal static double ToDouble(this byte? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this sbyte? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this short? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this ushort? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this int? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this uint? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this nint? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this nuint? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this long? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this ulong? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this float? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this decimal? number) => number is null ? 0d : Convert.ToDouble(number); + +#if NET7_0_OR_GREATER + internal static double ToDouble(this Int128 number) => Convert.ToDouble(number); + internal static double ToDouble(this UInt128 number) => Convert.ToDouble(number); + + internal static double ToDouble(this Int128? number) => number is null ? 0d : Convert.ToDouble(number); + internal static double ToDouble(this UInt128? number) => number is null ? 0d : Convert.ToDouble(number); +#endif + + + + // === IEnumerable + yeild === + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return (double)number; } + +#if NET7_0_OR_GREATER + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return (double)number; } + internal static IEnumerable ToDoubleIterator(this IEnumerable numbers) + { foreach (var number in numbers) yield return (double)number; } +#endif + + + + + // ======================================================================== + // ГРУППА 1: 32-битные типы (float, int, uint). 1 вектор дает 2 вектора + // ======================================================================== + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref float srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + + int vectorSize = Vector.Count; + int doubleVectorSize = Vector.Count; + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + var vSrc = Unsafe.As>(ref Unsafe.Add(ref srcRef, i)); + Vector.Widen(vSrc, out var vLow, out var vHigh); + + Unsafe.As>(ref Unsafe.Add(ref dstRef, i)) = vLow; + Unsafe.As>(ref Unsafe.Add(ref dstRef, i + doubleVectorSize)) = vHigh; + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref int srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + + int vectorSize = Vector.Count; + int doubleVectorSize = Vector.Count; + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + var vSrc = Unsafe.As>(ref Unsafe.Add(ref srcRef, i)); + + // Расширяем int (32bit) -> long (64bit), затем конвертируем long -> double + Vector.Widen(vSrc, out var vLowLong, out var vHighLong); + + Unsafe.As>(ref Unsafe.Add(ref dstRef, i)) = Vector.ConvertToDouble(vLowLong); + Unsafe.As>(ref Unsafe.Add(ref dstRef, i + doubleVectorSize)) = Vector.ConvertToDouble(vHighLong); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref uint srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + + int vectorSize = Vector.Count; + int doubleVectorSize = Vector.Count; + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + var vSrc = Unsafe.As>(ref Unsafe.Add(ref srcRef, i)); + Vector.Widen(vSrc, out var vLowULong, out var vHighULong); + + Unsafe.As>(ref Unsafe.Add(ref dstRef, i)) = Vector.ConvertToDouble(vLowULong); + Unsafe.As>(ref Unsafe.Add(ref dstRef, i + doubleVectorSize)) = Vector.ConvertToDouble(vHighULong); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + + // ======================================================================== + // ГРУППА 2: 64-битные типы (long, ulong). 1 вектор дает 1 вектор + // ======================================================================== + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref long srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + + int vectorSize = Vector.Count; + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + var vSrc = Unsafe.As>(ref Unsafe.Add(ref srcRef, i)); + Unsafe.As>(ref Unsafe.Add(ref dstRef, i)) = Vector.ConvertToDouble(vSrc); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref ulong srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0, vectorSize = Vector.Count; + int simdEnd = len & ~(vectorSize - 1); + + for (; i < simdEnd; i += vectorSize) + { + var vSrc = Unsafe.As>(ref Unsafe.Add(ref srcRef, i)); + Unsafe.As>(ref Unsafe.Add(ref dstRef, i)) = Vector.ConvertToDouble(vSrc); + } + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + + // ======================================================================== + // ГРУППА 3: 8 и 16-битные типы (byte, sbyte, short, ushort). + // Используем Unroll x8 (развернутый цикл), так как это быстрее 3-х каскадов Widen. + // ======================================================================== + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref short srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~7; // Кратность 8 + + for (; i < unrollEnd; i += 8) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3); + Unsafe.Add(ref dstRef, i + 4) = Unsafe.Add(ref srcRef, i + 4); + Unsafe.Add(ref dstRef, i + 5) = Unsafe.Add(ref srcRef, i + 5); + Unsafe.Add(ref dstRef, i + 6) = Unsafe.Add(ref srcRef, i + 6); + Unsafe.Add(ref dstRef, i + 7) = Unsafe.Add(ref srcRef, i + 7); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref ushort srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~7; // Кратность 8 + + for (; i < unrollEnd; i += 8) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3); + Unsafe.Add(ref dstRef, i + 4) = Unsafe.Add(ref srcRef, i + 4); + Unsafe.Add(ref dstRef, i + 5) = Unsafe.Add(ref srcRef, i + 5); + Unsafe.Add(ref dstRef, i + 6) = Unsafe.Add(ref srcRef, i + 6); + Unsafe.Add(ref dstRef, i + 7) = Unsafe.Add(ref srcRef, i + 7); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref byte srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~7; // Кратность 8 + + for (; i < unrollEnd; i += 8) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3); + Unsafe.Add(ref dstRef, i + 4) = Unsafe.Add(ref srcRef, i + 4); + Unsafe.Add(ref dstRef, i + 5) = Unsafe.Add(ref srcRef, i + 5); + Unsafe.Add(ref dstRef, i + 6) = Unsafe.Add(ref srcRef, i + 6); + Unsafe.Add(ref dstRef, i + 7) = Unsafe.Add(ref srcRef, i + 7); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref sbyte srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~7; // Кратность 8 + + for (; i < unrollEnd; i += 8) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3); + Unsafe.Add(ref dstRef, i + 4) = Unsafe.Add(ref srcRef, i + 4); + Unsafe.Add(ref dstRef, i + 5) = Unsafe.Add(ref srcRef, i + 5); + Unsafe.Add(ref dstRef, i + 6) = Unsafe.Add(ref srcRef, i + 6); + Unsafe.Add(ref dstRef, i + 7) = Unsafe.Add(ref srcRef, i + 7); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + + // ======================================================================== + // ГРУППА 4: Типы без SIMD и новые типы .NET 7 (decimal, nint, Int128, UInt128). + // Используем Unroll x4 (структуры тяжелые, х8 замусорит кэш инструкций). + // ======================================================================== + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref decimal srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~3; + + for (; i < unrollEnd; i += 4) + { + Unsafe.Add(ref dstRef, i) = (double)Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = (double)Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = (double)Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = (double)Unsafe.Add(ref srcRef, i + 3); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = (double)Unsafe.Add(ref srcRef, i); + } + +#if NET7_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref Int128 srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~3; + + for (; i < unrollEnd; i += 4) + { + Unsafe.Add(ref dstRef, i) = (double)Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = (double)Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = (double)Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = (double)Unsafe.Add(ref srcRef, i + 3); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = (double)Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref UInt128 srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~3; + + for (; i < unrollEnd; i += 4) + { + Unsafe.Add(ref dstRef, i) = (double)Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = (double)Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = (double)Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = (double)Unsafe.Add(ref srcRef, i + 3); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = (double)Unsafe.Add(ref srcRef, i); + } +#endif + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref nint srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~3; + + for (; i < unrollEnd; i += 4) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ToDoubleCore(this ReadOnlySpan source, int len, Span destination) + { + ref nuint srcRef = ref MemoryMarshal.GetReference(source); + ref double dstRef = ref MemoryMarshal.GetReference(destination); + int i = 0; + int unrollEnd = len & ~3; + + for (; i < unrollEnd; i += 4) + { + Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1); + Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2); + Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3); + } + + for (; i < len; i++) Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i); + } + + + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this byte[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is byte[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is byte[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is byte[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this sbyte[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is sbyte[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is sbyte[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is sbyte[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this short[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is short[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is short[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is short[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this ushort[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is ushort[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is ushort[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is ushort[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this int[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is int[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is int[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is int[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this uint[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is uint[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is uint[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is uint[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this nint[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is nint[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is nint[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is nint[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this nuint[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is nuint[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is nuint[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is nuint[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this long[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is long[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is long[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is long[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this ulong[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is ulong[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is ulong[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is ulong[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this float[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is float[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is float[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is float[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this decimal[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is decimal[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is decimal[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is decimal[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + +#if NET7_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this Int128[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is Int128[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is Int128[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is Int128[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static double[] ToDouble(this IEnumerable source, int count) + { + if (count == 0) return []; + int i = 0; + double[] destination = new double[count]; + ref double dstRef = ref MemoryMarshal.GetArrayDataReference(destination); + foreach (var item in source) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + return destination; + } + public static double[] ToDouble(this UInt128[] numbers) + { + if (numbers is null) return null!; + int len = numbers.Length; + if (len == 0) return []; + + var result = new double[len]; + numbers.ToDoubleCore(len, result); + return result; + } + public static List ToDouble(this List numbers) + { + if (numbers is null) return null!; + int len = numbers.Count; + if (len == 0) return []; + + var result = new double[len]; + CollectionsMarshal.AsSpan(numbers).ToDoubleCore(len, result); + return result.WrapAsList(); + } + public static void ToDouble(this ICollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is UInt128[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static void ToDouble(this IReadOnlyCollection numbers, Span destination) + { + if (numbers is null) return; + int count = numbers.Count; + if (count == 0) return; + if (destination.Length < count) + throw new ArgumentException("Destination too short"); + + if (numbers is UInt128[] array) { array.ToDoubleCore(count, destination); return; } + if (numbers is List list) { CollectionsMarshal.AsSpan(list).ToDoubleCore(count, destination); return; } + + int i = 0; + ref double dstRef = ref MemoryMarshal.GetReference(destination); + foreach (var item in numbers) + { + if ((uint)i >= (uint)count) break; + Unsafe.Add(ref dstRef, i++) = (double)item; + } + } + public static IEnumerable ToDouble(this IEnumerable numbers) + { + if (numbers is null) return null!; + if (numbers is UInt128[] array) return array.ToDouble(); + if (numbers is List list) return list.ToDouble(); + if (numbers is ICollection col) return col.ToDouble(col.Count); + if (numbers is IReadOnlyCollection roc) return roc.ToDouble(roc.Count); + return numbers.ToDoubleIterator(); + } +#endif +} \ No newline at end of file diff --git a/QWERTYkez.Mensura/Extensions/ToDouble.cs b/QWERTYkez.Mensura/Extensions/ToDouble.cs deleted file mode 100644 index 0cf525e..0000000 --- a/QWERTYkez.Mensura/Extensions/ToDouble.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace QWERTYkez.Mensura.Extensions; - -internal static partial class ToDoubleExtensions -{ - internal static double ToDouble(this sbyte number) => Convert.ToDouble(number); - internal static double ToDouble(this short number) => Convert.ToDouble(number); - internal static double ToDouble(this int number) => Convert.ToDouble(number); - internal static double ToDouble(this long number) => Convert.ToDouble(number); - internal static double ToDouble(this byte number) => Convert.ToDouble(number); - internal static double ToDouble(this ushort number) => Convert.ToDouble(number); - internal static double ToDouble(this uint number) => Convert.ToDouble(number); - internal static double ToDouble(this ulong number) => Convert.ToDouble(number); - internal static double ToDouble(this nint number) => Convert.ToDouble(number); - internal static double ToDouble(this nuint number) => Convert.ToDouble(number); - internal static double ToDouble(this float number) => Convert.ToDouble(number); - internal static double ToDouble(this decimal number) => Convert.ToDouble(number); - - internal static double ToDouble(this sbyte? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this short? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this int? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this long? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this byte? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this ushort? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this uint? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this ulong? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this nint? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this nuint? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this float? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this decimal? number) => number is null ? 0d : Convert.ToDouble(number); - -#if NET7_0_OR_GREATER - internal static double ToDouble(this Int128 number) => Convert.ToDouble(number); - internal static double ToDouble(this UInt128 number) => Convert.ToDouble(number); - - internal static double ToDouble(this Int128? number) => number is null ? 0d : Convert.ToDouble(number); - internal static double ToDouble(this UInt128? number) => number is null ? 0d : Convert.ToDouble(number); -#endif -} \ No newline at end of file diff --git a/QWERTYkez.Mensura/Units/XXXXXXXX.Gen.cs b/QWERTYkez.Mensura/Units/XXXXXXXX.Gen.cs index 7466f5d..3b36555 100644 --- a/QWERTYkez.Mensura/Units/XXXXXXXX.Gen.cs +++ b/QWERTYkez.Mensura/Units/XXXXXXXX.Gen.cs @@ -1,526 +1,649 @@ -//namespace QWERTYkez.Mensura.Units; - -//[JsonConverter(typeof(UnitJsonConverter))] -//public readonly partial record struct XXXXXXXX : IMensuraUnit, IEquatable, IMensuraUnit -//{ -// [JsonInclude, DataMember, JsonPropertyName("v"), Obsolete] // для JSON / EF на случай сбоев, если пробелма с _Value -// internal double Value { get => _Value; init => _Value = value; } -// internal readonly double _Value; -// internal XXXXXXXX(double value) => _Value = value; - -// public override int GetHashCode() => _Value.GetHashCode(); -// public int CompareTo(XXXXXXXX? other) => _Value.CompareTo(other is null ? 0d : other.Value._Value); -// public int CompareTo(XXXXXXXX other) => _Value.CompareTo(other._Value); - -// public bool Equals(XXXXXXXX? other) => _Value.Equals(other?._Value); - - -// public static explicit operator XXXXXXXX(double val) => Unsafe.As(ref val); -// public static explicit operator double(XXXXXXXX unit) => unit._Value; - - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// public XXXXXXXX Abs() => new(Math.Abs(_Value)); - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// internal R Pow2_Internal() where R : struct, IMensuraUnit, IEquatable => (_Value * _Value).ToUnit(); - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// internal R Sqrt_Internal() where R : struct, IMensuraUnit, IEquatable => Math.Sqrt(_Value).ToUnit(); - - - -// [JsonIgnore, IgnoreDataMember] public bool IsPositive => _Value >= 0; -// [JsonIgnore, IgnoreDataMember] public bool IsGreaterThanZero => _Value > 0; -// [JsonIgnore, IgnoreDataMember] public bool IsNegative => double.IsNegative(_Value); -// [JsonIgnore, IgnoreDataMember] public bool IsZero => _Value == 0; -// [JsonIgnore, IgnoreDataMember] public bool IsNaN => double.IsNaN(_Value); -// [JsonIgnore, IgnoreDataMember] public bool IsFinite => double.IsFinite(_Value); -// [JsonIgnore, IgnoreDataMember] public bool IsInfinity => double.IsInfinity(_Value); -// [JsonIgnore, IgnoreDataMember] public bool IsPositiveInfinity => double.IsPositiveInfinity(_Value); -// [JsonIgnore, IgnoreDataMember] public bool IsNegativeInfinity => double.IsNegativeInfinity(_Value); - - -// public static XXXXXXXX Zero { get; } = new(0d); -// public static XXXXXXXX Min { get; } = new(double.MinValue); -// public static XXXXXXXX Max { get; } = new(double.MaxValue); -// public static XXXXXXXX NegativeInfinity { get; } = new(double.NegativeInfinity); -// public static XXXXXXXX PositiveInfinity { get; } = new(double.PositiveInfinity); - -// public static bool operator ==(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() == T2.Protected(); -// public static bool operator !=(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() != T2.Protected(); - -// public static bool operator <(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() < T2.Protected(); -// public static bool operator <=(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() <= T2.Protected(); -// public static bool operator >(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() > T2.Protected(); -// public static bool operator >=(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() >= T2.Protected(); - - -// public static XXXXXXXX operator +(XXXXXXXX T2) => new(+T2._Value); -// public static XXXXXXXX operator +(XXXXXXXX T1, XXXXXXXX T2) => new(T1._Value + T2._Value); -// public static XXXXXXXX operator -(XXXXXXXX T2) => new(-T2._Value); -// public static XXXXXXXX operator -(XXXXXXXX T1, XXXXXXXX T2) => new(T1._Value - T2._Value); - - -// // double -// public static XXXXXXXX operator *(XXXXXXXX T1, double T2) => new(T1._Value * T2); -// public static XXXXXXXX operator *(XXXXXXXX T1, double? T2) => T1 * (T2 ?? 0d); -// public static XXXXXXXX operator *(double T1, XXXXXXXX T2) => new(T1 * T2._Value); -// public static XXXXXXXX operator *(double? T1, XXXXXXXX T2) => (T1 ?? 0d) * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, double T2) => new(T1._Value / T2); -// public static XXXXXXXX operator /(XXXXXXXX T1, double? T2) => T1 / (T2 ?? 0d); -// public static double operator /(XXXXXXXX T1, XXXXXXXX T2) => T1._Value / T2._Value; - -// // sbyte -// public static XXXXXXXX operator *(XXXXXXXX T1, sbyte T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, sbyte? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(sbyte T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(sbyte? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, sbyte T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, sbyte? T2) => T1 / T2.ToDouble(); - -// // short -// public static XXXXXXXX operator *(XXXXXXXX T1, short T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, short? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(short T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(short? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, short T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, short? T2) => T1 / T2.ToDouble(); - -// // int -// public static XXXXXXXX operator *(XXXXXXXX T1, int T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, int? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(int T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(int? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, int T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, int? T2) => T1 / T2.ToDouble(); - -// // long -// public static XXXXXXXX operator *(XXXXXXXX T1, long T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, long? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(long T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(long? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, long T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, long? T2) => T1 / T2.ToDouble(); - -// // byte -// public static XXXXXXXX operator *(XXXXXXXX T1, byte T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, byte? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(byte T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(byte? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, byte T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, byte? T2) => T1 / T2.ToDouble(); - -// // ushort -// public static XXXXXXXX operator *(XXXXXXXX T1, ushort T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, ushort? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(ushort T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(ushort? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, ushort T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, ushort? T2) => T1 / T2.ToDouble(); - -// // uint -// public static XXXXXXXX operator *(XXXXXXXX T1, uint T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, uint? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(uint T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(uint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, uint T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, uint? T2) => T1 / T2.ToDouble(); - -// // ulong -// public static XXXXXXXX operator *(XXXXXXXX T1, ulong T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, ulong? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(ulong T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(ulong? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, ulong T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, ulong? T2) => T1 / T2.ToDouble(); - -// // nint -// public static XXXXXXXX operator *(XXXXXXXX T1, nint T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, nint? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(nint T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(nint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, nint T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, nint? T2) => T1 / T2.ToDouble(); - -// // nuint -// public static XXXXXXXX operator *(XXXXXXXX T1, nuint T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, nuint? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(nuint T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(nuint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, nuint T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, nuint? T2) => T1 / T2.ToDouble(); - -// // float -// public static XXXXXXXX operator *(XXXXXXXX T1, float T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, float? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(float T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(float? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, float T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, float? T2) => T1 / T2.ToDouble(); - -// // decimal -// public static XXXXXXXX operator *(XXXXXXXX T1, decimal T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, decimal? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(decimal T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(decimal? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, decimal T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, decimal? T2) => T1 / T2.ToDouble(); - -//#if NET7_0_OR_GREATER -// // Int128 -// public static XXXXXXXX operator *(XXXXXXXX T1, Int128 T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, Int128? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(Int128 T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(Int128? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, Int128 T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, Int128? T2) => T1 / T2.ToDouble(); - -// // UInt128 -// public static XXXXXXXX operator *(XXXXXXXX T1, UInt128 T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(XXXXXXXX T1, UInt128? T2) => T1 * T2.ToDouble(); -// public static XXXXXXXX operator *(UInt128 T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator *(UInt128? T1, XXXXXXXX T2) => T1.ToDouble() * T2; -// public static XXXXXXXX operator /(XXXXXXXX T1, UInt128 T2) => T1 / T2.ToDouble(); -// public static XXXXXXXX operator /(XXXXXXXX T1, UInt128? T2) => T1 / T2.ToDouble(); -//#endif -//} - -//public static class XXXXXXXXExtensions -//{ -// public static double Protected(this XXXXXXXX? unit) => unit is null ? 0d : unit.Value._Value; - - - - - - -// // === ReadOnlySpan -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan units, -// double divisor, Span destination) => units.Div(divisor, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan units, -// double divisor, Span destination) => units.Div(divisor, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, -// ReadOnlySpan units, Span destination) => dividend.Div(units, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, -// ReadOnlySpan units, Span destination) => dividend.Div(units, destination); - -// // === Array === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Div( -// this XXXXXXXX[] units, double divisor) => units.Div(divisor); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Div( -// this XXXXXXXX?[] units, double divisor) => units.Div(divisor); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Div( -// this double dividend, XXXXXXXX[] units) => dividend.Div(units); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Div( -// this double dividend, XXXXXXXX?[] units) => dividend.Div(units); - -// // === List === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( -// this List units, double divisor) => units.Div(divisor); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( -// this List units, double divisor) => units.Div(divisor); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( -// this double dividend, List units) => dividend.Div(units); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( -// this double dividend, List units) => dividend.Div(units); - -// // === ICollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ICollection units, -// double divisor, Span destination) => units.Div(divisor, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ICollection units, -// double divisor, Span destination) => units.Div(divisor, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, -// ICollection units, Span destination) => dividend.Div(units, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, -// ICollection units, Span destination) => dividend.Div(units, destination); - -// // === IReadOnlyCollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Div(this IReadOnlyCollection units, -// double divisor, Span destination) => units.Div(divisor, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Div(this IReadOnlyCollection units, -// double divisor, Span destination) => units.Div(divisor, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, -// IReadOnlyCollection units, Span destination) => dividend.Div(units, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, -// IReadOnlyCollection units, Span destination) => dividend.Div(units, destination); - -// // === IEnumerable === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( -// this IEnumerable units, double divisor) => units.Div(divisor); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( -// this IEnumerable units, double divisor) => units.Div(divisor); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( -// this double dividend, IEnumerable units) => dividend.Div(units); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( -// this double dividend, IEnumerable units) => dividend.Div(units); - - - - - - -// // === ReadOnlySpan -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ReadOnlySpan units, -// double subtrahend, Span destination) => units.Minus(subtrahend, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ReadOnlySpan units, -// double subtrahend, Span destination) => units.Minus(subtrahend, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, -// ReadOnlySpan units, Span destination) => minuend.Minus(units, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, -// ReadOnlySpan units, Span destination) => minuend.Minus(units, destination); - -// // === Array === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Minus( -// this XXXXXXXX[] units, double subtrahend) => units.Minus(subtrahend); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Minus( -// this XXXXXXXX?[] units, double subtrahend) => units.Minus(subtrahend); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Minus( -// this double minuend, XXXXXXXX[] units) => minuend.Minus(units); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Minus( -// this double minuend, XXXXXXXX?[] units) => minuend.Minus(units); - -// // === List === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( -// this List units, double subtrahend) => units.Minus(subtrahend); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( -// this List units, double subtrahend) => units.Minus(subtrahend); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( -// this double minuend, List units) => minuend.Minus(units); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( -// this double minuend, List units) => minuend.Minus(units); - -// // === ICollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ICollection units, -// double subtrahend, Span destination) => units.Minus(subtrahend, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ICollection units, -// double subtrahend, Span destination) => units.Minus(subtrahend, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, -// ICollection units, Span destination) => minuend.Minus(units, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, -// ICollection units, Span destination) => minuend.Minus(units, destination); - -// // === IReadOnlyCollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Minus(this IReadOnlyCollection units, -// double subtrahend, Span destination) => units.Minus(subtrahend, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Minus(this IReadOnlyCollection units, -// double subtrahend, Span destination) => units.Minus(subtrahend, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, -// IReadOnlyCollection units, Span destination) => minuend.Minus(units, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, -// IReadOnlyCollection units, Span destination) => minuend.Minus(units, destination); - -// // === IEnumerable === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( -// this IEnumerable units, double subtrahend) => units.Minus(subtrahend); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( -// this IEnumerable units, double subtrahend) => units.Minus(subtrahend); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( -// this double minuend, IEnumerable units) => minuend.Minus(units); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( -// this double minuend, IEnumerable units) => minuend.Minus(units); - - - - - - -// // === ReadOnlySpan -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ReadOnlySpan units, -// double multiplicator, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ReadOnlySpan units, -// double multiplicator, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, -// ReadOnlySpan units, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, -// ReadOnlySpan units, Span destination) => units.Mul(multiplicator, destination); - -// // === Array === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Mul( -// this XXXXXXXX[] units, double multiplicator) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Mul( -// this XXXXXXXX?[] units, double multiplicator) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Mul( -// this double multiplicator, XXXXXXXX[] units) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Mul( -// this double multiplicator, XXXXXXXX?[] units) => units.Mul(multiplicator); - -// // === List === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( -// this List units, double multiplicator) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( -// this List units, double multiplicator) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( -// this double multiplicator, List units) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( -// this double multiplicator, List units) => units.Mul(multiplicator); - -// // === ICollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ICollection units, -// double multiplicator, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ICollection units, -// double multiplicator, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, -// ICollection units, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, -// ICollection units, Span destination) => units.Mul(multiplicator, destination); - -// // === IReadOnlyCollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Mul(this IReadOnlyCollection units, -// double multiplicator, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Mul(this IReadOnlyCollection units, -// double multiplicator, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, -// IReadOnlyCollection units, Span destination) => units.Mul(multiplicator, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, -// IReadOnlyCollection units, Span destination) => units.Mul(multiplicator, destination); - -// // === IEnumerable === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( -// this IEnumerable units, double multiplicator) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( -// this IEnumerable units, double multiplicator) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( -// this double multiplicator, IEnumerable units) => units.Mul(multiplicator); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( -// this double multiplicator, IEnumerable units) => units.Mul(multiplicator); - - - - - - -// // === ReadOnlySpan -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ReadOnlySpan units, -// double summand, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ReadOnlySpan units, -// double summand, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, -// ReadOnlySpan units, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, -// ReadOnlySpan units, Span destination) => units.Plus(summand, destination); - -// // === Array === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Plus( -// this XXXXXXXX[] units, double summand) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Plus( -// this XXXXXXXX?[] units, double summand) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Plus( -// this double summand, XXXXXXXX[] units) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Plus( -// this double summand, XXXXXXXX?[] units) => units.Plus(summand); - -// // === List === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( -// this List units, double summand) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( -// this List units, double summand) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( -// this double summand, List units) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( -// this double summand, List units) => units.Plus(summand); - -// // === ICollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ICollection units, -// double summand, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ICollection units, -// double summand, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, -// ICollection units, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, -// ICollection units, Span destination) => units.Plus(summand, destination); - -// // === IReadOnlyCollection === -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Plus(this IReadOnlyCollection units, -// double summand, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Plus(this IReadOnlyCollection units, -// double summand, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, -// IReadOnlyCollection units, Span destination) => units.Plus(summand, destination); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, -// IReadOnlyCollection units, Span destination) => units.Plus(summand, destination); - -// // === IEnumerable === -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( -// this IEnumerable units, double summand) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( -// this IEnumerable units, double summand) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( -// this double summand, IEnumerable units) => units.Plus(summand); -// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( -// this double summand, IEnumerable units) => units.Plus(summand); - - - - - - -// // Sum Average Max Min (не nullable) ========================================== - - -// // === ReadOnlySpan === SIMD -// public static XXXXXXXX Sum(this ReadOnlySpan units) => AggregateUnitExtensions.Sum(units); -// public static XXXXXXXX Average(this ReadOnlySpan units) => AggregateUnitExtensions.Average(units); -// public static XXXXXXXX Max(this ReadOnlySpan units) => AggregateUnitExtensions.Max(units); -// public static XXXXXXXX Min(this ReadOnlySpan units) => AggregateUnitExtensions.Min(units); - -// // === List === -// public static XXXXXXXX Sum(this List list) => AggregateUnitExtensions.Sum(list); -// public static XXXXXXXX Average(this List list) => AggregateUnitExtensions.Average(list); -// public static XXXXXXXX Max(this List list) => AggregateUnitExtensions.Max(list); -// public static XXXXXXXX Min(this List list) => AggregateUnitExtensions.Min(list); - -// // === ICollection === -// public static XXXXXXXX Sum(this ICollection collection) => AggregateUnitExtensions.Sum(collection); -// public static XXXXXXXX Average(this ICollection collection) => AggregateUnitExtensions.Average(collection); -// public static XXXXXXXX Max(this ICollection collection) => AggregateUnitExtensions.Max(collection); -// public static XXXXXXXX Min(this ICollection collection) => AggregateUnitExtensions.Min(collection); - -// // === IReadOnlyCollection === -// public static XXXXXXXX Sum(this IReadOnlyCollection collection) => AggregateUnitExtensions.Sum(collection); -// public static XXXXXXXX Average(this IReadOnlyCollection collection) => AggregateUnitExtensions.Average(collection); -// public static XXXXXXXX Max(this IReadOnlyCollection collection) => AggregateUnitExtensions.Max(collection); -// public static XXXXXXXX Min(this IReadOnlyCollection collection) => AggregateUnitExtensions.Min(collection); - - -// // === IEnumerable === -// public static XXXXXXXX Sum(this IEnumerable collection) => AggregateUnitExtensions.Sum(collection); -// public static XXXXXXXX Average(this IEnumerable collection) => AggregateUnitExtensions.Average(collection); -// public static XXXXXXXX Max(this IEnumerable collection) => AggregateUnitExtensions.Max(collection); -// public static XXXXXXXX Min(this IEnumerable collection) => AggregateUnitExtensions.Min(collection); - - - -// // Sum Average Max Min (nullable) ========================================== - - -// // === ReadOnlySpan === -// public static XXXXXXXX Sum(this ReadOnlySpan units) => AggregateUnitExtensions.Sum(units); -// public static XXXXXXXX Average(this ReadOnlySpan units) => AggregateUnitExtensions.Average(units); -// public static XXXXXXXX Max(this ReadOnlySpan units) => AggregateUnitExtensions.Max(units); -// public static XXXXXXXX Min(this ReadOnlySpan units) => AggregateUnitExtensions.Min(units); - -// // === List === -// public static XXXXXXXX Sum(this List list) => AggregateUnitExtensions.Sum(list); -// public static XXXXXXXX Average(this List list) => AggregateUnitExtensions.Average(list); -// public static XXXXXXXX Max(this List list) => AggregateUnitExtensions.Max(list); -// public static XXXXXXXX Min(this List list) => AggregateUnitExtensions.Min(list); - -// // === ICollection === -// public static XXXXXXXX Sum(this ICollection collection) => AggregateUnitExtensions.Sum(collection); -// public static XXXXXXXX Average(this ICollection collection) => AggregateUnitExtensions.Average(collection); -// public static XXXXXXXX Max(this ICollection collection) => AggregateUnitExtensions.Max(collection); -// public static XXXXXXXX Min(this ICollection collection) => AggregateUnitExtensions.Min(collection); - -// // === IReadOnlyCollection === -// public static XXXXXXXX Sum(this IReadOnlyCollection collection) => AggregateUnitExtensions.Sum(collection); -// public static XXXXXXXX Average(this IReadOnlyCollection collection) => AggregateUnitExtensions.Average(collection); -// public static XXXXXXXX Max(this IReadOnlyCollection collection) => AggregateUnitExtensions.Max(collection); -// public static XXXXXXXX Min(this IReadOnlyCollection collection) => AggregateUnitExtensions.Min(collection); - -// // === IEnumerable === -// public static XXXXXXXX Sum(this IEnumerable collection) => AggregateUnitExtensions.Sum(collection); -// public static XXXXXXXX Average(this IEnumerable collection) => AggregateUnitExtensions.Average(collection); -// public static XXXXXXXX Max(this IEnumerable collection) => AggregateUnitExtensions.Max(collection); -// public static XXXXXXXX Min(this IEnumerable collection) => AggregateUnitExtensions.Min(collection); -//} \ No newline at end of file +namespace QWERTYkez.Mensura.Units; + +[JsonConverter(typeof(UnitJsonConverter))] +public readonly partial record struct XXXXXXXX : IMensuraUnit, IEquatable, IMensuraUnit +{ + [JsonInclude, DataMember, JsonPropertyName("v"), Obsolete] // для JSON / EF на случай сбоев, если пробелма с _Value + internal double Value { get => _Value; init => _Value = value; } + internal readonly double _Value; + internal XXXXXXXX(double value) => _Value = value; + + public override int GetHashCode() => _Value.GetHashCode(); + public int CompareTo(XXXXXXXX? other) => _Value.CompareTo(other is null ? 0d : other.Value._Value); + public int CompareTo(XXXXXXXX other) => _Value.CompareTo(other._Value); + + public bool Equals(XXXXXXXX? other) => _Value.Equals(other?._Value); + + + public static explicit operator XXXXXXXX(double val) => Unsafe.As(ref val); + public static explicit operator double(XXXXXXXX unit) => unit._Value; + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public XXXXXXXX Abs() => new(Math.Abs(_Value)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal R Pow2_Internal() where R : struct, IMensuraUnit, IEquatable => (_Value * _Value).ToUnit(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal R Sqrt_Internal() where R : struct, IMensuraUnit, IEquatable => Math.Sqrt(_Value).ToUnit(); + + + + [JsonIgnore, IgnoreDataMember] public bool IsPositive => _Value >= 0; + [JsonIgnore, IgnoreDataMember] public bool IsGreaterThanZero => _Value > 0; + [JsonIgnore, IgnoreDataMember] public bool IsNegative => double.IsNegative(_Value); + [JsonIgnore, IgnoreDataMember] public bool IsZero => _Value == 0; + [JsonIgnore, IgnoreDataMember] public bool IsNaN => double.IsNaN(_Value); + [JsonIgnore, IgnoreDataMember] public bool IsFinite => double.IsFinite(_Value); + [JsonIgnore, IgnoreDataMember] public bool IsInfinity => double.IsInfinity(_Value); + [JsonIgnore, IgnoreDataMember] public bool IsPositiveInfinity => double.IsPositiveInfinity(_Value); + [JsonIgnore, IgnoreDataMember] public bool IsNegativeInfinity => double.IsNegativeInfinity(_Value); + + + public static XXXXXXXX Zero { get; } = new(0d); + public static XXXXXXXX Min { get; } = new(double.MinValue); + public static XXXXXXXX Max { get; } = new(double.MaxValue); + public static XXXXXXXX NegativeInfinity { get; } = new(double.NegativeInfinity); + public static XXXXXXXX PositiveInfinity { get; } = new(double.PositiveInfinity); + + public static bool operator ==(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() == T2.Protected(); + public static bool operator !=(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() != T2.Protected(); + + public static bool operator <(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() < T2.Protected(); + public static bool operator <=(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() <= T2.Protected(); + public static bool operator >(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() > T2.Protected(); + public static bool operator >=(XXXXXXXX? T1, XXXXXXXX? T2) => T1.Protected() >= T2.Protected(); + + + public static XXXXXXXX operator +(XXXXXXXX T2) => new(+T2._Value); + public static XXXXXXXX operator +(XXXXXXXX T1, XXXXXXXX T2) => new(T1._Value + T2._Value); + public static XXXXXXXX operator -(XXXXXXXX T2) => new(-T2._Value); + public static XXXXXXXX operator -(XXXXXXXX T1, XXXXXXXX T2) => new(T1._Value - T2._Value); + + + // double + public static XXXXXXXX operator *(XXXXXXXX T1, double T2) => new(T1._Value * T2); + public static XXXXXXXX operator *(XXXXXXXX T1, double? T2) => T1 * (T2 ?? 0d); + public static XXXXXXXX operator *(double T1, XXXXXXXX T2) => new(T1 * T2._Value); + public static XXXXXXXX operator *(double? T1, XXXXXXXX T2) => (T1 ?? 0d) * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, double T2) => new(T1._Value / T2); + public static XXXXXXXX operator /(XXXXXXXX T1, double? T2) => T1 / (T2 ?? 0d); + public static double operator /(XXXXXXXX T1, XXXXXXXX T2) => T1._Value / T2._Value; + + // sbyte + public static XXXXXXXX operator *(XXXXXXXX T1, sbyte T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, sbyte? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(sbyte T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(sbyte? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, sbyte T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, sbyte? T2) => T1 / T2.ToDouble(); + + // short + public static XXXXXXXX operator *(XXXXXXXX T1, short T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, short? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(short T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(short? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, short T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, short? T2) => T1 / T2.ToDouble(); + + // int + public static XXXXXXXX operator *(XXXXXXXX T1, int T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, int? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(int T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(int? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, int T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, int? T2) => T1 / T2.ToDouble(); + + // long + public static XXXXXXXX operator *(XXXXXXXX T1, long T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, long? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(long T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(long? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, long T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, long? T2) => T1 / T2.ToDouble(); + + // byte + public static XXXXXXXX operator *(XXXXXXXX T1, byte T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, byte? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(byte T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(byte? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, byte T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, byte? T2) => T1 / T2.ToDouble(); + + // ushort + public static XXXXXXXX operator *(XXXXXXXX T1, ushort T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, ushort? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(ushort T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(ushort? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, ushort T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, ushort? T2) => T1 / T2.ToDouble(); + + // uint + public static XXXXXXXX operator *(XXXXXXXX T1, uint T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, uint? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(uint T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(uint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, uint T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, uint? T2) => T1 / T2.ToDouble(); + + // ulong + public static XXXXXXXX operator *(XXXXXXXX T1, ulong T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, ulong? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(ulong T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(ulong? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, ulong T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, ulong? T2) => T1 / T2.ToDouble(); + + // nint + public static XXXXXXXX operator *(XXXXXXXX T1, nint T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, nint? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(nint T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(nint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, nint T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, nint? T2) => T1 / T2.ToDouble(); + + // nuint + public static XXXXXXXX operator *(XXXXXXXX T1, nuint T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, nuint? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(nuint T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(nuint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, nuint T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, nuint? T2) => T1 / T2.ToDouble(); + + // float + public static XXXXXXXX operator *(XXXXXXXX T1, float T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, float? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(float T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(float? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, float T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, float? T2) => T1 / T2.ToDouble(); + + // decimal + public static XXXXXXXX operator *(XXXXXXXX T1, decimal T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, decimal? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(decimal T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(decimal? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, decimal T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, decimal? T2) => T1 / T2.ToDouble(); + +#if NET7_0_OR_GREATER + // Int128 + public static XXXXXXXX operator *(XXXXXXXX T1, Int128 T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, Int128? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(Int128 T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(Int128? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, Int128 T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, Int128? T2) => T1 / T2.ToDouble(); + + // UInt128 + public static XXXXXXXX operator *(XXXXXXXX T1, UInt128 T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, UInt128? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(UInt128 T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(UInt128? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, UInt128 T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, UInt128? T2) => T1 / T2.ToDouble(); +#endif + + + + // double + public static XXXXXXXX operator *(XXXXXXXX T1, double[] T2) => new(T1._Value * T2); + public static XXXXXXXX operator *(double[] T1, XXXXXXXX T2) => new(T1 * T2._Value); + public static XXXXXXXX operator /(XXXXXXXX T1, double[] T2) => new(T1._Value / T2); + public static double operator /(XXXXXXXX T1, XXXXXXXX[] T2) => T1._Value / T2._Value; + public static double operator /(XXXXXXXX[] T1, XXXXXXXX T2) => T1._Value / T2._Value; + + // sbyte + public static XXXXXXXX operator *(XXXXXXXX T1, sbyte T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, sbyte? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(sbyte T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(sbyte? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, sbyte T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, sbyte? T2) => T1 / T2.ToDouble(); + + // short + public static XXXXXXXX operator *(XXXXXXXX T1, short T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, short? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(short T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(short? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, short T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, short? T2) => T1 / T2.ToDouble(); + + // int + public static XXXXXXXX operator *(XXXXXXXX T1, int T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, int? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(int T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(int? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, int T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, int? T2) => T1 / T2.ToDouble(); + + // long + public static XXXXXXXX operator *(XXXXXXXX T1, long T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, long? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(long T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(long? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, long T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, long? T2) => T1 / T2.ToDouble(); + + // byte + public static XXXXXXXX operator *(XXXXXXXX T1, byte T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, byte? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(byte T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(byte? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, byte T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, byte? T2) => T1 / T2.ToDouble(); + + // ushort + public static XXXXXXXX operator *(XXXXXXXX T1, ushort T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, ushort? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(ushort T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(ushort? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, ushort T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, ushort? T2) => T1 / T2.ToDouble(); + + // uint + public static XXXXXXXX operator *(XXXXXXXX T1, uint T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, uint? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(uint T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(uint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, uint T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, uint? T2) => T1 / T2.ToDouble(); + + // ulong + public static XXXXXXXX operator *(XXXXXXXX T1, ulong T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, ulong? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(ulong T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(ulong? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, ulong T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, ulong? T2) => T1 / T2.ToDouble(); + + // nint + public static XXXXXXXX operator *(XXXXXXXX T1, nint T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, nint? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(nint T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(nint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, nint T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, nint? T2) => T1 / T2.ToDouble(); + + // nuint + public static XXXXXXXX operator *(XXXXXXXX T1, nuint T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, nuint? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(nuint T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(nuint? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, nuint T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, nuint? T2) => T1 / T2.ToDouble(); + + // float + public static XXXXXXXX operator *(XXXXXXXX T1, float T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, float? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(float T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(float? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, float T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, float? T2) => T1 / T2.ToDouble(); + + // decimal + public static XXXXXXXX operator *(XXXXXXXX T1, decimal T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, decimal? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(decimal T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(decimal? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, decimal T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, decimal? T2) => T1 / T2.ToDouble(); + +#if NET7_0_OR_GREATER + // Int128 + public static XXXXXXXX operator *(XXXXXXXX T1, Int128 T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, Int128? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(Int128 T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(Int128? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, Int128 T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, Int128? T2) => T1 / T2.ToDouble(); + + // UInt128 + public static XXXXXXXX operator *(XXXXXXXX T1, UInt128 T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(XXXXXXXX T1, UInt128? T2) => T1 * T2.ToDouble(); + public static XXXXXXXX operator *(UInt128 T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator *(UInt128? T1, XXXXXXXX T2) => T1.ToDouble() * T2; + public static XXXXXXXX operator /(XXXXXXXX T1, UInt128 T2) => T1 / T2.ToDouble(); + public static XXXXXXXX operator /(XXXXXXXX T1, UInt128? T2) => T1 / T2.ToDouble(); +#endif +} + +public static class XXXXXXXXExtensions +{ + public static double Protected(this XXXXXXXX? unit) => unit is null ? 0d : unit.Value._Value; + + + + + + + // === ReadOnlySpan + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan units, + double divisor, Span destination) => units.Div(divisor, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan units, + double divisor, Span destination) => units.Div(divisor, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, + ReadOnlySpan units, Span destination) => dividend.Div(units, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, + ReadOnlySpan units, Span destination) => dividend.Div(units, destination); + + // === Array === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Div( + this XXXXXXXX[] units, double divisor) => units.Div(divisor); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Div( + this XXXXXXXX?[] units, double divisor) => units.Div(divisor); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Div( + this double dividend, XXXXXXXX[] units) => dividend.Div(units); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Div( + this double dividend, XXXXXXXX?[] units) => dividend.Div(units); + + // === List === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( + this List units, double divisor) => units.Div(divisor); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( + this List units, double divisor) => units.Div(divisor); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( + this double dividend, List units) => dividend.Div(units); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Div( + this double dividend, List units) => dividend.Div(units); + + // === ICollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ICollection units, + double divisor, Span destination) => units.Div(divisor, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ICollection units, + double divisor, Span destination) => units.Div(divisor, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, + ICollection units, Span destination) => dividend.Div(units, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, + ICollection units, Span destination) => dividend.Div(units, destination); + + // === IReadOnlyCollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Div(this IReadOnlyCollection units, + double divisor, Span destination) => units.Div(divisor, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Div(this IReadOnlyCollection units, + double divisor, Span destination) => units.Div(divisor, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, + IReadOnlyCollection units, Span destination) => dividend.Div(units, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend, + IReadOnlyCollection units, Span destination) => dividend.Div(units, destination); + + // === IEnumerable === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( + this IEnumerable units, double divisor) => units.Div(divisor); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( + this IEnumerable units, double divisor) => units.Div(divisor); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( + this double dividend, IEnumerable units) => dividend.Div(units); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Div( + this double dividend, IEnumerable units) => dividend.Div(units); + + + + + + + // === ReadOnlySpan + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ReadOnlySpan units, + double subtrahend, Span destination) => units.Minus(subtrahend, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ReadOnlySpan units, + double subtrahend, Span destination) => units.Minus(subtrahend, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, + ReadOnlySpan units, Span destination) => minuend.Minus(units, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, + ReadOnlySpan units, Span destination) => minuend.Minus(units, destination); + + // === Array === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Minus( + this XXXXXXXX[] units, double subtrahend) => units.Minus(subtrahend); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Minus( + this XXXXXXXX?[] units, double subtrahend) => units.Minus(subtrahend); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Minus( + this double minuend, XXXXXXXX[] units) => minuend.Minus(units); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Minus( + this double minuend, XXXXXXXX?[] units) => minuend.Minus(units); + + // === List === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( + this List units, double subtrahend) => units.Minus(subtrahend); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( + this List units, double subtrahend) => units.Minus(subtrahend); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( + this double minuend, List units) => minuend.Minus(units); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Minus( + this double minuend, List units) => minuend.Minus(units); + + // === ICollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ICollection units, + double subtrahend, Span destination) => units.Minus(subtrahend, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ICollection units, + double subtrahend, Span destination) => units.Minus(subtrahend, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, + ICollection units, Span destination) => minuend.Minus(units, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, + ICollection units, Span destination) => minuend.Minus(units, destination); + + // === IReadOnlyCollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Minus(this IReadOnlyCollection units, + double subtrahend, Span destination) => units.Minus(subtrahend, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Minus(this IReadOnlyCollection units, + double subtrahend, Span destination) => units.Minus(subtrahend, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, + IReadOnlyCollection units, Span destination) => minuend.Minus(units, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend, + IReadOnlyCollection units, Span destination) => minuend.Minus(units, destination); + + // === IEnumerable === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( + this IEnumerable units, double subtrahend) => units.Minus(subtrahend); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( + this IEnumerable units, double subtrahend) => units.Minus(subtrahend); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( + this double minuend, IEnumerable units) => minuend.Minus(units); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Minus( + this double minuend, IEnumerable units) => minuend.Minus(units); + + + + + + + // === ReadOnlySpan + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ReadOnlySpan units, + double multiplicator, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ReadOnlySpan units, + double multiplicator, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, + ReadOnlySpan units, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, + ReadOnlySpan units, Span destination) => units.Mul(multiplicator, destination); + + // === Array === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Mul( + this XXXXXXXX[] units, double multiplicator) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Mul( + this XXXXXXXX?[] units, double multiplicator) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Mul( + this double multiplicator, XXXXXXXX[] units) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Mul( + this double multiplicator, XXXXXXXX?[] units) => units.Mul(multiplicator); + + // === List === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( + this List units, double multiplicator) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( + this List units, double multiplicator) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( + this double multiplicator, List units) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Mul( + this double multiplicator, List units) => units.Mul(multiplicator); + + // === ICollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ICollection units, + double multiplicator, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ICollection units, + double multiplicator, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, + ICollection units, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, + ICollection units, Span destination) => units.Mul(multiplicator, destination); + + // === IReadOnlyCollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Mul(this IReadOnlyCollection units, + double multiplicator, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Mul(this IReadOnlyCollection units, + double multiplicator, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, + IReadOnlyCollection units, Span destination) => units.Mul(multiplicator, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator, + IReadOnlyCollection units, Span destination) => units.Mul(multiplicator, destination); + + // === IEnumerable === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( + this IEnumerable units, double multiplicator) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( + this IEnumerable units, double multiplicator) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( + this double multiplicator, IEnumerable units) => units.Mul(multiplicator); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Mul( + this double multiplicator, IEnumerable units) => units.Mul(multiplicator); + + + + + + + // === ReadOnlySpan + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ReadOnlySpan units, + double summand, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ReadOnlySpan units, + double summand, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, + ReadOnlySpan units, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, + ReadOnlySpan units, Span destination) => units.Plus(summand, destination); + + // === Array === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static XXXXXXXX[] Plus( + this XXXXXXXX[] units, double summand) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Plus( + this XXXXXXXX?[] units, double summand) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX[] Plus( + this double summand, XXXXXXXX[] units) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XXXXXXXX?[] Plus( + this double summand, XXXXXXXX?[] units) => units.Plus(summand); + + // === List === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( + this List units, double summand) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( + this List units, double summand) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( + this double summand, List units) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List Plus( + this double summand, List units) => units.Plus(summand); + + // === ICollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ICollection units, + double summand, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ICollection units, + double summand, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, + ICollection units, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, + ICollection units, Span destination) => units.Plus(summand, destination); + + // === IReadOnlyCollection === + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Plus(this IReadOnlyCollection units, + double summand, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Plus(this IReadOnlyCollection units, + double summand, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, + IReadOnlyCollection units, Span destination) => units.Plus(summand, destination); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand, + IReadOnlyCollection units, Span destination) => units.Plus(summand, destination); + + // === IEnumerable === + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( + this IEnumerable units, double summand) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( + this IEnumerable units, double summand) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( + this double summand, IEnumerable units) => units.Plus(summand); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Plus( + this double summand, IEnumerable units) => units.Plus(summand); + + + + + + + // Sum Average Max Min (не nullable) ========================================== + + + // === ReadOnlySpan === SIMD + public static XXXXXXXX Sum(this ReadOnlySpan units) => AggregateUnitExtensions.Sum(units); + public static XXXXXXXX Average(this ReadOnlySpan units) => AggregateUnitExtensions.Average(units); + public static XXXXXXXX Max(this ReadOnlySpan units) => AggregateUnitExtensions.Max(units); + public static XXXXXXXX Min(this ReadOnlySpan units) => AggregateUnitExtensions.Min(units); + + // === List === + public static XXXXXXXX Sum(this List list) => AggregateUnitExtensions.Sum(list); + public static XXXXXXXX Average(this List list) => AggregateUnitExtensions.Average(list); + public static XXXXXXXX Max(this List list) => AggregateUnitExtensions.Max(list); + public static XXXXXXXX Min(this List list) => AggregateUnitExtensions.Min(list); + + // === ICollection === + public static XXXXXXXX Sum(this ICollection collection) => AggregateUnitExtensions.Sum(collection); + public static XXXXXXXX Average(this ICollection collection) => AggregateUnitExtensions.Average(collection); + public static XXXXXXXX Max(this ICollection collection) => AggregateUnitExtensions.Max(collection); + public static XXXXXXXX Min(this ICollection collection) => AggregateUnitExtensions.Min(collection); + + // === IReadOnlyCollection === + public static XXXXXXXX Sum(this IReadOnlyCollection collection) => AggregateUnitExtensions.Sum(collection); + public static XXXXXXXX Average(this IReadOnlyCollection collection) => AggregateUnitExtensions.Average(collection); + public static XXXXXXXX Max(this IReadOnlyCollection collection) => AggregateUnitExtensions.Max(collection); + public static XXXXXXXX Min(this IReadOnlyCollection collection) => AggregateUnitExtensions.Min(collection); + + + // === IEnumerable === + public static XXXXXXXX Sum(this IEnumerable collection) => AggregateUnitExtensions.Sum(collection); + public static XXXXXXXX Average(this IEnumerable collection) => AggregateUnitExtensions.Average(collection); + public static XXXXXXXX Max(this IEnumerable collection) => AggregateUnitExtensions.Max(collection); + public static XXXXXXXX Min(this IEnumerable collection) => AggregateUnitExtensions.Min(collection); + + + + // Sum Average Max Min (nullable) ========================================== + + + // === ReadOnlySpan === + public static XXXXXXXX Sum(this ReadOnlySpan units) => AggregateUnitExtensions.Sum(units); + public static XXXXXXXX Average(this ReadOnlySpan units) => AggregateUnitExtensions.Average(units); + public static XXXXXXXX Max(this ReadOnlySpan units) => AggregateUnitExtensions.Max(units); + public static XXXXXXXX Min(this ReadOnlySpan units) => AggregateUnitExtensions.Min(units); + + // === List === + public static XXXXXXXX Sum(this List list) => AggregateUnitExtensions.Sum(list); + public static XXXXXXXX Average(this List list) => AggregateUnitExtensions.Average(list); + public static XXXXXXXX Max(this List list) => AggregateUnitExtensions.Max(list); + public static XXXXXXXX Min(this List list) => AggregateUnitExtensions.Min(list); + + // === ICollection === + public static XXXXXXXX Sum(this ICollection collection) => AggregateUnitExtensions.Sum(collection); + public static XXXXXXXX Average(this ICollection collection) => AggregateUnitExtensions.Average(collection); + public static XXXXXXXX Max(this ICollection collection) => AggregateUnitExtensions.Max(collection); + public static XXXXXXXX Min(this ICollection collection) => AggregateUnitExtensions.Min(collection); + + // === IReadOnlyCollection === + public static XXXXXXXX Sum(this IReadOnlyCollection collection) => AggregateUnitExtensions.Sum(collection); + public static XXXXXXXX Average(this IReadOnlyCollection collection) => AggregateUnitExtensions.Average(collection); + public static XXXXXXXX Max(this IReadOnlyCollection collection) => AggregateUnitExtensions.Max(collection); + public static XXXXXXXX Min(this IReadOnlyCollection collection) => AggregateUnitExtensions.Min(collection); + + // === IEnumerable === + public static XXXXXXXX Sum(this IEnumerable collection) => AggregateUnitExtensions.Sum(collection); + public static XXXXXXXX Average(this IEnumerable collection) => AggregateUnitExtensions.Average(collection); + public static XXXXXXXX Max(this IEnumerable collection) => AggregateUnitExtensions.Max(collection); + public static XXXXXXXX Min(this IEnumerable collection) => AggregateUnitExtensions.Min(collection); +} \ No newline at end of file