+++
This commit is contained in:
@@ -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;
|
||||
//}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
Reference in New Issue
Block a user