This commit is contained in:
melekhin
2026-06-11 15:42:01 +07:00
parent 343996ef46
commit 790a5f8e10
35 changed files with 5128 additions and 3595 deletions

View File

@@ -296,80 +296,6 @@ internal static partial class AggregateUnitExtensions
return CollectionsMarshal.AsSpan(list).Min();
}
// === ICollection<T> ===
internal static T Sum<T>(this ICollection<T> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return default;
if (collection is T[] array) return array.Sum();
if (collection is List<T> list) return list.Sum();
T[] sharedArray = ArrayPool<T>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0); // Встроенный CopyTo работает быстрее, чем ручной foreach
return new ReadOnlySpan<T>(sharedArray, 0, collection.Count).Sum();
}
finally
{
ArrayPool<T>.Shared.Return(sharedArray);
}
}
internal static T Avg<T>(this ICollection<T> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return double.NaN.ToUnit<T>();
if (collection is T[] array) return array.Avg();
if (collection is List<T> list) return list.Avg();
T[] sharedArray = ArrayPool<T>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T>(sharedArray, 0, collection.Count).Avg();
}
finally
{
ArrayPool<T>.Shared.Return(sharedArray);
}
}
internal static T Max<T>(this ICollection<T> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return double.MinValue.ToUnit<T>();
if (collection is T[] array) return array.Max();
if (collection is List<T> list) return list.Max();
T[] sharedArray = ArrayPool<T>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T>(sharedArray, 0, collection.Count).Max();
}
finally
{
ArrayPool<T>.Shared.Return(sharedArray);
}
}
internal static T Min<T>(this ICollection<T> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return double.MaxValue.ToUnit<T>();
if (collection is T[] array) return array.Min();
if (collection is List<T> list) return list.Min();
T[] sharedArray = ArrayPool<T>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T>(sharedArray, 0, collection.Count).Min();
}
finally
{
ArrayPool<T>.Shared.Return(sharedArray);
}
}
// === IReadOnlyCollection<T> ===
internal static T Sum<T>(this IReadOnlyCollection<T> collection)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -446,7 +372,6 @@ internal static partial class AggregateUnitExtensions
// Быстрый SIMD-путь для готовых коллекций (0 аллокаций)
if (collection is T[] array) return array.Sum();
if (collection is List<T> list) return list.Sum();
if (collection is ICollection<T> col) return col.Sum();
if (collection is IReadOnlyCollection<T> roc) return roc.Sum();
// Медленный путь для yield return: считаем на лету без буферов
@@ -468,7 +393,6 @@ internal static partial class AggregateUnitExtensions
if (collection is T[] array) return array.Avg();
if (collection is List<T> list) return list.Avg();
if (collection is ICollection<T> col) return col.Avg();
if (collection is IReadOnlyCollection<T> roc) return roc.Avg();
double sum = 0;
@@ -492,7 +416,6 @@ internal static partial class AggregateUnitExtensions
if (collection is T[] array) return array.Max();
if (collection is List<T> list) return list.Max();
if (collection is ICollection<T> col) return col.Max();
if (collection is IReadOnlyCollection<T> roc) return roc.Max();
double max = double.MinValue;
@@ -514,7 +437,6 @@ internal static partial class AggregateUnitExtensions
if (collection is T[] array) return array.Min();
if (collection is List<T> list) return list.Min();
if (collection is ICollection<T> col) return col.Min();
if (collection is IReadOnlyCollection<T> roc) return roc.Min();
double min = double.MaxValue;
@@ -708,80 +630,6 @@ internal static partial class AggregateUnitExtensions
return CollectionsMarshal.AsSpan(list).Min();
}
// === ICollection<T> ===
internal static T Sum<T>(this ICollection<T?> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return default;
if (collection is T?[] array) return array.Sum();
if (collection is List<T?> list) return list.Sum();
T?[] sharedArray = ArrayPool<T?>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T?>(sharedArray, 0, collection.Count).Sum();
}
finally
{
ArrayPool<T?>.Shared.Return(sharedArray);
}
}
internal static T Avg<T>(this ICollection<T?> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return double.NaN.ToUnit<T>();
if (collection is T?[] array) return array.Avg();
if (collection is List<T?> list) return list.Avg();
T?[] sharedArray = ArrayPool<T?>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T?>(sharedArray, 0, collection.Count).Avg();
}
finally
{
ArrayPool<T?>.Shared.Return(sharedArray);
}
}
internal static T Max<T>(this ICollection<T?> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return double.MinValue.ToUnit<T>();
if (collection is T?[] array) return array.Max();
if (collection is List<T?> list) return list.Max();
T?[] sharedArray = ArrayPool<T?>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T?>(sharedArray, 0, collection.Count).Max();
}
finally
{
ArrayPool<T?>.Shared.Return(sharedArray);
}
}
internal static T Min<T>(this ICollection<T?> collection)
where T : struct, IMensuraUnit, IEquatable<T>
{
if (collection == null || collection.Count == 0) return double.MaxValue.ToUnit<T>();
if (collection is T?[] array) return array.Min();
if (collection is List<T?> list) return list.Min();
T?[] sharedArray = ArrayPool<T?>.Shared.Rent(collection.Count);
try
{
collection.CopyTo(sharedArray, 0);
return new ReadOnlySpan<T?>(sharedArray, 0, collection.Count).Min();
}
finally
{
ArrayPool<T?>.Shared.Return(sharedArray);
}
}
// === IReadOnlyCollection<T> ===
internal static T Sum<T>(this IReadOnlyCollection<T?> collection)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -857,7 +705,6 @@ internal static partial class AggregateUnitExtensions
// Быстрый SIMD-путь для готовых коллекций за 0 аллокаций
if (collection is T?[] array) return array.Sum();
if (collection is List<T?> list) return list.Sum();
if (collection is ICollection<T?> col) return col.Sum();
if (collection is IReadOnlyCollection<T?> roc) return roc.Sum();
// Медленный путь для ленивого yield return: вычисляем на лету
@@ -882,7 +729,6 @@ internal static partial class AggregateUnitExtensions
if (collection is T?[] array) return array.Avg();
if (collection is List<T?> list) return list.Avg();
if (collection is ICollection<T?> col) return col.Avg();
if (collection is IReadOnlyCollection<T?> roc) return roc.Avg();
double sum = 0;
@@ -909,7 +755,6 @@ internal static partial class AggregateUnitExtensions
if (collection is T?[] array) return array.Max();
if (collection is List<T?> list) return list.Max();
if (collection is ICollection<T?> col) return col.Max();
if (collection is IReadOnlyCollection<T?> roc) return roc.Max();
double max = double.MinValue;
@@ -934,7 +779,6 @@ internal static partial class AggregateUnitExtensions
if (collection is T?[] array) return array.Min();
if (collection is List<T?> list) return list.Min();
if (collection is ICollection<T?> col) return col.Min();
if (collection is IReadOnlyCollection<T?> roc) return roc.Min();
double min = double.MaxValue;

View File

@@ -1,51 +1,35 @@
namespace QWERTYkez.Mensura.Extensions;
using System.Reflection;
using System.Reflection.Emit;
namespace QWERTYkez.Mensura.Extensions;
internal static partial class CastExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double ToDouble<T>(this T unit)
where T : struct, IMensuraUnit, IEquatable<T>
{
return Unsafe.As<T, double>(ref unit);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static T ToUnit<T>(this double val)
where T : struct, IMensuraUnit, IEquatable<T>
{
return Unsafe.As<double, T>(ref val);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void SetCountUnsafe<T>(this List<T> list, int count)
{
// Берем адрес управляемого объекта List в памяти
// Объект передается по ref-ссылке, преобразуется в указатель
ref var mimic = ref Unsafe.As<List<T>, Mimics<T>>(ref list);
// Меняем приватный размер напрямую в памяти объекта!
mimic.Size = count;
}
internal static double ToDouble<T>(this T unit) where T : struct, IMensuraUnit, IEquatable<T>
=> Unsafe.As<T, double>(ref unit);
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ToUnit<T>(this double val)
where T : struct, IMensuraUnit, IEquatable<T> => Unsafe.As<double, T>(ref val);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<R> WrapAsList<T, R>(this T[] array)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
// Создаём пустой список с нулевой ёмкостью
if (array is null) return null!;
// 1. Физически меняем паспорт (MethodTable) массива на целевой тип R[]
object arrObj = array;
unsafe { *(nint*)*(nint*)Unsafe.AsPointer(ref arrObj) = typeof(R[]).TypeHandle.Value; }
R[] morphedArray = Unsafe.As<R[]>(arrObj);
// 2. Вшиваем его в новый список
var list = new List<R>(0);
// Получаем внутреннюю структуру списка
ref var mimic = ref Unsafe.As<List<R>, Mimics<T>>(ref list);
// Подменяем массив и устанавливаем размер
mimic.Items = array;
ref var mimic = ref Unsafe.As<List<R>, ListMimic<R>>(ref list);
mimic.Items = morphedArray;
mimic.Size = array.Length;
mimic.Version = 1; // любое ненулевое значение для консистенции
mimic.Version = 1;
return list;
}
@@ -55,16 +39,17 @@ internal static partial class CastExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
// Создаём пустой список с нулевой ёмкостью
if (array is null) return null!;
object arrObj = array;
unsafe { *(nint*)*(nint*)Unsafe.AsPointer(ref arrObj) = typeof(R?[]).TypeHandle.Value; }
R?[] morphedArray = Unsafe.As<R?[]>(arrObj);
var list = new List<R?>(0);
// Получаем внутреннюю структуру списка
ref var mimic = ref Unsafe.As<List<R?>, Mimics<T?>>(ref list);
// Подменяем массив и устанавливаем размер
mimic.Items = array;
ref var mimic = ref Unsafe.As<List<R?>, ListMimic<R?>>(ref list);
mimic.Items = morphedArray;
mimic.Size = array.Length;
mimic.Version = 1; // любое ненулевое значение для консистенции
mimic.Version = 1;
return list;
}
@@ -73,16 +58,17 @@ internal static partial class CastExtensions
internal static List<double> WrapAsList<T>(this T[] array)
where T : struct, IMensuraUnit, IEquatable<T>
{
// Создаём пустой список с нулевой ёмкостью
if (array is null) return null!;
object arrObj = array;
unsafe { *(nint*)*(nint*)Unsafe.AsPointer(ref arrObj) = typeof(double[]).TypeHandle.Value; }
double[] morphedArray = Unsafe.As<double[]>(arrObj);
var list = new List<double>(0);
// Получаем внутреннюю структуру списка
ref var mimic = ref Unsafe.As<List<double>, Mimics<T>>(ref list);
// Подменяем массив и устанавливаем размер
mimic.Items = array;
ref var mimic = ref Unsafe.As<List<double>, ListMimic<double>>(ref list);
mimic.Items = morphedArray;
mimic.Size = array.Length;
mimic.Version = 1; // любое ненулевое значение для консистенции
mimic.Version = 1;
return list;
}
@@ -91,16 +77,17 @@ internal static partial class CastExtensions
internal static List<double?> WrapAsList<T>(this T?[] array)
where T : struct, IMensuraUnit, IEquatable<T>
{
// Создаём пустой список с нулевой ёмкостью
if (array is null) return null!;
object arrObj = array;
unsafe { *(nint*)*(nint*)Unsafe.AsPointer(ref arrObj) = typeof(double?[]).TypeHandle.Value; }
double?[] morphedArray = Unsafe.As<double?[]>(arrObj);
var list = new List<double?>(0);
// Получаем внутреннюю структуру списка
ref var mimic = ref Unsafe.As<List<double?>, Mimics<T?>>(ref list);
// Подменяем массив и устанавливаем размер
mimic.Items = array;
ref var mimic = ref Unsafe.As<List<double?>, ListMimic<double?>>(ref list);
mimic.Items = morphedArray;
mimic.Size = array.Length;
mimic.Version = 1; // любое ненулевое значение для консистенции
mimic.Version = 1;
return list;
}
@@ -108,16 +95,14 @@ internal static partial class CastExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<double> WrapAsList(this double[] array)
{
// Создаём пустой список с нулевой ёмкостью
if (array is null) return null!;
// Массив уже имеет тип double[], подмена MethodTable не требуется
var list = new List<double>(0);
// Получаем внутреннюю структуру списка
ref var mimic = ref Unsafe.As<List<double>, Mimics<double>>(ref list);
// Подменяем массив и устанавливаем размер
ref var mimic = ref Unsafe.As<List<double>, ListMimic<double>>(ref list);
mimic.Items = array;
mimic.Size = array.Length;
mimic.Version = 1; // любое ненулевое значение для консистенции
mimic.Version = 1;
return list;
}
@@ -125,28 +110,75 @@ internal static partial class CastExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<double?> WrapAsList(this double?[] array)
{
// Создаём пустой список с нулевой ёмкостью
if (array is null) return null!;
// Массив уже имеет тип double?[], подмена MethodTable не требуется
var list = new List<double?>(0);
// Получаем внутреннюю структуру списка
ref var mimic = ref Unsafe.As<List<double?>, Mimics<double?>>(ref list);
// Подменяем массив и устанавливаем размер
ref var mimic = ref Unsafe.As<List<double?>, ListMimic<double?>>(ref list);
mimic.Items = array;
mimic.Size = array.Length;
mimic.Version = 1; // любое ненулевое значение для консистенции
mimic.Version = 1;
return list;
}
#region Инфраструктура Нативного Доступа (Zero-Overhead)
// Генератор сверхбыстрого доступа к приватным полям List<T> через чистый IL.
// Работает со скоростью обычного обращения к полю (компилируется в смещение указателя).
private static class ListAccessor<T>
{
public delegate ref T[] GetItemsRefDelegate(List<T> list);
public static readonly GetItemsRefDelegate GetItemsRef;
static ListAccessor()
{
var field = typeof(List<T>).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance)
?? throw new InvalidOperationException("CLR Layout changed: _items field not found.");
var dm = new DynamicMethod("GetItemsRef", typeof(T[]).MakeByRefType(), [typeof(List<T>)], typeof(ListAccessor<T>).Module, true);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Загружаем ссылку на List<T>
il.Emit(OpCodes.Ldflda, field); // Получаем управляемый указатель (ref) на поле _items
il.Emit(OpCodes.Ret); // Возвращаем его
GetItemsRef = dm.CreateDelegate<GetItemsRefDelegate>();
}
}
#endregion
#region Реализация ReCast со сменой MethodTable (In-Place Object Morphing)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<R> ReCast<T, R>(this List<T> list)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
return Unsafe.As<List<T>, List<R>>(ref list);
if (list is null) return null!;
unsafe
{
// 1. Морфим внутренний массив со скоростью мысли
T[] items = ListAccessor<T>.GetItemsRef(list);
if (items is not null)
{
object itemsObj = items;
*(nint*)*(nint*)Unsafe.AsPointer(ref itemsObj) = typeof(R[]).TypeHandle.Value;
}
// 2. Морфим сам заголовок List
object listObj = list;
*(nint*)*(nint*)Unsafe.AsPointer(ref listObj) = typeof(List<R>).TypeHandle.Value;
return Unsafe.As<List<R>>(listObj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -154,21 +186,63 @@ internal static partial class CastExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
return Unsafe.As<List<T?>, List<R?>>(ref list);
if (list is null) return null!;
unsafe
{
T?[] items = ListAccessor<T?>.GetItemsRef(list);
if (items is not null)
{
object itemsObj = items;
*(nint*)*(nint*)Unsafe.AsPointer(ref itemsObj) = typeof(R?[]).TypeHandle.Value;
}
object listObj = list;
*(nint*)*(nint*)Unsafe.AsPointer(ref listObj) = typeof(List<R?>).TypeHandle.Value;
return Unsafe.As<List<R?>>(listObj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<double> ReCast<T>(this List<T> list)
where T : struct, IMensuraUnit, IEquatable<T>
{
return Unsafe.As<List<T>, List<double>>(ref list);
if (list is null) return null!;
unsafe
{
T[] items = ListAccessor<T>.GetItemsRef(list);
if (items is not null)
{
object itemsObj = items;
*(nint*)*(nint*)Unsafe.AsPointer(ref itemsObj) = typeof(double[]).TypeHandle.Value;
}
object listObj = list;
*(nint*)*(nint*)Unsafe.AsPointer(ref listObj) = typeof(List<double>).TypeHandle.Value;
return Unsafe.As<List<double>>(listObj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static List<double?> ReCast<T>(this List<T?> list)
where T : struct, IMensuraUnit, IEquatable<T>
{
return Unsafe.As<List<T?>, List<double?>>(ref list);
if (list is null) return null!;
unsafe
{
T?[] items = ListAccessor<T?>.GetItemsRef(list);
if (items is not null)
{
object itemsObj = items;
*(nint*)*(nint*)Unsafe.AsPointer(ref itemsObj) = typeof(double?[]).TypeHandle.Value;
}
object listObj = list;
*(nint*)*(nint*)Unsafe.AsPointer(ref listObj) = typeof(List<double?>).TypeHandle.Value;
return Unsafe.As<List<double?>>(listObj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -176,7 +250,14 @@ internal static partial class CastExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
return Unsafe.As<T[], R[]>(ref array);
if (array is null) return null!;
unsafe
{
object obj = array;
// Ужатие магии: берем адрес переменной на стеке -> читаем адрес объекта в куче -> пишем туда новый MethodTable
*(nint*)*(nint*)Unsafe.AsPointer(ref obj) = typeof(R[]).TypeHandle.Value;
return Unsafe.As<R[]>(obj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -184,34 +265,66 @@ internal static partial class CastExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
return Unsafe.As<T?[], R?[]>(ref array);
if (array is null) return null!;
unsafe
{
object obj = array;
*(nint*)*(nint*)Unsafe.AsPointer(ref obj) = typeof(R?[]).TypeHandle.Value;
return Unsafe.As<R?[]>(obj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double[] ReCast<T>(this T[] array)
where T : struct, IMensuraUnit, IEquatable<T>
{
return Unsafe.As<T[], double[]>(ref array);
if (array is null) return null!;
unsafe
{
object obj = array;
*(nint*)*(nint*)Unsafe.AsPointer(ref obj) = typeof(double[]).TypeHandle.Value;
return Unsafe.As<double[]>(obj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double?[] ReCast<T>(this T?[] array)
where T : struct, IMensuraUnit, IEquatable<T>
{
return Unsafe.As<T?[], double?[]>(ref array);
if (array is null) return null!;
unsafe
{
object obj = array;
*(nint*)*(nint*)Unsafe.AsPointer(ref obj) = typeof(double?[]).TypeHandle.Value;
return Unsafe.As<double?[]>(obj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static R[] ReCast<R>(this double[] array)
where R : struct, IMensuraUnit, IEquatable<R>
{
return Unsafe.As<double[], R[]>(ref array);
if (array is null) return null!;
unsafe
{
object obj = array;
*(nint*)*(nint*)Unsafe.AsPointer(ref obj) = typeof(R[]).TypeHandle.Value;
return Unsafe.As<R[]>(obj);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static R?[] ReCast<R>(this double?[] array)
where R : struct, IMensuraUnit, IEquatable<R>
{
return Unsafe.As<double?[], R?[]>(ref array);
if (array is null) return null!;
unsafe
{
object obj = array;
*(nint*)*(nint*)Unsafe.AsPointer(ref obj) = typeof(R?[]).TypeHandle.Value;
return Unsafe.As<R?[]>(obj);
}
}
#endregion
}

View File

@@ -264,80 +264,6 @@ internal static partial class CollectionsDivideExtensions
return resultArray.WrapAsList<R, R>();
}
// === ICollection<T> ===
internal static void Div<T, R>(this ICollection<T> units, double divisor, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { DivideCore(array, divisor, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).DivideCore(divisor, count, destination); return; }
int i = 0;
double invDivisor = 1.0 / divisor;
foreach (var item in units)
destination[i++] = (item.ToDouble() * invDivisor).ToUnit<R>();
}
internal static void Div<T, R>(this ICollection<T?> units, double divisor, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.DivideCore(divisor, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).DivideCore(divisor, count, destination); return; }
int i = 0;
double invDivisor = 1.0 / divisor;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
}
internal static void Div<T, R>(this double dividend, ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { dividend.DivideCore(array, count, destination); return; }
if (units is List<T> list) { dividend.DivideCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (dividend / item.ToDouble()).ToUnit<R>();
}
internal static void Div<T, R>(this double dividend, ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { dividend.DivideCore(array, count, destination); return; }
if (units is List<T?> list) { dividend.DivideCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend / item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Div<T, R>(this IReadOnlyCollection<T> units, double divisor, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -454,12 +380,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T[] array) return array.Div<T, R>(divisor);
if (units is List<T> list) return list.Div<T, R>(divisor);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Div(divisor, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -475,12 +395,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Div<T, R>(divisor);
if (units is List<T?> list) return list.Div<T, R>(divisor);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Div(divisor, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -496,12 +410,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T[] array) return dividend.Div<T, R>(array);
if (units is List<T> list) return dividend.Div<T, R>(list);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
dividend.Div(arr, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -517,12 +425,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T?[] array) return dividend.Div<T, R>(array);
if (units is List<T?> list) return dividend.Div<T, R>(list);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
dividend.Div(arr, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -670,76 +572,6 @@ internal static partial class CollectionsDivideExtensions
return resultArray.WrapAsList<T, T>();
}
// === ICollection<T> ===
internal static void Div<T>(this ICollection<T> units, double divisor, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { array.Div(divisor, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Div(divisor, destination); return; }
int i = 0;
double invDivisor = 1.0 / divisor;
foreach (var item in units)
destination[i++] = (item.ToDouble() * invDivisor).ToUnit<T>();
}
internal static void Div<T>(this ICollection<T?> units, double divisor, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { array.Div(divisor, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Div(divisor, destination); return; }
int i = 0;
double invDivisor = 1.0 / divisor;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * invDivisor).ToUnit<T>() : null;
}
internal static void Div<T>(this double dividend, ICollection<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { dividend.Div(array, destination); return; }
if (units is List<T> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (dividend / item.ToDouble()).ToUnit<T>();
}
internal static void Div<T>(this double dividend, ICollection<T?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { dividend.Div(array, destination); return; }
if (units is List<T?> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend / item.Value.ToDouble()).ToUnit<T>() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Div<T>(this IReadOnlyCollection<T> units, double divisor, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -847,12 +679,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T[] array) return array.Div(divisor);
if (units is List<T> list) return list.Div(divisor);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Div(divisor, arr);
return arr;
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -867,12 +693,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Div(divisor);
if (units is List<T?> list) return list.Div(divisor);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Div(divisor, arr);
return arr;
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -887,12 +707,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T[] array) return dividend.Div(array);
if (units is List<T> list) return dividend.Div(list);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
dividend.Div(arr, arr);
return arr;
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -907,12 +721,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T?[] array) return dividend.Div(array);
if (units is List<T?> list) return dividend.Div(list);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
dividend.Div(arr, arr);
return arr;
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -1365,76 +1173,6 @@ internal static partial class CollectionsDivideExtensions
return resultArray.WrapAsList<T, T>();
}
// === ICollection<T> ===
internal static void Div<T>(this ICollection<double> units, T divisor, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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<double> 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<T>();
}
internal static void Div<T>(this ICollection<double?> units, T divisor, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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<double?> 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<T>() : null;
}
internal static void Div<T>(this T dividend, ICollection<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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<double> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (dividend.ToDouble() / item).ToUnit<T>();
}
internal static void Div<T>(this T dividend, ICollection<double?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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<double?> 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<T>() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Div<T>(this IReadOnlyCollection<double> units, T divisor, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1542,12 +1280,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is double[] array) return array.Div(divisor);
if (units is List<double> list) return list.Div(divisor);
if (units is ICollection<double> col)
{
var arr = col.ToArray();
arr.DivCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
@@ -1562,12 +1294,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is double?[] array) return array.Div(divisor);
if (units is List<double?> list) return list.Div(divisor);
if (units is ICollection<double?> col)
{
var arr = col.ToArray();
arr.DivCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();
@@ -1582,12 +1308,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is double[] array) return dividend.Div(array);
if (units is List<double> list) return dividend.Div(list);
if (units is ICollection<double> col)
{
var arr = col.ToArray();
dividend.ToDouble().DivCore(arr, arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
@@ -1602,12 +1322,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is double?[] array) return dividend.Div(array);
if (units is List<double?> list) return dividend.Div(list);
if (units is ICollection<double?> col)
{
var arr = col.ToArray();
dividend.ToDouble().DivCore(arr, arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();
@@ -1915,76 +1629,6 @@ internal static partial class CollectionsDivideExtensions
return resultArray.WrapAsList();
}
// === ICollection<T> ===
internal static void Div<T>(this ICollection<T> units, T divisor, Span<double> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { array.Div(divisor, destination); return; }
if (units is List<T> 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.ToDouble() * invDivisor;
}
internal static void Div<T>(this ICollection<T?> units, T divisor, Span<double?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { array.Div(divisor, destination); return; }
if (units is List<T?> 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.ToDouble() * invDivisor : null;
}
internal static void Div<T>(this T dividend, ICollection<T> units, Span<double> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { dividend.Div(array, destination); return; }
if (units is List<T> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
var div = dividend.ToDouble();
foreach (var item in units)
destination[i++] = div / item.ToDouble();
}
internal static void Div<T>(this T dividend, ICollection<T?> units, Span<double?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { dividend.Div(array, destination); return; }
if (units is List<T?> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
var div = dividend.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue ? div / item.Value.ToDouble() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Div<T>(this IReadOnlyCollection<T> units, T divisor, Span<double> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -2092,12 +1736,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T[] array) return array.Div(divisor);
if (units is List<T> list) return list.Div(divisor);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.DivideCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -2112,12 +1750,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Div(divisor);
if (units is List<T?> list) return list.Div(divisor);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.DivideCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -2132,12 +1764,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T[] array) return dividend.Div(array);
if (units is List<T> list) return dividend.Div(list);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
dividend.ToDouble().DivideCore(arr, arr.Length, arr);
return arr.ReCast();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -2152,12 +1778,6 @@ internal static partial class CollectionsDivideExtensions
if (units is null) return null!;
if (units is T?[] array) return dividend.Div(array);
if (units is List<T?> list) return dividend.Div(list);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
dividend.ToDouble().DivideCore(arr, arr.Length, arr);
return arr.ReCast();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();

View File

@@ -259,78 +259,6 @@ internal static partial class CollectionsMinusExtensions
return resultArray.WrapAsList<R, R>();
}
// === ICollection<T> ===
internal static void Minus<T, R>(this ICollection<T> units, double subtrahend, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.MinusCore(subtrahend, count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item.ToDouble() - subtrahend).ToUnit<R>();
}
internal static void Minus<T, R>(this ICollection<T?> units, double subtrahend, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.MinusCore(subtrahend, count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
}
internal static void Minus<T, R>(this double minuend, ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { minuend.MinusCore(array, count, destination); return; }
if (units is List<T> list) { minuend.MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (minuend - item.ToDouble()).ToUnit<R>();
}
internal static void Minus<T, R>(this double minuend, ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { minuend.MinusCore(array, count, destination); return; }
if (units is List<T?> list) { minuend.MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (minuend - item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Minus<T, R>(this IReadOnlyCollection<T> units, double subtrahend, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -443,12 +371,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T[] array) return array.Minus<T, R>(subtrahend);
if (units is List<T> list) return list.Minus<T, R>(subtrahend);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Minus(subtrahend, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -464,12 +386,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Minus<T, R>(subtrahend);
if (units is List<T?> list) return list.Minus<T, R>(subtrahend);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Minus(subtrahend, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -485,12 +401,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T[] array) return minuend.Minus<T, R>(array);
if (units is List<T> list) return minuend.Minus<T, R>(list);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
minuend.Minus(arr, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -506,12 +416,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T?[] array) return minuend.Minus<T, R>(array);
if (units is List<T?> list) return minuend.Minus<T, R>(list);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
minuend.Minus(arr, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -660,74 +564,6 @@ internal static partial class CollectionsMinusExtensions
return resultArray.WrapAsList<T, T>();
}
// === ICollection<T> ===
internal static void Minus<T>(this ICollection<T> units, double subtrahend, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { array.Minus(subtrahend, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Minus(subtrahend, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item.ToDouble() - subtrahend).ToUnit<T>();
}
internal static void Minus<T>(this ICollection<T?> units, double subtrahend, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { array.Minus(subtrahend, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Minus(subtrahend, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() - subtrahend).ToUnit<T>() : null;
}
internal static void Minus<T>(this double minuend, ICollection<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { minuend.Minus(array, destination); return; }
if (units is List<T> list) { minuend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (minuend - item.ToDouble()).ToUnit<T>();
}
internal static void Minus<T>(this double minuend, ICollection<T?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { minuend.Minus(array, destination); return; }
if (units is List<T?> list) { minuend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (minuend - item.Value.ToDouble()).ToUnit<T>() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Minus<T>(this IReadOnlyCollection<T> units, double subtrahend, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -831,12 +667,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T[] array) return array.Minus(subtrahend);
if (units is List<T> list) return list.Minus(subtrahend);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Minus(subtrahend, arr);
return arr;
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -851,12 +681,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Minus(subtrahend);
if (units is List<T?> list) return list.Minus(subtrahend);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Minus(subtrahend, arr);
return arr;
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -871,12 +695,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T[] array) return minuend.Minus(array);
if (units is List<T> list) return minuend.Minus(list);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
minuend.Minus(arr, arr);
return arr;
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -891,12 +709,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is T?[] array) return minuend.Minus(array);
if (units is List<T?> list) return minuend.Minus(list);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
minuend.Minus(arr, arr);
return arr;
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -1339,76 +1151,6 @@ internal static partial class CollectionsMinusExtensions
return resultArray.WrapAsList<T, T>();
}
// === ICollection<T> ===
internal static void Minus<T>(this ICollection<double> units, T divisor, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.Minus(divisor, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).Minus(divisor, destination); return; }
int i = 0;
double invMinusisor = 1.0 / divisor.ToDouble();
foreach (var item in units)
destination[i++] = (item * invMinusisor).ToUnit<T>();
}
internal static void Minus<T>(this ICollection<double?> units, T divisor, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.Minus(divisor, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).Minus(divisor, destination); return; }
int i = 0;
double invMinusisor = 1.0 / divisor.ToDouble();
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value * invMinusisor).ToUnit<T>() : null;
}
internal static void Minus<T>(this T dividend, ICollection<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.Minus(array, destination); return; }
if (units is List<double> list) { dividend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (dividend.ToDouble() / item).ToUnit<T>();
}
internal static void Minus<T>(this T dividend, ICollection<double?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.Minus(array, destination); return; }
if (units is List<double?> list) { dividend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (dividend.ToDouble() / item.Value).ToUnit<T>() : null;
}
// === IReadOnlyCollection<T> ===
internal static void Minus<T>(this IReadOnlyCollection<double> units, T divisor, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -1516,12 +1258,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is double[] array) return array.Minus(divisor);
if (units is List<double> list) return list.Minus(divisor);
if (units is ICollection<double> col)
{
var arr = col.ToArray();
arr.MinusCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
@@ -1536,12 +1272,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is double?[] array) return array.Minus(divisor);
if (units is List<double?> list) return list.Minus(divisor);
if (units is ICollection<double?> col)
{
var arr = col.ToArray();
arr.MinusCore(divisor.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();
@@ -1556,12 +1286,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is double[] array) return dividend.Minus(array);
if (units is List<double> list) return dividend.Minus(list);
if (units is ICollection<double> col)
{
var arr = col.ToArray();
dividend.ToDouble().MinusCore(arr, arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
@@ -1576,12 +1300,6 @@ internal static partial class CollectionsMinusExtensions
if (units is null) return null!;
if (units is double?[] array) return dividend.Minus(array);
if (units is List<double?> list) return dividend.Minus(list);
if (units is ICollection<double?> col)
{
var arr = col.ToArray();
dividend.ToDouble().MinusCore(arr, arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();

View File

@@ -162,53 +162,6 @@ internal static partial class CollectionsMultiplyExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.Mul<T, R>(multiplicator);
// === ICollection<T> ===
internal static void Mul<T, R>(this ICollection<T> units, double multiplicator, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { MultiplyCore(array, multiplicator, count, destination); return; }
if (units is List<T> list) { MultiplyCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item.ToDouble() * multiplicator).ToUnit<R>();
}
internal static void Mul<T, R>(this ICollection<T?> units, double multiplicator, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { MultiplyCore(array, multiplicator, count, destination); return; }
if (units is List<T?> list) { MultiplyCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Mul<T, R>(this double multiplicator, ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.Mul(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Mul<T, R>(this double multiplicator, ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.Mul(multiplicator, destination);
// === IReadOnlyCollection<T> ===
internal static void Mul<T, R>(this IReadOnlyCollection<T> units, double multiplicator, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -281,12 +234,6 @@ internal static partial class CollectionsMultiplyExtensions
if (units is null) return null!;
if (units is T[] array) return array.Mul<T, R>(multiplicator);
if (units is List<T> list) return list.Mul<T, R>(multiplicator);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Mul(multiplicator, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -302,12 +249,6 @@ internal static partial class CollectionsMultiplyExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Mul<T, R>(multiplicator);
if (units is List<T?> list) return list.Mul<T, R>(multiplicator);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Mul(multiplicator, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -424,49 +365,6 @@ internal static partial class CollectionsMultiplyExtensions
internal static List<T?> Mul<T>(this double multiplicator, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T> => units.Mul(multiplicator);
// === ICollection<T> ===
internal static void Mul<T>(this ICollection<T> units, double multiplicator, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { array.Mul(multiplicator, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Mul(multiplicator, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item.ToDouble() * multiplicator).ToUnit<T>();
}
internal static void Mul<T>(this ICollection<T?> units, double multiplicator, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { array.Mul(multiplicator, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Mul(multiplicator, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() * multiplicator).ToUnit<T>() : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Mul<T>(this double multiplicator, ICollection<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Mul<T>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Mul<T>(this double multiplicator, ICollection<T?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Mul<T>(multiplicator, destination);
// === IReadOnlyCollection<T> ===
internal static void Mul<T>(this IReadOnlyCollection<T> units, double multiplicator, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -532,12 +430,6 @@ internal static partial class CollectionsMultiplyExtensions
if (units is null) return null!;
if (units is T[] array) return array.Mul(multiplicator);
if (units is List<T> list) return list.Mul(multiplicator);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Mul(multiplicator, arr);
return arr;
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -552,12 +444,6 @@ internal static partial class CollectionsMultiplyExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Mul(multiplicator);
if (units is List<T?> list) return list.Mul(multiplicator);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Mul(multiplicator, arr);
return arr;
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -832,49 +718,6 @@ internal static partial class CollectionsMultiplyExtensions
internal static List<T?> Mul<T>(this T multiplicator, List<double?> units)
where T : struct, IMensuraUnit, IEquatable<T> => units.Mul(multiplicator);
// === ICollection<T> ===
internal static void Mul<T>(this ICollection<double> units, T multiplicator, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.MultiplyCore(multiplicator.ToDouble(), array.Length, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MultiplyCore(multiplicator.ToDouble(), list.Count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item * multiplicator.ToDouble()).ToUnit<T>();
}
internal static void Mul<T>(this ICollection<double?> units, T multiplicator, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.MultiplyCore(multiplicator.ToDouble(), array.Length, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MultiplyCore(multiplicator.ToDouble(), list.Count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value * multiplicator.ToDouble()).ToUnit<T>() : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Mul<T>(this T multiplicator, ICollection<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Mul<T>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Mul<T>(this T multiplicator, ICollection<double?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Mul<T>(multiplicator, destination);
// === IReadOnlyCollection<T> ===
internal static void Mul<T>(this IReadOnlyCollection<double> units, T multiplicator, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -940,12 +783,6 @@ internal static partial class CollectionsMultiplyExtensions
if (units is null) return null!;
if (units is double[] array) return array.Mul(multiplicator);
if (units is List<double> list) return list.Mul(multiplicator);
if (units is ICollection<double> col)
{
var arr = col.ToArray();
arr.MultiplyCore(multiplicator.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
@@ -960,12 +797,6 @@ internal static partial class CollectionsMultiplyExtensions
if (units is null) return null!;
if (units is double?[] array) return array.Mul(multiplicator);
if (units is List<double?> list) return list.Mul(multiplicator);
if (units is ICollection<double?> col)
{
var arr = col.ToArray();
arr.MultiplyCore(multiplicator.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();

View File

@@ -163,53 +163,6 @@ internal static partial class CollectionsPlusExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.Plus<T, R>(summand);
// === ICollection<T> ===
internal static void Plus<T, R>(this ICollection<T> units, double summand, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { PlusCore(array, summand, count, destination); return; }
if (units is List<T> list) { PlusCore(CollectionsMarshal.AsSpan(list), summand, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item.ToDouble() + summand).ToUnit<R>();
}
internal static void Plus<T, R>(this ICollection<T?> units, double summand, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { PlusCore(array, summand, count, destination); return; }
if (units is List<T?> list) { PlusCore(CollectionsMarshal.AsSpan(list), summand, count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() + summand).ToUnit<R>() : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Plus<T, R>(this double summand, ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.Plus(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Plus<T, R>(this double summand, ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R> => units.Plus(summand, destination);
// === IReadOnlyCollection<T> ===
internal static void Plus<T, R>(this IReadOnlyCollection<T> units, double summand, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -282,12 +235,6 @@ internal static partial class CollectionsPlusExtensions
if (units is null) return null!;
if (units is T[] array) return array.Plus<T, R>(summand);
if (units is List<T> list) return list.Plus<T, R>(summand);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Plus(summand, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -303,12 +250,6 @@ internal static partial class CollectionsPlusExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Plus<T, R>(summand);
if (units is List<T?> list) return list.Plus<T, R>(summand);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Plus(summand, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -425,49 +366,6 @@ internal static partial class CollectionsPlusExtensions
internal static List<T?> Plus<T>(this double summand, List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T> => units.Plus(summand);
// === ICollection<T> ===
internal static void Plus<T>(this ICollection<T> units, double summand, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T[] array) { array.Plus(summand, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Plus(summand, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item.ToDouble() + summand).ToUnit<T>();
}
internal static void Plus<T>(this ICollection<T?> units, double summand, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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 T?[] array) { array.Plus(summand, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Plus(summand, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value.ToDouble() + summand).ToUnit<T>() : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Plus<T>(this double summand, ICollection<T> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Plus<T>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Plus<T>(this double summand, ICollection<T?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Plus<T>(summand, destination);
// === IReadOnlyCollection<T> ===
internal static void Plus<T>(this IReadOnlyCollection<T> units, double summand, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -533,12 +431,6 @@ internal static partial class CollectionsPlusExtensions
if (units is null) return null!;
if (units is T[] array) return array.Plus(summand);
if (units is List<T> list) return list.Plus(summand);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Plus(summand, arr);
return arr;
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -553,12 +445,6 @@ internal static partial class CollectionsPlusExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Plus(summand);
if (units is List<T?> list) return list.Plus(summand);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Plus(summand, arr);
return arr;
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -837,49 +723,6 @@ internal static partial class CollectionsPlusExtensions
internal static List<T?> Plus<T>(this T summand, List<double?> units)
where T : struct, IMensuraUnit, IEquatable<T> => units.Plus(summand);
// === ICollection<T> ===
internal static void Plus<T>(this ICollection<double> units, T summand, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.PlusCore(summand.ToDouble(), array.Length, destination); return; }
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = (item + summand.ToDouble()).ToUnit<T>();
}
internal static void Plus<T>(this ICollection<double?> units, T summand, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
{
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.PlusCore(summand.ToDouble(), array.Length, destination); return; }
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? (item.Value + summand.ToDouble()).ToUnit<T>() : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Plus<T>(this T summand, ICollection<double> units, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Plus<T>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Plus<T>(this T summand, ICollection<double?> units, Span<T?> destination)
where T : struct, IMensuraUnit, IEquatable<T> => units.Plus<T>(summand, destination);
// === IReadOnlyCollection<T> ===
internal static void Plus<T>(this IReadOnlyCollection<double> units, T summand, Span<T> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -945,12 +788,6 @@ internal static partial class CollectionsPlusExtensions
if (units is null) return null!;
if (units is double[] array) return array.Plus(summand);
if (units is List<double> list) return list.Plus(summand);
if (units is ICollection<double> col)
{
var arr = col.ToArray();
arr.PlusCore(summand.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double> roc)
{
var arr = roc.ToArray();
@@ -965,12 +802,6 @@ internal static partial class CollectionsPlusExtensions
if (units is null) return null!;
if (units is double?[] array) return array.Plus(summand);
if (units is List<double?> list) return list.Plus(summand);
if (units is ICollection<double?> col)
{
var arr = col.ToArray();
arr.PlusCore(summand.ToDouble(), arr.Length, arr);
return arr.ReCast<T>();
}
if (units is IReadOnlyCollection<double?> roc)
{
var arr = roc.ToArray();

View File

@@ -7,8 +7,8 @@ internal static partial class CollectionsPow2Extensions
// === ВТОРАЯ СТЕПЕНЬ ==========================================
// === Pow2Core2 === SIMD
internal static void Pow2Core2<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
// === Pow2Core === SIMD
internal static void Pow2Core<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -43,7 +43,7 @@ internal static partial class CollectionsPow2Extensions
dstDouble[i] = val * val;
}
}
internal static void Pow2Core2<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
internal static void Pow2Core<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
@@ -106,7 +106,7 @@ internal static partial class CollectionsPow2Extensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.Pow2Core2(len, destination);
units.Pow2Core(len, destination);
}
internal static void Pow2<T, R>(this ReadOnlySpan<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -117,7 +117,7 @@ internal static partial class CollectionsPow2Extensions
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.Pow2Core2(len, destination);
units.Pow2Core(len, destination);
}
// === Array ===
@@ -172,43 +172,6 @@ internal static partial class CollectionsPow2Extensions
return resultArray.WrapAsList<R, R>();
}
// === ICollection<Length> ===
internal static void Pow2<T, R>(this ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Pow2(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow2(destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.ToDouble().QuickPow2().ToUnit<R>();
}
internal static void Pow2<T, R>(this ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Pow2(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow2(destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? item.Value.ToDouble().QuickPow2().ToUnit<R>() : null;
}
// === IReadOnlyCollection<Length> ===
internal static void Pow2<T, R>(this IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -271,12 +234,6 @@ internal static partial class CollectionsPow2Extensions
if (units is null) return null!;
if (units is T[] array) return array.Pow2<T, R>();
if (units is List<T> list) return list.Pow2<T, R>();
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Pow2Core2(arr.Length, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -292,12 +249,6 @@ internal static partial class CollectionsPow2Extensions
if (units is null) return null!;
if (units is T?[] array) return array.Pow2<T, R>();
if (units is List<T?> list) return list.Pow2<T, R>();
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Pow2(arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();

View File

@@ -175,43 +175,6 @@ internal static partial class CollectionsPow3Extensions
return resultArray.WrapAsList<R, R>();
}
// === ICollection<Length> ===
internal static void Pow3<T, R>(this ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Pow3(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow3(destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.ToDouble().QuickPow3().ToUnit<R>();
}
internal static void Pow3<T, R>(this ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Pow3(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow3(destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? item.Value.ToDouble().QuickPow3().ToUnit<R>() : null;
}
// === IReadOnlyCollection<Length> ===
internal static void Pow3<T, R>(this IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -274,12 +237,6 @@ internal static partial class CollectionsPow3Extensions
if (units is null) return null!;
if (units is T[] array) return array.Pow3<T, R>();
if (units is List<T> list) return list.Pow3<T, R>();
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.PowCore3(arr.Length, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -295,12 +252,6 @@ internal static partial class CollectionsPow3Extensions
if (units is null) return null!;
if (units is T?[] array) return array.Pow3<T, R>();
if (units is List<T?> list) return list.Pow3<T, R>();
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Pow3(arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();

View File

@@ -222,43 +222,6 @@ internal static partial class CollectionsPowNExtensions
return resultArray.WrapAsList<R, R>();
}
// === ICollection<Length> ===
internal static void Pow<T, R>(this ICollection<T> units, int power, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Pow(power, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.ToDouble().QuickPow(power).ToUnit<R>();
}
internal static void Pow<T, R>(this ICollection<T?> units, int power, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Pow(power, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
int i = 0;
foreach (var item in units)
destination[i++] = item.HasValue
? item.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
}
// === IReadOnlyCollection<Length> ===
internal static void Pow<T, R>(this IReadOnlyCollection<T> units, int power, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -321,12 +284,6 @@ internal static partial class CollectionsPowNExtensions
if (units is null) return null!;
if (units is T[] array) return array.Pow<T, R>(power);
if (units is List<T> list) return list.Pow<T, R>(power);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.PowCore(power, arr.Length, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -342,12 +299,6 @@ internal static partial class CollectionsPowNExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Pow<T, R>(power);
if (units is List<T?> list) return list.Pow<T, R>(power);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Pow(power, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
@@ -534,43 +485,6 @@ internal static partial class CollectionsPowNExtensions
return result.WrapAsList<R, R>();
}
// === ICollection<Length> ===
internal static void Pow<T, R>(this ICollection<T> units, double power, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Pow(power, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
int i = 0;
foreach (T item in units)
destination[i++] = Math.Pow(item.ToDouble(), power).ToUnit<R>();
}
internal static void Pow<T, R>(this ICollection<T?> units, double power, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Pow(power, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Pow(item.Value.ToDouble(), power).ToUnit<R>() : null;
}
// === IReadOnlyCollection<Length> ===
internal static void Pow<T, R>(this IReadOnlyCollection<T> units, double power, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -633,12 +547,6 @@ internal static partial class CollectionsPowNExtensions
if (units is null) return null!;
if (units is T[] array) return array.Pow<T, R>(power);
if (units is List<T> list) return list.Pow<T, R>(power);
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Pow(power, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -654,12 +562,6 @@ internal static partial class CollectionsPowNExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Pow<T, R>(power);
if (units is List<T?> list) return list.Pow<T, R>(power);
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Pow(power, arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();

View File

@@ -0,0 +1,215 @@
using System.Runtime.Intrinsics.X86;
namespace QWERTYkez.Mensura.Extensions;
internal static partial class CollectionsRootOfCubeExtensions
{
// === CbrtCore === SIMD
internal static unsafe void CbrtCore<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
// Прямой каст без проверок размеров
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
Span<double> dstDouble = MemoryMarshal.Cast<R, double>(destination);
int i = 0;
ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
// 1. SIMD путь (AVX)
if (Avx.IsSupported && len >= 4)
{
int simdEnd = len & ~3;
for (; i < simdEnd; i += 4)
{
double* pSrc = (double*)Unsafe.AsPointer(ref Unsafe.Add(ref srcRef, i));
double* pDst = (double*)Unsafe.AsPointer(ref Unsafe.Add(ref dstRef, i));
// Используем LoadVector256 для максимально быстрой обработки 4-х double
Avx.Store(pDst, Avx.Sqrt(Avx.LoadVector256(pSrc)));
}
}
// 2. Fallback путь для остатка
for (; i < len; i++)
{
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i));
}
}
internal static void CbrtCore<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
ref var srcRef = ref MemoryMarshal.GetReference(units);
ref var dstRef = ref MemoryMarshal.GetReference(destination);
int i = 0, unrollEnd = len & ~3;
for (; i < unrollEnd; i += 4)
{
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 1)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 2)!.Value.ToDouble()).ToUnit<R>() : null;
Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 3)!.Value.ToDouble()).ToUnit<R>() : null;
}
for (; i < len; i++)
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Value.ToDouble()).ToUnit<R>() : null;
}
// === ReadOnlySpan ===
internal static void Cbrt<T, R>(this ReadOnlySpan<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units.IsEmpty) return;
int len = units.Length;
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.CbrtCore(len, destination);
}
internal static void Cbrt<T, R>(this ReadOnlySpan<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units.IsEmpty) return;
int len = units.Length;
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.CbrtCore(len, destination);
}
// === Array ===
internal static R[] Cbrt<T, R>(this T[] units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units.Length == 0) return [];
var result = new R[units.Length];
Cbrt(units, result);
return result;
}
internal static R?[] Cbrt<T, R>(this T?[] units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units.Length == 0) return [];
var result = new R?[units.Length];
Cbrt(units, result);
return result;
}
// === List ===
internal static List<R> Cbrt<T, R>(this List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
var resultArray = new R[len];
Cbrt(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
}
internal static List<R?> Cbrt<T, R>(this List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
var resultArray = new R?[len];
Cbrt(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
}
// === IReadOnlyCollection ===
internal static void Cbrt<T, R>(this IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.AsSpan().CbrtCore(count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).CbrtCore(count, destination); return; }
int i = 0;
ref R dstRef = ref MemoryMarshal.GetReference(destination);
foreach (T item in units) Unsafe.Add(ref dstRef, i++) = Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
internal static void Cbrt<T, R>(this IReadOnlyCollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Cbrt(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Cbrt(destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IEnumerable + yield ===
internal static IEnumerable<R> SqrtIterator3<T, R>(this IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units) yield return Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
internal static IEnumerable<R?> SqrtNullableIterator3<T, R>(this IEnumerable<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IEnumerable ===
internal static IEnumerable<R> Cbrt<T, R>(this IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units is T[] array) return array.Cbrt<T, R>();
if (units is List<T> list) return list.Cbrt<T, R>();
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Cbrt(arr);
return arr.ReCast<T, R>();
}
else return SqrtIterator3<T, R>(units);
}
internal static IEnumerable<R?> Cbrt<T, R>(this IEnumerable<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units is T?[] array) return array.Cbrt<T, R>();
if (units is List<T?> list) return list.Cbrt<T, R>();
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Cbrt(arr);
return arr.ReCast<T, R>();
}
else return SqrtNullableIterator3<T, R>(units);
}
}

View File

@@ -2,7 +2,7 @@
namespace QWERTYkez.Mensura.Extensions;
internal static partial class CollectionsSqrtExtensions
internal static partial class CollectionsRootOfSquareExtensions
{
// === SqrtCore === SIMD
internal static unsafe void SqrtCore<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
@@ -13,11 +13,10 @@ internal static partial class CollectionsSqrtExtensions
Span<double> dstDouble = MemoryMarshal.Cast<R, double>(destination);
int i = 0;
ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
// 1. ПУТЬ AVX (x64 Процессоры Intel/AMD) — обрабатываем по 4 элемента double
// 1. ПУТЬ AVX2 / AVX (x64 Процессоры) — обрабатываем по 4 элемента double за такт
if (Avx.IsSupported && len >= 4)
{
int simdEnd = len & ~3;
@@ -26,18 +25,16 @@ internal static partial class CollectionsSqrtExtensions
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
// Получаем указатели через Unsafe.AsPointer
double* pSrc = (double*)Unsafe.AsPointer(ref currentSrc);
double* pDst = (double*)Unsafe.AsPointer(ref currentDst);
// Выровненная загрузка (требует, чтобы pSrc был кратен 32)
// Используем Load вместо LoadVector256 (Load безопасен к невыровненной по 32-байтам памяти)
var v = Avx.LoadVector256(pSrc);
var sqrtV = Avx.Sqrt(v);
// Выровненное сохранение
Avx.Store(pDst, sqrtV);
}
}
// 2. ПУТЬ VECTOR (ARM64 / Apple Silicon / Старые CPU без AVX)
// 2. КРОССПЛАТФОРМЕННЫЙ VECTOR (ARM64 / Apple Silicon / NEON / SIMD Fallback)
else if (Vector.IsHardwareAccelerated && len >= Vector<double>.Count)
{
int vCount = Vector<double>.Count;
@@ -45,18 +42,13 @@ internal static partial class CollectionsSqrtExtensions
for (; i < simdEnd; i += vCount)
{
// Используем Span для кроссплатформенного создания вектора
var v = new Vector<double>(srcDouble.Slice(i, vCount));
// Кроссплатформенный аппаратный корень (на ARM превратится в NEON инструкцию)
var sqrtV = Vector.SquareRoot(v);
// Копируем напрямую в целевой Span
sqrtV.CopyTo(dstDouble.Slice(i, vCount));
}
}
// 3. Хвост массива (или обычный расчет, если SIMD на процессоре недоступен)
// 3. ХВОСТ МАССИВА (или работа на старых CPU)
for (; i < len; i++)
{
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i));
@@ -66,47 +58,41 @@ internal static partial class CollectionsSqrtExtensions
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
// Получаем прямые ref-ссылки на начало буферов за 0 тактов процессора
ref var srcRef = ref MemoryMarshal.GetReference(units);
ref var dstRef = ref MemoryMarshal.GetReference(destination);
int i = 0;
int unrollEnd = len & ~3; // Граница развернутого цикла (кратная 4)
int unrollEnd = len & ~3;
// 1. ОСНОВНОЙ ЦИКЛ: Конвейерная обработка по 4 элемента за итерацию
// ОСНОВНОЙ ЦИКЛ: Конвейерное чтение по 4 элемента (Развертка цикла повышает ILP процессора)
for (; i < unrollEnd; i += 4)
{
T? u0 = Unsafe.Add(ref srcRef, i);
T? u1 = Unsafe.Add(ref srcRef, i + 1);
T? u2 = Unsafe.Add(ref srcRef, i + 2);
T? u3 = Unsafe.Add(ref srcRef, i + 3);
ref readonly T? u0 = ref Unsafe.Add(ref srcRef, i);
ref readonly T? u1 = ref Unsafe.Add(ref srcRef, i + 1);
ref readonly T? u2 = ref Unsafe.Add(ref srcRef, i + 2);
ref readonly T? u3 = ref Unsafe.Add(ref srcRef, i + 3);
// Получаем ref-ссылки на целевые ячейки типа R? (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);
// Считаем нативный корень прямо в регистрах и трансформируем тип из T в R по месту
d0 = u0.HasValue ? Math.Sqrt(u0.Value.ToDouble()).ToUnit<R>() : null;
d1 = u1.HasValue ? Math.Sqrt(u1.Value.ToDouble()).ToUnit<R>() : null;
d2 = u2.HasValue ? Math.Sqrt(u2.Value.ToDouble()).ToUnit<R>() : null;
d3 = u3.HasValue ? Math.Sqrt(u3.Value.ToDouble()).ToUnit<R>() : null;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
// ХВОСТ ЦИКЛА: Остаток элементов
for (; i < len; i++)
{
T? unit = Unsafe.Add(ref srcRef, i);
ref readonly T? unit = ref Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? Math.Sqrt(unit.Value.ToDouble()).ToUnit<R>() : null;
}
}
// === ReadOnlySpan ===
// === ReadOnlySpan API ===
internal static void Sqrt<T, R>(this ReadOnlySpan<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
@@ -130,7 +116,7 @@ internal static partial class CollectionsSqrtExtensions
units.SqrtCore(len, destination);
}
// === Array ===
// === Array API ===
internal static R[] Sqrt<T, R>(this T[] units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
@@ -139,7 +125,7 @@ internal static partial class CollectionsSqrtExtensions
if (units.Length == 0) return [];
var result = new R[units.Length];
Sqrt(units, result);
units.AsSpan().SqrtCore(units.Length, result.AsSpan());
return result;
}
internal static R?[] Sqrt<T, R>(this T?[] units)
@@ -150,11 +136,11 @@ internal static partial class CollectionsSqrtExtensions
if (units.Length == 0) return [];
var result = new R?[units.Length];
Sqrt(units, result);
units.AsSpan().SqrtCore(units.Length, result.AsSpan());
return result;
}
// === List<Length> ===
// === List API ===
internal static List<R> Sqrt<T, R>(this List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
@@ -164,7 +150,7 @@ internal static partial class CollectionsSqrtExtensions
if (len == 0) return [];
var resultArray = new R[len];
Sqrt(CollectionsMarshal.AsSpan(units), resultArray);
CollectionsMarshal.AsSpan(units).SqrtCore(len, resultArray.AsSpan());
return resultArray.WrapAsList<R, R>();
}
internal static List<R?> Sqrt<T, R>(this List<T?> units)
@@ -176,48 +162,11 @@ internal static partial class CollectionsSqrtExtensions
if (len == 0) return [];
var resultArray = new R?[len];
Sqrt(CollectionsMarshal.AsSpan(units), resultArray);
CollectionsMarshal.AsSpan(units).SqrtCore(len, resultArray.AsSpan());
return resultArray.WrapAsList<R, R>();
}
// === ICollection<Length> ===
internal static void Sqrt<T, R>(this ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Sqrt(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Sqrt(destination); return; }
int i = 0;
foreach (T item in units)
destination[i++] = Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
internal static void Sqrt<T, R>(this ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Sqrt(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Sqrt(destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IReadOnlyCollection<Length> ===
// === IReadOnlyCollection ===
internal static void Sqrt<T, R>(this IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
@@ -228,12 +177,16 @@ internal static partial class CollectionsSqrtExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T[] array) { array.Sqrt(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Sqrt(destination); return; }
if (units is T[] array) { array.AsSpan().SqrtCore(count, destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).SqrtCore(count, destination); return; }
int i = 0;
ref R dstRef = ref MemoryMarshal.GetReference(destination);
foreach (T item in units)
destination[i++] = Math.Sqrt(item.ToDouble()).ToUnit<R>();
{
if ((uint)i >= (uint)count) break;
Unsafe.Add(ref dstRef, i++) = Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
}
internal static void Sqrt<T, R>(this IReadOnlyCollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
@@ -245,16 +198,20 @@ internal static partial class CollectionsSqrtExtensions
if (destination.Length < count)
throw new ArgumentException("Destination too short");
if (units is T?[] array) { array.Sqrt(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Sqrt(destination); return; }
if (units is T?[] array) { array.AsSpan().SqrtCore(count, destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).SqrtCore(count, destination); return; }
int i = 0;
ref R? dstRef = ref MemoryMarshal.GetReference(destination);
foreach (T? item in units)
destination[i++] = item.HasValue
{
if ((uint)i >= (uint)count) break;
Unsafe.Add(ref dstRef, i++) = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
}
// === IEnumerable<Length> + yield ===
// === IEnumerable Iterators ===
internal static IEnumerable<R> SqrtIterator<T, R>(this IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
@@ -271,7 +228,7 @@ internal static partial class CollectionsSqrtExtensions
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IEnumerable<Length> ===
// === IEnumerable API ===
internal static IEnumerable<R> Sqrt<T, R>(this IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
@@ -279,12 +236,6 @@ internal static partial class CollectionsSqrtExtensions
if (units is null) return null!;
if (units is T[] array) return array.Sqrt<T, R>();
if (units is List<T> list) return list.Sqrt<T, R>();
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Sqrt(arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
@@ -300,12 +251,6 @@ internal static partial class CollectionsSqrtExtensions
if (units is null) return null!;
if (units is T?[] array) return array.Sqrt<T, R>();
if (units is List<T?> list) return list.Sqrt<T, R>();
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Sqrt(arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();

View File

@@ -1,317 +0,0 @@
using System.Runtime.Intrinsics.X86;
namespace QWERTYkez.Mensura.Extensions;
internal static partial class CollectionsSqrt3Extensions
{
// === SqrtCore3 === SIMD
internal static unsafe void SqrtCore3<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
Span<double> dstDouble = MemoryMarshal.Cast<R, double>(destination);
int i = 0;
ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
// 1. ПУТЬ AVX (x64 Процессоры Intel/AMD) — обрабатываем по 4 элемента double
if (Avx.IsSupported && len >= 4)
{
int simdEnd = len & ~3;
for (; i < simdEnd; i += 4)
{
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
// Получаем указатели через Unsafe.AsPointer
double* pSrc = (double*)Unsafe.AsPointer(ref currentSrc);
double* pDst = (double*)Unsafe.AsPointer(ref currentDst);
// Выровненная загрузка (требует, чтобы pSrc был кратен 32)
var v = Avx.LoadVector256(pSrc);
var sqrtV = Avx.Sqrt(v);
// Выровненное сохранение
Avx.Store(pDst, sqrtV);
}
}
// 2. ПУТЬ VECTOR (ARM64 / Apple Silicon / Старые CPU без AVX)
else if (Vector.IsHardwareAccelerated && len >= Vector<double>.Count)
{
int vCount = Vector<double>.Count;
int simdEnd = len & ~(vCount - 1);
for (; i < simdEnd; i += vCount)
{
// Используем Span для кроссплатформенного создания вектора
var v = new Vector<double>(srcDouble.Slice(i, vCount));
// Кроссплатформенный аппаратный корень (на ARM превратится в NEON инструкцию)
var sqrtV = Vector.SquareRoot(v);
// Копируем напрямую в целевой Span
sqrtV.CopyTo(dstDouble.Slice(i, vCount));
}
}
// 3. Хвост массива (или обычный расчет, если SIMD на процессоре недоступен)
for (; i < len; i++)
{
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i));
}
}
internal static void SqrtCore3<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
// Получаем прямые ref-ссылки на начало буферов за 0 тактов процессора
ref var srcRef = ref MemoryMarshal.GetReference(units);
ref var dstRef = ref MemoryMarshal.GetReference(destination);
int i = 0;
int unrollEnd = len & ~3; // Граница развернутого цикла (кратная 4)
// 1. ОСНОВНОЙ ЦИКЛ: Конвейерная обработка по 4 элемента за итерацию
for (; i < unrollEnd; i += 4)
{
T? u0 = Unsafe.Add(ref srcRef, i);
T? u1 = Unsafe.Add(ref srcRef, i + 1);
T? u2 = Unsafe.Add(ref srcRef, i + 2);
T? u3 = Unsafe.Add(ref srcRef, i + 3);
// Получаем ref-ссылки на целевые ячейки типа R? (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);
// Считаем нативный корень прямо в регистрах и трансформируем тип из T в R по месту
d0 = u0.HasValue ? Math.Sqrt(u0.Value.ToDouble()).ToUnit<R>() : null;
d1 = u1.HasValue ? Math.Sqrt(u1.Value.ToDouble()).ToUnit<R>() : null;
d2 = u2.HasValue ? Math.Sqrt(u2.Value.ToDouble()).ToUnit<R>() : null;
d3 = u3.HasValue ? Math.Sqrt(u3.Value.ToDouble()).ToUnit<R>() : null;
}
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
for (; i < len; i++)
{
T? unit = Unsafe.Add(ref srcRef, i);
ref var dst = ref Unsafe.Add(ref dstRef, i);
dst = unit.HasValue ? Math.Sqrt(unit.Value.ToDouble()).ToUnit<R>() : null;
}
}
// === ReadOnlySpan ===
internal static void Sqrt3<T, R>(this ReadOnlySpan<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units.IsEmpty) return;
int len = units.Length;
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.SqrtCore3(len, destination);
}
internal static void Sqrt3<T, R>(this ReadOnlySpan<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units.IsEmpty) return;
int len = units.Length;
if (len > destination.Length)
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
units.SqrtCore3(len, destination);
}
// === Array ===
internal static R[] Sqrt3<T, R>(this T[] units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units.Length == 0) return [];
var result = new R[units.Length];
Sqrt3(units, result);
return result;
}
internal static R?[] Sqrt3<T, R>(this T?[] units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units.Length == 0) return [];
var result = new R?[units.Length];
Sqrt3(units, result);
return result;
}
// === List<Length> ===
internal static List<R> Sqrt3<T, R>(this List<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
var resultArray = new R[len];
Sqrt3(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
}
internal static List<R?> Sqrt3<T, R>(this List<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
int len = units.Count;
if (len == 0) return [];
var resultArray = new R?[len];
Sqrt3(CollectionsMarshal.AsSpan(units), resultArray);
return resultArray.WrapAsList<R, R>();
}
// === ICollection<Length> ===
internal static void Sqrt3<T, R>(this ICollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Sqrt3(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Sqrt3(destination); return; }
int i = 0;
foreach (T item in units)
destination[i++] = Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
internal static void Sqrt3<T, R>(this ICollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Sqrt3(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Sqrt3(destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IReadOnlyCollection<Length> ===
internal static void Sqrt3<T, R>(this IReadOnlyCollection<T> units, Span<R> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T[] array) { array.Sqrt3(destination); return; }
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Sqrt3(destination); return; }
int i = 0;
foreach (T item in units)
destination[i++] = Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
internal static void Sqrt3<T, R>(this IReadOnlyCollection<T?> units, Span<R?> destination)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
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 T?[] array) { array.Sqrt3(destination); return; }
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Sqrt3(destination); return; }
int i = 0;
foreach (T? item in units)
destination[i++] = item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IEnumerable<Length> + yield ===
internal static IEnumerable<R> SqrtIterator3<T, R>(this IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return Math.Sqrt(item.ToDouble()).ToUnit<R>();
}
internal static IEnumerable<R?> SqrtNullableIterator3<T, R>(this IEnumerable<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
foreach (var item in units)
yield return item.HasValue
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
}
// === IEnumerable<Length> ===
internal static IEnumerable<R> Sqrt3<T, R>(this IEnumerable<T> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units is T[] array) return array.Sqrt3<T, R>();
if (units is List<T> list) return list.Sqrt3<T, R>();
if (units is ICollection<T> col)
{
var arr = col.ToArray();
arr.Sqrt3(arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T> roc)
{
var arr = roc.ToArray();
arr.Sqrt3(arr);
return arr.ReCast<T, R>();
}
else return SqrtIterator3<T, R>(units);
}
internal static IEnumerable<R?> Sqrt3<T, R>(this IEnumerable<T?> units)
where T : struct, IMensuraUnit, IEquatable<T>
where R : struct, IMensuraUnit, IEquatable<R>
{
if (units is null) return null!;
if (units is T?[] array) return array.Sqrt3<T, R>();
if (units is List<T?> list) return list.Sqrt3<T, R>();
if (units is ICollection<T?> col)
{
var arr = col.ToArray();
arr.Sqrt3(arr);
return arr.ReCast<T, R>();
}
if (units is IReadOnlyCollection<T?> roc)
{
var arr = roc.ToArray();
arr.Sqrt3(arr);
return arr.ReCast<T, R>();
}
else return SqrtNullableIterator3<T, R>(units);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,16 @@
namespace QWERTYkez.Mensura;
[StructLayout(LayoutKind.Sequential)]
internal class Mimics<T>
internal class ListMimic<T>
{
public T[] Items = null!;
public int Size;
public int Version;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NullableDoubleMimic
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct NullableDoubleMimic
{
public double Value;
public byte HasValue;
[FieldOffset(0)] public bool HasValue;
[FieldOffset(8)] public double Value;
}

View File

@@ -5,7 +5,6 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>1701;1702;IDE1006</NoWarn>
@@ -13,8 +12,8 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" PrivateAssets="All" />
<ProjectReference Include="..\QWERTYkez.Mensura.Generator\QWERTYkez.Mensura.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\QWERTYkez.Mensura.Generator\QWERTYkez.Mensura.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<InternalsVisibleTo Include="QWERTYkez.Mensura.Tests" />
</ItemGroup>
</Project>

View File

@@ -61,21 +61,21 @@ public static class AreaSqrtExtension
{
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sqrt(
this ReadOnlySpan<Area> units, Span<Length> destination) => units.Sqrt3<Area, Length>(destination);
this ReadOnlySpan<Area> units, Span<Length> destination) => units.Cbrt<Area, Length>(destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sqrt(
this ReadOnlySpan<Area?> units, Span<Length?> destination) => units.Sqrt3<Area, Length>(destination);
this ReadOnlySpan<Area?> units, Span<Length?> destination) => units.Cbrt<Area, Length>(destination);
// === Array ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static Length[] Sqrt(this Area[] units) => units.Sqrt3<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static Length?[] Sqrt(this Area?[] units) => units.Sqrt3<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static Length[] Sqrt(this Area[] units) => units.Cbrt<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static Length?[] Sqrt(this Area?[] units) => units.Cbrt<Area, Length>();
// === List<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length> Sqrt(this List<Area> units) => units.Sqrt3<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length?> Sqrt(this List<Area?> units) => units.Sqrt3<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length> Sqrt(this List<Area> units) => units.Cbrt<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length?> Sqrt(this List<Area?> units) => units.Cbrt<Area, Length>();
// === IEnumerable<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length> Sqrt(this IEnumerable<Area> units) => units.Sqrt3<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length?> Sqrt(this IEnumerable<Area?> units) => units.Sqrt3<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length> Sqrt(this IEnumerable<Area> units) => units.Cbrt<Area, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length?> Sqrt(this IEnumerable<Area?> units) => units.Cbrt<Area, Length>();
}
internal readonly struct AreaConv

View File

@@ -38,22 +38,22 @@ public readonly partial record struct Volume
public static class VolumeSqrtExtension
{
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sqrt3(
this ReadOnlySpan<Volume> units, Span<Length> destination) => units.Sqrt3<Volume, Length>(destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sqrt3(
this ReadOnlySpan<Volume?> units, Span<Length?> destination) => units.Sqrt3<Volume, Length>(destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Cbrt(
this ReadOnlySpan<Volume> units, Span<Length> destination) => units.Cbrt<Volume, Length>(destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Cbrt(
this ReadOnlySpan<Volume?> units, Span<Length?> destination) => units.Cbrt<Volume, Length>(destination);
// === Array ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static Length[] Sqrt3(this Volume[] units) => units.Sqrt3<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static Length?[] Sqrt3(this Volume?[] units) => units.Sqrt3<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static Length[] Cbrt(this Volume[] units) => units.Cbrt<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static Length?[] Cbrt(this Volume?[] units) => units.Cbrt<Volume, Length>();
// === List<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length> Sqrt3(this List<Volume> units) => units.Sqrt3<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length?> Sqrt3(this List<Volume?> units) => units.Sqrt3<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length> Cbrt(this List<Volume> units) => units.Cbrt<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<Length?> Cbrt(this List<Volume?> units) => units.Cbrt<Volume, Length>();
// === IEnumerable<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length> Sqrt3(this IEnumerable<Volume> units) => units.Sqrt3<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length?> Sqrt3(this IEnumerable<Volume?> units) => units.Sqrt3<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length> Cbrt(this IEnumerable<Volume> units) => units.Cbrt<Volume, Length>();
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<Length?> Cbrt(this IEnumerable<Volume?> units) => units.Cbrt<Volume, Length>();
}
internal readonly struct VolumeConv

File diff suppressed because it is too large Load Diff

View File

@@ -1,70 +1,70 @@
//#if DEBUG
//namespace QWERTYkez.Mensura.Units;
#if DEBUG
namespace QWERTYkez.Mensura.Units;
///// <summary>
///// Base value is MilliMeters
///// </summary>
//[DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
//public readonly partial record struct XXXXXXXX
//{
// public static XXXXXXXX MilliMeter { get; } = new(1);
// [NotMapped, JsonIgnore, IgnoreDataMember] public double _MilliMeters { get => _Value; init => _Value = value; }
/// <summary>
/// Base value is MilliMeters
/// </summary>
[DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
public readonly partial record struct XXXXXXXX
{
public static XXXXXXXX MilliMeter { get; } = new(1);
[NotMapped, JsonIgnore, IgnoreDataMember] public double _MilliMeters { get => _Value; init => _Value = value; }
// public static XXXXXXXX CentiMeter { get; } = new(XXXXXXXXConv.CentiMeters.To(1));
// [NotMapped, JsonIgnore, IgnoreDataMember]
// public double CentiMeters
// {
// get => XXXXXXXXConv.CentiMeters.From(_Value);
// init
// {
// _Value = XXXXXXXXConv.CentiMeters.To(value);
// }
// }
public static XXXXXXXX CentiMeter { get; } = new(XXXXXXXXConv.CentiMeters.To(1));
[NotMapped, JsonIgnore, IgnoreDataMember]
public double CentiMeters
{
get => XXXXXXXXConv.CentiMeters.From(_Value);
init
{
_Value = XXXXXXXXConv.CentiMeters.To(value);
}
}
// public static XXXXXXXX DeciMeter { get; } = new(XXXXXXXXConv.DeciMeters.To(1));
// [NotMapped, JsonIgnore, IgnoreDataMember]
// public double DeciMeters
// {
// get => XXXXXXXXConv.DeciMeters.From(_Value);
// init => _Value = XXXXXXXXConv.DeciMeters.To(value);
// }
public static XXXXXXXX DeciMeter { get; } = new(XXXXXXXXConv.DeciMeters.To(1));
[NotMapped, JsonIgnore, IgnoreDataMember]
public double DeciMeters
{
get => XXXXXXXXConv.DeciMeters.From(_Value);
init => _Value = XXXXXXXXConv.DeciMeters.To(value);
}
// public static XXXXXXXX Meter { get; } = new(XXXXXXXXConv.Meters.To(1));
// [NotMapped, JsonIgnore, IgnoreDataMember]
// public double Meters
// {
// get => XXXXXXXXConv.Meters.From(_Value);
// init => _Value = XXXXXXXXConv.Meters.To(value);
// }
public static XXXXXXXX Meter { get; } = new(XXXXXXXXConv.Meters.To(1));
[NotMapped, JsonIgnore, IgnoreDataMember]
public double Meters
{
get => XXXXXXXXConv.Meters.From(_Value);
init => _Value = XXXXXXXXConv.Meters.To(value);
}
// public static XXXXXXXX KiloMeter { get; } = new(XXXXXXXXConv.KiloMeters.To(1));
// [NotMapped, JsonIgnore, IgnoreDataMember]
// public double KiloMeters
// {
// get => XXXXXXXXConv.KiloMeters.From(_Value);
// init => _Value = XXXXXXXXConv.KiloMeters.To(value);
// }
public static XXXXXXXX KiloMeter { get; } = new(XXXXXXXXConv.KiloMeters.To(1));
[NotMapped, JsonIgnore, IgnoreDataMember]
public double KiloMeters
{
get => XXXXXXXXConv.KiloMeters.From(_Value);
init => _Value = XXXXXXXXConv.KiloMeters.To(value);
}
// public XXXXXXXX AddMilliMeters(double value) => new(_Value + value);
// public XXXXXXXX AddCentiMeters(double value) => new(_Value + XXXXXXXXConv.CentiMeters.To(value));
// public XXXXXXXX AddDeciMeters(double value) => new(_Value + XXXXXXXXConv.DeciMeters.To(value));
// public XXXXXXXX AddMeters(double value) => new(_Value + XXXXXXXXConv.Meters.To(value));
// public XXXXXXXX AddKiloMeters(double value) => new(_Value + XXXXXXXXConv.KiloMeters.To(value));
//}
public XXXXXXXX AddMilliMeters(double value) => new(_Value + value);
public XXXXXXXX AddCentiMeters(double value) => new(_Value + XXXXXXXXConv.CentiMeters.To(value));
public XXXXXXXX AddDeciMeters(double value) => new(_Value + XXXXXXXXConv.DeciMeters.To(value));
public XXXXXXXX AddMeters(double value) => new(_Value + XXXXXXXXConv.Meters.To(value));
public XXXXXXXX AddKiloMeters(double value) => new(_Value + XXXXXXXXConv.KiloMeters.To(value));
}
//internal readonly struct XXXXXXXXConv
//{
// private XXXXXXXXConv(double multiplicator) => this.Multiplicator = multiplicator;
// public double To(double value) => value * Multiplicator;
// public double From(double value) => value / Multiplicator;
// public double Multiplicator { get; init; }
// public static XXXXXXXXConv MilliMeters { get; } = new(1);
// public static XXXXXXXXConv CentiMeters { get; } = new(10);
// public static XXXXXXXXConv DeciMeters { get; } = new(100);
// public static XXXXXXXXConv Meters { get; } = new(1000);
// public static XXXXXXXXConv KiloMeters { get; } = new(1000000);
//}
//#endif
internal readonly struct XXXXXXXXConv
{
private XXXXXXXXConv(double multiplicator) => this.Multiplicator = multiplicator;
public double To(double value) => value * Multiplicator;
public double From(double value) => value / Multiplicator;
public double Multiplicator { get; init; }
public static XXXXXXXXConv MilliMeters { get; } = new(1);
public static XXXXXXXXConv CentiMeters { get; } = new(10);
public static XXXXXXXXConv DeciMeters { get; } = new(100);
public static XXXXXXXXConv Meters { get; } = new(1000);
public static XXXXXXXXConv KiloMeters { get; } = new(1000000);
}
#endif