Open
Description
Following my comments on the subject in #1200 here is the proposed modification to the IQuantity
interfaces:
ILinearQuantity
- in v6 Wishlist #1200 I used the nameIVectorQuantity
but after some reflection I decided that the wordLinear
is a better fit (in fact, if we look at the conversion expressions- they are all of the formax
, without an offset)
/// <summary>
/// Represents a quantity that has both magnitude and direction, supporting various arithmetic operations and
/// comparisons.
/// </summary>
/// <remarks>
/// This interface defines standard linear arithmetic operations such as addition, subtraction, multiplication, and
/// division.
/// These types of quantities naturally support comparison operations with either absolute or relative tolerance, which
/// is useful for determining equality within a certain margin of error.
/// <para>
/// For more information, see the Wikipedia page on
/// <a href="https://en.wikipedia.org/wiki/Dimensional_analysis#Geometry:_position_vs._displacement">
/// Dimensional
/// Analysis
/// </a>
/// .
/// </para>
/// </remarks>
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
public interface ILinearQuantity<TSelf> : IQuantityInstance<TSelf>
#if NET7_0_OR_GREATER
, IAdditiveIdentity<TSelf, TSelf>
#endif
where TSelf : ILinearQuantity<TSelf>
{
#if NET7_0_OR_GREATER
/// <summary>
/// The zero value of this quantity.
/// </summary>
static abstract TSelf Zero { get; }
static TSelf IAdditiveIdentity<TSelf, TSelf>.AdditiveIdentity
{
get => TSelf.Zero;
}
#endif
#if EXTENDED_EQUALS_INTERFACE
/// <summary>
/// <para>
/// Compare equality to <paramref name="other"/> given a <paramref name="tolerance"/> for the maximum allowed +/- difference.
/// </para>
/// <example>
/// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
/// <code>
/// var a = Length.FromMeters(2.0);
/// var b = Length.FromMeters(2.1);
/// var tolerance = Length.FromCentimeters(10);
/// a.Equals(b, tolerance); // true, 2m equals 2.1m +/- 0.1m
/// </code>
/// </example>
/// <para>
/// It is generally advised against specifying "zero" tolerance, due to the nature of floating-point operations.
/// </para>
/// </summary>
/// <param name="other">The other quantity to compare to.</param>
/// <param name="tolerance">The absolute tolerance value. Must be greater than or equal to zero.</param>
/// <returns>True if the absolute difference between the two values is not greater than the specified tolerance.</returns>
bool Equals(TSelf? other, TSelf tolerance);
#endif
}
/// <summary>
/// An <see cref="IQuantity{TSelf, TUnitType}" /> that (in .NET 7+) implements generic math interfaces for arithmetic
/// operations.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TUnitType">The underlying unit enum type.</typeparam>
public interface IArithmeticQuantity<TSelf, TUnitType> : IQuantity<TSelf, TUnitType>, ILinearQuantity<TSelf>
#if NET7_0_OR_GREATER
, IAdditionOperators<TSelf, TSelf, TSelf>
, ISubtractionOperators<TSelf, TSelf, TSelf>
, IMultiplyOperators<TSelf, QuantityValue, TSelf>
, IDivisionOperators<TSelf, QuantityValue, TSelf>
, IUnaryNegationOperators<TSelf, TSelf>
#endif
where TSelf : IArithmeticQuantity<TSelf, TUnitType>
where TUnitType : struct, Enum
{
}
- ILogarithmicQuantity - in
NET7_OR_GREATER
I introduce the staticLogarithmicScalingFactor
, however innetstandard
this needs to either be an instance member ( 😞 ) or alternatively I could introduce an extra interface for it'sQuantityInfo
, overriding the property to something of the sortnew ILogarithmicQuantityInfo<TQuantity> QuantityInfo { get; }
/// <summary>
/// Represents a logarithmic quantity that supports arithmetic operations and implements generic math interfaces
/// (in .NET 7+). This interface is designed for quantities that are logarithmic in nature, such as decibels.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <remarks>
/// Logarithmic quantities are different from linear quantities in that they represent values on a logarithmic scale.
/// This interface extends <see cref="IQuantity{TSelf, TUnitType}" /> and provides additional functionality specific
/// to logarithmic quantities, including arithmetic operations and a logarithmic scaling factor.
/// The logarithmic scale assumed here is base-10.
/// </remarks>
public interface ILogarithmicQuantity<TSelf> : IQuantityInstance<TSelf>
#if NET7_0_OR_GREATER
, IMultiplicativeIdentity<TSelf, TSelf>
#endif
where TSelf : ILogarithmicQuantity<TSelf>
{
#if NET7_0_OR_GREATER
/// <summary>
/// Gets the logarithmic scaling factor used to convert between linear and logarithmic units.
/// This factor is typically 10, but there are exceptions such as the PowerRatio, which uses 20.
/// </summary>
/// <value>
/// The logarithmic scaling factor.
/// </value>
static abstract QuantityValue LogarithmicScalingFactor { get; }
/// <summary>
/// The zero value of this quantity.
/// </summary>
static abstract TSelf Zero { get; }
static TSelf IMultiplicativeIdentity<TSelf, TSelf>.MultiplicativeIdentity => TSelf.Zero;
#else
/// <summary>
/// Gets the logarithmic scaling factor used to convert between linear and logarithmic units.
/// This factor is typically 10, but there are exceptions such as the PowerRatio, which uses 20.
/// </summary>
/// <value>
/// The logarithmic scaling factor.
/// </value>
QuantityValue LogarithmicScalingFactor { get; }
#endif
}
/// <inheritdoc cref="ILogarithmicQuantity{TSelf}"/>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TUnitType">The underlying unit enum type.</typeparam>
public interface ILogarithmicQuantity<TSelf, TUnitType> : IQuantity<TSelf, TUnitType>, ILogarithmicQuantity<TSelf>
#if NET7_0_OR_GREATER
, IAdditionOperators<TSelf, TSelf, TSelf>
, ISubtractionOperators<TSelf, TSelf, TSelf>
, IMultiplyOperators<TSelf, QuantityValue, TSelf>
, IDivisionOperators<TSelf, QuantityValue, TSelf>
, IUnaryNegationOperators<TSelf, TSelf>
#endif
where TSelf : ILogarithmicQuantity<TSelf, TUnitType>
where TUnitType : struct, Enum
{
}
IAffineQuantity
: there is only one of these- theTemperature
with it'sTOffset
being theTemperatureDelta
(also note that the conversion functions here are of the formax + b
)
/// <summary>
/// An <see cref="IQuantity{TSelf}"/> that (in .NET 7+) implements generic math interfaces for arithmetic operations.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TOffset"></typeparam>
public interface IAffineQuantity<TSelf, TOffset> : IQuantityInstance<TSelf>
#if NET7_0_OR_GREATER
, IAdditiveIdentity<TSelf, TOffset>
where TOffset : IAdditiveIdentity<TOffset, TOffset>
#endif
where TSelf : IAffineQuantity<TSelf, TOffset>
{
#if NET7_0_OR_GREATER
/// <summary>
/// The zero value of this quantity.
/// </summary>
static abstract TSelf Zero { get; }
static TOffset IAdditiveIdentity<TSelf, TOffset>.AdditiveIdentity => TOffset.AdditiveIdentity;
#endif
#if EXTENDED_EQUALS_INTERFACE
/// <summary>
/// <para>
/// Compare equality to <paramref name="other"/> given a <paramref name="tolerance"/> for the maximum allowed +/- difference.
/// </para>
/// <example>
/// In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
/// <code>
/// var a = Length.FromMeters(2.0);
/// var b = Length.FromMeters(2.1);
/// var tolerance = Length.FromCentimeters(10);
/// a.Equals(b, tolerance); // true, 2m equals 2.1m +/- 0.1m
/// </code>
/// </example>
/// <para>
/// It is generally advised against specifying "zero" tolerance, due to the nature of floating-point operations.
/// </para>
/// </summary>
/// <param name="other">The other quantity to compare to.</param>
/// <param name="tolerance">The absolute tolerance value. Must be greater than or equal to zero.</param>
/// <returns>True if the absolute difference between the two values is not greater than the specified tolerance.</returns>
bool Equals(TSelf? other, TOffset tolerance);
#endif
}
/// <summary>
/// An <see cref="IQuantity{TSelf, TUnitType}"/> that (in .NET 7+) implements generic math interfaces for arithmetic operations.
/// </summary>
/// <typeparam name="TSelf">The type itself, for the CRT pattern.</typeparam>
/// <typeparam name="TUnitType">The underlying unit enum type.</typeparam>
/// <typeparam name="TOffset"></typeparam>
public interface IAffineQuantity<TSelf, TUnitType, TOffset> : IQuantity<TSelf, TUnitType>, IAffineQuantity<TSelf, TOffset>
#if NET7_0_OR_GREATER
, IAdditionOperators<TSelf, TOffset, TSelf>
, ISubtractionOperators<TSelf, TSelf, TOffset>
where TOffset : IAdditiveIdentity<TOffset, TOffset>
#endif
where TSelf : IAffineQuantity<TSelf, TUnitType, TOffset>
where TUnitType : struct, Enum
{
}