diff --git a/QWERTYkez.Mensura.Generator/OperatorsGenerator.cs b/QWERTYkez.Mensura.Generator/OperatorsGenerator.cs
index 55c1725..a2e4838 100644
--- a/QWERTYkez.Mensura.Generator/OperatorsGenerator.cs
+++ b/QWERTYkez.Mensura.Generator/OperatorsGenerator.cs
@@ -14,7 +14,7 @@ internal class CollectionsOperatorsGenerator : IIncrementalGenerator
private const string AttributeShortName = "CollectionsOperatorsGenerator";
private const string AttributeFullName = AttributeShortName + "Attribute";
- private const string AttributeSource = @"namespace MetricSystem.Generator;
+ private const string AttributeSource = @"namespace QWERTYkez.Mensura;
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
internal sealed class CollectionsOperatorsGeneratorAttribute : System.Attribute { }";
diff --git a/QWERTYkez.Mensura.Generator/QWERTYkez.Mensura.Generator.csproj b/QWERTYkez.Mensura.Generator/QWERTYkez.Mensura.Generator.csproj
index 1b8fd95..c59ec9c 100644
--- a/QWERTYkez.Mensura.Generator/QWERTYkez.Mensura.Generator.csproj
+++ b/QWERTYkez.Mensura.Generator/QWERTYkez.Mensura.Generator.csproj
@@ -15,12 +15,12 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/QWERTYkez.Mensura.Generator/UnitOperatorsGenerator.cs b/QWERTYkez.Mensura.Generator/UnitOperatorsGenerator.cs
index 62d2a53..bddb0ae 100644
--- a/QWERTYkez.Mensura.Generator/UnitOperatorsGenerator.cs
+++ b/QWERTYkez.Mensura.Generator/UnitOperatorsGenerator.cs
@@ -18,7 +18,7 @@ public class UnitOperatorsGenerator : IIncrementalGenerator
context.RegisterPostInitializationOutput(ctx =>
{
ctx.AddSource("UnitOperatorsGeneratorAttribute.g.cs",
- SourceText.From(@"namespace MetricSystem.Generator
+ SourceText.From(@"namespace QWERTYkez.Mensura
{
[System.AttributeUsage(System.AttributeTargets.Struct | System.AttributeTargets.RecordStruct, AllowMultiple = false)]
public sealed class UnitOperatorsGeneratorAttribute : System.Attribute { }
diff --git a/QWERTYkez.Mensura/Extensions.cs b/QWERTYkez.Mensura/Extensions.cs
new file mode 100644
index 0000000..03cce00
--- /dev/null
+++ b/QWERTYkez.Mensura/Extensions.cs
@@ -0,0 +1,315 @@
+namespace QWERTYkez.Mensura;
+
+public static partial class Extensions
+{
+ internal static double ToDouble(this sbyte number) => Convert.ToDouble(number);
+ internal static double ToDouble(this short number) => Convert.ToDouble(number);
+ internal static double ToDouble(this int number) => Convert.ToDouble(number);
+ internal static double ToDouble(this long number) => Convert.ToDouble(number);
+ internal static double ToDouble(this byte number) => Convert.ToDouble(number);
+ internal static double ToDouble(this ushort number) => Convert.ToDouble(number);
+ internal static double ToDouble(this uint number) => Convert.ToDouble(number);
+ internal static double ToDouble(this ulong number) => Convert.ToDouble(number);
+ internal static double ToDouble(this nint number) => Convert.ToDouble(number);
+ internal static double ToDouble(this nuint number) => Convert.ToDouble(number);
+ internal static double ToDouble(this float number) => Convert.ToDouble(number);
+ internal static double ToDouble(this decimal number) => Convert.ToDouble(number);
+
+ internal static double ToDouble(this sbyte? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this short? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this int? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this long? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this byte? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this ushort? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this uint? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this ulong? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this nint? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this nuint? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this float? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this decimal? number) => number is null ? 0d : Convert.ToDouble(number);
+
+#if NET7_0_OR_GREATER
+ internal static double ToDouble(this Int128 number) => Convert.ToDouble(number);
+ internal static double ToDouble(this UInt128 number) => Convert.ToDouble(number);
+
+ internal static double ToDouble(this Int128? number) => number is null ? 0d : Convert.ToDouble(number);
+ internal static double ToDouble(this UInt128? number) => number is null ? 0d : Convert.ToDouble(number);
+#endif
+
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static unsafe void SetCountUnsafe(this List list, int count)
+ {
+ // Берем адрес управляемого объекта List в памяти
+ // Объект передается по ref-ссылке, преобразуется в указатель
+ ref var mimic = ref Unsafe.As, ListLayoutMimic>(ref list);
+
+ // Меняем приватный размер напрямую в памяти объекта!
+ mimic.Size = count;
+ }
+
+
+
+
+
+
+
+
+ internal static U Protect(this U? metric) where U : class, IMetric, new() => metric ?? new();
+ internal static C Protect(this C? collection)
+ where C : IMetricCollection, new() where U : class, IMetric, new() => collection ?? new();
+
+
+ public static C MetricSelect(this C? collection, Func? selector)
+ where C : IMetricCollection, new() where U : class, IMetric, new()
+ {
+ var source = (collection ??= new());
+ var nColl = (C)source.CreateByInstanceU(source.Count);
+ if (selector is not null)
+ {
+ for (int i = 0; i < nColl.Count; i++)
+ nColl[i] = selector(source[i]);
+ return nColl;
+ }
+ return new();
+ }
+ public static IEnumerable MetricSelect(this IMetricCollection collection, Func selector)
+ where U : class, IMetric, new()
+ {
+ if (collection is not null)
+ {
+ if (selector is not null)
+ return collection.Select(selector);
+ return collection.Select(u => double.NaN);
+ }
+ else return [];
+ }
+
+
+
+
+ public static IMetricCollection MetricSelect(this IMetricCollection? collection, Func? selector)
+ where Ux : class, IMetric, new() where Uz : class, IMetric, new()
+ {
+ if (collection is not null && selector is not null)
+ {
+ var destCollection = collection.CreateByInstance(collection.Count);
+ for (int i = 0; i < collection.Count; i++)
+ destCollection[i] = selector(collection[i]);
+ return destCollection;
+ }
+ return null!;
+ }
+ public static MetricCollection MetricSelect(this MetricCollection? collection, Func? selector)
+ where Ux : class, IMetric, new() where Uz : class, IMetric, new()
+ {
+ if (collection is not null && selector is not null)
+ {
+ var destCollection = collection.CreateByInstance(collection.Count());
+ for (int i = 0; i < collection.Count(); i++)
+ destCollection[i] = selector(collection[i]);
+ return destCollection;
+ }
+ return null!;
+ }
+ public static MetricArray MetricSelect(this MetricArray? collection, Func? selector)
+ where Ux : class, IMetric, new() where Uz : class, IMetric, new()
+ {
+ var coll = collection?.ToArray();
+ if (coll is not null && selector is not null)
+ {
+ var destCollection = new MetricArray(coll.Length);
+ for (int i = 0; i < coll.Length; i++)
+ destCollection[i] = selector(coll[i]);
+ return destCollection;
+ }
+ return null!;
+ }
+ public static MetricList MetricSelect(this MetricList? collection, Func? selector)
+ where Ux : class, IMetric, new() where Uz : class, IMetric, new()
+ {
+ if (collection is not null && selector is not null)
+ {
+ var destCollection = new MetricList(collection.Count);
+ for (int i = 0; i < collection.Count; i++)
+ destCollection[i] = selector(collection[i]);
+ return destCollection;
+ }
+ return null!;
+ }
+ public static MetricObservableCollection MetricSelect(this MetricObservableCollection? collection, Func? selector)
+ where Ux : class, IMetric, new() where Uz : class, IMetric, new()
+ {
+ if (collection is not null && selector is not null)
+ {
+ var destCollection = new MetricObservableCollection(collection.Count);
+ for (int i = 0; i < collection.Count; i++)
+ destCollection[i] = selector(collection[i]);
+ return destCollection;
+ }
+ return null!;
+ }
+
+
+ public static double[] MetricSelect(this MetricArray collection, Func selector)
+ where U : class, IMetric, new()
+ {
+ var coll = collection ?? [];
+ var arr = new double[coll.Length];
+ if (selector is not null)
+ for (int i = 0; i < arr.Length; i++)
+ arr[i] = selector(coll[i]);
+ return arr;
+ }
+ public static List MetricSelect(this MetricList collection, Func selector)
+ where U : class, IMetric, new()
+ {
+ var coll = collection ?? [];
+ var list = new List(coll.Count);
+ if (selector is not null)
+ for (int i = 0; i < list.Count; i++)
+ list[i] = selector(coll[i]);
+ return list;
+ }
+ public static ObservableCollection MetricSelect(this MetricObservableCollection collection, Func selector)
+ where U : class, IMetric, new()
+ {
+ var coll = collection ?? [];
+ var list = new List(coll.Count);
+ if (selector is not null)
+ for (int i = 0; i < list.Count; i++)
+ list[i] = selector(coll[i]);
+ return new(list);
+ }
+ internal static C ForEachC(this C? collection, Func? Set)
+ where C : IMetricCollection, new() where U : class, IMetric, new()
+ {
+ var nColl = (C)(collection ??= new()).CreateByInstanceU(collection.Count);
+ if (Set is not null)
+ for (int i = 0; i < nColl.Count; i++)
+ nColl[i] = Set(nColl[i]);
+ return nColl;
+ }
+ internal static double ProtectValue(this IMetric? metric) => metric is null ? 0d : metric.Value;
+
+ public static U Min(this U? T1, U? T2) where U : class, IMetric, new() => (T1.ProtectValue() < T2.ProtectValue() ? T1 : T2).Protect();
+ public static U Min(this U T1, IEnumerable units) where U : class, IMetric, new() => (T1 ?? new()).Min((units ?? []).MaxBy(u => u.ProtectValue()));
+
+ public static U Max(this U? T1, U? T2) where U : class, IMetric, new() => (T1.ProtectValue() > T2.ProtectValue() ? T1 : T2).Protect();
+ public static U Max(this U T1, IEnumerable units) where U : class, IMetric, new() => (T1 ?? new()).Max((units ?? []).MaxBy(u => u.ProtectValue()));
+
+
+ //internal static double ToDouble(this double number) => number;
+ //internal static double ToDouble(this double? number) => number ?? 0d;
+ //internal static double ToDouble(this N number) where N : INumber => Convert.ToDouble(number);
+ //internal static double ToDouble(this N? number) where N : struct, INumber => number is not null ? Convert.ToDouble(number) : 0d;
+
+
+ internal static IEnumerable MetricSelect(this double[] nums, Func selector) where U : class, IMetric, new() => nums.Select(selector);
+ internal static IEnumerable MetricSelect(this double?[] nums, Func selector) where U : class, IMetric, new() => nums.Select(num => selector(num.ToDouble()));
+ internal static IEnumerable MetricSelect(this N[] nums, Func selector) where N : INumber where U : class, IMetric, new() => nums.Select(num => selector(num.ToDouble()));
+ internal static IEnumerable MetricSelect(this N?[] nums, Func selector) where N : struct, INumber where U : class, IMetric, new() => nums.Select(num => selector(num.ToDouble()));
+
+
+ internal static IEnumerable MetricSelect(this IEnumerable nums, Func selector) where U : class, IMetric, new() => nums.Select(selector);
+ internal static IEnumerable MetricSelect(this IEnumerable nums, Func selector) where U : class, IMetric, new() => nums.Select(num => selector(num.ToDouble()));
+ internal static IEnumerable MetricSelect(this IEnumerable nums, Func selector) where N : INumber where U : class, IMetric, new() => nums.Select(num => selector(num.ToDouble()));
+ internal static IEnumerable MetricSelect(this IEnumerable nums, Func selector) where N : struct, INumber where U : class, IMetric, new() => nums.Select(num => selector(num.ToDouble()));
+
+
+
+
+ public static U Clone(this U? metric) where U : class, IMetric, new() => new() { Value = metric.ProtectValue() };
+ public static U Abs(this U? metric) where U : class, IMetric, new() => new() { Value = Math.Abs(metric.ProtectValue()) };
+
+ /// C^2 = A^2 + B^2
+ /// C = (A^2 + B^2).Sqrt(2)
+ public static U Hypotenuse(this U? A, U? B) where U : class, IMetric, new()
+ {
+ var a = A.ProtectValue();
+ var b = B.ProtectValue();
+ return new U() { Value = Math.Sqrt(a * a + b * b) };
+ }
+ /// C^2 = A^2 + B^2
+ /// B = (C^2 - A^2).Sqrt(2)
+ public static U KatetFromHyp(this U? A, U? C) where U : class, IMetric, new()
+ {
+ var a = A.ProtectValue();
+ var c = C.ProtectValue();
+ return new U() { Value = Math.Sqrt(c * c - a * a) };
+ }
+ /// C^2 = A^2 + B^2
+ /// B = (C^2 - A^2).Sqrt(2)
+ public static U KatetFromKatet(this U? C, U? A) where U : class, IMetric, new()
+ {
+ var a = A.ProtectValue();
+ var c = C.ProtectValue();
+ return new U() { Value = Math.Sqrt(c * c - a * a) };
+ }
+
+ public static Area Pow(this Length? metric, double? val = 2) => new() { Value = Math.Pow(metric.ProtectValue(), val ?? 2) };
+ public static Length Sqrt(this Area? metric) => new() { Value = Math.Sqrt(metric.ProtectValue()) };
+
+
+ public static U MetricSum(this IEnumerable args) where U : IMetric, new() => new() { Value = args?.Where(t => t is not null).Sum(m => m.ProtectValue()) ?? 0d };
+ public static U MetricAverage(this IEnumerable args) where U : IMetric, new() => new() { Value = args?.Average(m => m.ProtectValue()) ?? double.NaN };
+ public static U MetricMax(this IEnumerable args) where U : IMetric, new() => new() { Value = args.Max(m => m.ProtectValue()) };
+ public static U MetricMin(this IEnumerable args) where U : IMetric, new() => new() { Value = args.Min(m => m.ProtectValue()) };
+
+
+
+ public static C MetricSum(this IEnumerable> collections)
+ where C : MetricCollection, ICreateByCapacity, new() where U : class, IMetric, new()
+ {
+ var cArr = collections.ToArray();
+ C accumulator = (C)cArr.FirstOrDefault(new C());
+ for (int i = 1; i < cArr.Length; i++)
+ accumulator = accumulator.FuncByPairOrOneToMany(cArr[i], (a, b) => a + b, out C _);
+ return accumulator;
+ }
+ public static C MetricAverage(this IEnumerable> collections)
+ where C : MetricCollection, ICreateByCapacity, new() where U : class, IMetric, new()
+ => collections.MetricSum() / collections.Count();
+
+
+
+ public static U MetricSumBy(this IEnumerable source, Func selector)
+ where U : class, IMetric, new()
+ {
+ if (source is null) return new();
+ if (selector is null) throw new ArgumentNullException("selector is null");
+
+ return new() { Value = source.Select(selector).Where(t => t is not null).Sum(t => t.ProtectValue()) };
+ }
+ public static U MetricAverageBy(this IEnumerable source, Func selector)
+ where U : class, IMetric, new()
+ {
+ if (source is null) return new();
+ if (selector is null) throw new ArgumentNullException("selector is null");
+
+ return new() { Value = source.Select(selector).Average(t => t.ProtectValue()) };
+ }
+
+
+ public static C MetricSumBy(this IEnumerable source, Func> selector)
+ where C : MetricCollection, ICreateByCapacity, new() where U : class, IMetric, new()
+ {
+ if (source is null) return new();
+ if (selector is null) throw new ArgumentNullException("selector is null");
+
+ return source.Select(selector).MetricSum();
+ }
+ public static C MetricAverageBy(this IEnumerable source, Func> selector)
+ where C : MetricCollection, ICreateByCapacity, new() where U : class, IMetric, new()
+ {
+ if (source is null) return new();
+ if (selector is null) throw new ArgumentNullException("selector is null");
+
+ return source.Select(selector).MetricAverage();
+ }
+
+
+
+ public static MetricArray ToMetricArray(this IEnumerable source) where U : class, IMetric, new() => new(source);
+ public static MetricList ToMetricList(this IEnumerable source) where U : class, IMetric, new() => new(source);
+}
\ No newline at end of file
diff --git a/QWERTYkez.Mensura/ListLayoutMimic.cs b/QWERTYkez.Mensura/ListLayoutMimic.cs
new file mode 100644
index 0000000..5154799
--- /dev/null
+++ b/QWERTYkez.Mensura/ListLayoutMimic.cs
@@ -0,0 +1,9 @@
+namespace QWERTYkez.Mensura;
+
+[StructLayout(LayoutKind.Sequential)]
+internal unsafe struct ListLayoutMimic
+{
+ public T[] Items;
+ public int Size;
+ public int Version;
+}
\ No newline at end of file
diff --git a/QWERTYkez.Mensura/QWERTYkez.Mensura.csproj b/QWERTYkez.Mensura/QWERTYkez.Mensura.csproj
index ff82a64..f11f431 100644
--- a/QWERTYkez.Mensura/QWERTYkez.Mensura.csproj
+++ b/QWERTYkez.Mensura/QWERTYkez.Mensura.csproj
@@ -1,9 +1,26 @@
-
+
- net6.0
+ net6.0;net7.0;net8.0;net9.0;net10.0
enable
enable
+ latest
+ false
+ false
+ true
+
+
+
+
+
+
+ 10.0.8
+
+
+ 10.0.8
+
+
+
\ No newline at end of file
diff --git a/QWERTYkez.Mensura/Units/Length.cs b/QWERTYkez.Mensura/Units/Length.cs
new file mode 100644
index 0000000..d662fe1
--- /dev/null
+++ b/QWERTYkez.Mensura/Units/Length.cs
@@ -0,0 +1,1144 @@
+namespace QWERTYkez.Mensura.Units;
+
+///
+/// Base value is MilliMeters
+///
+
+[UnitOperatorsGenerator, DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
+public readonly partial record struct Length
+{
+ public static Length MilliMeter { get; } = new(1);
+#pragma warning disable IDE1006 // _Подчеркивание для обозначения того, что это базовая единица
+ [NotMapped, JsonIgnore] public double _MilliMeters { get => _Value; init => _Value = value; }
+#pragma warning restore IDE1006
+
+
+ public static Length CentiMeter { get; } = new(LengthConv.CentiMeters.To(1));
+ [NotMapped, JsonIgnore] public double CentiMeters
+ {
+ get => LengthConv.CentiMeters.From(_Value);
+ init
+ {
+ Length aaa = new();
+ Length bbb = new();
+
+ if (aaa != bbb || aaa == bbb)
+ {
+
+ }
+
+ _Value = LengthConv.CentiMeters.To(value);
+ }
+ }
+
+ public static Length DeciMeter { get; } = new(LengthConv.DeciMeters.To(1));
+ [NotMapped, JsonIgnore] public double DeciMeters
+ {
+ get => LengthConv.DeciMeters.From(_Value);
+ init => _Value = LengthConv.DeciMeters.To(value);
+ }
+
+ public static Length Meter { get; } = new(LengthConv.Meters.To(1));
+ [NotMapped, JsonIgnore] public double Meters
+ {
+ get => LengthConv.Meters.From(_Value);
+ init => _Value = LengthConv.Meters.To(value);
+ }
+
+ public static Length KiloMeter { get; } = new(LengthConv.KiloMeters.To(1));
+ [NotMapped, JsonIgnore] public double KiloMeters
+ {
+ get => LengthConv.KiloMeters.From(_Value);
+ init => _Value = LengthConv.KiloMeters.To(value);
+ }
+
+
+ public Length AddMilliMeters(double value) => new(_Value + value);
+ public Length AddCentiMeters(double value) => new(_Value + LengthConv.CentiMeters.To(value));
+ public Length AddDeciMeters(double value) => new(_Value + LengthConv.DeciMeters.To(value));
+ public Length AddMeters(double value) => new(_Value + LengthConv.Meters.To(value));
+ public Length AddKiloMeters(double value) => new(_Value + LengthConv.KiloMeters.To(value));
+
+
+
+
+
+
+ public static explicit operator Length(double val) => new(val);
+ public static explicit operator double(Length unit) => unit._Value;
+
+ public Length Abs() => new(Math.Abs(_Value));
+
+ /// C^2 = this^2 + B^2 C = (this^2 + B^2).Sqrt(2)
+ public Length HypFromLeg(Length B) => new(Math.Sqrt(_Value * _Value + B._Value * B._Value));
+
+ /// C^2 = this^2 + B^2 C = (this^2 + B^2).Sqrt(2)
+ public Length HypFromLeg(Length? B)
+ {
+ double b = B is null ? 0d : B.Value._Value;
+ return new(Math.Sqrt(_Value * _Value + b * b));
+ }
+
+ /// C^2 = this^2 + B^2 B = (C^2 - this^2).Sqrt(2)
+ public Length LegFromHyp(Length C) => new(Math.Sqrt(C._Value * C._Value - _Value * _Value));
+
+ /// C^2 = this^2 + B^2 B = (C^2 - this^2).Sqrt(2)
+ public Length LegFromHyp(Length? C)
+ {
+ double c = C is null ? 0d : C.Value._Value;
+ return new(Math.Sqrt(c * c - _Value * _Value));
+ }
+
+ /// this^2 = A^2 + B^2 B = (this^2 - A^2).Sqrt(2)
+ public Length LegFromLeg(Length A) => new(Math.Sqrt(_Value * _Value - A._Value * A._Value));
+
+ /// this^2 = A^2 + B^2 B = (this^2 - A^2).Sqrt(2)
+ public Length LegFromLeg(Length? A)
+ {
+ double a = A is null ? 0d : A.Value._Value;
+ return new(Math.Sqrt(_Value * _Value - a * a));
+ }
+}
+
+public static class LengthExtension
+{
+ internal static double ToDouble(this Length? unit) => unit is null ? 0d : unit.Value._Value;
+
+ public static Length MetricSum(this IEnumerable units) => new() { Value = units?.Sum(m => m._Value) ?? 0d };
+ public static Length MetricAverage(this IEnumerable units) => new() { Value = units?.Average(m => m._Value) ?? double.NaN };
+ public static Length MetricMax(this IEnumerable units) => new() { Value = units?.Max(m => m._Value) ?? double.MinValue };
+ public static Length MetricMin(this IEnumerable units) => new() { Value = units?.Min(m => m._Value) ?? double.MaxValue };
+
+ public static Length MetricSum(this IEnumerable units) => new() { Value = units?.Sum(m => m.ToDouble()) ?? 0d };
+ public static Length MetricAverage(this IEnumerable units) => new() { Value = units?.Average(m => m.ToDouble()) ?? double.NaN };
+ public static Length MetricMax(this IEnumerable units) => new() { Value = units?.Max(m => m.ToDouble()) ?? double.MinValue };
+ public static Length MetricMin(this IEnumerable units) => new() { Value = units?.Min(m => m.ToDouble()) ?? double.MaxValue };
+
+
+ internal static void MultiplyCore(ReadOnlySpan source, double value, Span destination)
+ {
+ int len = source.Length;
+ ReadOnlySpan srcDouble = MemoryMarshal.Cast(source);
+ Span dstDouble = MemoryMarshal.Cast(destination);
+
+ var vectorizedValue = new Vector(value);
+ int vectorSize = Vector.Count;
+ int i = 0;
+
+ ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
+ ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
+
+ int SIMDEnd = len - (len % vectorSize);
+ for (; i < SIMDEnd; i += vectorSize)
+ {
+ ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
+ ReadOnlySpan srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
+ var vector = new Vector(srcWindow);
+ var multiplied = vector * vectorizedValue;
+ ref double currentDst = ref Unsafe.Add(ref dstRef, i);
+ Span dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
+ multiplied.CopyTo(dstWindow);
+ }
+
+ for (; i < len; i++)
+ {
+ Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * value;
+ }
+ }
+ internal static void DivideCore(ReadOnlySpan source, double divisor, Span destination)
+ {
+ // 1. Проверка на ноль
+ if (divisor == 0d || double.IsNaN(divisor))
+ throw new DivideByZeroException("Делитель не может быть равен нулю.");
+
+ int len = source.Length;
+ ReadOnlySpan srcDouble = MemoryMarshal.Cast(source);
+ Span dstDouble = MemoryMarshal.Cast(destination);
+
+ var vectorizedValue = new Vector(divisor);
+ int vectorSize = Vector.Count;
+ int i = 0;
+
+ ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
+ ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
+
+ int SIMDEnd = len - (len % vectorSize);
+ for (; i < SIMDEnd; i += vectorSize)
+ {
+ ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
+ ReadOnlySpan srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
+ var vector = new Vector(srcWindow);
+ var multiplied = vector / vectorizedValue;
+ ref double currentDst = ref Unsafe.Add(ref dstRef, i);
+ Span dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
+ multiplied.CopyTo(dstWindow);
+ }
+
+ for (; i < len; i++)
+ {
+ Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) / divisor;
+ }
+ }
+ internal static void DivideCore(double dividend, ReadOnlySpan source, Span destination)
+ {
+ int len = source.Length;
+ ReadOnlySpan srcDouble = MemoryMarshal.Cast(source);
+ Span dstDouble = MemoryMarshal.Cast(destination);
+
+ var vectorizedValue = new Vector(dividend);
+ var zeroVector = Vector.Zero; // Вектор из нулей для сравнения
+ int vectorSize = Vector.Count;
+ int i = 0;
+
+ ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
+ ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
+
+ int SIMDEnd = len - (len % vectorSize);
+ for (; i < SIMDEnd; i += vectorSize)
+ {
+ ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
+ ReadOnlySpan srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
+ var vector = new Vector(srcWindow);
+
+ // БЫСТРАЯ ПРОВЕРКА: Есть ли хотя бы один 0.0 в текущем векторе?
+ if (Vector.EqualsAny(vector, zeroVector))
+ {
+ throw new DivideByZeroException($"Обнаружен делитель, равный нулю, в районе индексов {i}..{i + vectorSize - 1}.");
+ }
+
+ var multiplied = vectorizedValue / vector;
+ ref double currentDst = ref Unsafe.Add(ref dstRef, i);
+ Span dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
+ multiplied.CopyTo(dstWindow);
+ }
+
+ // Хвостовой цикл
+ for (; i < len; i++)
+ {
+ double divisor = Unsafe.Add(ref srcRef, i);
+ if (divisor == 0.0)
+ {
+ throw new DivideByZeroException($"Обнаружен делитель, равный нулю, в индексе {i}.");
+ }
+ Unsafe.Add(ref dstRef, i) = dividend / divisor;
+ }
+ }
+ internal static void PlusCore(ReadOnlySpan source, double summand, Span destination)
+ {
+ int len = source.Length;
+ ReadOnlySpan srcDouble = MemoryMarshal.Cast(source);
+ Span dstDouble = MemoryMarshal.Cast(destination);
+
+ var vectorizedValue = new Vector(summand);
+ int vectorSize = Vector.Count;
+ int i = 0;
+
+ ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
+ ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
+
+ int SIMDEnd = len - (len % vectorSize);
+ for (; i < SIMDEnd; i += vectorSize)
+ {
+ ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
+ ReadOnlySpan srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
+ var vector = new Vector(srcWindow);
+ var multiplied = vector + vectorizedValue;
+ ref double currentDst = ref Unsafe.Add(ref dstRef, i);
+ Span dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
+ multiplied.CopyTo(dstWindow);
+ }
+
+ for (; i < len; i++)
+ {
+ Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) + summand;
+ }
+ }
+ internal static void MinusCore(ReadOnlySpan source, double subtrahend, Span destination)
+ {
+ int len = source.Length;
+ ReadOnlySpan srcDouble = MemoryMarshal.Cast(source);
+ Span dstDouble = MemoryMarshal.Cast(destination);
+
+ var vectorizedValue = new Vector(subtrahend);
+ int vectorSize = Vector.Count;
+ int i = 0;
+
+ ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
+ ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
+
+ int SIMDEnd = len - (len % vectorSize);
+ for (; i < SIMDEnd; i += vectorSize)
+ {
+ ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
+ ReadOnlySpan srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
+ var vector = new Vector(srcWindow);
+ var multiplied = vector - vectorizedValue;
+ ref double currentDst = ref Unsafe.Add(ref dstRef, i);
+ Span dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
+ multiplied.CopyTo(dstWindow);
+ }
+
+ for (; i < len; i++)
+ {
+ Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) - subtrahend;
+ }
+ }
+ internal static void MinusCore(double minuend, ReadOnlySpan source, Span destination)
+ {
+ int len = source.Length;
+ ReadOnlySpan srcDouble = MemoryMarshal.Cast(source);
+ Span dstDouble = MemoryMarshal.Cast(destination);
+
+ var vectorizedValue = new Vector(minuend);
+ int vectorSize = Vector.Count;
+ int i = 0;
+
+ ref double srcRef = ref MemoryMarshal.GetReference(srcDouble);
+ ref double dstRef = ref MemoryMarshal.GetReference(dstDouble);
+
+ int SIMDEnd = len - (len % vectorSize);
+ for (; i < SIMDEnd; i += vectorSize)
+ {
+ ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
+ ReadOnlySpan srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
+ var vector = new Vector