Skip to content

Commit

Permalink
Introduce factory class to create measures.
Browse files Browse the repository at this point in the history
  • Loading branch information
atmoos committed Oct 22, 2023
1 parent 7661512 commit f2aaa0b
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 142 deletions.
8 changes: 4 additions & 4 deletions source/Quantities.Benchmark/ConvertingQuantities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ .NET SDK 7.0.111
| Method | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|------------------------ |-----------:|----------:|----------:|------:|--------:|----------:|------------:|
| TrivialImplementation | 0.6493 ns | 0.0171 ns | 0.0152 ns | 1.00 | 0.00 | - | NA |
| QuantityImplementation | 2.9082 ns | 0.0899 ns | 0.0923 ns | 4.45 | 0.14 | - | NA |
| QuantityToSame | 26.5881 ns | 0.1631 ns | 0.1525 ns | 40.96 | 1.02 | - | NA |
| QuantityToVeryDifferent | 27.2572 ns | 0.1387 ns | 0.1083 ns | 42.25 | 0.86 | - | NA |
| TrivialImplementation | 0.5988 ns | 0.0069 ns | 0.0058 ns | 1.00 | 0.00 | - | NA |
| QuantityImplementation | 4.0346 ns | 0.0202 ns | 0.0158 ns | 6.74 | 0.06 | - | NA |
| QuantityToSame | 14.9515 ns | 0.1545 ns | 0.1370 ns | 24.94 | 0.35 | - | NA |
| QuantityToVeryDifferent | 17.1767 ns | 0.0614 ns | 0.0575 ns | 28.67 | 0.28 | - | NA |
*/
22 changes: 13 additions & 9 deletions source/Quantities.Benchmark/CreateQuantities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using Quantities.Units.Si.Metric;
using Quantities.Dimensions;

using static Quantities.Systems;
using static Quantities.AliasOf<Quantities.Dimensions.ILength>;

namespace Quantities.Benchmark;
Expand Down Expand Up @@ -39,6 +38,7 @@ public sealed class DummyObject : ICastOperators<DummyObject, Double>
//[EventPipeProfiler(EventPipeProfile.CpuSampling)]
public class CreateQuantities
{
private static readonly Creation.Product<Watt, Hour> kwh = Si<Kilo, Watt>().Dot(Metric<Hour>());
private static readonly Random random = new();
private readonly Double value = random.NextDouble();

Expand All @@ -62,6 +62,9 @@ public class CreateQuantities
[Benchmark]
public Energy CreateProductQuantity() => Energy.Of(in this.value, Si<Kilo, Watt>().Dot(Metric<Hour>()));

[Benchmark]
public Energy CreateCachedProductQuantity() => Energy.Of(in this.value, in kwh);

[Benchmark]
public Area CreateScalarPowerQuantity() => Area.Of(in this.value, AliasOf<ILength>.Metric<Are>());

Expand All @@ -81,12 +84,13 @@ .NET SDK 7.0.111
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------------------- |----------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|
| CreateObject | 6.780 ns | 0.0843 ns | 0.0788 ns | 1.00 | 0.00 | 0.0057 | 24 B | 1.00 |
| CreateStruct | 1.294 ns | 0.0125 ns | 0.0111 ns | 0.19 | 0.00 | - | - | 0.00 |
| CreateScalarQuantity | 4.461 ns | 0.0295 ns | 0.0276 ns | 0.66 | 0.01 | - | - | 0.00 |
| CreateScalarQuantityWithoutOpt | 3.312 ns | 0.0145 ns | 0.0121 ns | 0.49 | 0.01 | - | - | 0.00 |
| CreateQuotientQuantity | 24.993 ns | 0.1407 ns | 0.1247 ns | 3.69 | 0.05 | - | - | 0.00 |
| CreateProductQuantity | 26.276 ns | 0.5255 ns | 0.5396 ns | 3.88 | 0.11 | - | - | 0.00 |
| CreateScalarPowerQuantity | 16.077 ns | 0.0537 ns | 0.0476 ns | 2.37 | 0.02 | - | - | 0.00 |
| CreateSquarePowerQuantity | 13.729 ns | 0.0552 ns | 0.0461 ns | 2.03 | 0.02 | - | - | 0.00 |
| CreateObject | 5.937 ns | 0.1106 ns | 0.1035 ns | 1.00 | 0.00 | 0.0057 | 24 B | 1.00 |
| CreateStruct | 1.621 ns | 0.0464 ns | 0.0411 ns | 0.27 | 0.01 | - | - | 0.00 |
| CreateScalarQuantity | 5.468 ns | 0.0441 ns | 0.0412 ns | 0.92 | 0.02 | - | - | 0.00 |
| CreateScalarQuantityWithoutOpt | 4.514 ns | 0.0139 ns | 0.0123 ns | 0.76 | 0.01 | - | - | 0.00 |
| CreateQuotientQuantity | 15.357 ns | 0.0940 ns | 0.0879 ns | 2.59 | 0.05 | - | - | 0.00 |
| CreateProductQuantity | 15.606 ns | 0.2638 ns | 0.2467 ns | 2.63 | 0.08 | - | - | 0.00 |
| CreateCachedProductQuantity | 5.546 ns | 0.0397 ns | 0.0371 ns | 0.93 | 0.01 | - | - | 0.00 |
| CreateScalarPowerQuantity | 15.624 ns | 0.1290 ns | 0.1007 ns | 2.64 | 0.05 | - | - | 0.00 |
| CreateSquarePowerQuantity | 5.448 ns | 0.1203 ns | 0.1066 ns | 0.92 | 0.03 | - | - | 0.00 |
*/
4 changes: 1 addition & 3 deletions source/Quantities/Core/Measure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

namespace Quantities.Core;

internal abstract class Measure : IInjector
internal abstract class Measure
{
private readonly Polynomial conversion;
private Measure(in Polynomial conversion) => this.conversion = conversion;
public Polynomial Project(Measure other) => this.conversion / other.conversion;
public abstract TResult Inject<TResult>(IInject<TResult> inject);
public abstract Result Multiply(Measure other);
protected abstract Result Multiply<TMeasure>() where TMeasure : IMeasure;
public abstract Result Divide(Measure other);
Expand All @@ -26,6 +25,5 @@ public Impl() : base(TMeasure.Poly) { }
public override String ToString() => TMeasure.Representation;
protected override Result Multiply<TOtherMeasure>() => TOtherMeasure.Multiply<TMeasure>();
protected override Result Divide<TOtherMeasure>() => TOtherMeasure.Divide<TMeasure>();
public override TResult Inject<TResult>(IInject<TResult> inject) => inject.Inject<TMeasure>();
}
}
66 changes: 66 additions & 0 deletions source/Quantities/Creation/Creators.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Quantities.Dimensions;
using Quantities.Units;

namespace Quantities.Creation;

public readonly struct Scalar<TDim>
where TDim : IUnit, IDimension
{
private readonly Factory factory;
internal Factory Factory => this.factory;
internal Scalar(Factory factory) => this.factory = factory;
public Product<TDim, TRight> Dot<TRight>(in Scalar<TRight> rightTerm)
where TRight : IUnit, IDimension => new(rightTerm.factory.Inject(this.factory.Product));
public Quotient<TDim, TDenominator> Per<TDenominator>(in Scalar<TDenominator> denominator)
where TDenominator : IUnit, IDimension => new(denominator.factory.Inject(this.factory.Quotient));
internal Quantity Create(in Double value) => new(in value, this.factory.Create());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Create());
}

public readonly ref struct Alias<TUnit, TLinear>
where TUnit : IAlias<TLinear>, IUnit, IDimension
where TLinear : IDimension
{
private readonly Measure measure;
internal Alias(Measure measure) => this.measure = measure;
internal Quantity Create(in Double value) => new(in value, in this.measure);
internal Quantity Transform(in Quantity other) => other.Project(in this.measure);
}

public readonly struct Product<TLeft, TRight>
where TLeft : IUnit, IDimension
where TRight : IUnit, IDimension
{
private readonly Factory factory;
internal Product(Factory factory) => this.factory = factory;
internal Quantity Create(in Double value) => new(in value, this.factory.Create());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Create());
}

public readonly ref struct Quotient<TN, TD>
where TN : IUnit, IDimension
where TD : IUnit, IDimension
{
private readonly Factory factory;
internal Quotient(Factory factory) => this.factory = factory;
internal Quantity Create(in Double value) => new(in value, this.factory.Create());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Create());
}

public readonly ref struct Square<TDim>
where TDim : IUnit, IDimension
{
private readonly Factory factory;
internal Square(Factory factory) => this.factory = factory;
internal Quantity Create(in Double value) => new(in value, this.factory.Square());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Square());
}

public readonly ref struct Cubic<TDim>
where TDim : IUnit, IDimension
{
private readonly Factory factory;
internal Cubic(Factory factory) => this.factory = factory;
internal Quantity Create(in Double value) => new(in value, this.factory.Cubic());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Cubic());
}
79 changes: 0 additions & 79 deletions source/Quantities/Creation/Factories.cs

This file was deleted.

37 changes: 37 additions & 0 deletions source/Quantities/Creation/Factory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace Quantities.Creation;

internal abstract class Factory : IInjector
{
public IInject<Factory> Product { get; }
public IInject<Factory> Quotient { get; }
private Factory(IInject<Factory> product, IInject<Factory> quotient) => (Product, Quotient) = (product, quotient);
public abstract Measure Create();
public abstract Measure Square();
public abstract Measure Cubic();
public abstract TResult Inject<TResult>(IInject<TResult> inject);
public static Factory Of<TMeasure>() where TMeasure : IMeasure => AllocationFree<Impl<TMeasure>>.Item;

private sealed class Impl<TMeasure> : Factory
where TMeasure : IMeasure
{
private static readonly IInject<Factory> product = new ProductInject<TMeasure>();
private static readonly IInject<Factory> quotient = new QuotientInject<TMeasure>();
public Impl() : base(product, quotient) { }
public override Measure Create() => Measure.Of<TMeasure>();
public override Measure Square() => Measure.Of<Measures.Power<Measures.Square, TMeasure>>();
public override Measure Cubic() => Measure.Of<Measures.Power<Measures.Cubic, TMeasure>>();
public override TResult Inject<TResult>(IInject<TResult> inject) => inject.Inject<TMeasure>();
}

private sealed class ProductInject<TLeftTerm> : IInject<Factory>
where TLeftTerm : IMeasure
{
public Factory Inject<TMeasure>() where TMeasure : IMeasure => Of<Measures.Product<TLeftTerm, TMeasure>>();
}

private sealed class QuotientInject<TLeftTerm> : IInject<Factory>
where TLeftTerm : IMeasure
{
public Factory Inject<TMeasure>() where TMeasure : IMeasure => Of<Measures.Quotient<TLeftTerm, TMeasure>>();
}
}
39 changes: 0 additions & 39 deletions source/Quantities/Creation/Injectors.cs

This file was deleted.

16 changes: 8 additions & 8 deletions source/Quantities/Systems.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ namespace Quantities;
public static class Systems
{
public static Scalar<TDim> Si<TDim>()
where TDim : ISiUnit, IDimension => new(Measure.Of<Si<TDim>>());
where TDim : ISiUnit, IDimension => new(Factory.Of<Si<TDim>>());
public static Scalar<TDim> Si<TPrefix, TDim>()
where TPrefix : IMetricPrefix
where TDim : ISiUnit, IDimension => new(Measure.Of<Si<TPrefix, TDim>>());
where TDim : ISiUnit, IDimension => new(Factory.Of<Si<TPrefix, TDim>>());
public static Scalar<TDim> Metric<TDim>()
where TDim : IMetricUnit, IDimension => new(Measure.Of<Metric<TDim>>());
where TDim : IMetricUnit, IDimension => new(Factory.Of<Metric<TDim>>());
public static Scalar<TDim> Metric<TPrefix, TDim>()
where TPrefix : IMetricPrefix
where TDim : IMetricUnit, IDimension => new(Measure.Of<Metric<TPrefix, TDim>>());
where TDim : IMetricUnit, IDimension => new(Factory.Of<Metric<TPrefix, TDim>>());
public static Scalar<TDim> Imperial<TDim>()
where TDim : IImperialUnit, IDimension => new(Measure.Of<Imperial<TDim>>());
where TDim : IImperialUnit, IDimension => new(Factory.Of<Imperial<TDim>>());
public static Scalar<TDim> NonStandard<TDim>()
where TDim : INonStandardUnit, IDimension => new(Measure.Of<NonStandard<TDim>>());
public static Cubic<TDim> Cubic<TDim>(in Scalar<TDim> scalar) where TDim : IUnit, IDimension => new(scalar.Cubic());
public static Square<TDim> Square<TDim>(in Scalar<TDim> scalar) where TDim : IUnit, IDimension => new(scalar.Square());
where TDim : INonStandardUnit, IDimension => new(Factory.Of<NonStandard<TDim>>());
public static Cubic<TDim> Cubic<TDim>(in Scalar<TDim> scalar) where TDim : IUnit, IDimension => new(scalar.Factory);
public static Square<TDim> Square<TDim>(in Scalar<TDim> scalar) where TDim : IUnit, IDimension => new(scalar.Factory);
}

public static class AliasOf<TLinear>
Expand Down

0 comments on commit f2aaa0b

Please sign in to comment.