This commit is contained in:
2026-06-01 01:31:31 +07:00
parent ba77411c4a
commit e43c885fbe
7 changed files with 5146 additions and 2238 deletions

View File

@@ -1,226 +1,226 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
//using Microsoft.CodeAnalysis;
//using Microsoft.CodeAnalysis.CSharp.Syntax;
//using Microsoft.CodeAnalysis.Text;
//using System.Collections.Generic;
//using System.Collections.Immutable;
//using System.Linq;
//using System.Text;
namespace QWERTYkez.Mensura.Generator;
//namespace QWERTYkez.Mensura.Generator;
[Generator(LanguageNames.CSharp)]
internal class CollectionsOperatorsGenerator : IIncrementalGenerator
{
private const string AttributeShortName = "CollectionsOperatorsGenerator";
private const string AttributeFullName = AttributeShortName + "Attribute";
//[Generator(LanguageNames.CSharp)]
//internal class CollectionsOperatorsGenerator : IIncrementalGenerator
//{
// private const string AttributeShortName = "CollectionsOperatorsGenerator";
// private const string AttributeFullName = AttributeShortName + "Attribute";
private const string AttributeSource = @"namespace QWERTYkez.Mensura;
// private const string AttributeSource = @"namespace QWERTYkez.Mensura;
[System.AttributeUsage(System.AttributeTargets.Struct | System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
internal sealed class CollectionsOperatorsGeneratorAttribute : System.Attribute { }";
//[System.AttributeUsage(System.AttributeTargets.Struct | System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
//internal sealed class CollectionsOperatorsGeneratorAttribute : System.Attribute { }";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(context =>
context.AddSource(
$"{AttributeFullName}.g",
SourceText.From(AttributeSource, Encoding.UTF8)));
// public void Initialize(IncrementalGeneratorInitializationContext context)
// {
// context.RegisterPostInitializationOutput(context =>
// context.AddSource(
// $"{AttributeFullName}.g",
// SourceText.From(AttributeSource, Encoding.UTF8)));
var operatorsPipeline =
context.SyntaxProvider.CreateSyntaxProvider<KeyValuePair<ClassData, ImmutableArray<Operation>>>(
(node, _) =>
{
if (node is ClassDeclarationSyntax cds)
{
SyntaxNode sn = cds;
while (sn.Parent is not null &&
sn.Parent is not FileScopedNamespaceDeclarationSyntax)
{
sn = sn.Parent;
}
if (sn.Parent is FileScopedNamespaceDeclarationSyntax
&& cds.TypeParameterList is null
&&
((cds.Members.OfType<OperatorDeclarationSyntax>()
.Where(m => m.AttributeLists.SelectMany(al => al.Attributes)
.Any(a => a.Name.GetText().ToString().Contains(AttributeShortName)))
.Any())
||
(cds.Modifiers.Any(m => m.Text == "partial")
&& cds.AttributeLists
.SelectMany(al => al.Attributes)
.Any(a => a.Name
.GetText()
.ToString()
.Contains(AttributeShortName)))))
{
return true;
}
}
return false;
},
(syntax, _) =>
{
string nameSpace;
var cds = (ClassDeclarationSyntax)syntax.Node;
{
SyntaxNode sn = cds;
while (sn.Parent is not FileScopedNamespaceDeclarationSyntax)
{
sn = sn.Parent!;
}
var nds = (FileScopedNamespaceDeclarationSyntax)sn.Parent;
nameSpace = nds.Name.ToString();
}
var Res = new StringBuilder();
{
Res.Append(cds.Modifiers);
Res.Append(" class ");
Res.Append(cds.Identifier.Text);
Res.Append(" ");
Res.Append(cds.BaseList);
Res.Append(" ");
Res.Append(cds.ConstraintClauses);
}
// var operatorsPipeline =
// context.SyntaxProvider.CreateSyntaxProvider<KeyValuePair<ClassData, ImmutableArray<Operation>>>(
// (node, _) =>
// {
// if (node is ClassDeclarationSyntax cds)
// {
// SyntaxNode sn = cds;
// while (sn.Parent is not null &&
// sn.Parent is not FileScopedNamespaceDeclarationSyntax)
// {
// sn = sn.Parent;
// }
// if (sn.Parent is FileScopedNamespaceDeclarationSyntax
// && cds.TypeParameterList is null
// &&
// ((cds.Members.OfType<OperatorDeclarationSyntax>()
// .Where(m => m.AttributeLists.SelectMany(al => al.Attributes)
// .Any(a => a.Name.GetText().ToString().Contains(AttributeShortName)))
// .Any())
// ||
// (cds.Modifiers.Any(m => m.Text == "partial")
// && cds.AttributeLists
// .SelectMany(al => al.Attributes)
// .Any(a => a.Name
// .GetText()
// .ToString()
// .Contains(AttributeShortName)))))
// {
// return true;
// }
// }
// return false;
// },
// (syntax, _) =>
// {
// string nameSpace;
// var cds = (ClassDeclarationSyntax)syntax.Node;
// {
// SyntaxNode sn = cds;
// while (sn.Parent is not FileScopedNamespaceDeclarationSyntax)
// {
// sn = sn.Parent!;
// }
// var nds = (FileScopedNamespaceDeclarationSyntax)sn.Parent;
// nameSpace = nds.Name.ToString();
// }
// var Res = new StringBuilder();
// {
// Res.Append(cds.Modifiers);
// Res.Append(" class ");
// Res.Append(cds.Identifier.Text);
// Res.Append(" ");
// Res.Append(cds.BaseList);
// Res.Append(" ");
// Res.Append(cds.ConstraintClauses);
// }
var operators = cds.Members.OfType<OperatorDeclarationSyntax>()
.Where(m => m.AttributeLists
.SelectMany(al => al.Attributes)
.Any(a => a.Name.GetText().ToString().Contains(AttributeShortName)))
.Where(mb => mb.ParameterList.Parameters.Count == 2)
.Select(mb => new Operation()
{
ReturnType = mb.ReturnType.ToString(),
OperatorToken = mb.OperatorToken.Text,
TypeA = mb.ParameterList.Parameters[0].Type!.ToString(),
TypeB = mb.ParameterList.Parameters[1].Type!.ToString(),
});
return new(new(nameSpace, cds.Identifier.Text, Res.ToString()), [.. operators]);
})
.Collect();
// var operators = cds.Members.OfType<OperatorDeclarationSyntax>()
// .Where(m => m.AttributeLists
// .SelectMany(al => al.Attributes)
// .Any(a => a.Name.GetText().ToString().Contains(AttributeShortName)))
// .Where(mb => mb.ParameterList.Parameters.Count == 2)
// .Select(mb => new Operation()
// {
// ReturnType = mb.ReturnType.ToString(),
// OperatorToken = mb.OperatorToken.Text,
// TypeA = mb.ParameterList.Parameters[0].Type!.ToString(),
// TypeB = mb.ParameterList.Parameters[1].Type!.ToString(),
// });
// return new(new(nameSpace, cds.Identifier.Text, Res.ToString()), [.. operators]);
// })
// .Collect();
context.RegisterSourceOutput(operatorsPipeline, GenerateOperators);
}
// context.RegisterSourceOutput(operatorsPipeline, GenerateOperators);
// }
readonly static string[] CollectionTypes = ["MetricArray", "MetricList", "MetricObservableCollection"];
static void GenerateOperators(SourceProductionContext context, ImmutableArray<KeyValuePair<ClassData, ImmutableArray<Operation>>> pairs)
{
foreach (var ng in pairs.GroupBy(c => c.Key.NameSpace))
{
StringBuilder document = new("namespace ");
document.Append(ng.Key);
document.Append(";");
// readonly static string[] CollectionTypes = ["MetricArray", "MetricList", "MetricObservableCollection"];
// static void GenerateOperators(SourceProductionContext context, ImmutableArray<KeyValuePair<ClassData, ImmutableArray<Operation>>> pairs)
// {
// foreach (var ng in pairs.GroupBy(c => c.Key.NameSpace))
// {
// StringBuilder document = new("namespace ");
// document.Append(ng.Key);
// document.Append(";");
var classes = ng.ToList().Select(c => (ClassData?)c.Key).ToList();
var operations = ng.ToList().SelectMany(c => c.Value).ToList();
var multiplications = operations.Where(op => op.OperatorToken == "*").ToList();
var divisions = operations.Where(op => op.OperatorToken == "/").ToList();
// var classes = ng.ToList().Select(c => (ClassData?)c.Key).ToList();
// var operations = ng.ToList().SelectMany(c => c.Value).ToList();
// var multiplications = operations.Where(op => op.OperatorToken == "*").ToList();
// var divisions = operations.Where(op => op.OperatorToken == "/").ToList();
foreach (var ops in multiplications.GroupBy(op => op.TypeA))
{
var Class = classes.FirstOrDefault(cl => cl!.Value.ClassName == ops.Key);
if (Class is not null)
{
document.AppendLine();
document.AppendLine();
document.AppendLine(Class.Value.ClassHeader);
document.AppendLine("{");
foreach (var op in ops)
foreach (var ct in CollectionTypes)
{
document.AppendLine(@$"
public static {ct}<{op.ReturnType}> operator *({op.TypeA} left, {ct}<{op.TypeB}> right) => right.MetricSelect(UU => left * UU);
public static {ct}<{op.ReturnType}> operator *({ct}<{op.TypeB}> left, {op.TypeA} right) => left.MetricSelect(UU => UU * right);
");
}
document.Append("}");
}
else
{
context.ReportDiagnostic(Diagnostic.Create(new(
"MSG0001",
"Need a class with an attribute",
$"It is necessary to have a empty partial class \"{ops.Key}\" with the attribute \"{AttributeShortName}\"",
"category",
DiagnosticSeverity.Error,
true), null, ops.Key));
}
}
// foreach (var ops in multiplications.GroupBy(op => op.TypeA))
// {
// var Class = classes.FirstOrDefault(cl => cl!.Value.ClassName == ops.Key);
// if (Class is not null)
// {
// document.AppendLine();
// document.AppendLine();
// document.AppendLine(Class.Value.ClassHeader);
// document.AppendLine("{");
// foreach (var op in ops)
// foreach (var ct in CollectionTypes)
// {
// document.AppendLine(@$"
// public static {ct}<{op.ReturnType}> operator *({op.TypeA} left, {ct}<{op.TypeB}> right) => right.MetricSelect(UU => left * UU);
// public static {ct}<{op.ReturnType}> operator *({ct}<{op.TypeB}> left, {op.TypeA} right) => left.MetricSelect(UU => UU * right);
//");
// }
// document.Append("}");
// }
// else
// {
// context.ReportDiagnostic(Diagnostic.Create(new(
// "MSG0001",
// "Need a class with an attribute",
// $"It is necessary to have a empty partial class \"{ops.Key}\" with the attribute \"{AttributeShortName}\"",
// "category",
// DiagnosticSeverity.Error,
// true), null, ops.Key));
// }
// }
foreach (var ops in divisions.GroupBy(op => op.TypeA))
{
var Class = classes.FirstOrDefault(cl => cl!.Value.ClassName == ops.Key);
if (Class is not null)
{
document.AppendLine();
document.AppendLine();
document.AppendLine(Class.Value.ClassHeader);
document.AppendLine("{");
foreach (var op in ops)
foreach (var ct in CollectionTypes)
{
document.AppendLine(@$"
public static {ct}<{op.ReturnType}> operator /({op.TypeA} left, {ct}<{op.TypeB}> right) => right.MetricSelect(UU => left / UU);
");
}
document.Append("}");
}
else
{
context.ReportDiagnostic(Diagnostic.Create(new(
"MSG0001",
"Need a class with an attribute",
$"It is necessary to have a empty partial class \"{ops.Key}\" with the attribute \"{AttributeShortName}\"",
"category",
DiagnosticSeverity.Error,
true), null, ops.Key));
}
}
foreach (var ops in divisions.GroupBy(op => op.TypeB))
{
var Class = classes.FirstOrDefault(cl => cl!.Value.ClassName == ops.Key);
if (Class is not null)
{
document.AppendLine();
document.AppendLine();
document.AppendLine(Class.Value.ClassHeader);
document.AppendLine("{");
foreach (var op in ops)
foreach (var ct in CollectionTypes)
{
document.AppendLine(@$"
public static {ct}<{op.ReturnType}> operator /({ct}<{op.TypeA}> left, {op.TypeB} right) => left.MetricSelect(UU => UU / right);
");
}
document.Append("}");
}
else
{
context.ReportDiagnostic(Diagnostic.Create(new(
"MSG0001",
"Need a class with an attribute",
$"It is necessary to have a empty partial class \"{ops.Key}\" with the attribute \"{AttributeShortName}\"",
"category",
DiagnosticSeverity.Error,
true), null, ops.Key));
}
}
// foreach (var ops in divisions.GroupBy(op => op.TypeA))
// {
// var Class = classes.FirstOrDefault(cl => cl!.Value.ClassName == ops.Key);
// if (Class is not null)
// {
// document.AppendLine();
// document.AppendLine();
// document.AppendLine(Class.Value.ClassHeader);
// document.AppendLine("{");
// foreach (var op in ops)
// foreach (var ct in CollectionTypes)
// {
// document.AppendLine(@$"
// public static {ct}<{op.ReturnType}> operator /({op.TypeA} left, {ct}<{op.TypeB}> right) => right.MetricSelect(UU => left / UU);
//");
// }
// document.Append("}");
// }
// else
// {
// context.ReportDiagnostic(Diagnostic.Create(new(
// "MSG0001",
// "Need a class with an attribute",
// $"It is necessary to have a empty partial class \"{ops.Key}\" with the attribute \"{AttributeShortName}\"",
// "category",
// DiagnosticSeverity.Error,
// true), null, ops.Key));
// }
// }
// foreach (var ops in divisions.GroupBy(op => op.TypeB))
// {
// var Class = classes.FirstOrDefault(cl => cl!.Value.ClassName == ops.Key);
// if (Class is not null)
// {
// document.AppendLine();
// document.AppendLine();
// document.AppendLine(Class.Value.ClassHeader);
// document.AppendLine("{");
// foreach (var op in ops)
// foreach (var ct in CollectionTypes)
// {
// document.AppendLine(@$"
// public static {ct}<{op.ReturnType}> operator /({ct}<{op.TypeA}> left, {op.TypeB} right) => left.MetricSelect(UU => UU / right);
//");
// }
// document.Append("}");
// }
// else
// {
// context.ReportDiagnostic(Diagnostic.Create(new(
// "MSG0001",
// "Need a class with an attribute",
// $"It is necessary to have a empty partial class \"{ops.Key}\" with the attribute \"{AttributeShortName}\"",
// "category",
// DiagnosticSeverity.Error,
// true), null, ops.Key));
// }
// }
context.AddSource($"operations.{ng.Key}.g", document.ToString());
}
}
}
// context.AddSource($"operations.{ng.Key}.g", document.ToString());
// }
// }
//}
public struct ClassData(string nameSpace, string className, string classHeader)
{
public string NameSpace = nameSpace;
public string ClassName = className;
public string ClassHeader = classHeader;
}
public struct Operation(string operatorToken, string typeA, string typeB, string returnType)
{
public string ReturnType = returnType;
public string OperatorToken = operatorToken;
public string TypeA = typeA;
public string TypeB = typeB;
}
//public struct ClassData(string nameSpace, string className, string classHeader)
//{
// public string NameSpace = nameSpace;
// public string ClassName = className;
// public string ClassHeader = classHeader;
//}
//public struct Operation(string operatorToken, string typeA, string typeB, string returnType)
//{
// public string ReturnType = returnType;
// public string OperatorToken = operatorToken;
// public string TypeA = typeA;
// public string TypeB = typeB;
//}

View File

@@ -87,12 +87,12 @@ namespace QWERTYkez.Mensura
string ns = info.Namespace;
// Здесь должен быть полный код из вашего файла XXXXXXXXXXXX.cs
// с заменой XXXXXXXXXXXXXX на {typeName}. Для краткости приведён скелет.
// с заменой {typeName} на {typeName}. Для краткости приведён скелет.
// Вы должны скопировать сюда всё содержимое вашего второго файла,
// заменив XXXXXXXXXXXXXX на {typeName}.
// заменив {typeName} на {typeName}.
string skeleton = @"
global using {typeName} = QWERTYkez.Mensura.Units.{typeName};
global using {typeName}Extensions = QWERTYkez.Mensura.Units.{typeName}Extensions;
global using {typeName}Extensions = QWERTYkez.Mensura.Units.{typeName}Extension;
global using {typeName}Converter = QWERTYkez.Mensura.Units.{typeName}Converter;
using System.Globalization;
@@ -118,13 +118,8 @@ public readonly partial record struct {typeName} : IMensuraUnit<{typeName}>, IEq
[JsonIgnore, IgnoreDataMember] public bool IsPositive => _Value >= 0;
[JsonIgnore, IgnoreDataMember] public bool IsGreaterThanZero => _Value > 0;
[JsonIgnore, IgnoreDataMember] public bool IsNegative => double.IsNegative(_Value);
[JsonIgnore, IgnoreDataMember] public bool IsNegative => _Value < 0;
[JsonIgnore, IgnoreDataMember] public bool IsZero => _Value == 0;
[JsonIgnore, IgnoreDataMember] public bool IsNaN => double.IsNaN(_Value);
[JsonIgnore, IgnoreDataMember] public bool IsFinite => double.IsFinite(_Value);
[JsonIgnore, IgnoreDataMember] public bool IsInfinity => double.IsInfinity(_Value);
[JsonIgnore, IgnoreDataMember] public bool IsPositiveInfinity => double.IsPositiveInfinity(_Value);
[JsonIgnore, IgnoreDataMember] public bool IsNegativeInfinity => double.IsNegativeInfinity(_Value);
public static {typeName} Zero { get; } = new(0d);
@@ -308,19 +303,19 @@ public readonly partial record struct {typeName} : IMensuraUnit<{typeName}>, IEq
}
}
public static class {typeName}Extensions
public static class {typeName}Extension
{
internal static double ToDouble(this {typeName}? unit) => unit is null ? 0d : unit.Value._Value;
public static {typeName} MetricSum(this IEnumerable<{typeName}> units) => new() { Value = units?.Sum(m => m._Value) ?? 0d };
public static {typeName} MetricAverage(this IEnumerable<{typeName}> units) => new() { Value = units?.Average(m => m._Value) ?? double.NaN };
public static {typeName} MetricMax(this IEnumerable<{typeName}> units) => new() { Value = units?.Max(m => m._Value) ?? double.MinValue };
public static {typeName} MetricMin(this IEnumerable<{typeName}> units) => new() { Value = units?.Min(m => m._Value) ?? double.MaxValue };
public static {typeName} MetricSum(this IEnumerable<{typeName}> units) => new(units?.Sum(m => m._Value) ?? 0d);
public static {typeName} MetricAverage(this IEnumerable<{typeName}> units) => new(units?.Average(m => m._Value) ?? double.NaN);
public static {typeName} MetricMax(this IEnumerable<{typeName}> units) => new(units?.Max(m => m._Value) ?? double.MinValue);
public static {typeName} MetricMin(this IEnumerable<{typeName}> units) => new(units?.Min(m => m._Value) ?? double.MaxValue);
public static {typeName} MetricSum(this IEnumerable<{typeName}?> units) => new() { Value = units?.Sum(m => m.ToDouble()) ?? 0d };
public static {typeName} MetricAverage(this IEnumerable<{typeName}?> units) => new() { Value = units?.Average(m => m.ToDouble()) ?? double.NaN };
public static {typeName} MetricMax(this IEnumerable<{typeName}?> units) => new() { Value = units?.Max(m => m.ToDouble()) ?? double.MinValue };
public static {typeName} MetricMin(this IEnumerable<{typeName}?> units) => new() { Value = units?.Min(m => m.ToDouble()) ?? double.MaxValue };
public static {typeName} MetricSum(this IEnumerable<{typeName}?> units) => new(units?.Sum(m => m.ToDouble()) ?? 0d);
public static {typeName} MetricAverage(this IEnumerable<{typeName}?> units) => new(units?.Average(m => m.ToDouble()) ?? double.NaN);
public static {typeName} MetricMax(this IEnumerable<{typeName}?> units) => new(units?.Max(m => m.ToDouble()) ?? double.MinValue);
public static {typeName} MetricMin(this IEnumerable<{typeName}?> units) => new(units?.Min(m => m.ToDouble()) ?? double.MaxValue);
internal static void MultiplyCore(ReadOnlySpan<{typeName}> source, double value, Span<{typeName}> destination)
@@ -329,7 +324,7 @@ public static class {typeName}Extensions
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<{typeName}, double>(source);
Span<double> dstDouble = MemoryMarshal.Cast<{typeName}, double>(destination);
var vectorizedValue = new Vector<double>(value);
var vectorized_Value = new Vector<double>(value);
int vectorSize = Vector<double>.Count;
int i = 0;
@@ -342,7 +337,7 @@ public static class {typeName}Extensions
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ReadOnlySpan<double> srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
var vector = new Vector<double>(srcWindow);
var multiplied = vector * vectorizedValue;
var multiplied = vector * vectorized_Value;
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
Span<double> dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
multiplied.CopyTo(dstWindow);
@@ -363,7 +358,7 @@ public static class {typeName}Extensions
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<{typeName}, double>(source);
Span<double> dstDouble = MemoryMarshal.Cast<{typeName}, double>(destination);
var vectorizedValue = new Vector<double>(divisor);
var vectorized_Value = new Vector<double>(divisor);
int vectorSize = Vector<double>.Count;
int i = 0;
@@ -376,7 +371,7 @@ public static class {typeName}Extensions
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ReadOnlySpan<double> srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
var vector = new Vector<double>(srcWindow);
var multiplied = vector / vectorizedValue;
var multiplied = vector / vectorized_Value;
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
Span<double> dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
multiplied.CopyTo(dstWindow);
@@ -393,7 +388,7 @@ public static class {typeName}Extensions
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<{typeName}, double>(source);
Span<double> dstDouble = MemoryMarshal.Cast<{typeName}, double>(destination);
var vectorizedValue = new Vector<double>(dividend);
var vectorized_Value = new Vector<double>(dividend);
var zeroVector = Vector<double>.Zero; // Вектор из нулей для сравнения
int vectorSize = Vector<double>.Count;
int i = 0;
@@ -414,7 +409,7 @@ public static class {typeName}Extensions
throw new DivideByZeroException($""Обнаружен делитель, равный нулю, в районе индексов {i}..{i + vectorSize - 1}."");
}
var multiplied = vectorizedValue / vector;
var multiplied = vectorized_Value / vector;
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
Span<double> dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
multiplied.CopyTo(dstWindow);
@@ -437,7 +432,7 @@ public static class {typeName}Extensions
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<{typeName}, double>(source);
Span<double> dstDouble = MemoryMarshal.Cast<{typeName}, double>(destination);
var vectorizedValue = new Vector<double>(summand);
var vectorized_Value = new Vector<double>(summand);
int vectorSize = Vector<double>.Count;
int i = 0;
@@ -450,7 +445,7 @@ public static class {typeName}Extensions
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ReadOnlySpan<double> srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
var vector = new Vector<double>(srcWindow);
var multiplied = vector + vectorizedValue;
var multiplied = vector + vectorized_Value;
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
Span<double> dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
multiplied.CopyTo(dstWindow);
@@ -467,7 +462,7 @@ public static class {typeName}Extensions
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<{typeName}, double>(source);
Span<double> dstDouble = MemoryMarshal.Cast<{typeName}, double>(destination);
var vectorizedValue = new Vector<double>(subtrahend);
var vectorized_Value = new Vector<double>(subtrahend);
int vectorSize = Vector<double>.Count;
int i = 0;
@@ -480,7 +475,7 @@ public static class {typeName}Extensions
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ReadOnlySpan<double> srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
var vector = new Vector<double>(srcWindow);
var multiplied = vector - vectorizedValue;
var multiplied = vector - vectorized_Value;
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
Span<double> dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
multiplied.CopyTo(dstWindow);
@@ -497,7 +492,7 @@ public static class {typeName}Extensions
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<{typeName}, double>(source);
Span<double> dstDouble = MemoryMarshal.Cast<{typeName}, double>(destination);
var vectorizedValue = new Vector<double>(minuend);
var vectorized_Value = new Vector<double>(minuend);
int vectorSize = Vector<double>.Count;
int i = 0;
@@ -510,7 +505,7 @@ public static class {typeName}Extensions
ref double currentSrc = ref Unsafe.Add(ref srcRef, i);
ReadOnlySpan<double> srcWindow = MemoryMarshal.CreateReadOnlySpan(ref currentSrc, vectorSize);
var vector = new Vector<double>(srcWindow);
var multiplied = vectorizedValue - vector;
var multiplied = vectorized_Value - vector;
ref double currentDst = ref Unsafe.Add(ref dstRef, i);
Span<double> dstWindow = MemoryMarshal.CreateSpan(ref currentDst, vectorSize);
multiplied.CopyTo(dstWindow);
@@ -550,7 +545,7 @@ public static class {typeName}Extensions
if (exp < 0)
{
baseVector = Vector<double>.One / baseVector;
exp = -exp; // Внимание: может переполниться при int.MinValue, но для степеней это редчайший кейс
exp = -exp; // Внимание: может переполниться при int.Min_Value, но для степеней это редчайший кейс
}
var result = Vector<double>.One;
@@ -731,7 +726,7 @@ public static class {typeName}Extensions
public static Tcoll Multiply<Tcoll>(this ICollection<{typeName}> units, double multiplicator)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -744,7 +739,7 @@ public static class {typeName}Extensions
public static Tcoll Multiply<Tcoll>(this ICollection<{typeName}?> units, double multiplicator)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -936,7 +931,7 @@ public static class {typeName}Extensions
public static Tcoll Divide<Tcoll>(this ICollection<{typeName}> units, double divisor)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -947,7 +942,7 @@ public static class {typeName}Extensions
public static Tcoll Divide<Tcoll>(this double dividend, ICollection<{typeName}> units)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -958,7 +953,7 @@ public static class {typeName}Extensions
public static Tcoll Divide<Tcoll>(this ICollection<{typeName}?> units, double divisor)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -969,7 +964,7 @@ public static class {typeName}Extensions
public static Tcoll Divide<Tcoll>(this double dividend, ICollection<{typeName}?> units)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1101,7 +1096,7 @@ public static class {typeName}Extensions
public static Tcoll Plus<Tcoll>(this ICollection<{typeName}> units, double summand)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1114,7 +1109,7 @@ public static class {typeName}Extensions
public static Tcoll Plus<Tcoll>(this ICollection<{typeName}?> units, double summand)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1297,7 +1292,7 @@ public static class {typeName}Extensions
public static Tcoll Minus<Tcoll>(this ICollection<{typeName}> units, double subtrahend)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1308,7 +1303,7 @@ public static class {typeName}Extensions
public static Tcoll Minus<Tcoll>(this double minuend, ICollection<{typeName}> units)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1319,7 +1314,7 @@ public static class {typeName}Extensions
public static Tcoll Minus<Tcoll>(this ICollection<{typeName}?> units, double subtrahend)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1330,7 +1325,7 @@ public static class {typeName}Extensions
public static Tcoll Minus<Tcoll>(this double minuend, ICollection<{typeName}?> units)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1453,7 +1448,7 @@ public static class {typeName}Extensions
public static Tcoll Pow<Tcoll>(this ICollection<{typeName}> units, int power)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1464,7 +1459,7 @@ public static class {typeName}Extensions
public static Tcoll Pow<Tcoll>(this ICollection<{typeName}?> units, int power)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1573,7 +1568,7 @@ public static class {typeName}Extensions
public static Tcoll Pow<Tcoll>(this ICollection<{typeName}> units, double power)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1584,7 +1579,7 @@ public static class {typeName}Extensions
public static Tcoll Pow<Tcoll>(this ICollection<{typeName}?> units, double power)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1694,7 +1689,7 @@ public static class {typeName}Extensions
public static Tcoll Pow<Tcoll>(this ICollection<{typeName}> units)
where Tcoll : class, ICollection<{typeName}>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1705,7 +1700,7 @@ public static class {typeName}Extensions
public static Tcoll Pow<Tcoll>(this ICollection<{typeName}?> units)
where Tcoll : class, ICollection<{typeName}?>, new()
{
ArgumentNullException.ThrowIfNull(units);
if (units is null) return null!;
var tColl = new Tcoll();
if (tColl is List<{typeName}> list)
list.Capacity = units.Count;
@@ -1737,12 +1732,12 @@ public class {typeName}Converter : JsonConverter<{typeName}>
public override {typeName} Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
double doubleValue;
double double_Value;
if (reader.TokenType == JsonTokenType.String)
{
// Безопасно парсим double из строки с поддержкой точки как разделителя
if (!double.TryParse(reader.GetString(), NumberStyles.Float, Culture, out doubleValue))
if (!double.TryParse(reader.GetString(), NumberStyles.Float, Culture, out double_Value))
{
throw new JsonException($""Не удалось преобразовать строковое значение в double для метрики {nameof({typeName})}."");
}
@@ -1750,10 +1745,10 @@ public class {typeName}Converter : JsonConverter<{typeName}>
else
{
// Прямое быстрое чтение числа из JSON
doubleValue = reader.GetDouble();
double_Value = reader.GetDouble();
}
return new(doubleValue);
return new(double_Value);
}
public override void Write(Utf8JsonWriter writer, {typeName} value, JsonSerializerOptions options)
@@ -1774,12 +1769,12 @@ public class {typeName}Converter : JsonConverter<{typeName}>
{
string propertyName = reader.GetString()!;
if (!double.TryParse(propertyName, NumberStyles.Float, Culture, out double doubleValue))
if (!double.TryParse(propertyName, NumberStyles.Float, Culture, out double double_Value))
{
throw new JsonException($""Невалидное числовое значение в ключе свойства JSON: '{propertyName}' для метрики {nameof({typeName})}."");
}
return new(doubleValue);
return new(double_Value);
}
}
";

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
global using PogonMass = QWERTYkez.Mensura.Units.Pogon.PogonMass;
#if DEBUG
global using PogonMass = QWERTYkez.Mensura.Units.Pogon.PogonMass;
global using PogonMassExtensions = QWERTYkez.Mensura.Units.Pogon.PogonMassExtensions;
global using PogonMassConverter = QWERTYkez.Mensura.Units.Pogon.PogonMassConverter;
@@ -20,8 +21,7 @@ namespace QWERTYkez.Mensura.Units
if (len == 0) return [];
var result = new Mass[len];
for (int i = 0; i < len; i++)
result[i] = right * left[i];
PogonMassExtensions.MultiplyCore(left, right, result);
return result;
}
public static Mass[] operator *(PogonMass[] left, Length? right)
@@ -367,7 +367,7 @@ namespace QWERTYkez.Mensura.Units.Pogon
internal static void MultiplyCore(ReadOnlySpan<PogonMass> source, Length value, Span<Mass> destination)
internal static void MultiplyCore(this ReadOnlySpan<PogonMass> source, Length value, Span<Mass> destination)
{
var dVal = value._Value;
int len = source.Length;
@@ -398,7 +398,7 @@ namespace QWERTYkez.Mensura.Units.Pogon
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * dVal;
}
}
internal static void MultiplyCore(ReadOnlySpan<Length> source, PogonMass value, Span<Mass> destination)
internal static void MultiplyCore(this ReadOnlySpan<Length> source, PogonMass value, Span<Mass> destination)
{
var dVal = value._Value;
int len = source.Length;
@@ -431,7 +431,7 @@ namespace QWERTYkez.Mensura.Units.Pogon
}
internal static void DivideCore(ReadOnlySpan<Mass> source, PogonMass divisor, Span<Length> destination)
internal static void DivideCore(this ReadOnlySpan<Mass> source, PogonMass divisor, Span<Length> destination)
{
// 1. Проверка на ноль
if (divisor.IsZero || divisor.IsNaN)
@@ -466,7 +466,7 @@ namespace QWERTYkez.Mensura.Units.Pogon
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) / dVal;
}
}
internal static void DivideCore(Mass dividend, ReadOnlySpan<PogonMass> source, Span<Length> destination)
internal static void DivideCore(this Mass dividend, ReadOnlySpan<PogonMass> source, Span<Length> destination)
{
var dVal = dividend._Value;
int len = source.Length;
@@ -565,4 +565,5 @@ namespace QWERTYkez.Mensura.Units.Pogon
return new(double_Value);
}
}
}
}
#endif

View File

@@ -1,4 +1,5 @@
namespace QWERTYkez.Mensura.Units.Pogon;
#if DEBUG
namespace QWERTYkez.Mensura.Units.Pogon;
public readonly partial record struct PogonMass
{
@@ -30,4 +31,5 @@ public readonly partial record struct PogonMass
init => _Value = value._Value / LengthConv.KiloMeters.Multiplicator;
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +1,74 @@
//namespace QWERTYkez.Mensura.Units;
#if DEBUG
namespace QWERTYkez.Mensura.Units;
///// <summary>
///// Base value is MilliMeters
///// </summary>
//[UnitOperatorsGenerator, DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
//public readonly partial record struct XXXXXXXXXXXXXX
//{
// public static XXXXXXXXXXXXXX MilliMeter { get; } = new(1);
//#pragma warning disable IDE1006 // _Подчеркивание для обозначения того, что это базовая единица
// [NotMapped, JsonIgnore] public double _MilliMeters { get => _Value; init => _Value = value; }
//#pragma warning restore IDE1006
/// <summary>
/// Base value is MilliMeters
/// </summary>
[DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
public readonly partial record struct XXXXXXXXXXXXXX
{
public static XXXXXXXXXXXXXX MilliMeter { get; } = new(1);
[NotMapped, JsonIgnore] public double _MilliMeters { get => _Value; init => _Value = value; }
// public static XXXXXXXXXXXXXX CentiMeter { get; } = new(XXXXXXXXXXXXXXConv.CentiMeters.To(1));
// [NotMapped, JsonIgnore] public double CentiMeters
// {
// get => XXXXXXXXXXXXXXConv.CentiMeters.From(_Value);
// init
// {
// XXXXXXXXXXXXXX aaa = new();
// XXXXXXXXXXXXXX bbb = new();
public static XXXXXXXXXXXXXX CentiMeter { get; } = new(XXXXXXXXXXXXXXConv.CentiMeters.To(1));
[NotMapped, JsonIgnore] public double CentiMeters
{
get => XXXXXXXXXXXXXXConv.CentiMeters.From(_Value);
init
{
XXXXXXXXXXXXXX aaa = new();
XXXXXXXXXXXXXX bbb = new();
// if (aaa != bbb || aaa == bbb)
// {
if (aaa != bbb || aaa == bbb)
{
// }
}
// _Value = XXXXXXXXXXXXXXConv.CentiMeters.To(value);
// }
// }
_Value = XXXXXXXXXXXXXXConv.CentiMeters.To(value);
}
}
// public static XXXXXXXXXXXXXX DeciMeter { get; } = new(XXXXXXXXXXXXXXConv.DeciMeters.To(1));
// [NotMapped, JsonIgnore] public double DeciMeters
// {
// get => XXXXXXXXXXXXXXConv.DeciMeters.From(_Value);
// init => _Value = XXXXXXXXXXXXXXConv.DeciMeters.To(value);
// }
public static XXXXXXXXXXXXXX DeciMeter { get; } = new(XXXXXXXXXXXXXXConv.DeciMeters.To(1));
[NotMapped, JsonIgnore] public double DeciMeters
{
get => XXXXXXXXXXXXXXConv.DeciMeters.From(_Value);
init => _Value = XXXXXXXXXXXXXXConv.DeciMeters.To(value);
}
// public static XXXXXXXXXXXXXX Meter { get; } = new(XXXXXXXXXXXXXXConv.Meters.To(1));
// [NotMapped, JsonIgnore] public double Meters
// {
// get => XXXXXXXXXXXXXXConv.Meters.From(_Value);
// init => _Value = XXXXXXXXXXXXXXConv.Meters.To(value);
// }
public static XXXXXXXXXXXXXX Meter { get; } = new(XXXXXXXXXXXXXXConv.Meters.To(1));
[NotMapped, JsonIgnore] public double Meters
{
get => XXXXXXXXXXXXXXConv.Meters.From(_Value);
init => _Value = XXXXXXXXXXXXXXConv.Meters.To(value);
}
// public static XXXXXXXXXXXXXX KiloMeter { get; } = new(XXXXXXXXXXXXXXConv.KiloMeters.To(1));
// [NotMapped, JsonIgnore] public double KiloMeters
// {
// get => XXXXXXXXXXXXXXConv.KiloMeters.From(_Value);
// init => _Value = XXXXXXXXXXXXXXConv.KiloMeters.To(value);
// }
public static XXXXXXXXXXXXXX KiloMeter { get; } = new(XXXXXXXXXXXXXXConv.KiloMeters.To(1));
[NotMapped, JsonIgnore] public double KiloMeters
{
get => XXXXXXXXXXXXXXConv.KiloMeters.From(_Value);
init => _Value = XXXXXXXXXXXXXXConv.KiloMeters.To(value);
}
// public XXXXXXXXXXXXXX AddMilliMeters(double value) => new(_Value + value);
// public XXXXXXXXXXXXXX AddCentiMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.CentiMeters.To(value));
// public XXXXXXXXXXXXXX AddDeciMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.DeciMeters.To(value));
// public XXXXXXXXXXXXXX AddMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.Meters.To(value));
// public XXXXXXXXXXXXXX AddKiloMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.KiloMeters.To(value));
//}
public XXXXXXXXXXXXXX AddMilliMeters(double value) => new(_Value + value);
public XXXXXXXXXXXXXX AddCentiMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.CentiMeters.To(value));
public XXXXXXXXXXXXXX AddDeciMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.DeciMeters.To(value));
public XXXXXXXXXXXXXX AddMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.Meters.To(value));
public XXXXXXXXXXXXXX AddKiloMeters(double value) => new(_Value + XXXXXXXXXXXXXXConv.KiloMeters.To(value));
}
//internal readonly struct XXXXXXXXXXXXXXConv
//{
// private XXXXXXXXXXXXXXConv(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 XXXXXXXXXXXXXXConv MilliMeters { get; } = new(1);
// public static XXXXXXXXXXXXXXConv CentiMeters { get; } = new(10);
// public static XXXXXXXXXXXXXXConv DeciMeters { get; } = new(100);
// public static XXXXXXXXXXXXXXConv Meters { get; } = new(1000);
// public static XXXXXXXXXXXXXXConv KiloMeters { get; } = new(1000000);
//}
internal readonly struct XXXXXXXXXXXXXXConv
{
private XXXXXXXXXXXXXXConv(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 XXXXXXXXXXXXXXConv MilliMeters { get; } = new(1);
public static XXXXXXXXXXXXXXConv CentiMeters { get; } = new(10);
public static XXXXXXXXXXXXXXConv DeciMeters { get; } = new(100);
public static XXXXXXXXXXXXXXConv Meters { get; } = new(1000);
public static XXXXXXXXXXXXXXConv KiloMeters { get; } = new(1000000);
}
#endif