Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more quantities #47

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions source/Quantities.Test/AccelerationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Quantities.Units.NonStandard.Acceleration;
using Quantities.Units.NonStandard.Length;
using Quantities.Units.NonStandard.Velocity;
using Quantities.Units.Si.Metric;

namespace Quantities.Test;

public class AccelerationTest
{
[Fact]
public void MetrePerSquareSecondToString() => FormattingMatches(v => Acceleration.Of(v, Si<Metre>().Per(Square(Si<Second>()))), "m/s²");

[Fact]
public void KnotPerHourIsSameAsNauticalMilePerSquareHour()
{
Velocity knots = Velocity.Of(6, NonStandard<Knot>());
Time hours = Time.Of(2, Metric<Hour>());
Acceleration expected = Acceleration.Of(3, NonStandard<NauticalMile>().Per(Square(Metric<Hour>())));

Acceleration actual = knots / hours;

actual.Equal(expected);
}

[Fact]
public void OneStandardGravityInMetersPerSecondSquared()
{
var standardGravity = Acceleration.Of(1, NonStandard<StandardGravity>());
var expected = Acceleration.Of(9.80665, Si<Metre>().Per(Square(Si<Second>())));

var actual = standardGravity.To(Si<Metre>().Per(Square(Si<Second>())));

actual.Matches(expected);
}
}
2 changes: 1 addition & 1 deletion source/Quantities.Test/VelocityTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Quantities.units.NonStandard.Length;
using Quantities.Units.NonStandard.Length;
using Quantities.Units.NonStandard.Velocity;
using Quantities.Units.Si.Metric;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Quantities.Dimensions;

namespace Quantities.Units.NonStandard.Acceleration;

// See: https://en.wikipedia.org/wiki/Standard_gravity
public class StandardGravity : INonStandardUnit, IAcceleration
{
public static Transformation ToSi(Transformation self) => 9.80665 * self; // 9.80665 m/s2
public static String Representation => "gₙ";
}
3 changes: 1 addition & 2 deletions source/Quantities.Units/NonStandard/Length/NauticalMile.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using Quantities.Dimensions;
using Quantities.Units;
using Quantities.Units.Si;

namespace Quantities.units.NonStandard.Length;
namespace Quantities.Units.NonStandard.Length;

// https://en.wikipedia.org/wiki/Nautical_mile
public readonly struct NauticalMile : INonStandardUnit, ILength
Expand Down
2 changes: 1 addition & 1 deletion source/Quantities.Units/NonStandard/Velocity/Knot.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Quantities.Dimensions;
using Quantities.units.NonStandard.Length;
using Quantities.Units.NonStandard.Length;
using Quantities.Units.Si.Metric;
using static Quantities.Extensions;

Expand Down
6 changes: 5 additions & 1 deletion source/Quantities.Units/Quantities.Units.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Atmoos.Quantities" Version="1.0.0" />
<ProjectReference Include="..\Quantities\Quantities.csproj" Condition="'$(Configuration)'=='DEBUG'"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Atmoos.Quantities" Version="1.0.0" Condition="'$(Configuration)'!='DEBUG'"/>
</ItemGroup>

</Project>
15 changes: 7 additions & 8 deletions source/Quantities/Creation/Creators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public Product<TUnit, TRight> Times<TRight>(in Scalar<TRight> rightTerm)
where TRight : IUnit, IDimension => new(rightTerm.factory.Inject(this.factory.Product));
public Quotient<TUnit, TDenominator> Per<TDenominator>(in Scalar<TDenominator> denominator)
where TDenominator : IUnit, IDimension => new(denominator.factory.Inject(this.factory.Quotient));
public Quotient<TUnit, Square<TDenominator>> Per<TDenominator>(in Square<TDenominator> denominator)
where TDenominator : IUnit, IDimension => new(denominator.Factory.Inject<Measures.Square, Factory>(this.factory.Quotient));
internal Quantity Create(in Double value) => new(in value, this.factory.Create());
internal Quantity Create<TAlias, TLinear>(in Double value)
where TAlias : TUnit, IAlias<TLinear>
Expand All @@ -24,8 +26,6 @@ internal Quantity Transform<TAlias, TLinear>(in Quantity other)
}

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;
Expand All @@ -34,8 +34,6 @@ public readonly struct Product<TLeft, TRight>
}

public readonly struct Quotient<TN, TD>
where TN : IUnit, IDimension
where TD : IUnit, IDimension
{
private readonly Factory factory;
internal Quotient(Factory factory) => this.factory = factory;
Expand All @@ -47,16 +45,17 @@ public readonly struct Square<TUnit>
where TUnit : IUnit, IDimension
{
private readonly Factory factory;
internal Factory Factory => this.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());
internal Quantity Create(in Double value) => new(in value, this.factory.Create<Measures.Square>());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Create<Measures.Square>());
}

public readonly struct Cubic<TUnit>
where TUnit : 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());
internal Quantity Create(in Double value) => new(in value, this.factory.Create<Measures.Cubic>());
internal Quantity Transform(in Quantity other) => other.Project(this.factory.Create<Measures.Cubic>());
}
8 changes: 4 additions & 4 deletions source/Quantities/Creation/Factory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ internal abstract class Factory
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 Measure Create<TExp>() where TExp : IExponent;
public abstract TResult Inject<TResult>(IInject<TResult> inject);
public abstract TResult Inject<TExp, TResult>(IInject<TResult> inject) where TExp : IExponent;
public abstract Measure AliasTo<TUnit, TLinear>()
where TUnit : IAlias<TLinear>, IDimension
where TLinear : IDimension, ILinear;
Expand All @@ -25,10 +25,10 @@ private sealed class Impl<TMeasure> : Factory
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<Power<Square, TMeasure>>();
public override Measure Cubic() => Measure.Of<Power<Cubic, TMeasure>>();
public override Measure Create<TExp>() => Measure.Of<Power<TExp, TMeasure>>();
public override Measure AliasTo<TUnit, TLinear>() => AliasFor<TUnit, TLinear>.Measure;
public override TResult Inject<TResult>(IInject<TResult> inject) => inject.Inject<TMeasure>();
public override TResult Inject<TExp, TResult>(IInject<TResult> inject) => inject.Inject<Power<TExp, TMeasure>>();

private static class AliasFor<TUnit, TLinear>
where TUnit : IAlias<TLinear>, IDimension
Expand Down
3 changes: 2 additions & 1 deletion source/Quantities/Dimensions/DerivedDimensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
public interface IArea : ISquare<ILength>, IDerivedQuantity { /* marker interface */ }
public interface IVolume : ICubic<ILength>, IDerivedQuantity { /* marker interface */ }
public interface IVelocity : IQuotient<ILength, ITime>, IDerivedQuantity { /* marker interface */ }
// Dim<Length>.Times<Mass>() * Dim<Time>.Pow(-2)
public interface IAcceleration : IQuotient<ILength, ISquare<ITime>>, IDerivedQuantity { /* marker interface */ }
public interface IForce : IQuotient<IProduct<ILength, IMass>, ISquare<ITime>>, IDerivedQuantity { /* marker interface */ }
public interface IPower : ILinear<IPower>, IDerivedQuantity { /* marker interface */ }
public interface IEnergy : IProduct<IPower, ITime>, IDerivedQuantity { /* marker interface */ }
public interface IAngle : IQuotient<ILength, ILength>, IDerivedQuantity { /* marker interface */ }
public interface ISpecificMass : IQuotient<IMass, IVolume>, IDerivedQuantity { /* marker interface */ }
45 changes: 45 additions & 0 deletions source/Quantities/Quantities/Acceleration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Numerics;
using Quantities.Creation;
using Quantities.Dimensions;
using Quantities.Units;

namespace Quantities;

public readonly struct Acceleration : IQuantity<Acceleration>, IAcceleration
, IScalar<Acceleration, IAcceleration>
, IMultiplyOperators<Acceleration, Time, Velocity>
{
private readonly Quantity acceleration;
internal Quantity Value => this.acceleration;
Quantity IQuantity<Acceleration>.Value => this.acceleration;
private Acceleration(in Quantity value) => this.acceleration = value;
public Acceleration To<TAcceleration>(in Scalar<TAcceleration> other)
where TAcceleration : IAcceleration, IUnit => new(other.Transform(in this.acceleration));
public Acceleration To<TNominator, TDenominator>(in Quotient<TNominator, Square<TDenominator>> other)
where TNominator : ILength, IUnit
where TDenominator : ITime, IUnit => new(other.Transform(in this.acceleration));
public static Acceleration Of<TAcceleration>(in Double value, in Scalar<TAcceleration> measure)
where TAcceleration : IAcceleration, IUnit => new(measure.Create(in value));
public static Acceleration Of<TNominator, TDenominator>(in Double value, in Quotient<TNominator, Square<TDenominator>> measure)
where TNominator : ILength, IUnit
where TDenominator : ITime, IUnit => new(measure.Create(in value));
static Acceleration IFactory<Acceleration>.Create(in Quantity value) => new(in value);
internal static Acceleration From(in Velocity velocity, in Time time) => new(velocity.Value / time.Value);
public Boolean Equals(Acceleration other) => this.acceleration.Equals(other.acceleration);
public override Boolean Equals(Object? obj) => obj is Acceleration acceleration && Equals(acceleration);
public override Int32 GetHashCode() => this.acceleration.GetHashCode();
public override String ToString() => this.acceleration.ToString();
public String ToString(String? format, IFormatProvider? provider) => this.acceleration.ToString(format, provider);

public static implicit operator Double(Acceleration acceleration) => acceleration.acceleration;
public static Boolean operator ==(Acceleration left, Acceleration right) => left.Equals(right);
public static Boolean operator !=(Acceleration left, Acceleration right) => !left.Equals(right);
public static Acceleration operator +(Acceleration left, Acceleration right) => new(left.acceleration + right.acceleration);
public static Acceleration operator -(Acceleration left, Acceleration right) => new(left.acceleration - right.acceleration);
public static Acceleration operator *(Double scalar, Acceleration right) => new(scalar * right.acceleration);
public static Acceleration operator *(Acceleration left, Double scalar) => new(scalar * left.acceleration);
public static Acceleration operator /(Acceleration left, Double scalar) => new(left.acceleration / scalar);
public static Double operator /(Acceleration left, Acceleration right) => left.acceleration.Ratio(in right.acceleration);

public static Velocity operator *(Acceleration acceleration, Time time) => Velocity.From(in acceleration, in time);
}
34 changes: 34 additions & 0 deletions source/Quantities/Quantities/AmountOfSubstance.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Quantities.Creation;
using Quantities.Dimensions;
using Quantities.Units;

namespace Quantities;

public readonly struct AmountOfSubstance : IQuantity<AmountOfSubstance>, IAmountOfSubstance
, IScalar<AmountOfSubstance, IAmountOfSubstance>
{
private readonly Quantity amountOfSubstance;
internal Quantity Value => this.amountOfSubstance;
Quantity IQuantity<AmountOfSubstance>.Value => this.amountOfSubstance;
private AmountOfSubstance(in Quantity value) => this.amountOfSubstance = value;
public AmountOfSubstance To<TAmountOfSubstance>(in Scalar<TAmountOfSubstance> other)
where TAmountOfSubstance : IAmountOfSubstance, IUnit => new(other.Transform(in this.amountOfSubstance));
public static AmountOfSubstance Of<TAmountOfSubstance>(in Double value, in Scalar<TAmountOfSubstance> measure)
where TAmountOfSubstance : IAmountOfSubstance, IUnit => new(measure.Create(in value));
static AmountOfSubstance IFactory<AmountOfSubstance>.Create(in Quantity value) => new(in value);
public Boolean Equals(AmountOfSubstance other) => this.amountOfSubstance.Equals(other.amountOfSubstance);
public override Boolean Equals(Object? obj) => obj is AmountOfSubstance amountOfSubstance && Equals(amountOfSubstance);
public override Int32 GetHashCode() => this.amountOfSubstance.GetHashCode();
public override String ToString() => this.amountOfSubstance.ToString();
public String ToString(String? format, IFormatProvider? provider) => this.amountOfSubstance.ToString(format, provider);

public static implicit operator Double(AmountOfSubstance amountOfSubstance) => amountOfSubstance.amountOfSubstance;
public static Boolean operator ==(AmountOfSubstance left, AmountOfSubstance right) => left.Equals(right);
public static Boolean operator !=(AmountOfSubstance left, AmountOfSubstance right) => !left.Equals(right);
public static AmountOfSubstance operator +(AmountOfSubstance left, AmountOfSubstance right) => new(left.amountOfSubstance + right.amountOfSubstance);
public static AmountOfSubstance operator -(AmountOfSubstance left, AmountOfSubstance right) => new(left.amountOfSubstance - right.amountOfSubstance);
public static AmountOfSubstance operator *(Double scalar, AmountOfSubstance right) => new(scalar * right.amountOfSubstance);
public static AmountOfSubstance operator *(AmountOfSubstance left, Double scalar) => new(scalar * left.amountOfSubstance);
public static AmountOfSubstance operator /(AmountOfSubstance left, Double scalar) => new(left.amountOfSubstance / scalar);
public static Double operator /(AmountOfSubstance left, AmountOfSubstance right) => left.amountOfSubstance.Ratio(in right.amountOfSubstance);
}
39 changes: 39 additions & 0 deletions source/Quantities/Quantities/ElectricCharge.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Numerics;
using Quantities.Creation;
using Quantities.Dimensions;
using Quantities.Units;

namespace Quantities;

public readonly struct ElectricCharge : IQuantity<ElectricCharge>, IElectricCharge
, IScalar<ElectricCharge, IElectricCharge>
, IMultiplyOperators<ElectricCharge, ElectricPotential, Energy>
{
private readonly Quantity electricCharge;
internal Quantity Value => this.electricCharge;
Quantity IQuantity<ElectricCharge>.Value => this.electricCharge;
private ElectricCharge(in Quantity value) => this.electricCharge = value;
public ElectricCharge To<TElectricCharge>(in Scalar<TElectricCharge> other)
where TElectricCharge : IElectricCharge, IUnit => new(other.Transform(in this.electricCharge));
public static ElectricCharge Of<TElectricCharge>(in Double value, in Scalar<TElectricCharge> measure)
where TElectricCharge : IElectricCharge, IUnit => new(measure.Create(in value));
static ElectricCharge IFactory<ElectricCharge>.Create(in Quantity value) => new(in value);
internal static ElectricCharge From(in Energy energy, in ElectricPotential potential) => new(energy.Value / potential.Value);
public Boolean Equals(ElectricCharge other) => this.electricCharge.Equals(other.electricCharge);
public override Boolean Equals(Object? obj) => obj is ElectricCharge electricCharge && Equals(electricCharge);
public override Int32 GetHashCode() => this.electricCharge.GetHashCode();
public override String ToString() => this.electricCharge.ToString();
public String ToString(String? format, IFormatProvider? provider) => this.electricCharge.ToString(format, provider);

public static implicit operator Double(ElectricCharge electricCharge) => electricCharge.electricCharge;
public static Boolean operator ==(ElectricCharge left, ElectricCharge right) => left.Equals(right);
public static Boolean operator !=(ElectricCharge left, ElectricCharge right) => !left.Equals(right);
public static ElectricCharge operator +(ElectricCharge left, ElectricCharge right) => new(left.electricCharge + right.electricCharge);
public static ElectricCharge operator -(ElectricCharge left, ElectricCharge right) => new(left.electricCharge - right.electricCharge);
public static ElectricCharge operator *(Double scalar, ElectricCharge right) => new(scalar * right.electricCharge);
public static ElectricCharge operator *(ElectricCharge left, Double scalar) => new(scalar * left.electricCharge);
public static ElectricCharge operator /(ElectricCharge left, Double scalar) => new(left.electricCharge / scalar);
public static Double operator /(ElectricCharge left, ElectricCharge right) => left.electricCharge.Ratio(in right.electricCharge);

public static Energy operator *(ElectricCharge charge, ElectricPotential potential) => Energy.Times(in charge, in potential);
}
4 changes: 4 additions & 0 deletions source/Quantities/Quantities/ElectricPotential.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Quantities;
public readonly struct ElectricPotential : IQuantity<ElectricPotential>, IElectricPotential
, IScalar<ElectricPotential, IElectricPotential>
, IMultiplyOperators<ElectricPotential, ElectricCurrent, Power>
, IMultiplyOperators<ElectricPotential, ElectricCharge, Energy>
, IDivisionOperators<ElectricPotential, ElectricCurrent, ElectricalResistance>
, IDivisionOperators<ElectricPotential, ElectricalResistance, ElectricCurrent>
{
Expand All @@ -22,6 +23,7 @@ public static ElectricPotential Of<TUnit>(in Double value, in Scalar<TUnit> meas
static ElectricPotential IFactory<ElectricPotential>.Create(in Quantity value) => new(in value);
internal static ElectricPotential From(in ElectricCurrent current, in ElectricalResistance resistance) => new(current.Value * resistance.Value);
internal static ElectricPotential From(in Power power, in ElectricCurrent current) => new(power.Value / current.Value);
internal static ElectricPotential From(in Energy energy, in ElectricCharge charge) => new(energy.Value / charge.Value);
public Boolean Equals(ElectricPotential other) => this.potential.Equals(other.potential);
public String ToString(String? format, IFormatProvider? provider) => this.potential.ToString(format, provider);
public override Boolean Equals(Object? obj) => obj is ElectricPotential potential && Equals(potential);
Expand All @@ -44,4 +46,6 @@ public static ElectricPotential Of<TUnit>(in Double value, in Scalar<TUnit> meas
#endregion Ohm's Law

public static Power operator *(ElectricPotential potential, ElectricCurrent current) => Power.From(in potential, in current);

public static Energy operator *(ElectricPotential potential, ElectricCharge charge) => Energy.Times(in potential, in charge);
}
Loading
Loading