Merge branch 'master' of https://lancool.qwertykez.fun/QWERTYkez/QWERTYkez.Mensura
All checks were successful
Publish NuGet packages / publish (push) Successful in 1m1s
All checks were successful
Publish NuGet packages / publish (push) Successful in 1m1s
This commit is contained in:
36
.gitea/workflows/publish.yml
Normal file
36
.gitea/workflows/publish.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
name: Publish NuGet packages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
dotnet-version: '8.x'
|
||||||
|
|
||||||
|
- name: Get version from tag
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$tag = "$env:GITHUB_REF_NAME"
|
||||||
|
$version = $tag -replace '^v', ''
|
||||||
|
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
|
||||||
|
- name: Pack Mensura
|
||||||
|
run: dotnet pack QWERTYkez.Mensura/QWERTYkez.Mensura.csproj -c Release -o ./packages -p:Version=${{ env.VERSION }}
|
||||||
|
|
||||||
|
- name: Push to Gitea
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
Get-ChildItem -Path ./packages -Filter *.nupkg | ForEach-Object {
|
||||||
|
dotnet nuget push $_.FullName --source https://lancool.qwertykez.fun/api/packages/QWERTYkez/nuget --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate
|
||||||
|
}
|
||||||
201
LICENSE.txt
Normal file
201
LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -81,6 +81,24 @@ namespace QWERTYkez.Mensura
|
|||||||
sb.AppendLine("}");
|
sb.AppendLine("}");
|
||||||
|
|
||||||
spc.AddSource(".ComplexUnits.MensuraBinder.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
spc.AddSource(".ComplexUnits.MensuraBinder.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
||||||
|
|
||||||
|
|
||||||
|
sb = new StringBuilder();
|
||||||
|
sb.AppendLine("using Microsoft.EntityFrameworkCore;");
|
||||||
|
sb.AppendLine("namespace QWERTYkez.Mensura.Extensions;");
|
||||||
|
sb.AppendLine("public static partial class EFCoreExtension");
|
||||||
|
sb.AppendLine("{");
|
||||||
|
sb.AppendLine(" [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]");
|
||||||
|
sb.AppendLine(" internal static void AddGeneratedComplexConverters(ModelConfigurationBuilder configurationBuilder)");
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
foreach (var structInfo in structs)
|
||||||
|
{
|
||||||
|
sb.AppendLine($" configurationBuilder.Properties<{structInfo.TypeName}>().HaveConversion<MensuraUnitConverter<{structInfo.TypeName}>>();");
|
||||||
|
}
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
sb.AppendLine("}");
|
||||||
|
|
||||||
|
spc.AddSource(".ComplexUnits.EFCoreExtension.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1254,15 +1272,6 @@ public readonly partial record struct {typeNameZ} : IMensuraUnit<{typeNameZ}>, I
|
|||||||
|
|
||||||
public static class {typeNameZ}Extensions
|
public static class {typeNameZ}Extensions
|
||||||
{
|
{
|
||||||
internal static double Protected(this {typeNameZ}? unit) => unit is null ? 0d : unit.Value._Value;
|
|
||||||
internal static {typeNameZ} ProtectedU(this {typeNameZ}? unit) => unit is null ? {typeNameZ}.Zero : unit.Value;
|
|
||||||
internal static double ToDouble(this {typeNameB}? unit) => unit?._Value ?? 0d;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// === ReadOnlySpan
|
// === ReadOnlySpan
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeNameZ}> units,
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeNameZ}> units,
|
||||||
double divisor, Span<{typeNameZ}> destination) => units.Div<{typeNameZ}>(divisor, destination);
|
double divisor, Span<{typeNameZ}> destination) => units.Div<{typeNameZ}>(divisor, destination);
|
||||||
|
|||||||
@@ -67,6 +67,24 @@ namespace QWERTYkez.Mensura
|
|||||||
sb.AppendLine("}");
|
sb.AppendLine("}");
|
||||||
|
|
||||||
spc.AddSource(".Units.MensuraBinder.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
spc.AddSource(".Units.MensuraBinder.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
||||||
|
|
||||||
|
|
||||||
|
sb = new StringBuilder();
|
||||||
|
sb.AppendLine("using Microsoft.EntityFrameworkCore;");
|
||||||
|
sb.AppendLine("namespace QWERTYkez.Mensura.Extensions;");
|
||||||
|
sb.AppendLine("public static partial class EFCoreExtension");
|
||||||
|
sb.AppendLine("{");
|
||||||
|
sb.AppendLine(" [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]");
|
||||||
|
sb.AppendLine(" internal static void AddGeneratedConverters(ModelConfigurationBuilder configurationBuilder)");
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
foreach (var structInfo in structs)
|
||||||
|
{
|
||||||
|
sb.AppendLine($" configurationBuilder.Properties<{structInfo.TypeName}>().HaveConversion<MensuraUnitConverter<{structInfo.TypeName}>>();");
|
||||||
|
}
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
sb.AppendLine("}");
|
||||||
|
|
||||||
|
spc.AddSource(".Units.EFCoreExtension.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1073,14 +1091,6 @@ public readonly partial record struct {typeName} : IMensuraUnit<{typeName}>, IEq
|
|||||||
|
|
||||||
public static class {typeName}Extensions
|
public static class {typeName}Extensions
|
||||||
{
|
{
|
||||||
internal static double Protected(this {typeName}? unit) => unit is null ? 0d : unit.Value._Value;
|
|
||||||
internal static {typeName} ProtectedU(this {typeName}? unit) => unit is null ? {typeName}.Zero : unit.Value;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// === ReadOnlySpan
|
// === ReadOnlySpan
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeName}> units,
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeName}> units,
|
||||||
double divisor, Span<{typeName}> destination) => units.Div<{typeName}>(divisor, destination);
|
double divisor, Span<{typeName}> destination) => units.Div<{typeName}>(divisor, destination);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class AggregateUnitExtensions
|
public class AggregateUnitExtensionsTest
|
||||||
{
|
{
|
||||||
// Вспомогательный метод для создания объекта Length.
|
// Вспомогательный метод для создания объекта Length.
|
||||||
// Если у вас используется фабричный метод (например, Length.FromMeters), замените код внутри.
|
// Если у вас используется фабричный метод (например, Length.FromMeters), замените код внутри.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class CastExtensions
|
public class CastExtensionsTest
|
||||||
{
|
{
|
||||||
private const double NormalValue1 = 42.42;
|
private const double NormalValue1 = 42.42;
|
||||||
private const double NormalValue2 = 100.05;
|
private const double NormalValue2 = 100.05;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests
|
namespace QWERTYkez.Mensura.Tests
|
||||||
{
|
{
|
||||||
public class CollectionsDivideExtensionsTests
|
public class CollectionsDivideExtensionsTest
|
||||||
{
|
{
|
||||||
private const double Tolerance = 1e-12;
|
private const double Tolerance = 1e-12;
|
||||||
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
var result = nullableUnitsArray.Div<Length>(scalarDouble);
|
var result = nullableUnitsArray.Div<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 / 2.0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
|
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
var result = scalarDouble.Div<Length>(nullableUnitsArray);
|
var result = scalarDouble.Div<Length>(nullableUnitsArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(2.0 / 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
|
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
var result = nullableUnitsList.Div<Length>(scalarDouble);
|
var result = nullableUnitsList.Div<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 / 2.0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
|
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
var result = scalarDouble.Div<Length>(nullableUnitsList);
|
var result = scalarDouble.Div<Length>(nullableUnitsList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(2.0 / 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
|
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
((IReadOnlyCollection<Length?>)nullableUnitsArray).Div(scalarDouble, dest);
|
((IReadOnlyCollection<Length?>)nullableUnitsArray).Div(scalarDouble, dest);
|
||||||
Assert.Equal(1000 / 2.0, (double)dest[0]!, Tolerance);
|
Assert.Equal(1000 / 2.0, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]);
|
Assert.Equal(0 / 2.0, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(1 / 2.0, (double)dest[2]!, Tolerance);
|
Assert.Equal(1 / 2.0, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
scalarDouble.Div((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
scalarDouble.Div((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
||||||
Assert.Equal(2.0 / 1000, (double)dest[0]!, Tolerance);
|
Assert.Equal(2.0 / 1000, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]);
|
Assert.Equal(2.0 / 0, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(2.0 / 1, (double)dest[2]!, Tolerance);
|
Assert.Equal(2.0 / 1, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
var result = ((IEnumerable<Length?>)nullableUnitsArray).Div<Length>(scalarDouble).ToList();
|
var result = ((IEnumerable<Length?>)nullableUnitsArray).Div<Length>(scalarDouble).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 / 2.0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
|
Assert.Equal(1 / 2.0, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@
|
|||||||
var result = scalarDouble.Div<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
var result = scalarDouble.Div<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(2.0 / 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
|
Assert.Equal(2.0 / 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
var result = nullableDoubleArray.Div(scalarUnit);
|
var result = nullableDoubleArray.Div(scalarUnit);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 / 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(3.0 / 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(3.0 / 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
var result = scalarUnit.Div(nullableDoubleArray);
|
var result = scalarUnit.Div(nullableDoubleArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 / 0.0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 / 3.0, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 / 3.0, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@
|
|||||||
var result = list.Div(scalarUnit);
|
var result = list.Div(scalarUnit);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2.0 / 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 / 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(3.0 / 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(3.0 / 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@
|
|||||||
var result = scalarUnit.Div(list);
|
var result = scalarUnit.Div(list);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 / 2.0, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 / 0.0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 / 3.0, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 / 3.0, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests
|
namespace QWERTYkez.Mensura.Tests
|
||||||
{
|
{
|
||||||
public class CollectionsMinusExtensionsTests
|
public class CollectionsMinusExtensionsTest
|
||||||
{
|
{
|
||||||
private const double Tolerance = 1e-12;
|
private const double Tolerance = 1e-12;
|
||||||
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
var result = nullableUnitsArray.Minus<Length>(scalarDouble);
|
var result = nullableUnitsArray.Minus<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
var result = scalarDouble.Minus<Length>(nullableUnitsArray);
|
var result = scalarDouble.Minus<Length>(nullableUnitsArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
var result = nullableUnitsList.Minus<Length>(scalarDouble);
|
var result = nullableUnitsList.Minus<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
var result = scalarDouble.Minus<Length>(nullableUnitsList);
|
var result = scalarDouble.Minus<Length>(nullableUnitsList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
((IReadOnlyCollection<Length?>)nullableUnitsArray).Minus<Length>(scalarDouble, dest);
|
((IReadOnlyCollection<Length?>)nullableUnitsArray).Minus<Length>(scalarDouble, dest);
|
||||||
Assert.Equal(1000 - 1000, (double)dest[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]);
|
Assert.Equal(0 - 1000, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(1 - 1000, (double)dest[2]!, Tolerance);
|
Assert.Equal(1 - 1000, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
scalarDouble.Minus<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
scalarDouble.Minus<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
||||||
Assert.Equal(1000 - 1000, (double)dest[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]);
|
Assert.Equal(1000 - 0, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(1000 - 1, (double)dest[2]!, Tolerance);
|
Assert.Equal(1000 - 1, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@
|
|||||||
var result = ((IEnumerable<Length?>)nullableUnitsArray).Minus<Length>(scalarDouble).ToList();
|
var result = ((IEnumerable<Length?>)nullableUnitsArray).Minus<Length>(scalarDouble).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(1 - 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
var result = scalarDouble.Minus<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
var result = scalarDouble.Minus<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 - 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
var result = nullableDoubleArray.Minus(scalarUnit);
|
var result = nullableDoubleArray.Minus(scalarUnit);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(500 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(500 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(200 - 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(200 - 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@
|
|||||||
var result = scalarUnit.Minus(nullableDoubleArray);
|
var result = scalarUnit.Minus(nullableDoubleArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 - 500, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 500, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 - 200, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 - 200, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
var result = nullableDoubleList.Minus(scalarUnit);
|
var result = nullableDoubleList.Minus(scalarUnit);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(500 - 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(500 - 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0 - 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(200 - 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(200 - 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@
|
|||||||
var result = scalarUnit.Minus(nullableDoubleList);
|
var result = scalarUnit.Minus(nullableDoubleList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 - 500, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 - 500, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(1000 - 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 - 200, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 - 200, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests
|
namespace QWERTYkez.Mensura.Tests
|
||||||
{
|
{
|
||||||
public class CollectionsMultiplyExtensionsTests
|
public class CollectionsMultiplyExtensionsTest
|
||||||
{
|
{
|
||||||
private const double Tolerance = 1e-12;
|
private const double Tolerance = 1e-12;
|
||||||
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
var result = nullableUnitsArray.Mul<Length>(scalarDouble);
|
var result = nullableUnitsArray.Mul<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null * 2 = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
|
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
var result = scalarDouble.Mul<Length>(nullableUnitsArray);
|
var result = scalarDouble.Mul<Length>(nullableUnitsArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // 2 * null = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
|
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
var result = nullableUnitsList.Mul<Length>(scalarDouble);
|
var result = nullableUnitsList.Mul<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null * 2 = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
|
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
var result = scalarDouble.Mul<Length>(nullableUnitsList);
|
var result = scalarDouble.Mul<Length>(nullableUnitsList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // 2 * null = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
|
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
((IReadOnlyCollection<Length?>)nullableUnitsArray).Mul<Length>(scalarDouble, dest);
|
((IReadOnlyCollection<Length?>)nullableUnitsArray).Mul<Length>(scalarDouble, dest);
|
||||||
Assert.Equal(1000 * 2, (double)dest[0]!, Tolerance);
|
Assert.Equal(1000 * 2, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]); // null * 2 = null
|
Assert.Equal(0, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(1 * 2, (double)dest[2]!, Tolerance);
|
Assert.Equal(1 * 2, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
scalarDouble.Mul<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
scalarDouble.Mul<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
||||||
Assert.Equal(2 * 1000, (double)dest[0]!, Tolerance);
|
Assert.Equal(2 * 1000, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]); // 2 * null = null
|
Assert.Equal(0, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(2 * 1, (double)dest[2]!, Tolerance);
|
Assert.Equal(2 * 1, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@
|
|||||||
var result = ((IEnumerable<Length?>)nullableUnitsArray).Mul<Length>(scalarDouble).ToList();
|
var result = ((IEnumerable<Length?>)nullableUnitsArray).Mul<Length>(scalarDouble).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 * 2, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null * 2 = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
|
Assert.Equal(1 * 2, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
var result = scalarDouble.Mul<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
var result = scalarDouble.Mul<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(2 * 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // 2 * null = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
|
Assert.Equal(2 * 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
var result = nullableDoubleArray.Mul(scalarUnit);
|
var result = nullableDoubleArray.Mul(scalarUnit);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(5 * 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(5 * 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null * Length = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(3 * 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(3 * 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
var result = scalarUnit.Mul(nullableDoubleArray);
|
var result = scalarUnit.Mul(nullableDoubleArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 * 5, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 * 5, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // Length * null = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 * 3, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 * 3, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@
|
|||||||
var result = nullableDoubleList.Mul(scalarUnit);
|
var result = nullableDoubleList.Mul(scalarUnit);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(5 * 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(5 * 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null * Length = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(3 * 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(3 * 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@
|
|||||||
var result = scalarUnit.Mul(nullableDoubleList);
|
var result = scalarUnit.Mul(nullableDoubleList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 * 5, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 * 5, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // Length * null = null
|
Assert.Equal(0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 * 3, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 * 3, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,29 +1,22 @@
|
|||||||
using System;
|
namespace QWERTYkez.Mensura.Tests
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using QWERTYkez.Mensura.Units;
|
|
||||||
using QWERTYkez.Mensura.Extensions;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace QWERTYkez.Mensura.Tests
|
|
||||||
{
|
{
|
||||||
public class CollectionsPlusExtensionsTests
|
public class CollectionsPlusExtensionsTest
|
||||||
{
|
{
|
||||||
private const double Tolerance = 1e-12;
|
private const double Tolerance = 1e-12;
|
||||||
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
private static readonly Length scalarUnit = Length.Meter; // 1000 mm
|
||||||
private static readonly double scalarDouble = 500.0; // прибавляемое значение в мм
|
private static readonly double scalarDouble = 500.0; // прибавляемое значение в мм
|
||||||
|
|
||||||
// Коллекции единиц
|
// Коллекции единиц
|
||||||
private static readonly Length[] unitsArray = new[] { Length.Meter, Length._MilliMeter };
|
private static readonly Length[] unitsArray = [Length.Meter, Length._MilliMeter];
|
||||||
private static readonly Length?[] nullableUnitsArray = new Length?[] { Length.Meter, null, Length._MilliMeter };
|
private static readonly Length?[] nullableUnitsArray = [Length.Meter, null, Length._MilliMeter];
|
||||||
private static readonly List<Length> unitsList = new List<Length> { Length.Meter, Length._MilliMeter };
|
private static readonly List<Length> unitsList = [Length.Meter, Length._MilliMeter];
|
||||||
private static readonly List<Length?> nullableUnitsList = new List<Length?> { Length.Meter, null, Length._MilliMeter };
|
private static readonly List<Length?> nullableUnitsList = [Length.Meter, null, Length._MilliMeter];
|
||||||
|
|
||||||
// Коллекции double
|
// Коллекции double
|
||||||
private static readonly double[] doubleArray = new double[] { 200.0, 300.0 };
|
private static readonly double[] doubleArray = [200.0, 300.0];
|
||||||
private static readonly double?[] nullableDoubleArray = new double?[] { 200.0, null, 300.0 };
|
private static readonly double?[] nullableDoubleArray = [200.0, null, 300.0];
|
||||||
private static readonly List<double> doubleList = new List<double> { 200.0, 300.0 };
|
private static readonly List<double> doubleList = [200.0, 300.0];
|
||||||
private static readonly List<double?> nullableDoubleList = new List<double?> { 200.0, null, 300.0 };
|
private static readonly List<double?> nullableDoubleList = [200.0, null, 300.0];
|
||||||
|
|
||||||
// ====================== 1. T[] + double ======================
|
// ====================== 1. T[] + double ======================
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -42,7 +35,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = nullableUnitsArray.Plus<Length>(scalarDouble);
|
var result = nullableUnitsArray.Plus<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null + число = null
|
Assert.Equal(0 + 500, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
|
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +56,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = scalarDouble.Plus<Length>(nullableUnitsArray);
|
var result = scalarDouble.Plus<Length>(nullableUnitsArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // число + null = null
|
Assert.Equal(500 + 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
|
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +77,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = nullableUnitsList.Plus<Length>(scalarDouble);
|
var result = nullableUnitsList.Plus<Length>(scalarDouble);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null + число = null
|
Assert.Equal(0 + 500, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
|
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +98,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = scalarDouble.Plus<Length>(nullableUnitsList);
|
var result = scalarDouble.Plus<Length>(nullableUnitsList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // число + null = null
|
Assert.Equal(500 + 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
|
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +119,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
((IReadOnlyCollection<Length?>)nullableUnitsArray).Plus<Length>(scalarDouble, dest);
|
((IReadOnlyCollection<Length?>)nullableUnitsArray).Plus<Length>(scalarDouble, dest);
|
||||||
Assert.Equal(1000 + 500, (double)dest[0]!, Tolerance);
|
Assert.Equal(1000 + 500, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]); // null + число = null
|
Assert.Equal(0 + 500, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(1 + 500, (double)dest[2]!, Tolerance);
|
Assert.Equal(1 + 500, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +140,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
Span<Length?> dest = new Length?[3];
|
Span<Length?> dest = new Length?[3];
|
||||||
scalarDouble.Plus<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
scalarDouble.Plus<Length>((IReadOnlyCollection<Length?>)nullableUnitsArray, dest);
|
||||||
Assert.Equal(500 + 1000, (double)dest[0]!, Tolerance);
|
Assert.Equal(500 + 1000, (double)dest[0]!, Tolerance);
|
||||||
Assert.Null(dest[1]); // число + null = null
|
Assert.Equal(500 + 0, (double)dest[1]!, Tolerance);
|
||||||
Assert.Equal(500 + 1, (double)dest[2]!, Tolerance);
|
Assert.Equal(500 + 1, (double)dest[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +161,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = ((IEnumerable<Length?>)nullableUnitsArray).Plus<Length>(scalarDouble).ToList();
|
var result = ((IEnumerable<Length?>)nullableUnitsArray).Plus<Length>(scalarDouble).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 + 500, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null + число = null
|
Assert.Equal(0 + 500, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
|
Assert.Equal(1 + 500, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +182,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = scalarDouble.Plus<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
var result = scalarDouble.Plus<Length>((IEnumerable<Length?>)nullableUnitsArray).ToList();
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(500 + 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // число + null = null
|
Assert.Equal(500 + 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
|
Assert.Equal(500 + 1, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +203,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = nullableDoubleArray.Plus(scalarUnit);
|
var result = nullableDoubleArray.Plus(scalarUnit);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(200 + 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(200 + 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null + Length = null
|
Assert.Equal(0 + 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(300 + 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(300 + 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +224,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = scalarUnit.Plus(nullableDoubleArray);
|
var result = scalarUnit.Plus(nullableDoubleArray);
|
||||||
Assert.Equal(3, result.Length);
|
Assert.Equal(3, result.Length);
|
||||||
Assert.Equal(1000 + 200, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 + 200, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // Length + null = null
|
Assert.Equal(1000 + 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 + 300, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 + 300, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +245,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = nullableDoubleList.Plus(scalarUnit);
|
var result = nullableDoubleList.Plus(scalarUnit);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(200 + 1000, (double)result[0]!, Tolerance);
|
Assert.Equal(200 + 1000, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // null + Length = null
|
Assert.Equal(0 + 1000, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(300 + 1000, (double)result[2]!, Tolerance);
|
Assert.Equal(300 + 1000, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +266,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
var result = scalarUnit.Plus(nullableDoubleList);
|
var result = scalarUnit.Plus(nullableDoubleList);
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
Assert.Equal(1000 + 200, (double)result[0]!, Tolerance);
|
Assert.Equal(1000 + 200, (double)result[0]!, Tolerance);
|
||||||
Assert.Null(result[1]); // Length + null = null
|
Assert.Equal(1000 + 0, (double)result[1]!, Tolerance);
|
||||||
Assert.Equal(1000 + 300, (double)result[2]!, Tolerance);
|
Assert.Equal(1000 + 300, (double)result[2]!, Tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +303,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void Plus_NullArray_ReturnsNull()
|
public void Plus_NullArray_ReturnsNull()
|
||||||
{
|
{
|
||||||
Length[] nullArray = null;
|
Length[] nullArray = null!;
|
||||||
var result = nullArray.Plus<Length>(5.0);
|
var result = nullArray.Plus<Length>(5.0);
|
||||||
Assert.Null(result);
|
Assert.Null(result);
|
||||||
}
|
}
|
||||||
@@ -318,7 +311,7 @@ namespace QWERTYkez.Mensura.Tests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void Plus_NullList_ReturnsNull()
|
public void Plus_NullList_ReturnsNull()
|
||||||
{
|
{
|
||||||
List<Length> nullList = null;
|
List<Length> nullList = null!;
|
||||||
var result = nullList.Plus<Length>(5.0);
|
var result = nullList.Plus<Length>(5.0);
|
||||||
Assert.Null(result);
|
Assert.Null(result);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class CollectionsPow2Extensions
|
public class CollectionsPow2ExtensionsTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Pow2_Array_CalculatesCorrectly()
|
public void Pow2_Array_CalculatesCorrectly()
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class Pow3ExtensionsTests
|
public class CollectionsPow3ExtensionsTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Pow3_Array_CalculatesCorrectly()
|
public void Pow3_Array_CalculatesCorrectly()
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class CollectionsPowNExtensions
|
public class CollectionsPowNExtensionsTest
|
||||||
{
|
{
|
||||||
private const double BaseVal = 3.0;
|
private const double BaseVal = 3.0;
|
||||||
private const double Expected = 9.0; // 3^2 = 9
|
private const double Expected = 9.0; // 3^2 = 9
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class CollectionsRootOfCubeExtensions
|
public class CollectionsRootOfCubeExtensionsTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Cbrt_Array_CalculatesCorrectly()
|
public void Cbrt_Array_CalculatesCorrectly()
|
||||||
@@ -23,7 +23,7 @@ public class CollectionsRootOfCubeExtensions
|
|||||||
var result = source.Cbrt<Length, Length>();
|
var result = source.Cbrt<Length, Length>();
|
||||||
|
|
||||||
Assert.Equal(4, result[0]?._Value);
|
Assert.Equal(4, result[0]?._Value);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0, result[1]?._Value);
|
||||||
Assert.Equal(6, result[2]?._Value);
|
Assert.Equal(6, result[2]?._Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
namespace QWERTYkez.Mensura.Tests;
|
||||||
|
|
||||||
public class CollectionsRootOfSquareExtensions
|
public class CollectionsRootOfSquareExtensionsTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Sqrt_Array_ShouldCalculateCorrectly()
|
public void Sqrt_Array_ShouldCalculateCorrectly()
|
||||||
@@ -28,7 +28,7 @@ public class CollectionsRootOfSquareExtensions
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(5, result[0]?._Value);
|
Assert.Equal(5, result[0]?._Value);
|
||||||
Assert.Null(result[1]);
|
Assert.Equal(0, result[1]?._Value);
|
||||||
Assert.Equal(10, result[2]?._Value);
|
Assert.Equal(10, result[2]?._Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
namespace QWERTYkez.Mensura.Tests;
|
|
||||||
|
|
||||||
public class DoubleExtensions
|
|
||||||
{
|
|
||||||
#region 1. Тесты скалярных типов (Обычные, Экзотические и Nullable)
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ToDouble_Should_Convert_ExoticTypes_Without_InvalidCastException()
|
|
||||||
{
|
|
||||||
// Проверяем типы, которые раньше могли падать в рантайме из-за Convert.ToDouble(object)
|
|
||||||
Half halfValue = (Half)3.14f;
|
|
||||||
Int128 int128Value = Int128.Parse("1234567890123456789012345");
|
|
||||||
UInt128 uInt128Value = UInt128.Parse("9876543210987654321098765");
|
|
||||||
nint nintValue = 42;
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
Assert.Equal(3.14, halfValue.ToDouble(), 2);
|
|
||||||
Assert.Equal((double)int128Value, int128Value.ToDouble());
|
|
||||||
Assert.Equal((double)uInt128Value, uInt128Value.ToDouble());
|
|
||||||
Assert.Equal(42.0, nintValue.ToDouble());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData((int)100, 100.0)]
|
|
||||||
[InlineData((byte)5, 5.0)]
|
|
||||||
[InlineData((float)1.5f, 1.5)]
|
|
||||||
public void ToDouble_StandardScalars_ShouldConvertCorrectly(object input, double expected)
|
|
||||||
{
|
|
||||||
double result = input switch
|
|
||||||
{
|
|
||||||
int i => i.ToDouble(),
|
|
||||||
byte b => b.ToDouble(),
|
|
||||||
float f => f.ToDouble(),
|
|
||||||
_ => throw new ArgumentException("Unsupported type in test")
|
|
||||||
};
|
|
||||||
|
|
||||||
Assert.Equal(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ToDouble_NullableScalars_Should_Return_Zero_When_Null()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
int? nullInt = null;
|
|
||||||
Half? nullHalf = null;
|
|
||||||
Int128? nullInt128 = null;
|
|
||||||
|
|
||||||
int? validInt = 10;
|
|
||||||
Half? validHalf = (Half)2.5f;
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
Assert.Equal(0d, nullInt.ToDouble());
|
|
||||||
Assert.Equal(0d, nullHalf.ToDouble());
|
|
||||||
Assert.Equal(0d, nullInt128.ToDouble());
|
|
||||||
|
|
||||||
Assert.Equal(10d, validInt.ToDouble());
|
|
||||||
Assert.Equal(2.5d, validHalf.ToDouble(), 1);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 2. Тесты SIMD и оптимизаций коллекций (Различные длины массивов)
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(0)] // Пустой массив
|
|
||||||
[InlineData(1)] // 1 элемент (чисто скалярный fallback)
|
|
||||||
[InlineData(7)] // Нечетное число элементов
|
|
||||||
[InlineData(16)] // Кратный размер (размер Vector128/Vector256)
|
|
||||||
[InlineData(35)] // Большой массив с остатком для скалярного хвоста
|
|
||||||
public void ToDouble_ArrayAndList_Should_Correctly_Map_Via_SIMD_Or_Fallback(int count)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
float[] sourceArray = [.. Enumerable.Range(1, count).Select(x => x * 1.5f)];
|
|
||||||
List<float> sourceList = [.. sourceArray];
|
|
||||||
|
|
||||||
double[] destFromArray = new double[count];
|
|
||||||
double[] destFromList = new double[count];
|
|
||||||
|
|
||||||
// Act
|
|
||||||
// Явное приведение к IReadOnlyCollection устраняет ошибку CS0121 (неоднозначность вызова)
|
|
||||||
((IReadOnlyCollection<float>)sourceArray).ToDouble(destFromArray);
|
|
||||||
((IReadOnlyCollection<float>)sourceList).ToDouble(destFromList);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
double expected = sourceArray[i];
|
|
||||||
Assert.Equal(expected, destFromArray[i]);
|
|
||||||
Assert.Equal(expected, destFromList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 3. Тесты Nullable-коллекций (Проверка на null-элементы внутри)
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ToDouble_Nullable_Collections_Should_Keep_Nulls_In_Destination()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
UInt128?[] sourceArray = [10, null, 20, null, 30];
|
|
||||||
double?[] destination = new double?[sourceArray.Length];
|
|
||||||
|
|
||||||
// Act
|
|
||||||
((IReadOnlyCollection<UInt128?>)sourceArray).ToDouble(destination);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(10d, destination[0]);
|
|
||||||
Assert.Null(destination[1]);
|
|
||||||
Assert.Equal(20d, destination[2]);
|
|
||||||
Assert.Null(destination[3]);
|
|
||||||
Assert.Equal(30d, destination[4]);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 4. Тесты LINQ / Отложенного выполнения (IEnumerable)
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ToDouble_IEnumerable_Extension_Should_Handle_Execution_Types_Correctly()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
int[] array = [1, 2, 3];
|
|
||||||
List<int> list = [4, 5, 6];
|
|
||||||
IEnumerable<int> genericEnum = Enumerable.Range(7, 3);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var resFromArray = array.ToDouble(); // Быстрый бранч для массива
|
|
||||||
var resFromList = list.ToDouble(); // Быстрый бранч для списка
|
|
||||||
var resFromEnum = genericEnum.ToDouble(); // Медленный итератор по IEnumerable
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal([1d, 2d, 3d], resFromArray);
|
|
||||||
Assert.Equal([4d, 5d, 6d], resFromList);
|
|
||||||
Assert.Equal([7d, 8d, 9d], resFromEnum);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 5. Тесты безопасности и валидации аргументов
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ToDouble_Should_Throw_ArgumentException_When_Destination_Is_Too_Short()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
int[] source = [1, 2, 3, 4, 5];
|
|
||||||
double[] destinationTooShort = new double[4]; // Нужен размер >= 5
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
Assert.Throws<ArgumentException>(() => ((IReadOnlyCollection<int>)source).ToDouble(destinationTooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ToDouble_Should_Do_Nothing_And_Return_When_Collection_Is_Empty_Or_Null()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
int[]? nullArray = null;
|
|
||||||
int[] emptyArray = [];
|
|
||||||
double[] destination = new double[5];
|
|
||||||
|
|
||||||
// Act & Assert (Не должно выбрасывать NullReferenceException или ArgumentException)
|
|
||||||
((IReadOnlyCollection<int>?)nullArray)!.ToDouble(destination);
|
|
||||||
((IReadOnlyCollection<int>)emptyArray).ToDouble(destination);
|
|
||||||
|
|
||||||
Assert.All(destination, x => Assert.Equal(0d, x)); // Назначение осталось нетронутым (все нули по умолчанию)
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
394
QWERTYkez.Mensura.Tests/DoubleExtensionsTest.cs
Normal file
394
QWERTYkez.Mensura.Tests/DoubleExtensionsTest.cs
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using QWERTYkez.Mensura.Extensions;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace QWERTYkez.Mensura.Tests
|
||||||
|
{
|
||||||
|
public class DoubleExtensionsTests
|
||||||
|
{
|
||||||
|
private const double Tolerance = 1e-12;
|
||||||
|
|
||||||
|
#region Single value conversions (non-nullable)
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(255)]
|
||||||
|
public void ToDouble_Byte_ReturnsExpected(byte value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-128)]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(127)]
|
||||||
|
public void ToDouble_SByte_ReturnsExpected(sbyte value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-32768)]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(32767)]
|
||||||
|
public void ToDouble_Short_ReturnsExpected(short value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(65535)]
|
||||||
|
public void ToDouble_UShort_ReturnsExpected(ushort value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-2147483648)]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(2147483647)]
|
||||||
|
public void ToDouble_Int_ReturnsExpected(int value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0U)]
|
||||||
|
[InlineData(1U)]
|
||||||
|
[InlineData(uint.MaxValue)]
|
||||||
|
public void ToDouble_UInt_ReturnsExpected(uint value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-9223372036854775808)]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(9223372036854775807)]
|
||||||
|
public void ToDouble_Long_ReturnsExpected(long value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0UL)]
|
||||||
|
[InlineData(1UL)]
|
||||||
|
[InlineData(ulong.MaxValue)]
|
||||||
|
public void ToDouble_ULong_ReturnsExpected(ulong value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-123456789)]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(123456789)]
|
||||||
|
public void ToDouble_NInt_ReturnsExpected(nint value) => Assert.Equal(value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0u)]
|
||||||
|
[InlineData(123456789u)]
|
||||||
|
public void ToDouble_NUInt_ReturnsExpected(nuint value) => Assert.Equal((double)value, value.ToDouble());
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.0f)]
|
||||||
|
[InlineData(123.456f)]
|
||||||
|
[InlineData(-987.654f)]
|
||||||
|
[InlineData(float.Epsilon)]
|
||||||
|
[InlineData(float.MaxValue)]
|
||||||
|
public void ToDouble_Float_ReturnsExpected(float value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.0)]
|
||||||
|
[InlineData(123.456)]
|
||||||
|
[InlineData(-987.654)]
|
||||||
|
public void ToDouble_Decimal_ReturnsExpected(decimal value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.0)]
|
||||||
|
[InlineData(123.456)]
|
||||||
|
[InlineData(-987.654)]
|
||||||
|
public void ToDouble_Half_ReturnsExpected(Half value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Single value conversions (nullable)
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableByte_Null_ReturnsZero() => Assert.Equal(0.0, ((byte?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableSByte_Null_ReturnsZero() => Assert.Equal(0.0, ((sbyte?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableShort_Null_ReturnsZero() => Assert.Equal(0.0, ((short?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableUShort_Null_ReturnsZero() => Assert.Equal(0.0, ((ushort?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableInt_Null_ReturnsZero() => Assert.Equal(0.0, ((int?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableUInt_Null_ReturnsZero() => Assert.Equal(0.0, ((uint?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableLong_Null_ReturnsZero() => Assert.Equal(0.0, ((long?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableULong_Null_ReturnsZero() => Assert.Equal(0.0, ((ulong?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableNInt_Null_ReturnsZero() => Assert.Equal(0.0, ((nint?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableNUInt_Null_ReturnsZero() => Assert.Equal(0.0, ((nuint?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableFloat_Null_ReturnsZero() => Assert.Equal(0.0, ((float?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableDecimal_Null_ReturnsZero() => Assert.Equal(0.0, ((decimal?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableHalf_Null_ReturnsZero() => Assert.Equal(0.0, ((Half?)null).ToDouble());
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region NET7_0_OR_GREATER
|
||||||
|
|
||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(-1)]
|
||||||
|
[InlineData(long.MaxValue)]
|
||||||
|
public void ToDouble_Int128_ReturnsExpected(Int128 value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(ulong.MaxValue)]
|
||||||
|
public void ToDouble_UInt128_ReturnsExpected(UInt128 value) => Assert.Equal((double)value, value.ToDouble(), Tolerance);
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableInt128_Null_ReturnsZero() => Assert.Equal(0.0, ((Int128?)null).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableUInt128_Null_ReturnsZero() => Assert.Equal(0.0, ((UInt128?)null).ToDouble());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable<T> -> IEnumerable<double> (non-nullable)
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableByte_ReturnsCorrect()
|
||||||
|
{
|
||||||
|
byte[] source = [1, 2, 3];
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Equal(new double[] { 1, 2, 3 }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableByte_Empty_ReturnsEmpty()
|
||||||
|
{
|
||||||
|
var source = Array.Empty<byte>();
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Empty(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableByte_Null_Throws() => Assert.Null(((IEnumerable<byte>)null!).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableInt_ReturnsCorrect()
|
||||||
|
{
|
||||||
|
int[] source = [-5, 0, 10];
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Equal(new double[] { -5, 0, 10 }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableInt_Null_Throws() => Assert.Null(((IEnumerable<int>)null!).ToDouble());
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable<T?> -> IEnumerable<double?>
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableNullableInt_ReturnsCorrect()
|
||||||
|
{
|
||||||
|
int?[] source = [1, null, 3];
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Equal(3, result.Length);
|
||||||
|
Assert.Equal(1.0, result.First());
|
||||||
|
Assert.Null(result.Skip(1).First());
|
||||||
|
Assert.Equal(3.0, result.Last());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IEnumerableNullableInt_Null_Throws() => Assert.Null(((IEnumerable<int?>)null!).ToDouble());
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Array and List conversions (non-nullable)
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_ByteArray_ReturnsDoubleArray()
|
||||||
|
{
|
||||||
|
byte[] arr = [10, 20];
|
||||||
|
var result = arr.ToDouble();
|
||||||
|
Assert.Equal(new double[] { 10, 20 }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_ByteArray_Null_ReturnsNull() => Assert.Null(((byte[])null!).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_ByteList_ReturnsDoubleList()
|
||||||
|
{
|
||||||
|
var list = new List<byte> { 10, 20 };
|
||||||
|
var result = list.ToDouble();
|
||||||
|
Assert.Equal([10, 20], result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_ByteList_Null_ReturnsNull() => Assert.Null(((List<byte>)null!).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IntArray_ReturnsDoubleArray()
|
||||||
|
{
|
||||||
|
int[] arr = [-5, 0, 7];
|
||||||
|
var result = arr.ToDouble();
|
||||||
|
Assert.Equal(new double[] { -5, 0, 7 }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IntList_ReturnsDoubleList()
|
||||||
|
{
|
||||||
|
var list = new List<int> { -5, 0, 7 };
|
||||||
|
var result = list.ToDouble();
|
||||||
|
Assert.Equal([-5, 0, 7], result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Array and List conversions (nullable)
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableIntArray_ReturnsNullableDoubleArray()
|
||||||
|
{
|
||||||
|
int?[] arr = [1, null, 3];
|
||||||
|
var result = arr.ToDouble();
|
||||||
|
Assert.Equal(3, result.Length);
|
||||||
|
Assert.Equal(1.0, result[0]);
|
||||||
|
Assert.Null(result[1]);
|
||||||
|
Assert.Equal(3.0, result[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableIntArray_Null_ReturnsNull() => Assert.Null(((int?[])null!).ToDouble());
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableIntList_ReturnsNullableDoubleList()
|
||||||
|
{
|
||||||
|
var list = new List<int?> { 1, null, 3 };
|
||||||
|
var result = list.ToDouble();
|
||||||
|
Assert.Equal(3, result.Count);
|
||||||
|
Assert.Equal(1.0, result[0]);
|
||||||
|
Assert.Null(result[1]);
|
||||||
|
Assert.Equal(3.0, result[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_NullableIntList_Null_ReturnsNull() => Assert.Null(((List<int?>)null!).ToDouble());
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IReadOnlyCollection<T> -> Span<double>
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IReadOnlyCollectionByte_Span_Works()
|
||||||
|
{
|
||||||
|
byte[] source = [1, 2];
|
||||||
|
Span<double> dest = new double[source.Length];
|
||||||
|
((IReadOnlyCollection<byte>)source).ToDouble(dest);
|
||||||
|
Assert.Equal(1.0, dest[0]);
|
||||||
|
Assert.Equal(2.0, dest[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IReadOnlyCollectionByte_EmptySpan_Works()
|
||||||
|
{
|
||||||
|
byte[] source = [];
|
||||||
|
Span<double> dest = [];
|
||||||
|
((IReadOnlyCollection<byte>)source).ToDouble(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IReadOnlyCollectionByte_DestinationTooShort_Throws()
|
||||||
|
{
|
||||||
|
byte[] source = [1, 2];
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<double> dest = new double[1];
|
||||||
|
((IReadOnlyCollection<byte>)source).ToDouble(dest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_IReadOnlyCollectionNullableInt_Span_HandlesNulls()
|
||||||
|
{
|
||||||
|
int?[] source = [1, null, 3];
|
||||||
|
Span<double?> dest = new double?[3];
|
||||||
|
((IReadOnlyCollection<int?>)source).ToDouble(dest);
|
||||||
|
Assert.Equal(1.0, dest[0]);
|
||||||
|
Assert.Null(dest[1]);
|
||||||
|
Assert.Equal(3.0, dest[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Span conversions (ToDoubleCore) - через массивы
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IntSpan_ToDouble_ConversionWorks()
|
||||||
|
{
|
||||||
|
int[] source = [1, 2, 3];
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Equal(new double[] { 1, 2, 3 }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FloatSpan_ToDouble_ConversionWorks()
|
||||||
|
{
|
||||||
|
float[] source = [1.1f, -2.2f];
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Equal(1.1f, result[0], Tolerance);
|
||||||
|
Assert.Equal(-2.2f, result[1], Tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NullableDecimalSpan_ToDouble_HandlesNulls()
|
||||||
|
{
|
||||||
|
decimal?[] source = [1.5m, null, -3.3m];
|
||||||
|
var result = source.ToDouble();
|
||||||
|
Assert.Equal(3, result.Length);
|
||||||
|
Assert.Equal(1.5, result[0]!.Value, Tolerance);
|
||||||
|
Assert.Null(result[1]);
|
||||||
|
Assert.Equal(-3.3, result[2]!.Value, Tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Edge cases
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_LongMaxValue_DoesNotOverflow()
|
||||||
|
{
|
||||||
|
long max = long.MaxValue;
|
||||||
|
double result = max.ToDouble();
|
||||||
|
Assert.Equal((double)max, result, Tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_ULongMaxValue_DoesNotOverflow()
|
||||||
|
{
|
||||||
|
ulong max = ulong.MaxValue;
|
||||||
|
double result = max.ToDouble();
|
||||||
|
Assert.Equal((double)max, result, Tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToDouble_Decimal_HighPrecision_DoesNotCrash()
|
||||||
|
{
|
||||||
|
decimal huge = decimal.MaxValue;
|
||||||
|
var result = huge.ToDouble();
|
||||||
|
Assert.False(double.IsInfinity(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,9 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="10.0.9" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.9" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.9" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
@@ -31,8 +34,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\QWERTYkez.Mensura\QWERTYkez.Mensura.csproj" />
|
<ProjectReference Include="..\QWERTYkez.Mensura\QWERTYkez.Mensura.csproj" />
|
||||||
<InternalsVisibleTo Include="..\QWERTYkez.Mensura\QWERTYkez.Mensura.csproj" />
|
|
||||||
|
|
||||||
<ProjectReference Include="..\QWERTYkez.Mensura.Generator\QWERTYkez.Mensura.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\QWERTYkez.Mensura.Generator\QWERTYkez.Mensura.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
98
QWERTYkez.Mensura.Tests/TestEntity.cs
Normal file
98
QWERTYkez.Mensura.Tests/TestEntity.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace QWERTYkez.Mensura.Tests
|
||||||
|
{
|
||||||
|
public class TestEntity1
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public Length Length { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestEntity2
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public double Length { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SharedDbContext(DbContextOptions<SharedDbContext> options) : DbContext(options)
|
||||||
|
{
|
||||||
|
public DbSet<TestEntity1> Entities1 { get; set; }
|
||||||
|
public DbSet<TestEntity2> Entities2 { get; set; }
|
||||||
|
|
||||||
|
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
|
||||||
|
{
|
||||||
|
configurationBuilder.UseMensuraUnits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IdentityConversionTest : IDisposable
|
||||||
|
{
|
||||||
|
private readonly SqliteConnection _connection;
|
||||||
|
|
||||||
|
public IdentityConversionTest()
|
||||||
|
{
|
||||||
|
_connection = new SqliteConnection("Filename=:memory:");
|
||||||
|
_connection.Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_connection?.Dispose();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Length_And_Double_Are_Stored_Identically()
|
||||||
|
{
|
||||||
|
// 1. Сохраняем Length → читаем как double
|
||||||
|
double savedDoubleFromLength;
|
||||||
|
using (var context = new SharedDbContext(new DbContextOptionsBuilder<SharedDbContext>().UseSqlite(_connection).Options))
|
||||||
|
{
|
||||||
|
context.Database.EnsureCreated();
|
||||||
|
var expectedLength = Length.Meter; // 1000 мм
|
||||||
|
context.Entities1.Add(new TestEntity1 { Length = expectedLength });
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
using var cmd = context.Database.GetDbConnection().CreateCommand();
|
||||||
|
cmd.CommandText = "SELECT Length FROM Entities1";
|
||||||
|
savedDoubleFromLength = (double)cmd.ExecuteScalar()!;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Сохраняем double → читаем как Length
|
||||||
|
double savedDoubleFromDouble = 1234.5;
|
||||||
|
using (var context = new SharedDbContext(new DbContextOptionsBuilder<SharedDbContext>().UseSqlite(_connection).Options))
|
||||||
|
{
|
||||||
|
context.Database.EnsureCreated();
|
||||||
|
context.Entities2.Add(new TestEntity2 { Length = savedDoubleFromDouble });
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
using var cmd = context.Database.GetDbConnection().CreateCommand();
|
||||||
|
cmd.CommandText = "SELECT Length FROM Entities2";
|
||||||
|
savedDoubleFromDouble = (double)cmd.ExecuteScalar()!; // должно быть 1234.5
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Проверяем, что сырые значения сохранены корректно
|
||||||
|
Assert.Equal(1000.0, savedDoubleFromLength);
|
||||||
|
Assert.Equal(1234.5, savedDoubleFromDouble);
|
||||||
|
|
||||||
|
// 4. Проверяем обратимость: читаем из Entities1 как TestEntity2
|
||||||
|
using (var context = new SharedDbContext(new DbContextOptionsBuilder<SharedDbContext>().UseSqlite(_connection).Options))
|
||||||
|
{
|
||||||
|
var fromLengthTable = context.Entities2
|
||||||
|
.FromSqlRaw("SELECT Id, Length FROM Entities1")
|
||||||
|
.First();
|
||||||
|
Assert.Equal(1000.0, fromLengthTable.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Проверяем обратимость: читаем из Entities2 как TestEntity1
|
||||||
|
using (var context = new SharedDbContext(new DbContextOptionsBuilder<SharedDbContext>().UseSqlite(_connection).Options))
|
||||||
|
{
|
||||||
|
var fromDoubleTable = context.Entities1
|
||||||
|
.FromSqlRaw("SELECT Id, Length FROM Entities2")
|
||||||
|
.First();
|
||||||
|
Assert.Equal(1234.5, (double)fromDoubleTable.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,19 @@ namespace QWERTYkez.Mensura.Extensions;
|
|||||||
|
|
||||||
internal static partial class CastExtensions
|
internal static partial class CastExtensions
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double ToDouble<T>(this T unit)
|
||||||
internal static double ToDouble<T>(this T unit) where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T> => Unsafe.As<T, double>(ref unit);
|
||||||
=> Unsafe.As<T, double>(ref unit);
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double Protected<T>(this T? unit)
|
||||||
|
where T : struct, IMensuraUnit, IEquatable<T> => unit.GetValueOrDefault().ToDouble();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ProtectedU<T>(this T? unit)
|
||||||
|
where T : struct, IMensuraUnit, IEquatable<T> => unit ?? default;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ToUnit<T>(this double val)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ToUnit<T>(this double val)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T> => Unsafe.As<double, T>(ref val);
|
where T : struct, IMensuraUnit, IEquatable<T> => Unsafe.As<double, T>(ref val);
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static List<R> WrapAsList<T, R>(this T[] array)
|
internal static List<R> WrapAsList<T, R>(this T[] array)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
internal static partial class CollectionsDivideExtensions
|
internal static partial class CollectionsDivideExtensions
|
||||||
{
|
{
|
||||||
// === DivideCore === SIMD
|
// === DivCore === SIMD
|
||||||
internal static void DivideCore<T, R>(this ReadOnlySpan<T> units, double divisor, int len, Span<R> destination)
|
internal static void DivCore<T, R>(this ReadOnlySpan<T> units, double divisor, int len, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor;
|
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void DivideCore<T, R>(this ReadOnlySpan<T?> units, double divisor, int len, Span<R?> destination)
|
internal static void DivCore<T, R>(this ReadOnlySpan<T?> units, double divisor, int len, Span<R?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -67,10 +67,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
d0 = (u0.Protected() * invDivisor).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
d1 = (u1.Protected() * invDivisor).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
d2 = (u2.Protected() * invDivisor).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
d3 = (u3.Protected() * invDivisor).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -78,12 +78,11 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit.Protected() * invDivisor).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (unit.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
internal static void DivideCore<T, R>(this double dividend, ReadOnlySpan<T> units, int len, Span<R> destination)
|
internal static void DivCore<T, R>(this double dividend, ReadOnlySpan<T> units, int len, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -118,7 +117,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = dividend / Unsafe.Add(ref srcRef, i);
|
Unsafe.Add(ref dstRef, i) = dividend / Unsafe.Add(ref srcRef, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void DivideCore<T, R>(this double dividend, ReadOnlySpan<T?> units, int len, Span<R?> destination)
|
internal static void DivCore<T, R>(this double dividend, ReadOnlySpan<T?> units, int len, Span<R?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -144,10 +143,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (dividend / u0.Value.ToDouble()).ToUnit<R>() : null;
|
d0 = (dividend / u0.Protected()).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (dividend / u1.Value.ToDouble()).ToUnit<R>() : null;
|
d1 = (dividend / u1.Protected()).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (dividend / u2.Value.ToDouble()).ToUnit<R>() : null;
|
d2 = (dividend / u2.Protected()).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (dividend / u3.Value.ToDouble()).ToUnit<R>() : null;
|
d3 = (dividend / u3.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -156,7 +155,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
|
||||||
dst = unit.HasValue ? (dividend / unit.Value.ToDouble()).ToUnit<R>() : null;
|
dst = (dividend / unit.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +173,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
units.DivideCore(divisor, len, result);
|
units.DivCore(divisor, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Div<T, R>(this T?[] units, double divisor)
|
internal static R?[] Div<T, R>(this T?[] units, double divisor)
|
||||||
@@ -186,7 +185,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
units.DivideCore(divisor, len, result);
|
units.DivCore(divisor, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R[] Div<T, R>(this double dividend, T[] units)
|
internal static R[] Div<T, R>(this double dividend, T[] units)
|
||||||
@@ -198,7 +197,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
dividend.DivideCore(units, len, result);
|
dividend.DivCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Div<T, R>(this double dividend, T?[] units)
|
internal static R?[] Div<T, R>(this double dividend, T?[] units)
|
||||||
@@ -210,7 +209,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
dividend.DivideCore(units, len, result);
|
dividend.DivCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,9 +222,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
DivideCore(CollectionsMarshal.AsSpan(units), divisor, count, resultArray);
|
DivCore(CollectionsMarshal.AsSpan(units), divisor, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Div<T, R>(this List<T?> units, double divisor)
|
internal static List<R?> Div<T, R>(this List<T?> units, double divisor)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -235,9 +234,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
DivideCore(CollectionsMarshal.AsSpan(units), divisor, count, resultArray);
|
DivCore(CollectionsMarshal.AsSpan(units), divisor, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R> Div<T, R>(this double dividend, List<T> units)
|
internal static List<R> Div<T, R>(this double dividend, List<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -247,9 +246,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
DivideCore(dividend, CollectionsMarshal.AsSpan(units), count, resultArray);
|
DivCore(dividend, CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Div<T, R>(this double dividend, List<T?> units)
|
internal static List<R?> Div<T, R>(this double dividend, List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -259,9 +258,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
DivideCore(dividend, CollectionsMarshal.AsSpan(units), count, resultArray);
|
DivCore(dividend, CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
@@ -275,8 +274,8 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.DivideCore(divisor, count, destination); return; }
|
if (units is T[] array) { array.DivCore(divisor, count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).DivideCore(divisor, count, destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).DivCore(divisor, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
double invDivisor = 1.0 / divisor;
|
double invDivisor = 1.0 / divisor;
|
||||||
@@ -293,14 +292,13 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.DivideCore(divisor, count, destination); return; }
|
if (units is T?[] array) { array.DivCore(divisor, count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).DivideCore(divisor, count, destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).DivCore(divisor, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
double invDivisor = 1.0 / divisor;
|
double invDivisor = 1.0 / divisor;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() * invDivisor).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
internal static void Div<T, R>(this double dividend, IReadOnlyCollection<T> units, Span<R> destination)
|
internal static void Div<T, R>(this double dividend, IReadOnlyCollection<T> units, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -312,8 +310,8 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { dividend.DivideCore(array, count, destination); return; }
|
if (units is T[] array) { dividend.DivCore(array, count, destination); return; }
|
||||||
if (units is List<T> list) { dividend.DivideCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
if (units is List<T> list) { dividend.DivCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -329,13 +327,12 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { dividend.DivideCore(array, count, destination); return; }
|
if (units is T?[] array) { dividend.DivCore(array, count, destination); return; }
|
||||||
if (units is List<T?> list) { dividend.DivideCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
if (units is List<T?> list) { dividend.DivCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (dividend / item.Protected()).ToUnit<R>();
|
||||||
? (dividend / item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
@@ -353,8 +350,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
double invDivisor = 1.0 / divisor;
|
double invDivisor = 1.0 / divisor;
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() * invDivisor).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() * invDivisor).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
static IEnumerable<R> DivideIterator<T, R>(double dividend, IEnumerable<T> units)
|
static IEnumerable<R> DivideIterator<T, R>(double dividend, IEnumerable<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -368,8 +364,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (dividend / item.Protected()).ToUnit<R>();
|
||||||
? (dividend / item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -383,7 +378,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Div(divisor, arr);
|
arr.DivCore(divisor, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return DivideIterator<T, R>(units, divisor);
|
return DivideIterator<T, R>(units, divisor);
|
||||||
@@ -398,7 +393,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Div(divisor, arr);
|
arr.DivCore(divisor, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return DivideNullableIterator<T, R>(units, divisor);
|
return DivideNullableIterator<T, R>(units, divisor);
|
||||||
@@ -413,7 +408,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.Div(arr, arr);
|
dividend.DivCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return DivideIterator<T, R>(dividend, units);
|
return DivideIterator<T, R>(dividend, units);
|
||||||
@@ -428,7 +423,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.Div(arr, arr);
|
dividend.DivCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return DivideNullableIterator<T, R>(dividend, units);
|
return DivideNullableIterator<T, R>(dividend, units);
|
||||||
@@ -447,7 +442,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.DivideCore(divisor, len, destination);
|
units.DivCore(divisor, len, destination);
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this ReadOnlySpan<T?> units, double divisor, Span<T?> destination)
|
internal static void Div<T>(this ReadOnlySpan<T?> units, double divisor, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -457,7 +452,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.DivideCore(divisor, len, destination);
|
units.DivCore(divisor, len, destination);
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this double dividend, ReadOnlySpan<T> units, Span<T> destination)
|
internal static void Div<T>(this double dividend, ReadOnlySpan<T> units, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -467,7 +462,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
dividend.DivideCore(units, len, destination);
|
dividend.DivCore(units, len, destination);
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this double dividend, ReadOnlySpan<T?> units, Span<T?> destination)
|
internal static void Div<T>(this double dividend, ReadOnlySpan<T?> units, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -477,7 +472,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
dividend.DivideCore(units, len, destination);
|
dividend.DivCore(units, len, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Array ===
|
// === Array ===
|
||||||
@@ -489,7 +484,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Div(units, divisor, result);
|
units.DivCore(divisor, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Div<T>(this T?[] units, double divisor)
|
internal static T?[] Div<T>(this T?[] units, double divisor)
|
||||||
@@ -500,7 +495,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Div(units, divisor, result);
|
units.DivCore(divisor, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T[] Div<T>(this double dividend, T[] units)
|
internal static T[] Div<T>(this double dividend, T[] units)
|
||||||
@@ -511,7 +506,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Div(dividend, units, result);
|
dividend.DivCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Div<T>(this double dividend, T?[] units)
|
internal static T?[] Div<T>(this double dividend, T?[] units)
|
||||||
@@ -522,7 +517,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Div(dividend, units, result);
|
dividend.DivCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,12 +526,12 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
|
CollectionsMarshal.AsSpan(units).DivCore(divisor, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Div<T>(this List<T?> units, double divisor)
|
internal static List<T?> Div<T>(this List<T?> units, double divisor)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -545,9 +540,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
|
CollectionsMarshal.AsSpan(units).DivCore(divisor, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T> Div<T>(this double dividend, List<T> units)
|
internal static List<T> Div<T>(this double dividend, List<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -556,9 +551,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[count];
|
var result = new T[count];
|
||||||
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
|
dividend.DivCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Div<T>(this double dividend, List<T?> units)
|
internal static List<T?> Div<T>(this double dividend, List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -567,9 +562,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
|
dividend.DivCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
@@ -605,8 +600,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
double invDivisor = 1.0 / divisor;
|
double invDivisor = 1.0 / divisor;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() * invDivisor).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() * invDivisor).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this double dividend, IReadOnlyCollection<T> units, Span<T> destination)
|
internal static void Div<T>(this double dividend, IReadOnlyCollection<T> units, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -638,8 +632,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (dividend / item.Protected()).ToUnit<T>();
|
||||||
? (dividend / item.Value.ToDouble()).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
@@ -655,8 +648,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
double invDivisor = 1.0 / divisor;
|
double invDivisor = 1.0 / divisor;
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() * invDivisor).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() * invDivisor).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
static IEnumerable<T> DivideIterator<T>(double dividend, IEnumerable<T> units)
|
static IEnumerable<T> DivideIterator<T>(double dividend, IEnumerable<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -668,8 +660,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (dividend / item.Protected()).ToUnit<T>();
|
||||||
? (dividend / item.Value.ToDouble()).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -682,7 +673,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Div(divisor, arr);
|
arr.DivCore(divisor, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return DivideIterator(units, divisor);
|
return DivideIterator(units, divisor);
|
||||||
@@ -696,7 +687,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Div(divisor, arr);
|
arr.DivCore(divisor, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return DivideNullableIterator(units, divisor);
|
return DivideNullableIterator(units, divisor);
|
||||||
@@ -710,7 +701,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.Div(arr, arr);
|
dividend.DivCore(arr, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return DivideIterator(dividend, units);
|
return DivideIterator(dividend, units);
|
||||||
@@ -724,7 +715,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.Div(arr, arr);
|
dividend.DivCore(arr, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return DivideNullableIterator(dividend, units);
|
return DivideNullableIterator(dividend, units);
|
||||||
@@ -738,7 +729,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// === DivideCore === SIMD
|
// === DivCore === SIMD
|
||||||
internal static void DivCore<R>(this ReadOnlySpan<double> dividends, double unit, int len, Span<R> destination)
|
internal static void DivCore<R>(this ReadOnlySpan<double> dividends, double unit, int len, Span<R> destination)
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -800,10 +791,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value * invDivisor).ToUnit<R>() : null;
|
d0 = ((u0 ?? 0d) * invDivisor).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value * invDivisor).ToUnit<R>() : null;
|
d1 = ((u1 ?? 0d) * invDivisor).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value * invDivisor).ToUnit<R>() : null;
|
d2 = ((u2 ?? 0d) * invDivisor).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value * invDivisor).ToUnit<R>() : null;
|
d3 = ((u3 ?? 0d) * invDivisor).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -811,8 +802,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
var div = Unsafe.Add(ref srcRef, i);
|
var div = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = ((div ?? 0d) * invDivisor).ToUnit<R>();
|
||||||
dst = div.HasValue ? (div.Value * invDivisor).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
@@ -874,10 +864,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (unit / u0.Value).ToUnit<R>() : null;
|
d0 = (unit / (u0 ?? 0d)).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (unit / u1.Value).ToUnit<R>() : null;
|
d1 = (unit / (u1 ?? 0d)).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (unit / u2.Value).ToUnit<R>() : null;
|
d2 = (unit / (u2 ?? 0d)).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (unit / u3.Value).ToUnit<R>() : null;
|
d3 = (unit / (u3 ?? 0d)).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -886,12 +876,12 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
var div = Unsafe.Add(ref srcRef, i);
|
var div = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
|
||||||
dst = div.HasValue ? (unit / div.Value).ToUnit<R>() : null;
|
dst = (unit / (div ?? 0d)).ToUnit<R>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === DivideCore === SIMD
|
// === DivCore === SIMD
|
||||||
internal static void DivCore(this ReadOnlySpan<double> dividends, double unit, int len, Span<double> dstDouble)
|
internal static void DivCore(this ReadOnlySpan<double> dividends, double unit, int len, Span<double> dstDouble)
|
||||||
{
|
{
|
||||||
// Вместо деления в цикле, умножаем на обратное число (invDivisor)
|
// Вместо деления в цикле, умножаем на обратное число (invDivisor)
|
||||||
@@ -949,10 +939,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? u0.Value * invDivisor : null;
|
d0 = (u0 ?? 0d) * invDivisor;
|
||||||
d1 = u1.HasValue ? u1.Value * invDivisor : null;
|
d1 = (u1 ?? 0d) * invDivisor;
|
||||||
d2 = u2.HasValue ? u2.Value * invDivisor : null;
|
d2 = (u2 ?? 0d) * invDivisor;
|
||||||
d3 = u3.HasValue ? u3.Value * invDivisor : null;
|
d3 = (u3 ?? 0d) * invDivisor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -960,8 +950,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
double? div = Unsafe.Add(ref srcRef, i);
|
double? div = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (div ?? 0d) * invDivisor;
|
||||||
dst = div.HasValue ? div.Value * invDivisor : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
@@ -1019,10 +1008,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? dUnit / u0.Value : null;
|
d0 = dUnit / (u0 ?? 0d);
|
||||||
d1 = u1.HasValue ? dUnit / u1.Value : null;
|
d1 = dUnit / (u1 ?? 0d);
|
||||||
d2 = u2.HasValue ? dUnit / u2.Value : null;
|
d2 = dUnit / (u2 ?? 0d);
|
||||||
d3 = u3.HasValue ? dUnit / u3.Value : null;
|
d3 = dUnit / (u3 ?? 0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -1030,8 +1019,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
double? div = Unsafe.Add(ref srcRef, i);
|
double? div = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = dUnit / (div ?? 0d);
|
||||||
dst = div.HasValue ? dUnit / div.Value : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,7 +1078,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Div(units, divisor, result);
|
units.DivCore(divisor.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Div<T>(this double?[] units, T divisor)
|
internal static T?[] Div<T>(this double?[] units, T divisor)
|
||||||
@@ -1101,7 +1089,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Div(units, divisor, result);
|
units.DivCore(divisor.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T[] Div<T>(this T dividend, double[] units)
|
internal static T[] Div<T>(this T dividend, double[] units)
|
||||||
@@ -1112,7 +1100,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Div(dividend, units, result);
|
dividend.ToDouble().DivCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Div<T>(this T dividend, double?[] units)
|
internal static T?[] Div<T>(this T dividend, double?[] units)
|
||||||
@@ -1123,7 +1111,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Div(dividend, units, result);
|
dividend.ToDouble().DivCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1132,12 +1120,12 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
|
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Div<T>(this List<double?> units, T divisor)
|
internal static List<T?> Div<T>(this List<double?> units, T divisor)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1146,9 +1134,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Div(CollectionsMarshal.AsSpan(units), divisor, resultArray);
|
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T> Div<T>(this T dividend, List<double> units)
|
internal static List<T> Div<T>(this T dividend, List<double> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1157,9 +1145,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[count];
|
var result = new T[count];
|
||||||
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
|
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Div<T>(this T dividend, List<double?> units)
|
internal static List<T?> Div<T>(this T dividend, List<double?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1168,9 +1156,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Div(dividend, CollectionsMarshal.AsSpan(units), resultArray);
|
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
@@ -1206,8 +1194,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
double invDivisor = 1.0 / divisor.ToDouble();
|
double invDivisor = 1.0 / divisor.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = ((item ?? 0d) * invDivisor).ToUnit<T>();
|
||||||
? (item.Value * invDivisor).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this T dividend, IReadOnlyCollection<double> units, Span<T> destination)
|
internal static void Div<T>(this T dividend, IReadOnlyCollection<double> units, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1238,9 +1225,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is List<double?> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
|
if (units is List<double?> list) { dividend.Div(CollectionsMarshal.AsSpan(list), destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var divD = dividend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (divD / (item ?? 0d)).ToUnit<T>();
|
||||||
? (dividend.ToDouble() / item.Value).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
@@ -1256,8 +1243,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
double invDivisor = 1.0 / divisor;
|
double invDivisor = 1.0 / divisor;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return ((item ?? 0d) * invDivisor).ToUnit<T>();
|
||||||
? (item.Value * invDivisor).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
static IEnumerable<T> DivideIterator<T>(double dividend, IEnumerable<double> units)
|
static IEnumerable<T> DivideIterator<T>(double dividend, IEnumerable<double> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1269,8 +1255,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return (dividend / (item ?? 0d)).ToUnit<T>();
|
||||||
? (dividend / item.Value).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -1339,8 +1324,8 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// === DivideCore === SIMD
|
// === DivCore === SIMD
|
||||||
internal static void DivideCore<T>(this ReadOnlySpan<T> units, double divisor, int len, Span<double> dstDouble)
|
internal static void DivCore<T>(this ReadOnlySpan<T> units, double divisor, int len, Span<double> dstDouble)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
|
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
|
||||||
@@ -1375,7 +1360,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor;
|
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * invDivisor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void DivideCore<T>(this ReadOnlySpan<T?> units, double divisor, int len, Span<double?> destination)
|
internal static void DivCore<T>(this ReadOnlySpan<T?> units, double divisor, int len, Span<double?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
||||||
@@ -1401,10 +1386,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? u0.Value.ToDouble() * invDivisor : null;
|
d0 = u0.Protected() * invDivisor;
|
||||||
d1 = u1.HasValue ? u1.Value.ToDouble() * invDivisor : null;
|
d1 = u1.Protected() * invDivisor;
|
||||||
d2 = u2.HasValue ? u2.Value.ToDouble() * invDivisor : null;
|
d2 = u2.Protected() * invDivisor;
|
||||||
d3 = u3.HasValue ? u3.Value.ToDouble() * invDivisor : null;
|
d3 = u3.Protected() * invDivisor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -1413,11 +1398,11 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
|
||||||
dst = unit.HasValue ? unit.Value.ToDouble() * invDivisor : null;
|
dst = unit.Protected() * invDivisor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
internal static void DivideCore<T>(this double dividend, ReadOnlySpan<T> units, int len, Span<double> dstDouble)
|
internal static void DivCore<T>(this double dividend, ReadOnlySpan<T> units, int len, Span<double> dstDouble)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
|
ReadOnlySpan<double> srcDouble = MemoryMarshal.Cast<T, double>(units);
|
||||||
@@ -1450,7 +1435,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = dividend / Unsafe.Add(ref srcRef, i);
|
Unsafe.Add(ref dstRef, i) = dividend / Unsafe.Add(ref srcRef, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void DivideCore<T>(this double dividend, ReadOnlySpan<T?> units, int len, Span<double?> destination)
|
internal static void DivCore<T>(this double dividend, ReadOnlySpan<T?> units, int len, Span<double?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
||||||
@@ -1475,10 +1460,10 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? dividend / u0.Value.ToDouble() : null;
|
d0 = dividend / u0.Protected();
|
||||||
d1 = u1.HasValue ? dividend / u1.Value.ToDouble() : null;
|
d1 = dividend / u1.Protected();
|
||||||
d2 = u2.HasValue ? dividend / u2.Value.ToDouble() : null;
|
d2 = dividend / u2.Protected();
|
||||||
d3 = u3.HasValue ? dividend / u3.Value.ToDouble() : null;
|
d3 = dividend / u3.Protected();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -1487,7 +1472,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
|
||||||
dst = unit.HasValue ? dividend / unit.Value.ToDouble() : null;
|
dst = dividend / unit.Protected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1504,7 +1489,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.DivideCore(divisor.ToDouble(), len, destination);
|
units.DivCore(divisor.ToDouble(), len, destination);
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this ReadOnlySpan<T?> units, T divisor, Span<double?> destination)
|
internal static void Div<T>(this ReadOnlySpan<T?> units, T divisor, Span<double?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1514,7 +1499,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.DivideCore(divisor.ToDouble(), len, destination);
|
units.DivCore(divisor.ToDouble(), len, destination);
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this T dividend, ReadOnlySpan<T> units, Span<double> destination)
|
internal static void Div<T>(this T dividend, ReadOnlySpan<T> units, Span<double> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1524,7 +1509,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
dividend.ToDouble().DivideCore(units, len, destination);
|
dividend.ToDouble().DivCore(units, len, destination);
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this T dividend, ReadOnlySpan<T?> units, Span<double?> destination)
|
internal static void Div<T>(this T dividend, ReadOnlySpan<T?> units, Span<double?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1534,7 +1519,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
dividend.ToDouble().DivideCore(units, len, destination);
|
dividend.ToDouble().DivCore(units, len, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Array ===
|
// === Array ===
|
||||||
@@ -1546,7 +1531,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
units.DivideCore(divisor.ToDouble(), len, result);
|
units.DivCore(divisor.ToDouble(), len, result);
|
||||||
return result.ReCast();
|
return result.ReCast();
|
||||||
}
|
}
|
||||||
internal static double?[] Div<T>(this T?[] units, T divisor)
|
internal static double?[] Div<T>(this T?[] units, T divisor)
|
||||||
@@ -1557,7 +1542,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
units.DivideCore(divisor.ToDouble(), len, result);
|
units.DivCore(divisor.ToDouble(), len, result);
|
||||||
return result.ReCast();
|
return result.ReCast();
|
||||||
}
|
}
|
||||||
internal static double[] Div<T>(this T dividend, T[] units)
|
internal static double[] Div<T>(this T dividend, T[] units)
|
||||||
@@ -1568,7 +1553,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
dividend.ToDouble().DivideCore(units, len, result);
|
dividend.ToDouble().DivCore(units, len, result);
|
||||||
return result.ReCast();
|
return result.ReCast();
|
||||||
}
|
}
|
||||||
internal static double?[] Div<T>(this T dividend, T?[] units)
|
internal static double?[] Div<T>(this T dividend, T?[] units)
|
||||||
@@ -1579,7 +1564,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
dividend.ToDouble().DivideCore(units, len, result);
|
dividend.ToDouble().DivCore(units, len, result);
|
||||||
return result.ReCast();
|
return result.ReCast();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1591,9 +1576,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int len = units.Count;
|
int len = units.Count;
|
||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var resultArray = new double[len];
|
var result = new double[len];
|
||||||
CollectionsMarshal.AsSpan(units).DivideCore(divisor.ToDouble(), len, resultArray);
|
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), len, result);
|
||||||
return resultArray.WrapAsList();
|
return result.WrapAsList();
|
||||||
}
|
}
|
||||||
internal static List<double?> Div<T>(this List<T?> units, T divisor)
|
internal static List<double?> Div<T>(this List<T?> units, T divisor)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1602,9 +1587,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new double?[count];
|
var result = new double?[count];
|
||||||
CollectionsMarshal.AsSpan(units).DivideCore(divisor.ToDouble(), count, resultArray);
|
CollectionsMarshal.AsSpan(units).DivCore(divisor.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList();
|
return result.WrapAsList();
|
||||||
}
|
}
|
||||||
internal static List<double> Div<T>(this T dividend, List<T> units)
|
internal static List<double> Div<T>(this T dividend, List<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1613,9 +1598,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[count];
|
var result = new T[count];
|
||||||
dividend.ToDouble().DivideCore(CollectionsMarshal.AsSpan(units), count, resultArray);
|
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList();
|
return result.WrapAsList();
|
||||||
}
|
}
|
||||||
internal static List<double?> Div<T>(this T dividend, List<T?> units)
|
internal static List<double?> Div<T>(this T dividend, List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1624,9 +1609,9 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
dividend.ToDouble().DivideCore(CollectionsMarshal.AsSpan(units), count, resultArray);
|
dividend.ToDouble().DivCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList();
|
return result.WrapAsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
@@ -1662,7 +1647,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
double invDivisor = 1.0 / divisor.ToDouble();
|
double invDivisor = 1.0 / divisor.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue ? item.Value.ToDouble() * invDivisor : null;
|
destination[i++] = item.Protected() * invDivisor;
|
||||||
}
|
}
|
||||||
internal static void Div<T>(this T dividend, IReadOnlyCollection<T> units, Span<double> destination)
|
internal static void Div<T>(this T dividend, IReadOnlyCollection<T> units, Span<double> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1696,7 +1681,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
var div = dividend.ToDouble();
|
var div = dividend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue ? div / item.Value.ToDouble() : null;
|
destination[i++] = div / item.Protected();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
@@ -1712,7 +1697,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
double invDivisor = 1.0 / divisor.ToDouble();
|
double invDivisor = 1.0 / divisor.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue ? item.Value.ToDouble() * invDivisor : null;
|
yield return item.Protected() * invDivisor;
|
||||||
}
|
}
|
||||||
static IEnumerable<double> DivideIterator<T>(T dividend, IEnumerable<T> units)
|
static IEnumerable<double> DivideIterator<T>(T dividend, IEnumerable<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -1726,7 +1711,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
{
|
{
|
||||||
var div = dividend.ToDouble();
|
var div = dividend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue ? div / item.Value.ToDouble() : null;
|
yield return div / item.Protected();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -1739,7 +1724,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.DivideCore(divisor.ToDouble(), arr.Length, arr);
|
arr.DivCore(divisor.ToDouble(), arr.Length, arr);
|
||||||
return arr.ReCast();
|
return arr.ReCast();
|
||||||
}
|
}
|
||||||
return DivideIterator(units, divisor);
|
return DivideIterator(units, divisor);
|
||||||
@@ -1753,7 +1738,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.DivideCore(divisor.ToDouble(), arr.Length, arr);
|
arr.DivCore(divisor.ToDouble(), arr.Length, arr);
|
||||||
return arr.ReCast();
|
return arr.ReCast();
|
||||||
}
|
}
|
||||||
return DivideNullableIterator(units, divisor);
|
return DivideNullableIterator(units, divisor);
|
||||||
@@ -1767,7 +1752,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.ToDouble().DivideCore(arr, arr.Length, arr);
|
dividend.ToDouble().DivCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast();
|
return arr.ReCast();
|
||||||
}
|
}
|
||||||
return DivideIterator(dividend, units);
|
return DivideIterator(dividend, units);
|
||||||
@@ -1781,7 +1766,7 @@ internal static partial class CollectionsDivideExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.ToDouble().DivideCore(arr, arr.Length, arr);
|
dividend.ToDouble().DivCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast();
|
return arr.ReCast();
|
||||||
}
|
}
|
||||||
return DivideNullableIterator(dividend, units);
|
return DivideNullableIterator(dividend, units);
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
d0 = (u0.Protected() - subtrahend).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
d1 = (u1.Protected() - subtrahend).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
d2 = (u2.Protected() - subtrahend).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
d3 = (u3.Protected() - subtrahend).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -73,8 +73,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
{
|
{
|
||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit.Protected() - subtrahend).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (unit.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
@@ -139,10 +138,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (minuend - u0.Value.ToDouble()).ToUnit<R>() : null;
|
d0 = (minuend - u0.Protected()).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (minuend - u1.Value.ToDouble()).ToUnit<R>() : null;
|
d1 = (minuend - u1.Protected()).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (minuend - u2.Value.ToDouble()).ToUnit<R>() : null;
|
d2 = (minuend - u2.Protected()).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (minuend - u3.Value.ToDouble()).ToUnit<R>() : null;
|
d3 = (minuend - u3.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -150,8 +149,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
{
|
{
|
||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (minuend - unit.Protected()).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (minuend - unit.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,9 +216,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, resultArray);
|
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Minus<T, R>(this List<T?> units, double subtrahend)
|
internal static List<R?> Minus<T, R>(this List<T?> units, double subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -230,9 +228,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, resultArray);
|
MinusCore(CollectionsMarshal.AsSpan(units), subtrahend, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R> Minus<T, R>(this double minuend, List<T> units)
|
internal static List<R> Minus<T, R>(this double minuend, List<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -242,9 +240,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, resultArray);
|
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Minus<T, R>(this double minuend, List<T?> units)
|
internal static List<R?> Minus<T, R>(this double minuend, List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -254,9 +252,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, resultArray);
|
MinusCore(minuend, CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
@@ -292,8 +290,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() - subtrahend).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
internal static void Minus<T, R>(this double minuend, IReadOnlyCollection<T> units, Span<R> destination)
|
internal static void Minus<T, R>(this double minuend, IReadOnlyCollection<T> units, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -327,8 +324,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (minuend - item.Protected()).ToUnit<R>();
|
||||||
? (minuend - item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
@@ -344,8 +340,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() - subtrahend).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() - subtrahend).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
static IEnumerable<R> MinusIterator<T, R>(double minuend, IEnumerable<T> units)
|
static IEnumerable<R> MinusIterator<T, R>(double minuend, IEnumerable<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -359,8 +354,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (minuend - item.Protected()).ToUnit<R>();
|
||||||
? (minuend - item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -374,7 +368,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Minus(subtrahend, arr);
|
arr.MinusCore(subtrahend, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return MinusIterator<T, R>(units, subtrahend);
|
return MinusIterator<T, R>(units, subtrahend);
|
||||||
@@ -389,7 +383,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Minus(subtrahend, arr);
|
arr.MinusCore(subtrahend, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return MinusNullableIterator<T, R>(units, subtrahend);
|
return MinusNullableIterator<T, R>(units, subtrahend);
|
||||||
@@ -404,7 +398,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
minuend.Minus(arr, arr);
|
minuend.MinusCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return MinusIterator<T, R>(minuend, units);
|
return MinusIterator<T, R>(minuend, units);
|
||||||
@@ -419,7 +413,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
minuend.Minus(arr, arr);
|
minuend.MinusCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return MinusNullableIterator<T, R>(minuend, units);
|
return MinusNullableIterator<T, R>(minuend, units);
|
||||||
@@ -481,7 +475,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Minus(units, subtrahend, result);
|
units.MinusCore(subtrahend, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Minus<T>(this T?[] units, double subtrahend)
|
internal static T?[] Minus<T>(this T?[] units, double subtrahend)
|
||||||
@@ -492,7 +486,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Minus(units, subtrahend, result);
|
units.MinusCore(subtrahend, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T[] Minus<T>(this double minuend, T[] units)
|
internal static T[] Minus<T>(this double minuend, T[] units)
|
||||||
@@ -503,7 +497,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Minus(minuend, units, result);
|
minuend.MinusCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Minus<T>(this double minuend, T?[] units)
|
internal static T?[] Minus<T>(this double minuend, T?[] units)
|
||||||
@@ -514,7 +508,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Minus(minuend, units, result);
|
minuend.MinusCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,12 +517,12 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Minus(CollectionsMarshal.AsSpan(units), subtrahend, resultArray);
|
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Minus<T>(this List<T?> units, double subtrahend)
|
internal static List<T?> Minus<T>(this List<T?> units, double subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -537,9 +531,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Minus(CollectionsMarshal.AsSpan(units), subtrahend, resultArray);
|
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T> Minus<T>(this double minuend, List<T> units)
|
internal static List<T> Minus<T>(this double minuend, List<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -548,9 +542,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[count];
|
var result = new T[count];
|
||||||
Minus(minuend, CollectionsMarshal.AsSpan(units), resultArray);
|
minuend.MinusCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Minus<T>(this double minuend, List<T?> units)
|
internal static List<T?> Minus<T>(this double minuend, List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -559,9 +553,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Minus(minuend, CollectionsMarshal.AsSpan(units), resultArray);
|
minuend.MinusCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
@@ -574,8 +568,8 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Minus(subtrahend, destination); return; }
|
if (units is T[] array) { array.MinusCore(subtrahend, count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Minus(subtrahend, destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -590,13 +584,12 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Minus(subtrahend, destination); return; }
|
if (units is T?[] array) { array.MinusCore(subtrahend, count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Minus(subtrahend, destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() - subtrahend).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() - subtrahend).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this double minuend, IReadOnlyCollection<T> units, Span<T> destination)
|
internal static void Minus<T>(this double minuend, IReadOnlyCollection<T> units, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -607,8 +600,8 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { minuend.Minus(array, destination); return; }
|
if (units is T[] array) { minuend.MinusCore(array, count, destination); return; }
|
||||||
if (units is List<T> list) { minuend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
|
if (units is List<T> list) { minuend.MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -623,13 +616,12 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { minuend.Minus(array, destination); return; }
|
if (units is T?[] array) { minuend.MinusCore(array, count, destination); return; }
|
||||||
if (units is List<T?> list) { minuend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
|
if (units is List<T?> list) { minuend.MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (minuend - item.Protected()).ToUnit<T>();
|
||||||
? (minuend - item.Value.ToDouble()).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
@@ -643,8 +635,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() - subtrahend).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() - subtrahend).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
static IEnumerable<T> MinusIterator<T>(double minuend, IEnumerable<T> units)
|
static IEnumerable<T> MinusIterator<T>(double minuend, IEnumerable<T> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -656,8 +647,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (minuend - item.Protected()).ToUnit<T>();
|
||||||
? (minuend - item.Value.ToDouble()).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -670,7 +660,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Minus(subtrahend, arr);
|
arr.MinusCore(subtrahend, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return MinusIterator(units, subtrahend);
|
return MinusIterator(units, subtrahend);
|
||||||
@@ -684,7 +674,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Minus(subtrahend, arr);
|
arr.MinusCore(subtrahend, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return MinusNullableIterator(units, subtrahend);
|
return MinusNullableIterator(units, subtrahend);
|
||||||
@@ -698,7 +688,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
minuend.Minus(arr, arr);
|
minuend.MinusCore(arr, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return MinusIterator(minuend, units);
|
return MinusIterator(minuend, units);
|
||||||
@@ -712,7 +702,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
minuend.Minus(arr, arr);
|
minuend.MinusCore(arr, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return MinusNullableIterator(minuend, units);
|
return MinusNullableIterator(minuend, units);
|
||||||
@@ -783,10 +773,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value - subtrahend).ToUnit<R>() : null;
|
d0 = ((u0 ?? 0d) - subtrahend).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value - subtrahend).ToUnit<R>() : null;
|
d1 = ((u1 ?? 0d) - subtrahend).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value - subtrahend).ToUnit<R>() : null;
|
d2 = ((u2 ?? 0d) - subtrahend).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value - subtrahend).ToUnit<R>() : null;
|
d3 = ((u3 ?? 0d) - subtrahend).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -794,8 +784,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = ((unit ?? 0d) - subtrahend).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (unit.Value - subtrahend).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
@@ -857,10 +846,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (minuend - u0.Value).ToUnit<R>() : null;
|
d0 = (minuend - (u0 ?? 0d)).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (minuend - u1.Value).ToUnit<R>() : null;
|
d1 = (minuend - (u1 ?? 0d)).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (minuend - u2.Value).ToUnit<R>() : null;
|
d2 = (minuend - (u2 ?? 0d)).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (minuend - u3.Value).ToUnit<R>() : null;
|
d3 = (minuend - (u3 ?? 0d)).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -868,13 +857,12 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (minuend - (unit ?? 0d)).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (minuend - unit.Value).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === DivideCore === SIMD
|
// === DivCore === SIMD
|
||||||
internal static void MinusCore(this ReadOnlySpan<double> srcDouble, double subtrahend, int len, Span<double> dstDouble)
|
internal static void MinusCore(this ReadOnlySpan<double> srcDouble, double subtrahend, int len, Span<double> dstDouble)
|
||||||
{
|
{
|
||||||
var vectorizedSubtrahend = new Vector<double>(subtrahend);
|
var vectorizedSubtrahend = new Vector<double>(subtrahend);
|
||||||
@@ -927,10 +915,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? u0.Value - subtrahend : null;
|
d0 = (u0 ?? 0d) - subtrahend;
|
||||||
d1 = u1.HasValue ? u1.Value - subtrahend : null;
|
d1 = (u1 ?? 0d) - subtrahend;
|
||||||
d2 = u2.HasValue ? u2.Value - subtrahend : null;
|
d2 = (u2 ?? 0d) - subtrahend;
|
||||||
d3 = u3.HasValue ? u3.Value - subtrahend : null;
|
d3 = (u3 ?? 0d) - subtrahend;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -938,8 +926,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit ?? 0d) - subtrahend;
|
||||||
dst = unit.HasValue ? unit.Value - subtrahend : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SIMD
|
//SIMD
|
||||||
@@ -997,10 +984,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? minuend - u0.Value : null;
|
d0 = minuend - u0 ?? 0d;
|
||||||
d1 = u1.HasValue ? minuend - u1.Value : null;
|
d1 = minuend - u1 ?? 0d;
|
||||||
d2 = u2.HasValue ? minuend - u2.Value : null;
|
d2 = minuend - u2 ?? 0d;
|
||||||
d3 = u3.HasValue ? minuend - u3.Value : null;
|
d3 = minuend - u3 ?? 0d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -1008,8 +995,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = minuend - unit ?? 0d;
|
||||||
dst = unit.HasValue ? minuend - unit.Value : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,7 +1004,7 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
|
|
||||||
|
|
||||||
// === ReadOnlySpan
|
// === ReadOnlySpan
|
||||||
internal static void Minus<T>(this ReadOnlySpan<double> units, T divisor, Span<T> destination)
|
internal static void Minus<T>(this ReadOnlySpan<double> units, T subtrahend, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units.IsEmpty) return;
|
if (units.IsEmpty) return;
|
||||||
@@ -1026,9 +1012,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.MinusCore(divisor.ToDouble(), len, destination);
|
units.MinusCore(subtrahend.ToDouble(), len, destination);
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this ReadOnlySpan<double?> units, T divisor, Span<T?> destination)
|
internal static void Minus<T>(this ReadOnlySpan<double?> units, T subtrahend, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units.IsEmpty) return;
|
if (units.IsEmpty) return;
|
||||||
@@ -1036,9 +1022,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.MinusCore(divisor.ToDouble(), len, destination);
|
units.MinusCore(subtrahend.ToDouble(), len, destination);
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this T dividend, ReadOnlySpan<double> units, Span<T> destination)
|
internal static void Minus<T>(this T minuend, ReadOnlySpan<double> units, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units.IsEmpty) return;
|
if (units.IsEmpty) return;
|
||||||
@@ -1046,9 +1032,9 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
dividend.ToDouble().MinusCore(units, len, destination);
|
minuend.ToDouble().MinusCore(units, len, destination);
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this T dividend, ReadOnlySpan<double?> units, Span<T?> destination)
|
internal static void Minus<T>(this T minuend, ReadOnlySpan<double?> units, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units.IsEmpty) return;
|
if (units.IsEmpty) return;
|
||||||
@@ -1056,11 +1042,11 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
dividend.ToDouble().MinusCore(units, len, destination);
|
minuend.ToDouble().MinusCore(units, len, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Array ===
|
// === Array ===
|
||||||
internal static T[] Minus<T>(this double[] units, T divisor)
|
internal static T[] Minus<T>(this double[] units, T subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
@@ -1068,10 +1054,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Minus(units, divisor, result);
|
units.MinusCore(subtrahend.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Minus<T>(this double?[] units, T divisor)
|
internal static T?[] Minus<T>(this double?[] units, T subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
@@ -1079,10 +1065,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Minus(units, divisor, result);
|
units.MinusCore(subtrahend.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T[] Minus<T>(this T dividend, double[] units)
|
internal static T[] Minus<T>(this T minuend, double[] units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
@@ -1090,10 +1076,10 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Minus(dividend, units, result);
|
minuend.ToDouble().MinusCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Minus<T>(this T dividend, double?[] units)
|
internal static T?[] Minus<T>(this T minuend, double?[] units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
@@ -1101,58 +1087,58 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Minus(dividend, units, result);
|
minuend.ToDouble().MinusCore(units, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// === List<T> ===
|
// === List<T> ===
|
||||||
internal static List<T> Minus<T>(this List<double> units, T divisor)
|
internal static List<T> Minus<T>(this List<double> units, T subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
|
||||||
{
|
|
||||||
if (units is null) return null!;
|
|
||||||
int len = units.Count;
|
|
||||||
if (len == 0) return [];
|
|
||||||
|
|
||||||
var resultArray = new T[len];
|
|
||||||
Minus(CollectionsMarshal.AsSpan(units), divisor, resultArray);
|
|
||||||
return resultArray.WrapAsList<T, T>();
|
|
||||||
}
|
|
||||||
internal static List<T?> Minus<T>(this List<double?> units, T divisor)
|
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T[count];
|
||||||
Minus(CollectionsMarshal.AsSpan(units), divisor, resultArray);
|
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T> Minus<T>(this T dividend, List<double> units)
|
internal static List<T?> Minus<T>(this List<double?> units, T subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[count];
|
var result = new T?[count];
|
||||||
Minus(dividend, CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).MinusCore(subtrahend.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Minus<T>(this T dividend, List<double?> units)
|
internal static List<T> Minus<T>(this T minuend, List<double> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T[count];
|
||||||
Minus(dividend, CollectionsMarshal.AsSpan(units), resultArray);
|
minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
|
}
|
||||||
|
internal static List<T?> Minus<T>(this T minuend, List<double?> units)
|
||||||
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
|
{
|
||||||
|
if (units is null) return null!;
|
||||||
|
int count = units.Count;
|
||||||
|
if (count == 0) return [];
|
||||||
|
|
||||||
|
var result = new T?[count];
|
||||||
|
minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(units), count, result);
|
||||||
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<T> ===
|
// === IReadOnlyCollection<T> ===
|
||||||
internal static void Minus<T>(this IReadOnlyCollection<double> units, T divisor, Span<T> destination)
|
internal static void Minus<T>(this IReadOnlyCollection<double> units, T subtrahend, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return;
|
if (units is null) return;
|
||||||
@@ -1161,15 +1147,15 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is double[] array) { array.Minus(divisor, destination); return; }
|
if (units is double[] array) { array.MinusCore(subtrahend.ToDouble(), count, destination); return; }
|
||||||
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).Minus(divisor, destination); return; }
|
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend.ToDouble(), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
double invMinusisor = 1.0 / divisor.ToDouble();
|
double invMinusisor = 1.0 / subtrahend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = (item * invMinusisor).ToUnit<T>();
|
destination[i++] = (item * invMinusisor).ToUnit<T>();
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this IReadOnlyCollection<double?> units, T divisor, Span<T?> destination)
|
internal static void Minus<T>(this IReadOnlyCollection<double?> units, T subtrahend, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return;
|
if (units is null) return;
|
||||||
@@ -1178,16 +1164,15 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is double?[] array) { array.Minus(divisor, destination); return; }
|
if (units is double?[] array) { array.MinusCore(subtrahend.ToDouble(), count, destination); return; }
|
||||||
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).Minus(divisor, destination); return; }
|
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MinusCore(subtrahend.ToDouble(), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
double invMinusisor = 1.0 / divisor.ToDouble();
|
double invMinusisor = 1.0 / subtrahend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = ((item ?? 0d) * invMinusisor).ToUnit<T>();
|
||||||
? (item.Value * invMinusisor).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this T dividend, IReadOnlyCollection<double> units, Span<T> destination)
|
internal static void Minus<T>(this T minuend, IReadOnlyCollection<double> units, Span<T> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return;
|
if (units is null) return;
|
||||||
@@ -1196,14 +1181,15 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is double[] array) { dividend.Minus(array, destination); return; }
|
if (units is double[] array) { minuend.ToDouble().MinusCore(array, count, destination); return; }
|
||||||
if (units is List<double> list) { dividend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
|
if (units is List<double> list) { minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var div = minuend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = (dividend.ToDouble() / item).ToUnit<T>();
|
destination[i++] = (div / item).ToUnit<T>();
|
||||||
}
|
}
|
||||||
internal static void Minus<T>(this T dividend, IReadOnlyCollection<double?> units, Span<T?> destination)
|
internal static void Minus<T>(this T minuend, IReadOnlyCollection<double?> units, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return;
|
if (units is null) return;
|
||||||
@@ -1212,100 +1198,98 @@ internal static partial class CollectionsMinusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is double?[] array) { dividend.Minus(array, destination); return; }
|
if (units is double?[] array) { minuend.ToDouble().MinusCore(array, count, destination); return; }
|
||||||
if (units is List<double?> list) { dividend.Minus(CollectionsMarshal.AsSpan(list), destination); return; }
|
if (units is List<double?> list) { minuend.ToDouble().MinusCore(CollectionsMarshal.AsSpan(list), count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var div = minuend.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (div / (item ?? 0d)).ToUnit<T>();
|
||||||
? (dividend.ToDouble() / item.Value).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> + yeild ===
|
// === IEnumerable<T> + yeild ===
|
||||||
static IEnumerable<T> MinusideIterator<T>(IEnumerable<double> units, double divisor)
|
static IEnumerable<T> MinusideIterator<T>(IEnumerable<double> units, double subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
double invMinusisor = 1.0 / divisor;
|
double invMinusisor = 1.0 / subtrahend;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return (item * invMinusisor).ToUnit<T>();
|
yield return (item * invMinusisor).ToUnit<T>();
|
||||||
}
|
}
|
||||||
static IEnumerable<T?> MinusideNullableIterator<T>(IEnumerable<double?> units, double divisor)
|
static IEnumerable<T?> MinusideNullableIterator<T>(IEnumerable<double?> units, double subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
double invMinusisor = 1.0 / divisor;
|
double invMinusisor = 1.0 / subtrahend;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return ((item ?? 0d) * invMinusisor).ToUnit<T>();
|
||||||
? (item.Value * invMinusisor).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
static IEnumerable<T> MinusideIterator<T>(double dividend, IEnumerable<double> units)
|
static IEnumerable<T> MinusideIterator<T>(double minuend, IEnumerable<double> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return (dividend / item).ToUnit<T>();
|
yield return (minuend / item).ToUnit<T>();
|
||||||
}
|
}
|
||||||
static IEnumerable<T?> MinusideNullableIterator<T>(double dividend, IEnumerable<double?> units)
|
static IEnumerable<T?> MinusideNullableIterator<T>(double minuend, IEnumerable<double?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return (minuend / (item ?? 0d)).ToUnit<T>();
|
||||||
? (dividend / item.Value).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
internal static IEnumerable<T> Minus<T>(this IEnumerable<double> units, T divisor)
|
internal static IEnumerable<T> Minus<T>(this IEnumerable<double> units, T subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
if (units is double[] array) return array.Minus(divisor);
|
if (units is double[] array) return array.Minus(subtrahend);
|
||||||
if (units is List<double> list) return list.Minus(divisor);
|
if (units is List<double> list) return list.Minus(subtrahend);
|
||||||
if (units is IReadOnlyCollection<double> roc)
|
if (units is IReadOnlyCollection<double> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.MinusCore(divisor.ToDouble(), arr.Length, arr);
|
arr.MinusCore(subtrahend.ToDouble(), arr.Length, arr);
|
||||||
return arr.ReCast<T>();
|
return arr.ReCast<T>();
|
||||||
}
|
}
|
||||||
return MinusideIterator<T>(units, divisor.ToDouble());
|
return MinusideIterator<T>(units, subtrahend.ToDouble());
|
||||||
}
|
}
|
||||||
internal static IEnumerable<T?> Minus<T>(this IEnumerable<double?> units, T divisor)
|
internal static IEnumerable<T?> Minus<T>(this IEnumerable<double?> units, T subtrahend)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
if (units is double?[] array) return array.Minus(divisor);
|
if (units is double?[] array) return array.Minus(subtrahend);
|
||||||
if (units is List<double?> list) return list.Minus(divisor);
|
if (units is List<double?> list) return list.Minus(subtrahend);
|
||||||
if (units is IReadOnlyCollection<double?> roc)
|
if (units is IReadOnlyCollection<double?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.MinusCore(divisor.ToDouble(), arr.Length, arr);
|
arr.MinusCore(subtrahend.ToDouble(), arr.Length, arr);
|
||||||
return arr.ReCast<T>();
|
return arr.ReCast<T>();
|
||||||
}
|
}
|
||||||
return MinusideNullableIterator<T>(units, divisor.ToDouble());
|
return MinusideNullableIterator<T>(units, subtrahend.ToDouble());
|
||||||
}
|
}
|
||||||
internal static IEnumerable<T> Minus<T>(this T dividend, IEnumerable<double> units)
|
internal static IEnumerable<T> Minus<T>(this T minuend, IEnumerable<double> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
if (units is double[] array) return dividend.Minus(array);
|
if (units is double[] array) return minuend.Minus(array);
|
||||||
if (units is List<double> list) return dividend.Minus(list);
|
if (units is List<double> list) return minuend.Minus(list);
|
||||||
if (units is IReadOnlyCollection<double> roc)
|
if (units is IReadOnlyCollection<double> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.ToDouble().MinusCore(arr, arr.Length, arr);
|
minuend.ToDouble().MinusCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast<T>();
|
return arr.ReCast<T>();
|
||||||
}
|
}
|
||||||
return MinusideIterator<T>(dividend.ToDouble(), units);
|
return MinusideIterator<T>(minuend.ToDouble(), units);
|
||||||
}
|
}
|
||||||
internal static IEnumerable<T?> Minus<T>(this T dividend, IEnumerable<double?> units)
|
internal static IEnumerable<T?> Minus<T>(this T minuend, IEnumerable<double?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
if (units is double?[] array) return dividend.Minus(array);
|
if (units is double?[] array) return minuend.Minus(array);
|
||||||
if (units is List<double?> list) return dividend.Minus(list);
|
if (units is List<double?> list) return minuend.Minus(list);
|
||||||
if (units is IReadOnlyCollection<double?> roc)
|
if (units is IReadOnlyCollection<double?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
dividend.ToDouble().MinusCore(arr, arr.Length, arr);
|
minuend.ToDouble().MinusCore(arr, arr.Length, arr);
|
||||||
return arr.ReCast<T>();
|
return arr.ReCast<T>();
|
||||||
}
|
}
|
||||||
return MinusideNullableIterator<T>(dividend.ToDouble(), units);
|
return MinusideNullableIterator<T>(minuend.ToDouble(), units);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
internal static partial class CollectionsMultiplyExtensions
|
internal static partial class CollectionsMultiplyExtensions
|
||||||
{
|
{
|
||||||
// === MultiplyCore === SIMD
|
// === MulCore === SIMD
|
||||||
internal static void MultiplyCore<T, R>(this ReadOnlySpan<T> units, double multiplicator, int len, Span<R> destination)
|
internal static void MulCore<T, R>(this ReadOnlySpan<T> units, double multiplicator, int len, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
|
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void MultiplyCore<T, R>(this ReadOnlySpan<T?> units, double multiplicator, int len, Span<R?> destination)
|
internal static void MulCore<T, R>(this ReadOnlySpan<T?> units, double multiplicator, int len, Span<R?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -61,10 +61,10 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
d0 = (u0.Protected() * multiplicator).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
d1 = (u1.Protected() * multiplicator).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
d2 = (u2.Protected() * multiplicator).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
d3 = (u3.Protected() * multiplicator).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -72,20 +72,19 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
{
|
{
|
||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit.Protected() * multiplicator).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (unit.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static void MultiplyCore<T, R>(this double multiplicator, ReadOnlySpan<T> units, int len, Span<R> destination)
|
internal static void MulCore<T, R>(this double multiplicator, ReadOnlySpan<T> units, int len, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
|
where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static void MultiplyCore<T, R>(this double multiplicator, ReadOnlySpan<T?> units, int len, Span<R?> destination)
|
internal static void MulCore<T, R>(this double multiplicator, ReadOnlySpan<T?> units, int len, Span<R?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
|
where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -100,7 +99,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
units.MultiplyCore(multiplicator, len, result);
|
units.MulCore(multiplicator, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Mul<T, R>(this T?[] units, double multiplicator)
|
internal static R?[] Mul<T, R>(this T?[] units, double multiplicator)
|
||||||
@@ -112,7 +111,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
units.MultiplyCore(multiplicator, len, result);
|
units.MulCore(multiplicator, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,9 +134,9 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
MultiplyCore(CollectionsMarshal.AsSpan(units), multiplicator, count, resultArray);
|
MulCore(CollectionsMarshal.AsSpan(units), multiplicator, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Mul<T, R>(this List<T?> units, double multiplicator)
|
internal static List<R?> Mul<T, R>(this List<T?> units, double multiplicator)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -147,9 +146,9 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
MultiplyCore(CollectionsMarshal.AsSpan(units), multiplicator, count, resultArray);
|
MulCore(CollectionsMarshal.AsSpan(units), multiplicator, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -173,8 +172,8 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { MultiplyCore(array, multiplicator, count, destination); return; }
|
if (units is T[] array) { MulCore(array, multiplicator, count, destination); return; }
|
||||||
if (units is List<T> list) { MultiplyCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
|
if (units is List<T> list) { MulCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -190,13 +189,12 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { MultiplyCore(array, multiplicator, count, destination); return; }
|
if (units is T?[] array) { MulCore(array, multiplicator, count, destination); return; }
|
||||||
if (units is List<T?> list) { MultiplyCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
|
if (units is List<T?> list) { MulCore(CollectionsMarshal.AsSpan(list), multiplicator, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() * multiplicator).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -222,8 +220,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() * multiplicator).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() * multiplicator).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -237,7 +234,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Mul(multiplicator, arr);
|
arr.MulCore(multiplicator, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return MultiplyIterator<T, R>(units, multiplicator);
|
return MultiplyIterator<T, R>(units, multiplicator);
|
||||||
@@ -252,7 +249,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Mul(multiplicator, arr);
|
arr.MulCore(multiplicator, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return MultiplyNullableIterator<T, R>(units, multiplicator);
|
return MultiplyNullableIterator<T, R>(units, multiplicator);
|
||||||
@@ -280,7 +277,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.MultiplyCore(multiplicator, len, destination);
|
units.MulCore(multiplicator, len, destination);
|
||||||
}
|
}
|
||||||
internal static void Mul<T>(this ReadOnlySpan<T?> units, double multiplicator, Span<T?> destination)
|
internal static void Mul<T>(this ReadOnlySpan<T?> units, double multiplicator, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -290,7 +287,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.MultiplyCore(multiplicator, len, destination);
|
units.MulCore(multiplicator, len, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -310,7 +307,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Mul(units, multiplicator, result);
|
units.MulCore(multiplicator, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Mul<T>(this T?[] units, double multiplicator)
|
internal static T?[] Mul<T>(this T?[] units, double multiplicator)
|
||||||
@@ -321,7 +318,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Mul(units, multiplicator, result);
|
units.MulCore(multiplicator, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,12 +335,12 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
|
CollectionsMarshal.AsSpan(units).MulCore(multiplicator, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Mul<T>(this List<T?> units, double multiplicator)
|
internal static List<T?> Mul<T>(this List<T?> units, double multiplicator)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -352,9 +349,9 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
|
CollectionsMarshal.AsSpan(units).MulCore(multiplicator, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -375,8 +372,8 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Mul(multiplicator, destination); return; }
|
if (units is T[] array) { array.MulCore(multiplicator, array.Length, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Mul(multiplicator, destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator, list.Count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -391,13 +388,12 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Mul(multiplicator, destination); return; }
|
if (units is T?[] array) { array.MulCore(multiplicator, array.Length, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Mul(multiplicator, destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator, list.Count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() * multiplicator).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() * multiplicator).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -419,8 +415,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() * multiplicator).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() * multiplicator).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -433,7 +428,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Mul(multiplicator, arr);
|
arr.MulCore(multiplicator, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return MultiplyIterator(units, multiplicator);
|
return MultiplyIterator(units, multiplicator);
|
||||||
@@ -447,7 +442,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Mul(multiplicator, arr);
|
arr.MulCore(multiplicator, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return MultiplyNullableIterator(units, multiplicator);
|
return MultiplyNullableIterator(units, multiplicator);
|
||||||
@@ -469,8 +464,8 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// === MultiplyCore === SIMD
|
// === MulCore === SIMD
|
||||||
internal static void MultiplyCore<R>(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<R> destination)
|
internal static void MulCore<R>(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<R> destination)
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
Span<double> dstDouble = MemoryMarshal.Cast<R, double>(destination);
|
Span<double> dstDouble = MemoryMarshal.Cast<R, double>(destination);
|
||||||
@@ -500,7 +495,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
|
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void MultiplyCore<R>(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<R?> destination)
|
internal static void MulCore<R>(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<R?> destination)
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
||||||
@@ -525,10 +520,10 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value * multiplicator).ToUnit<R>() : null;
|
d0 = ((u0 ?? 0d) * multiplicator).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value * multiplicator).ToUnit<R>() : null;
|
d1 = ((u1 ?? 0d) * multiplicator).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value * multiplicator).ToUnit<R>() : null;
|
d2 = ((u2 ?? 0d) * multiplicator).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value * multiplicator).ToUnit<R>() : null;
|
d3 = ((u3 ?? 0d) * multiplicator).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -537,18 +532,18 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
|
||||||
dst = unit.HasValue ? (unit.Value * multiplicator).ToUnit<R>() : null;
|
dst = ((unit ?? 0d) * multiplicator).ToUnit<R>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore<R>(this double multiplicator, ReadOnlySpan<double> units,
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore<R>(this double multiplicator, ReadOnlySpan<double> units,
|
||||||
int len, Span<R> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
|
int len, Span<R> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore<R>(this double multiplicator, ReadOnlySpan<double?> units,
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore<R>(this double multiplicator, ReadOnlySpan<double?> units,
|
||||||
int len, Span<R?> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MultiplyCore(multiplicator, len, destination);
|
int len, Span<R?> destination) where R : struct, IMensuraUnit, IEquatable<R> => units.MulCore(multiplicator, len, destination);
|
||||||
|
|
||||||
|
|
||||||
// === MultiplyCore === SIMD
|
// === MulCore === SIMD
|
||||||
internal static void MultiplyCore(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<double> dstDouble)
|
internal static void MulCore(this ReadOnlySpan<double> srcDouble, double multiplicator, int len, Span<double> dstDouble)
|
||||||
{
|
{
|
||||||
var vectorizedMultiplicator = new Vector<double>(multiplicator);
|
var vectorizedMultiplicator = new Vector<double>(multiplicator);
|
||||||
int vectorSize = Vector<double>.Count;
|
int vectorSize = Vector<double>.Count;
|
||||||
@@ -575,7 +570,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
|
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i) * multiplicator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void MultiplyCore(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<double?> destination)
|
internal static void MulCore(this ReadOnlySpan<double?> units, double multiplicator, int len, Span<double?> destination)
|
||||||
{
|
{
|
||||||
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
// Получаем прямые неуправляемые ref-ссылки на начало буферов за 0 тактов
|
||||||
ref var srcRef = ref MemoryMarshal.GetReference(units);
|
ref var srcRef = ref MemoryMarshal.GetReference(units);
|
||||||
@@ -599,10 +594,10 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? u0.Value * multiplicator : null;
|
d0 = (u0 ?? 0d) * multiplicator;
|
||||||
d1 = u1.HasValue ? u1.Value * multiplicator : null;
|
d1 = (u1 ?? 0d) * multiplicator;
|
||||||
d2 = u2.HasValue ? u2.Value * multiplicator : null;
|
d2 = (u2 ?? 0d) * multiplicator;
|
||||||
d3 = u3.HasValue ? u3.Value * multiplicator : null;
|
d3 = (u3 ?? 0d) * multiplicator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -610,15 +605,14 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit ?? 0d) * multiplicator;
|
||||||
dst = unit.HasValue ? unit.Value * multiplicator : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore(this double multiplicator,
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore(this double multiplicator,
|
||||||
ReadOnlySpan<double> units, int len, Span<double> destination) => units.MultiplyCore(multiplicator, len, destination);
|
ReadOnlySpan<double> units, int len, Span<double> destination) => units.MulCore(multiplicator, len, destination);
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MultiplyCore(this double multiplicator,
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void MulCore(this double multiplicator,
|
||||||
ReadOnlySpan<double?> units, int len, Span<double?> destination) => units.MultiplyCore(multiplicator, len, destination);
|
ReadOnlySpan<double?> units, int len, Span<double?> destination) => units.MulCore(multiplicator, len, destination);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -633,7 +627,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.MultiplyCore(multiplicator.ToDouble(), len, destination);
|
units.MulCore(multiplicator.ToDouble(), len, destination);
|
||||||
}
|
}
|
||||||
internal static void Mul<T>(this ReadOnlySpan<double?> units, T multiplicator, Span<T?> destination)
|
internal static void Mul<T>(this ReadOnlySpan<double?> units, T multiplicator, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -643,7 +637,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.MultiplyCore(multiplicator.ToDouble(), len, destination);
|
units.MulCore(multiplicator.ToDouble(), len, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -663,7 +657,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Mul(units, multiplicator, result);
|
units.MulCore(multiplicator.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Mul<T>(this double?[] units, T multiplicator)
|
internal static T?[] Mul<T>(this double?[] units, T multiplicator)
|
||||||
@@ -674,7 +668,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Mul(units, multiplicator, result);
|
units.MulCore(multiplicator.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,12 +685,12 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
|
CollectionsMarshal.AsSpan(units).MulCore(multiplicator.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Mul<T>(this List<double?> units, T multiplicator)
|
internal static List<T?> Mul<T>(this List<double?> units, T multiplicator)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -705,9 +699,9 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Mul(CollectionsMarshal.AsSpan(units), multiplicator, resultArray);
|
CollectionsMarshal.AsSpan(units).MulCore(multiplicator.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -728,12 +722,13 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is double[] array) { array.MultiplyCore(multiplicator.ToDouble(), array.Length, destination); return; }
|
if (units is double[] array) { array.MulCore(multiplicator.ToDouble(), array.Length, destination); return; }
|
||||||
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MultiplyCore(multiplicator.ToDouble(), list.Count, destination); return; }
|
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator.ToDouble(), list.Count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var mul = multiplicator.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = (item * multiplicator.ToDouble()).ToUnit<T>();
|
destination[i++] = (item * mul).ToUnit<T>();
|
||||||
}
|
}
|
||||||
internal static void Mul<T>(this IReadOnlyCollection<double?> units, T multiplicator, Span<T?> destination)
|
internal static void Mul<T>(this IReadOnlyCollection<double?> units, T multiplicator, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -744,13 +739,13 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is double?[] array) { array.MultiplyCore(multiplicator.ToDouble(), array.Length, destination); return; }
|
if (units is double?[] array) { array.MulCore(multiplicator.ToDouble(), array.Length, destination); return; }
|
||||||
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MultiplyCore(multiplicator.ToDouble(), list.Count, destination); return; }
|
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).MulCore(multiplicator.ToDouble(), list.Count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var mul = multiplicator.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = ((item ?? 0d) * mul).ToUnit<T>();
|
||||||
? (item.Value * multiplicator.ToDouble()).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -772,8 +767,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return ((item ?? 0d) * multiplicator).ToUnit<T>();
|
||||||
? (item.Value * multiplicator).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -786,7 +780,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (units is IReadOnlyCollection<double> roc)
|
if (units is IReadOnlyCollection<double> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.MultiplyCore(multiplicator.ToDouble(), arr.Length, arr);
|
arr.MulCore(multiplicator.ToDouble(), arr.Length, arr);
|
||||||
return arr.ReCast<T>();
|
return arr.ReCast<T>();
|
||||||
}
|
}
|
||||||
return MultiplyIterator<T>(units, multiplicator.ToDouble());
|
return MultiplyIterator<T>(units, multiplicator.ToDouble());
|
||||||
@@ -800,7 +794,7 @@ internal static partial class CollectionsMultiplyExtensions
|
|||||||
if (units is IReadOnlyCollection<double?> roc)
|
if (units is IReadOnlyCollection<double?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.MultiplyCore(multiplicator.ToDouble(), arr.Length, arr);
|
arr.MulCore(multiplicator.ToDouble(), arr.Length, arr);
|
||||||
return arr.ReCast<T>();
|
return arr.ReCast<T>();
|
||||||
}
|
}
|
||||||
return MultiplyNullableIterator<T>(units, multiplicator.ToDouble());
|
return MultiplyNullableIterator<T>(units, multiplicator.ToDouble());
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value.ToDouble() + summand).ToUnit<R>() : null;
|
d0 = (u0.Protected() + summand).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value.ToDouble() + summand).ToUnit<R>() : null;
|
d1 = (u1.Protected() + summand).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value.ToDouble() + summand).ToUnit<R>() : null;
|
d2 = (u2.Protected() + summand).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value.ToDouble() + summand).ToUnit<R>() : null;
|
d3 = (u3.Protected() + summand).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -73,8 +73,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
{
|
{
|
||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit.Protected() + summand).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (unit.Value.ToDouble() + summand).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,9 +135,9 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, resultArray);
|
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Plus<T, R>(this List<T?> units, double summand)
|
internal static List<R?> Plus<T, R>(this List<T?> units, double summand)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -148,9 +147,9 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, resultArray);
|
PlusCore(CollectionsMarshal.AsSpan(units), summand, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -196,8 +195,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() + summand).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() + summand).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -223,8 +221,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() + summand).ToUnit<R>();
|
||||||
? (item.Value.ToDouble() + summand).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -238,7 +235,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Plus(summand, arr);
|
arr.PlusCore(summand, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return PlusIterator<T, R>(units, summand);
|
return PlusIterator<T, R>(units, summand);
|
||||||
@@ -253,7 +250,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Plus(summand, arr);
|
arr.PlusCore(summand, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
return PlusNullableIterator<T, R>(units, summand);
|
return PlusNullableIterator<T, R>(units, summand);
|
||||||
@@ -311,7 +308,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Plus(units, summand, result);
|
units.PlusCore(summand, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Plus<T>(this T?[] units, double summand)
|
internal static T?[] Plus<T>(this T?[] units, double summand)
|
||||||
@@ -322,7 +319,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Plus(units, summand, result);
|
PlusCore(units, summand, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,12 +336,12 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
|
CollectionsMarshal.AsSpan(units).PlusCore(summand, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Plus<T>(this List<T?> units, double summand)
|
internal static List<T?> Plus<T>(this List<T?> units, double summand)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -353,9 +350,9 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
|
CollectionsMarshal.AsSpan(units).PlusCore(summand, count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -376,8 +373,8 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Plus(summand, destination); return; }
|
if (units is T[] array) { array.PlusCore(summand, count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Plus(summand, destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -392,13 +389,12 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Plus(summand, destination); return; }
|
if (units is T?[] array) { array.PlusCore(summand, count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Plus(summand, destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = (item.Protected() + summand).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() + summand).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -420,8 +416,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
yield return item.HasValue
|
yield return (item.Protected() + summand).ToUnit<T>();
|
||||||
? (item.Value.ToDouble() + summand).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
@@ -434,7 +429,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Plus(summand, arr);
|
arr.PlusCore(summand, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return PlusIterator(units, summand);
|
return PlusIterator(units, summand);
|
||||||
@@ -448,7 +443,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Plus(summand, arr);
|
arr.PlusCore(summand, arr.Length, arr);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
return PlusNullableIterator(units, summand);
|
return PlusNullableIterator(units, summand);
|
||||||
@@ -526,10 +521,10 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? (u0.Value + summand).ToUnit<R>() : null;
|
d0 = ((u0 ?? 0d) + summand).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? (u1.Value + summand).ToUnit<R>() : null;
|
d1 = ((u1 ?? 0d) + summand).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? (u2.Value + summand).ToUnit<R>() : null;
|
d2 = ((u2 ?? 0d) + summand).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? (u3.Value + summand).ToUnit<R>() : null;
|
d3 = ((u3 ?? 0d) + summand).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -537,8 +532,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = ((unit ?? 0d) + summand).ToUnit<R>();
|
||||||
dst = unit.HasValue ? (unit.Value + summand).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,10 +596,10 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
// Пишем строго по месту. Если HasValue == false, в ячейку dX запишется null (сбросятся байты флага)
|
||||||
d0 = u0.HasValue ? u0.Value + summand : null;
|
d0 = (u0 ?? 0d) + summand;
|
||||||
d1 = u1.HasValue ? u1.Value + summand : null;
|
d1 = (u1 ?? 0d) + summand;
|
||||||
d2 = u2.HasValue ? u2.Value + summand : null;
|
d2 = (u2 ?? 0d) + summand;
|
||||||
d3 = u3.HasValue ? u3.Value + summand : null;
|
d3 = (u3 ?? 0d) + summand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 штук)
|
||||||
@@ -613,8 +607,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
{
|
{
|
||||||
var unit = Unsafe.Add(ref srcRef, i);
|
var unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
dst = (unit ?? 0d) + summand;
|
||||||
dst = unit.HasValue ? unit.Value + summand : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,7 +661,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T[len];
|
var result = new T[len];
|
||||||
Plus(units, summand, result);
|
units.PlusCore(summand.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static T?[] Plus<T>(this double?[] units, T summand)
|
internal static T?[] Plus<T>(this double?[] units, T summand)
|
||||||
@@ -679,7 +672,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new T?[len];
|
var result = new T?[len];
|
||||||
Plus(units, summand, result);
|
units.PlusCore(summand.ToDouble(), len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,12 +689,12 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T[len];
|
var result = new T[count];
|
||||||
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
|
CollectionsMarshal.AsSpan(units).PlusCore(summand.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
internal static List<T?> Plus<T>(this List<double?> units, T summand)
|
internal static List<T?> Plus<T>(this List<double?> units, T summand)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -710,9 +703,9 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new T?[count];
|
var result = new T?[count];
|
||||||
Plus(CollectionsMarshal.AsSpan(units), summand, resultArray);
|
CollectionsMarshal.AsSpan(units).PlusCore(summand.ToDouble(), count, result);
|
||||||
return resultArray.WrapAsList<T, T>();
|
return result.WrapAsList<T, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -737,8 +730,9 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
|
if (units is List<double> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var sum = summand.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = (item + summand.ToDouble()).ToUnit<T>();
|
destination[i++] = (item + sum).ToUnit<T>();
|
||||||
}
|
}
|
||||||
internal static void Plus<T>(this IReadOnlyCollection<double?> units, T summand, Span<T?> destination)
|
internal static void Plus<T>(this IReadOnlyCollection<double?> units, T summand, Span<T?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -753,9 +747,9 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
|
if (units is List<double?> list) { CollectionsMarshal.AsSpan(list).PlusCore(summand.ToDouble(), list.Count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
var sum = summand.ToDouble();
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = ((item ?? 0d) + sum).ToUnit<T>();
|
||||||
? (item.Value + summand.ToDouble()).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -777,8 +771,7 @@ internal static partial class CollectionsPlusExtensions
|
|||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return ((item ?? 0d) + summand).ToUnit<T>();
|
||||||
? (item.Value + summand).ToUnit<T>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T> ===
|
// === IEnumerable<T> ===
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
Pow2(units, result);
|
units.Pow2Core(len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Pow2<T, R>(this T?[] units)
|
internal static R?[] Pow2<T, R>(this T?[] units)
|
||||||
@@ -142,7 +142,7 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
Pow2(units, result);
|
units.Pow2Core(len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,9 +155,9 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
Pow2(CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).Pow2Core(count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Pow2<T, R>(this List<T?> units)
|
internal static List<R?> Pow2<T, R>(this List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -167,9 +167,9 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
Pow2(CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).Pow2Core(count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<Length> ===
|
// === IReadOnlyCollection<Length> ===
|
||||||
@@ -183,8 +183,8 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Pow2(destination); return; }
|
if (units is T[] array) { array.Pow2Core(count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow2(destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow2Core(count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -200,13 +200,12 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Pow2(destination); return; }
|
if (units is T?[] array) { array.Pow2Core(count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow2(destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow2Core(count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = item.Protected().QuickPow2().ToUnit<R>();
|
||||||
? item.Value.ToDouble().QuickPow2().ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T, R> + yeild ===
|
// === IEnumerable<T, R> + yeild ===
|
||||||
@@ -222,8 +221,7 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return item.Protected().QuickPow2().ToUnit<R>();
|
||||||
? item.Value.ToDouble().QuickPow2().ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<Length> ===
|
// === IEnumerable<Length> ===
|
||||||
@@ -237,7 +235,7 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow2(arr);
|
arr.Pow2Core(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return Pow2Iterator<T, R>(units);
|
else return Pow2Iterator<T, R>(units);
|
||||||
@@ -252,7 +250,7 @@ internal static partial class CollectionsPow2Extensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow2(arr);
|
arr.Pow2Core(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return Pow2NullableIterator<T, R>(units);
|
else return Pow2NullableIterator<T, R>(units);
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using System.Runtime.Intrinsics;
|
namespace QWERTYkez.Mensura.Extensions;
|
||||||
using System.Runtime.Intrinsics.X86;
|
|
||||||
|
|
||||||
namespace QWERTYkez.Mensura.Extensions;
|
|
||||||
|
|
||||||
internal static partial class CollectionsPow3Extensions
|
internal static partial class CollectionsPow3Extensions
|
||||||
{
|
{
|
||||||
@@ -10,8 +7,8 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
|
|
||||||
// === ТРЕТЬЯ СТЕПЕНЬ ==========================================
|
// === ТРЕТЬЯ СТЕПЕНЬ ==========================================
|
||||||
|
|
||||||
// === PowCore3 === SIMD
|
// === Pow3Core === SIMD
|
||||||
internal static void PowCore3<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
|
internal static void Pow3Core<T, R>(this ReadOnlySpan<T> units, int len, Span<R> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -46,7 +43,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
dstDouble[i] = val * val * val;
|
dstDouble[i] = val * val * val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal static void PowCore3<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
|
internal static void Pow3Core<T, R>(this ReadOnlySpan<T?> units, int len, Span<R?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
@@ -109,7 +106,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.PowCore3(len, destination);
|
units.Pow3Core(len, destination);
|
||||||
}
|
}
|
||||||
internal static void Pow3<T, R>(this ReadOnlySpan<T?> units, Span<R?> destination)
|
internal static void Pow3<T, R>(this ReadOnlySpan<T?> units, Span<R?> destination)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -120,7 +117,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (len > destination.Length)
|
if (len > destination.Length)
|
||||||
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
throw new ArgumentException("Целевой буфер destination меньше исходного source.");
|
||||||
|
|
||||||
units.PowCore3(len, destination);
|
units.Pow3Core(len, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Array ===
|
// === Array ===
|
||||||
@@ -133,7 +130,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
Pow3(units, result);
|
units.Pow3Core(len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Pow3<T, R>(this T?[] units)
|
internal static R?[] Pow3<T, R>(this T?[] units)
|
||||||
@@ -145,7 +142,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
Pow3(units, result);
|
units.Pow3Core(len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,9 +155,9 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
Pow3(CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).Pow3Core(count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Pow3<T, R>(this List<T?> units)
|
internal static List<R?> Pow3<T, R>(this List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -170,9 +167,9 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
Pow3(CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).Pow3Core(count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<Length> ===
|
// === IReadOnlyCollection<Length> ===
|
||||||
@@ -186,8 +183,8 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Pow3(destination); return; }
|
if (units is T[] array) { array.Pow3Core(count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow3(destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow3Core(count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -203,13 +200,12 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Pow3(destination); return; }
|
if (units is T?[] array) { array.Pow3Core(count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow3(destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow3Core(count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = item.Protected().QuickPow3().ToUnit<R>();
|
||||||
? item.Value.ToDouble().QuickPow3().ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T, R> + yeild ===
|
// === IEnumerable<T, R> + yeild ===
|
||||||
@@ -225,8 +221,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return item.Protected().QuickPow3().ToUnit<R>();
|
||||||
? item.Value.ToDouble().QuickPow3().ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<Length> ===
|
// === IEnumerable<Length> ===
|
||||||
@@ -240,7 +235,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow3(arr);
|
arr.Pow3Core(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return PowIterator3<T, R>(units);
|
else return PowIterator3<T, R>(units);
|
||||||
@@ -255,7 +250,7 @@ internal static partial class CollectionsPow3Extensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow3(arr);
|
arr.Pow3Core(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return PowNullableIterator3<T, R>(units);
|
else return PowNullableIterator3<T, R>(units);
|
||||||
|
|||||||
@@ -129,10 +129,10 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
// Выполняем быструю бинарную математику и трансформируем тип из T в R по месту
|
// Выполняем быструю бинарную математику и трансформируем тип из T в R по месту
|
||||||
d0 = u0.HasValue ? u0.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
d0 = u0.Protected().QuickPow(power).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? u1.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
d1 = u1.Protected().QuickPow(power).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? u2.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
d2 = u2.Protected().QuickPow(power).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? u3.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
d3 = u3.Protected().QuickPow(power).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 шчку)
|
// 2. ХВОСТ ЦИКЛА: Довычисляем остаток элементов (от 1 до 3 шчку)
|
||||||
@@ -141,7 +141,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
T? unit = Unsafe.Add(ref srcRef, i);
|
T? unit = Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
|
|
||||||
dst = unit.HasValue ? unit.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
dst = unit.Protected().QuickPow(power).ToUnit<R>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
Pow(units, power, result);
|
units.PowCore(power, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Pow<T, R>(this T?[] units, int power)
|
internal static R?[] Pow<T, R>(this T?[] units, int power)
|
||||||
@@ -192,7 +192,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
Pow(units, power, result);
|
units.PowCore(power, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +205,9 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[count];
|
var result = new R[count];
|
||||||
Pow(CollectionsMarshal.AsSpan(units), power, resultArray);
|
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Pow<T, R>(this List<T?> units, int power)
|
internal static List<R?> Pow<T, R>(this List<T?> units, int power)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
@@ -217,9 +217,9 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
int count = units.Count;
|
int count = units.Count;
|
||||||
if (count == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[count];
|
var result = new R?[count];
|
||||||
Pow(CollectionsMarshal.AsSpan(units), power, resultArray);
|
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection<Length> ===
|
// === IReadOnlyCollection<Length> ===
|
||||||
@@ -233,8 +233,8 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Pow(power, destination); return; }
|
if (units is T[] array) { array.PowCore(power, count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
@@ -250,13 +250,12 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Pow(power, destination); return; }
|
if (units is T?[] array) { array.PowCore(power, count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = item.Protected().QuickPow(power).ToUnit<R>();
|
||||||
? item.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<T, R> + yeild ===
|
// === IEnumerable<T, R> + yeild ===
|
||||||
@@ -272,8 +271,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return item.Protected().QuickPow(power).ToUnit<R>();
|
||||||
? item.Value.ToDouble().QuickPow(power).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<Length> ===
|
// === IEnumerable<Length> ===
|
||||||
@@ -287,7 +285,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow(power, arr);
|
arr.PowCore(power, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return PowIterator<T, R>(units, power);
|
else return PowIterator<T, R>(units, power);
|
||||||
@@ -302,7 +300,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow(power, arr);
|
arr.PowCore(power, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return PowNullableIterator<T, R>(units, power);
|
else return PowNullableIterator<T, R>(units, power);
|
||||||
@@ -402,7 +400,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
{
|
{
|
||||||
// Прямая ref-запись в переданный снаружи destination
|
// Прямая ref-запись в переданный снаружи destination
|
||||||
ref var dst = ref destination[i];
|
ref var dst = ref destination[i];
|
||||||
dst = Math.Pow(item.Value.ToDouble(), power).ToUnit<R>();
|
dst = Math.Pow(item.Protected(), power).ToUnit<R>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,7 +441,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[len];
|
||||||
units.Pow(power, result);
|
units.PowCore(power, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Pow<T, R>(this T?[] units, double power)
|
internal static R?[] Pow<T, R>(this T?[] units, double power)
|
||||||
@@ -455,7 +453,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (len == 0) return [];
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[len];
|
||||||
units.Pow(power, result);
|
units.PowCore(power, len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,11 +463,11 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var result = new R[len];
|
var result = new R[count];
|
||||||
CollectionsMarshal.AsSpan(units).Pow(power, result);
|
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
|
||||||
return result.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Pow<T, R>(this List<T?> units, double power)
|
internal static List<R?> Pow<T, R>(this List<T?> units, double power)
|
||||||
@@ -477,11 +475,11 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var result = new R?[len];
|
var result = new R?[count];
|
||||||
CollectionsMarshal.AsSpan(units).Pow(power, result);
|
CollectionsMarshal.AsSpan(units).PowCore(power, count, result);
|
||||||
return result.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,8 +494,8 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T[] array) { array.Pow(power, destination); return; }
|
if (units is T[] array) { array.PowCore(power, count, destination); return; }
|
||||||
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
|
if (units is List<T> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (T item in units)
|
foreach (T item in units)
|
||||||
@@ -513,13 +511,12 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Pow(power, destination); return; }
|
if (units is T?[] array) { array.PowCore(power, count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Pow(power, destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).PowCore(power, count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = Math.Pow(item.Protected(), power).ToUnit<R>();
|
||||||
? Math.Pow(item.Value.ToDouble(), power).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<Length> + yield ===
|
// === IEnumerable<Length> + yield ===
|
||||||
@@ -535,8 +532,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return Math.Pow(item.Protected(), power).ToUnit<R>();
|
||||||
? Math.Pow(item.Value.ToDouble(), power).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable<Length> ===
|
// === IEnumerable<Length> ===
|
||||||
@@ -550,7 +546,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow(power, arr);
|
arr.PowCore(power, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return PowIterator<T, R>(units, power);
|
else return PowIterator<T, R>(units, power);
|
||||||
@@ -565,7 +561,7 @@ internal static partial class CollectionsPowNExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Pow(power, arr);
|
arr.PowCore(power, arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return PowNullableIterator<T, R>(units, power);
|
else return PowNullableIterator<T, R>(units, power);
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
|
|
||||||
for (; i < unrollEnd; i += 4)
|
for (; i < unrollEnd; i += 4)
|
||||||
{
|
{
|
||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Value.ToDouble()).ToUnit<R>() : null;
|
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Protected()).ToUnit<R>();
|
||||||
Unsafe.Add(ref dstRef, i + 1) = Unsafe.Add(ref srcRef, i + 1).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 1)!.Value.ToDouble()).ToUnit<R>() : null;
|
Unsafe.Add(ref dstRef, i + 1) = Math.Sqrt(Unsafe.Add(ref srcRef, i + 1)!.Protected()).ToUnit<R>();
|
||||||
Unsafe.Add(ref dstRef, i + 2) = Unsafe.Add(ref srcRef, i + 2).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 2)!.Value.ToDouble()).ToUnit<R>() : null;
|
Unsafe.Add(ref dstRef, i + 2) = Math.Sqrt(Unsafe.Add(ref srcRef, i + 2)!.Protected()).ToUnit<R>();
|
||||||
Unsafe.Add(ref dstRef, i + 3) = Unsafe.Add(ref srcRef, i + 3).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i + 3)!.Value.ToDouble()).ToUnit<R>() : null;
|
Unsafe.Add(ref dstRef, i + 3) = Math.Sqrt(Unsafe.Add(ref srcRef, i + 3)!.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
for (; i < len; i++)
|
for (; i < len; i++)
|
||||||
Unsafe.Add(ref dstRef, i) = Unsafe.Add(ref srcRef, i).HasValue ? Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Value.ToDouble()).ToUnit<R>() : null;
|
Unsafe.Add(ref dstRef, i) = Math.Sqrt(Unsafe.Add(ref srcRef, i)!.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === ReadOnlySpan ===
|
// === ReadOnlySpan ===
|
||||||
@@ -85,10 +85,11 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
if (units.Length == 0) return [];
|
var len = units.Length;
|
||||||
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R[units.Length];
|
var result = new R[len];
|
||||||
Cbrt(units, result);
|
units.CbrtCore(len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal static R?[] Cbrt<T, R>(this T?[] units)
|
internal static R?[] Cbrt<T, R>(this T?[] units)
|
||||||
@@ -96,10 +97,11 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
if (units.Length == 0) return [];
|
var len = units.Length;
|
||||||
|
if (len == 0) return [];
|
||||||
|
|
||||||
var result = new R?[units.Length];
|
var result = new R?[len];
|
||||||
Cbrt(units, result);
|
units.CbrtCore(len, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,24 +111,24 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[len];
|
var result = new R[count];
|
||||||
Cbrt(CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).CbrtCore(count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Cbrt<T, R>(this List<T?> units)
|
internal static List<R?> Cbrt<T, R>(this List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[len];
|
var result = new R?[count];
|
||||||
Cbrt(CollectionsMarshal.AsSpan(units), resultArray);
|
CollectionsMarshal.AsSpan(units).CbrtCore(count, result);
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection ===
|
// === IReadOnlyCollection ===
|
||||||
@@ -156,13 +158,12 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
if (destination.Length < count)
|
if (destination.Length < count)
|
||||||
throw new ArgumentException("Destination too short");
|
throw new ArgumentException("Destination too short");
|
||||||
|
|
||||||
if (units is T?[] array) { array.Cbrt(destination); return; }
|
if (units is T?[] array) { array.CbrtCore(count, destination); return; }
|
||||||
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).Cbrt(destination); return; }
|
if (units is List<T?> list) { CollectionsMarshal.AsSpan(list).CbrtCore(count, destination); return; }
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
destination[i++] = item.HasValue
|
destination[i++] = Math.Sqrt(item.Protected()).ToUnit<R>();
|
||||||
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable + yield ===
|
// === IEnumerable + yield ===
|
||||||
@@ -177,8 +178,7 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return Math.Sqrt(item.Protected()).ToUnit<R>();
|
||||||
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable ===
|
// === IEnumerable ===
|
||||||
@@ -192,7 +192,7 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Cbrt(arr);
|
arr.CbrtCore(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return SqrtIterator3<T, R>(units);
|
else return SqrtIterator3<T, R>(units);
|
||||||
@@ -207,7 +207,7 @@ internal static partial class CollectionsRootOfCubeExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Cbrt(arr);
|
arr.CbrtCore(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return SqrtNullableIterator3<T, R>(units);
|
else return SqrtNullableIterator3<T, R>(units);
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
ref var d2 = ref Unsafe.Add(ref dstRef, i + 2);
|
ref var d2 = ref Unsafe.Add(ref dstRef, i + 2);
|
||||||
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
ref var d3 = ref Unsafe.Add(ref dstRef, i + 3);
|
||||||
|
|
||||||
d0 = u0.HasValue ? Math.Sqrt(u0.Value.ToDouble()).ToUnit<R>() : null;
|
d0 = Math.Sqrt(u0.Protected()).ToUnit<R>();
|
||||||
d1 = u1.HasValue ? Math.Sqrt(u1.Value.ToDouble()).ToUnit<R>() : null;
|
d1 = Math.Sqrt(u1.Protected()).ToUnit<R>();
|
||||||
d2 = u2.HasValue ? Math.Sqrt(u2.Value.ToDouble()).ToUnit<R>() : null;
|
d2 = Math.Sqrt(u2.Protected()).ToUnit<R>();
|
||||||
d3 = u3.HasValue ? Math.Sqrt(u3.Value.ToDouble()).ToUnit<R>() : null;
|
d3 = Math.Sqrt(u3.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ХВОСТ ЦИКЛА: Остаток элементов
|
// ХВОСТ ЦИКЛА: Остаток элементов
|
||||||
@@ -88,7 +88,7 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
{
|
{
|
||||||
ref readonly T? unit = ref Unsafe.Add(ref srcRef, i);
|
ref readonly T? unit = ref Unsafe.Add(ref srcRef, i);
|
||||||
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
ref var dst = ref Unsafe.Add(ref dstRef, i);
|
||||||
dst = unit.HasValue ? Math.Sqrt(unit.Value.ToDouble()).ToUnit<R>() : null;
|
dst = Math.Sqrt(unit.Protected()).ToUnit<R>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,24 +146,24 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R[len];
|
var result = new R[count];
|
||||||
CollectionsMarshal.AsSpan(units).SqrtCore(len, resultArray.AsSpan());
|
CollectionsMarshal.AsSpan(units).SqrtCore(count, result.AsSpan());
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
internal static List<R?> Sqrt<T, R>(this List<T?> units)
|
internal static List<R?> Sqrt<T, R>(this List<T?> units)
|
||||||
where T : struct, IMensuraUnit, IEquatable<T>
|
where T : struct, IMensuraUnit, IEquatable<T>
|
||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
if (units is null) return null!;
|
if (units is null) return null!;
|
||||||
int len = units.Count;
|
int count = units.Count;
|
||||||
if (len == 0) return [];
|
if (count == 0) return [];
|
||||||
|
|
||||||
var resultArray = new R?[len];
|
var result = new R?[count];
|
||||||
CollectionsMarshal.AsSpan(units).SqrtCore(len, resultArray.AsSpan());
|
CollectionsMarshal.AsSpan(units).SqrtCore(count, result.AsSpan());
|
||||||
return resultArray.WrapAsList<R, R>();
|
return result.WrapAsList<R, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IReadOnlyCollection ===
|
// === IReadOnlyCollection ===
|
||||||
@@ -206,8 +206,7 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
foreach (T? item in units)
|
foreach (T? item in units)
|
||||||
{
|
{
|
||||||
if ((uint)i >= (uint)count) break;
|
if ((uint)i >= (uint)count) break;
|
||||||
Unsafe.Add(ref dstRef, i++) = item.HasValue
|
Unsafe.Add(ref dstRef, i++) = Math.Sqrt(item.Protected()).ToUnit<R>();
|
||||||
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,8 +223,7 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
where R : struct, IMensuraUnit, IEquatable<R>
|
where R : struct, IMensuraUnit, IEquatable<R>
|
||||||
{
|
{
|
||||||
foreach (var item in units)
|
foreach (var item in units)
|
||||||
yield return item.HasValue
|
yield return Math.Sqrt(item.Protected()).ToUnit<R>();
|
||||||
? Math.Sqrt(item.Value.ToDouble()).ToUnit<R>() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// === IEnumerable API ===
|
// === IEnumerable API ===
|
||||||
@@ -239,7 +237,7 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
if (units is IReadOnlyCollection<T> roc)
|
if (units is IReadOnlyCollection<T> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Sqrt(arr);
|
arr.SqrtCore(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return SqrtIterator<T, R>(units);
|
else return SqrtIterator<T, R>(units);
|
||||||
@@ -254,7 +252,7 @@ internal static partial class CollectionsRootOfSquareExtensions
|
|||||||
if (units is IReadOnlyCollection<T?> roc)
|
if (units is IReadOnlyCollection<T?> roc)
|
||||||
{
|
{
|
||||||
var arr = roc.ToArray();
|
var arr = roc.ToArray();
|
||||||
arr.Sqrt(arr);
|
arr.SqrtCore(arr.Length, arr);
|
||||||
return arr.ReCast<T, R>();
|
return arr.ReCast<T, R>();
|
||||||
}
|
}
|
||||||
else return SqrtNullableIterator<T, R>(units);
|
else return SqrtNullableIterator<T, R>(units);
|
||||||
|
|||||||
@@ -16,18 +16,18 @@ internal static partial class DoubleExtensions
|
|||||||
internal static double ToDouble(this float number) => number;
|
internal static double ToDouble(this float number) => number;
|
||||||
internal static double ToDouble(this decimal number) => (double)number;
|
internal static double ToDouble(this decimal number) => (double)number;
|
||||||
|
|
||||||
internal static double ToDouble(this byte? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this byte? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this sbyte? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this sbyte? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this short? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this short? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this ushort? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this ushort? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this int? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this int? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this uint? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this uint? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this nint? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this nint? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this nuint? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this nuint? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this long? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this long? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this ulong? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this ulong? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this Half? number) => number.HasValue ? (double)number.Value : 0d;
|
internal static double ToDouble(this Half? number) => number.HasValue ? (double)number.Value : 0d;
|
||||||
internal static double ToDouble(this float? number) => number.HasValue ? number.Value : 0d;
|
internal static double ToDouble(this float? number) => number ?? 0d;
|
||||||
internal static double ToDouble(this decimal? number) => number.HasValue ? (double)number.Value : 0d;
|
internal static double ToDouble(this decimal? number) => number.HasValue ? (double)number.Value : 0d;
|
||||||
|
|
||||||
#if NET7_0_OR_GREATER
|
#if NET7_0_OR_GREATER
|
||||||
@@ -1432,12 +1432,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1451,12 +1451,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1470,12 +1470,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1489,12 +1489,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1508,12 +1508,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1527,12 +1527,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1546,12 +1546,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1565,12 +1565,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1584,12 +1584,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1603,12 +1603,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1622,12 +1622,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1641,12 +1641,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1660,12 +1660,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NET7_0_OR_GREATER
|
#if NET7_0_OR_GREATER
|
||||||
@@ -1680,12 +1680,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1699,12 +1699,12 @@ internal static partial class DoubleExtensions
|
|||||||
{
|
{
|
||||||
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
var u0 = Unsafe.Add(ref srcRef, i); var u1 = Unsafe.Add(ref srcRef, i + 1);
|
||||||
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
var u2 = Unsafe.Add(ref srcRef, i + 2); var u3 = Unsafe.Add(ref srcRef, i + 3);
|
||||||
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double)u0.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i) = u0.HasValue ? (double?)(double)u0.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double)u1.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 1) = u1.HasValue ? (double?)(double)u1.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double)u2.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 2) = u2.HasValue ? (double?)(double)u2.Value : null;
|
||||||
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double)u3.GetValueOrDefault() : null;
|
Unsafe.Add(ref dstRef, i + 3) = u3.HasValue ? (double?)(double)u3.Value : null;
|
||||||
}
|
}
|
||||||
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double)u.GetValueOrDefault() : null; }
|
for (; i < len; i++) { var u = Unsafe.Add(ref srcRef, i); Unsafe.Add(ref dstRef, i) = u.HasValue ? (double?)(double)u.Value : null; }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
20
QWERTYkez.Mensura/Extensions/EFCoreExtension.cs
Normal file
20
QWERTYkez.Mensura/Extensions/EFCoreExtension.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace QWERTYkez.Mensura.Extensions;
|
||||||
|
|
||||||
|
public static partial class EFCoreExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Регистрирует ValueConverter для всех типов, реализующих IMensuraUnit.
|
||||||
|
/// </summary>
|
||||||
|
public static void UseMensuraUnits(this ModelConfigurationBuilder configurationBuilder)
|
||||||
|
{
|
||||||
|
AddGeneratedConverters(configurationBuilder);
|
||||||
|
AddGeneratedComplexConverters(configurationBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MensuraUnitConverter<U>()
|
||||||
|
: ValueConverter<U, double>(unit => unit.ToDouble(), value => value.ToUnit<U>())
|
||||||
|
where U : struct, IMensuraUnit, IEquatable<U> { }
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ internal class ListMimic<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 16)]
|
[StructLayout(LayoutKind.Explicit, Size = 16)]
|
||||||
public struct NullableDoubleMimic
|
internal struct NullableDoubleMimic
|
||||||
{
|
{
|
||||||
[FieldOffset(0)] public bool HasValue;
|
[FieldOffset(0)] public bool HasValue;
|
||||||
[FieldOffset(8)] public double Value;
|
[FieldOffset(8)] public double Value;
|
||||||
|
|||||||
@@ -11,9 +11,17 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" PrivateAssets="All" />
|
|
||||||
<ProjectReference Include="..\QWERTYkez.Mensura.Generator\QWERTYkez.Mensura.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\QWERTYkez.Mensura.Generator\QWERTYkez.Mensura.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
<InternalsVisibleTo Include="QWERTYkez.Mensura.Tests" />
|
<InternalsVisibleTo Include="QWERTYkez.Mensura.Tests" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.36" Condition="'$(TargetFramework)' == 'net6.0'" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" Condition="'$(TargetFramework)' == 'net7.0'" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.28" Condition="'$(TargetFramework)' == 'net8.0'" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.17" Condition="'$(TargetFramework)' == 'net9.0'" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.9" Condition="'$(TargetFramework)' == 'net10.0'" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,70 +1,70 @@
|
|||||||
#if DEBUG
|
//#if DEBUG
|
||||||
namespace QWERTYkez.Mensura.Units;
|
//namespace QWERTYkez.Mensura.Units;
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Base value is MilliMeters
|
///// Base value is MilliMeters
|
||||||
/// </summary>
|
///// </summary>
|
||||||
[DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
|
//[DebuggerDisplay("mm = {_MilliMeters.ToString(\"0.###\")}, m = {Meters.ToString(\"0.###\")}")]
|
||||||
public readonly partial record struct XXXXXXXX
|
//public readonly partial record struct XXXXXXXX
|
||||||
{
|
//{
|
||||||
public static XXXXXXXX MilliMeter { get; } = new(1);
|
// public static XXXXXXXX MilliMeter { get; } = new(1);
|
||||||
[NotMapped, JsonIgnore, IgnoreDataMember] public double _MilliMeters { get => _Value; init => _Value = value; }
|
// [NotMapped, JsonIgnore, IgnoreDataMember] public double _MilliMeters { get => _Value; init => _Value = value; }
|
||||||
|
|
||||||
|
|
||||||
public static XXXXXXXX CentiMeter { get; } = new(XXXXXXXXConv.CentiMeters.To(1));
|
// public static XXXXXXXX CentiMeter { get; } = new(XXXXXXXXConv.CentiMeters.To(1));
|
||||||
[NotMapped, JsonIgnore, IgnoreDataMember]
|
// [NotMapped, JsonIgnore, IgnoreDataMember]
|
||||||
public double CentiMeters
|
// public double CentiMeters
|
||||||
{
|
// {
|
||||||
get => XXXXXXXXConv.CentiMeters.From(_Value);
|
// get => XXXXXXXXConv.CentiMeters.From(_Value);
|
||||||
init
|
// init
|
||||||
{
|
// {
|
||||||
_Value = XXXXXXXXConv.CentiMeters.To(value);
|
// _Value = XXXXXXXXConv.CentiMeters.To(value);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static XXXXXXXX DeciMeter { get; } = new(XXXXXXXXConv.DeciMeters.To(1));
|
// public static XXXXXXXX DeciMeter { get; } = new(XXXXXXXXConv.DeciMeters.To(1));
|
||||||
[NotMapped, JsonIgnore, IgnoreDataMember]
|
// [NotMapped, JsonIgnore, IgnoreDataMember]
|
||||||
public double DeciMeters
|
// public double DeciMeters
|
||||||
{
|
// {
|
||||||
get => XXXXXXXXConv.DeciMeters.From(_Value);
|
// get => XXXXXXXXConv.DeciMeters.From(_Value);
|
||||||
init => _Value = XXXXXXXXConv.DeciMeters.To(value);
|
// init => _Value = XXXXXXXXConv.DeciMeters.To(value);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static XXXXXXXX Meter { get; } = new(XXXXXXXXConv.Meters.To(1));
|
// public static XXXXXXXX Meter { get; } = new(XXXXXXXXConv.Meters.To(1));
|
||||||
[NotMapped, JsonIgnore, IgnoreDataMember]
|
// [NotMapped, JsonIgnore, IgnoreDataMember]
|
||||||
public double Meters
|
// public double Meters
|
||||||
{
|
// {
|
||||||
get => XXXXXXXXConv.Meters.From(_Value);
|
// get => XXXXXXXXConv.Meters.From(_Value);
|
||||||
init => _Value = XXXXXXXXConv.Meters.To(value);
|
// init => _Value = XXXXXXXXConv.Meters.To(value);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static XXXXXXXX KiloMeter { get; } = new(XXXXXXXXConv.KiloMeters.To(1));
|
// public static XXXXXXXX KiloMeter { get; } = new(XXXXXXXXConv.KiloMeters.To(1));
|
||||||
[NotMapped, JsonIgnore, IgnoreDataMember]
|
// [NotMapped, JsonIgnore, IgnoreDataMember]
|
||||||
public double KiloMeters
|
// public double KiloMeters
|
||||||
{
|
// {
|
||||||
get => XXXXXXXXConv.KiloMeters.From(_Value);
|
// get => XXXXXXXXConv.KiloMeters.From(_Value);
|
||||||
init => _Value = XXXXXXXXConv.KiloMeters.To(value);
|
// init => _Value = XXXXXXXXConv.KiloMeters.To(value);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
public XXXXXXXX AddMilliMeters(double value) => new(_Value + value);
|
// public XXXXXXXX AddMilliMeters(double value) => new(_Value + value);
|
||||||
public XXXXXXXX AddCentiMeters(double value) => new(_Value + XXXXXXXXConv.CentiMeters.To(value));
|
// public XXXXXXXX AddCentiMeters(double value) => new(_Value + XXXXXXXXConv.CentiMeters.To(value));
|
||||||
public XXXXXXXX AddDeciMeters(double value) => new(_Value + XXXXXXXXConv.DeciMeters.To(value));
|
// public XXXXXXXX AddDeciMeters(double value) => new(_Value + XXXXXXXXConv.DeciMeters.To(value));
|
||||||
public XXXXXXXX AddMeters(double value) => new(_Value + XXXXXXXXConv.Meters.To(value));
|
// public XXXXXXXX AddMeters(double value) => new(_Value + XXXXXXXXConv.Meters.To(value));
|
||||||
public XXXXXXXX AddKiloMeters(double value) => new(_Value + XXXXXXXXConv.KiloMeters.To(value));
|
// public XXXXXXXX AddKiloMeters(double value) => new(_Value + XXXXXXXXConv.KiloMeters.To(value));
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
internal readonly struct XXXXXXXXConv
|
//internal readonly struct XXXXXXXXConv
|
||||||
{
|
//{
|
||||||
private XXXXXXXXConv(double multiplicator) => this.Multiplicator = multiplicator;
|
// private XXXXXXXXConv(double multiplicator) => this.Multiplicator = multiplicator;
|
||||||
public double To(double value) => value * Multiplicator;
|
// public double To(double value) => value * Multiplicator;
|
||||||
public double From(double value) => value / Multiplicator;
|
// public double From(double value) => value / Multiplicator;
|
||||||
public double Multiplicator { get; init; }
|
// public double Multiplicator { get; init; }
|
||||||
public static XXXXXXXXConv MilliMeters { get; } = new(1);
|
// public static XXXXXXXXConv MilliMeters { get; } = new(1);
|
||||||
public static XXXXXXXXConv CentiMeters { get; } = new(10);
|
// public static XXXXXXXXConv CentiMeters { get; } = new(10);
|
||||||
public static XXXXXXXXConv DeciMeters { get; } = new(100);
|
// public static XXXXXXXXConv DeciMeters { get; } = new(100);
|
||||||
public static XXXXXXXXConv Meters { get; } = new(1000);
|
// public static XXXXXXXXConv Meters { get; } = new(1000);
|
||||||
public static XXXXXXXXConv KiloMeters { get; } = new(1000000);
|
// public static XXXXXXXXConv KiloMeters { get; } = new(1000000);
|
||||||
}
|
//}
|
||||||
#endif
|
//#endif
|
||||||
Reference in New Issue
Block a user